    001package net.minecraft.block;
    002
    003import static net.minecraftforge.common.ForgeDirection.DOWN;
    004import static net.minecraftforge.common.ForgeDirection.UP;
    005
    006import java.util.ArrayList;
    007import java.util.List;
    008import java.util.Random;
    009
    010import net.minecraft.block.material.Material;
    011import net.minecraft.client.particle.EffectRenderer;
    012import net.minecraft.client.renderer.texture.IconRegister;
    013import net.minecraft.creativetab.CreativeTabs;
    014import net.minecraft.enchantment.EnchantmentHelper;
    015import net.minecraft.entity.Entity;
    016import net.minecraft.entity.EntityLiving;
    017import net.minecraft.entity.EnumCreatureType;
    018import net.minecraft.entity.item.EntityItem;
    019import net.minecraft.entity.item.EntityXPOrb;
    020import net.minecraft.entity.player.EntityPlayer;
    021import net.minecraft.item.Item;
    022import net.minecraft.item.ItemAnvilBlock;
    023import net.minecraft.item.ItemBlock;
    024import net.minecraft.item.ItemCloth;
    025import net.minecraft.item.ItemColored;
    026import net.minecraft.item.ItemLeaves;
    027import net.minecraft.item.ItemLilyPad;
    028import net.minecraft.item.ItemMultiTextureTile;
    029import net.minecraft.item.ItemPiston;
    030import net.minecraft.item.ItemSlab;
    031import net.minecraft.item.ItemSnow;
    032import net.minecraft.item.ItemStack;
    033import net.minecraft.stats.StatList;
    034import net.minecraft.tileentity.TileEntity;
    035import net.minecraft.tileentity.TileEntitySign;
    036import net.minecraft.util.AxisAlignedBB;
    037import net.minecraft.util.ChunkCoordinates;
    038import net.minecraft.util.Icon;
    039import net.minecraft.util.MovingObjectPosition;
    040import net.minecraft.util.StatCollector;
    041import net.minecraft.util.Vec3;
    042import net.minecraft.world.Explosion;
    043import net.minecraft.world.IBlockAccess;
    044import net.minecraft.world.World;
    045import net.minecraft.world.WorldProviderEnd;
    046import net.minecraftforge.common.EnumPlantType;
    047import net.minecraftforge.common.ForgeDirection;
    048import net.minecraftforge.common.ForgeHooks;
    049import net.minecraftforge.common.IPlantable;
    050import cpw.mods.fml.relauncher.Side;
    051import cpw.mods.fml.relauncher.SideOnly;
    052
    053public class Block
    054{
    055    protected static int[] blockFireSpreadSpeed = new int[4096];
    056    protected static int[] blockFlammability = new int[4096];
    057    /**
    058     * used as foreach item, if item.tab = current tab, display it on the screen
    059     */
    060    private CreativeTabs displayOnCreativeTab;
    061    public static final StepSound soundPowderFootstep = new StepSound("stone", 1.0F, 1.0F);
    062    public static final StepSound soundWoodFootstep = new StepSound("wood", 1.0F, 1.0F);
    063    public static final StepSound soundGravelFootstep = new StepSound("gravel", 1.0F, 1.0F);
    064    public static final StepSound soundGrassFootstep = new StepSound("grass", 1.0F, 1.0F);
    065    public static final StepSound soundStoneFootstep = new StepSound("stone", 1.0F, 1.0F);
    066    public static final StepSound soundMetalFootstep = new StepSound("stone", 1.0F, 1.5F);
    067    public static final StepSound soundGlassFootstep = new StepSoundStone("stone", 1.0F, 1.0F);
    068    public static final StepSound soundClothFootstep = new StepSound("cloth", 1.0F, 1.0F);
    069    public static final StepSound soundSandFootstep = new StepSound("sand", 1.0F, 1.0F);
    070    public static final StepSound soundSnowFootstep = new StepSound("snow", 1.0F, 1.0F);
    071    public static final StepSound soundLadderFootstep = new StepSoundSand("ladder", 1.0F, 1.0F);
    072    public static final StepSound soundAnvilFootstep = new StepSoundAnvil("anvil", 0.3F, 1.0F);
    073
    074    /** List of ly/ff (BlockType) containing the already registered blocks. */
    075    public static final Block[] blocksList = new Block[4096];
    076
    077    /**
    078     * An array of 4096 booleans corresponding to the result of the isOpaqueCube() method for each block ID
    079     */
    080    public static final boolean[] opaqueCubeLookup = new boolean[4096];
    081
    082    /** How much light is subtracted for going through this block */
    083    public static final int[] lightOpacity = new int[4096];
    084
    085    /** Array of booleans that tells if a block can grass */
    086    public static final boolean[] canBlockGrass = new boolean[4096];
    087
    088    /** Amount of light emitted */
    089    public static final int[] lightValue = new int[4096];
    090
    091    /**
    092     * Flag if block ID should use the brightest neighbor light value as its own
    093     */
    094    public static boolean[] useNeighborBrightness = new boolean[4096];
    095    public static final Block stone = (new BlockStone(1)).setHardness(1.5F).setResistance(10.0F).setStepSound(soundStoneFootstep).setUnlocalizedName("stone");
    096    public static final BlockGrass grass = (BlockGrass)(new BlockGrass(2)).setHardness(0.6F).setStepSound(soundGrassFootstep).setUnlocalizedName("grass");
    097    public static final Block dirt = (new BlockDirt(3)).setHardness(0.5F).setStepSound(soundGravelFootstep).setUnlocalizedName("dirt");
    098    public static final Block cobblestone = (new Block(4, Material.rock)).setHardness(2.0F).setResistance(10.0F).setStepSound(soundStoneFootstep).setUnlocalizedName("stonebrick").setCreativeTab(CreativeTabs.tabBlock);
    099    public static final Block planks = (new BlockWood(5)).setHardness(2.0F).setResistance(5.0F).setStepSound(soundWoodFootstep).setUnlocalizedName("wood");
    100    public static final Block sapling = (new BlockSapling(6)).setHardness(0.0F).setStepSound(soundGrassFootstep).setUnlocalizedName("sapling");
    101    public static final Block bedrock = (new Block(7, Material.rock)).setBlockUnbreakable().setResistance(6000000.0F).setStepSound(soundStoneFootstep).setUnlocalizedName("bedrock").disableStats().setCreativeTab(CreativeTabs.tabBlock);
    102    public static final BlockFluid waterMoving = (BlockFluid)(new BlockFlowing(8, Material.water)).setHardness(100.0F).setLightOpacity(3).setUnlocalizedName("water").disableStats();
    103    public static final Block waterStill = (new BlockStationary(9, Material.water)).setHardness(100.0F).setLightOpacity(3).setUnlocalizedName("water").disableStats();
    104    public static final BlockFluid lavaMoving = (BlockFluid)(new BlockFlowing(10, Material.lava)).setHardness(0.0F).setLightValue(1.0F).setUnlocalizedName("lava").disableStats();
    105
    106    /** Stationary lava source block */
    107    public static final Block lavaStill = (new BlockStationary(11, Material.lava)).setHardness(100.0F).setLightValue(1.0F).setUnlocalizedName("lava").disableStats();
    108    public static final Block sand = (new BlockSand(12)).setHardness(0.5F).setStepSound(soundSandFootstep).setUnlocalizedName("sand");
    109    public static final Block gravel = (new BlockGravel(13)).setHardness(0.6F).setStepSound(soundGravelFootstep).setUnlocalizedName("gravel");
    110    public static final Block oreGold = (new BlockOre(14)).setHardness(3.0F).setResistance(5.0F).setStepSound(soundStoneFootstep).setUnlocalizedName("oreGold");
    111    public static final Block oreIron = (new BlockOre(15)).setHardness(3.0F).setResistance(5.0F).setStepSound(soundStoneFootstep).setUnlocalizedName("oreIron");
    112    public static final Block oreCoal = (new BlockOre(16)).setHardness(3.0F).setResistance(5.0F).setStepSound(soundStoneFootstep).setUnlocalizedName("oreCoal");
    113    public static final Block wood = (new BlockLog(17)).setHardness(2.0F).setStepSound(soundWoodFootstep).setUnlocalizedName("log");
    114    public static final BlockLeaves leaves = (BlockLeaves)(new BlockLeaves(18)).setHardness(0.2F).setLightOpacity(1).setStepSound(soundGrassFootstep).setUnlocalizedName("leaves");
    115    public static final Block sponge = (new BlockSponge(19)).setHardness(0.6F).setStepSound(soundGrassFootstep).setUnlocalizedName("sponge");
    116    public static final Block glass = (new BlockGlass(20, Material.glass, false)).setHardness(0.3F).setStepSound(soundGlassFootstep).setUnlocalizedName("glass");
    117    public static final Block oreLapis = (new BlockOre(21)).setHardness(3.0F).setResistance(5.0F).setStepSound(soundStoneFootstep).setUnlocalizedName("oreLapis");
    118    public static final Block blockLapis = (new Block(22, Material.rock)).setHardness(3.0F).setResistance(5.0F).setStepSound(soundStoneFootstep).setUnlocalizedName("blockLapis").setCreativeTab(CreativeTabs.tabBlock);
    119    public static final Block dispenser = (new BlockDispenser(23)).setHardness(3.5F).setStepSound(soundStoneFootstep).setUnlocalizedName("dispenser");
    120    public static final Block sandStone = (new BlockSandStone(24)).setStepSound(soundStoneFootstep).setHardness(0.8F).setUnlocalizedName("sandStone");
    121    public static final Block music = (new BlockNote(25)).setHardness(0.8F).setUnlocalizedName("musicBlock");
    122    public static final Block bed = (new BlockBed(26)).setHardness(0.2F).setUnlocalizedName("bed").disableStats();
    123    public static final Block railPowered = (new BlockRailPowered(27)).setHardness(0.7F).setStepSound(soundMetalFootstep).setUnlocalizedName("goldenRail");
    124    public static final Block railDetector = (new BlockDetectorRail(28)).setHardness(0.7F).setStepSound(soundMetalFootstep).setUnlocalizedName("detectorRail");
    125    public static final BlockPistonBase pistonStickyBase = (BlockPistonBase)(new BlockPistonBase(29, true)).setUnlocalizedName("pistonStickyBase");
    126    public static final Block web = (new BlockWeb(30)).setLightOpacity(1).setHardness(4.0F).setUnlocalizedName("web");
    127    public static final BlockTallGrass tallGrass = (BlockTallGrass)(new BlockTallGrass(31)).setHardness(0.0F).setStepSound(soundGrassFootstep).setUnlocalizedName("tallgrass");
    128    public static final BlockDeadBush deadBush = (BlockDeadBush)(new BlockDeadBush(32)).setHardness(0.0F).setStepSound(soundGrassFootstep).setUnlocalizedName("deadbush");
    129    public static final BlockPistonBase pistonBase = (BlockPistonBase)(new BlockPistonBase(33, false)).setUnlocalizedName("pistonBase");
    130    public static final BlockPistonExtension pistonExtension = new BlockPistonExtension(34);
    131    public static final Block cloth = (new BlockCloth()).setHardness(0.8F).setStepSound(soundClothFootstep).setUnlocalizedName("cloth");
    132    public static final BlockPistonMoving pistonMoving = new BlockPistonMoving(36);
    133    public static final BlockFlower plantYellow = (BlockFlower)(new BlockFlower(37)).setHardness(0.0F).setStepSound(soundGrassFootstep).setUnlocalizedName("flower");
    134    public static final BlockFlower plantRed = (BlockFlower)(new BlockFlower(38)).setHardness(0.0F).setStepSound(soundGrassFootstep).setUnlocalizedName("rose");
    135    public static final BlockFlower mushroomBrown = (BlockFlower)(new BlockMushroom(39, "mushroom_brown")).setHardness(0.0F).setStepSound(soundGrassFootstep).setLightValue(0.125F).setUnlocalizedName("mushroom");
    136    public static final BlockFlower mushroomRed = (BlockFlower)(new BlockMushroom(40, "mushroom_red")).setHardness(0.0F).setStepSound(soundGrassFootstep).setUnlocalizedName("mushroom");
    137    public static final Block blockGold = (new BlockOreStorage(41)).setHardness(3.0F).setResistance(10.0F).setStepSound(soundMetalFootstep).setUnlocalizedName("blockGold");
    138    public static final Block blockSteel = (new BlockOreStorage(42)).setHardness(5.0F).setResistance(10.0F).setStepSound(soundMetalFootstep).setUnlocalizedName("blockIron");
    139
    140    /** stoneDoubleSlab */
    141    public static final BlockHalfSlab stoneDoubleSlab = (BlockHalfSlab)(new BlockStep(43, true)).setHardness(2.0F).setResistance(10.0F).setStepSound(soundStoneFootstep).setUnlocalizedName("stoneSlab");
    142
    143    /** stoneSingleSlab */
    144    public static final BlockHalfSlab stoneSingleSlab = (BlockHalfSlab)(new BlockStep(44, false)).setHardness(2.0F).setResistance(10.0F).setStepSound(soundStoneFootstep).setUnlocalizedName("stoneSlab");
    145    public static final Block brick = (new Block(45, Material.rock)).setHardness(2.0F).setResistance(10.0F).setStepSound(soundStoneFootstep).setUnlocalizedName("brick").setCreativeTab(CreativeTabs.tabBlock);
    146    public static final Block tnt = (new BlockTNT(46)).setHardness(0.0F).setStepSound(soundGrassFootstep).setUnlocalizedName("tnt");
    147    public static final Block bookShelf = (new BlockBookshelf(47)).setHardness(1.5F).setStepSound(soundWoodFootstep).setUnlocalizedName("bookshelf");
    148    public static final Block cobblestoneMossy = (new Block(48, Material.rock)).setHardness(2.0F).setResistance(10.0F).setStepSound(soundStoneFootstep).setUnlocalizedName("stoneMoss").setCreativeTab(CreativeTabs.tabBlock);
    149    public static final Block obsidian = (new BlockObsidian(49)).setHardness(50.0F).setResistance(2000.0F).setStepSound(soundStoneFootstep).setUnlocalizedName("obsidian");
    150    public static final Block torchWood = (new BlockTorch(50)).setHardness(0.0F).setLightValue(0.9375F).setStepSound(soundWoodFootstep).setUnlocalizedName("torch");
    151    public static final BlockFire fire = (BlockFire)(new BlockFire(51)).setHardness(0.0F).setLightValue(1.0F).setStepSound(soundWoodFootstep).setUnlocalizedName("fire").disableStats();
    152    public static final Block mobSpawner = (new BlockMobSpawner(52)).setHardness(5.0F).setStepSound(soundMetalFootstep).setUnlocalizedName("mobSpawner").disableStats();
    153    public static final Block stairCompactPlanks = (new BlockStairs(53, planks, 0)).setUnlocalizedName("stairsWood");
    154    public static final BlockChest chest = (BlockChest)(new BlockChest(54, 0)).setHardness(2.5F).setStepSound(soundWoodFootstep).setUnlocalizedName("chest");
    155    public static final BlockRedstoneWire redstoneWire = (BlockRedstoneWire)(new BlockRedstoneWire(55)).setHardness(0.0F).setStepSound(soundPowderFootstep).setUnlocalizedName("redstoneDust").disableStats();
    156    public static final Block oreDiamond = (new BlockOre(56)).setHardness(3.0F).setResistance(5.0F).setStepSound(soundStoneFootstep).setUnlocalizedName("oreDiamond");
    157    public static final Block blockDiamond = (new BlockOreStorage(57)).setHardness(5.0F).setResistance(10.0F).setStepSound(soundMetalFootstep).setUnlocalizedName("blockDiamond");
    158    public static final Block workbench = (new BlockWorkbench(58)).setHardness(2.5F).setStepSound(soundWoodFootstep).setUnlocalizedName("workbench");
    159    public static final Block crops = (new BlockCrops(59)).setUnlocalizedName("crops");
    160    public static final Block tilledField = (new BlockFarmland(60)).setHardness(0.6F).setStepSound(soundGravelFootstep).setUnlocalizedName("farmland");
    161    public static final Block furnaceIdle = (new BlockFurnace(61, false)).setHardness(3.5F).setStepSound(soundStoneFootstep).setUnlocalizedName("furnace").setCreativeTab(CreativeTabs.tabDecorations);
    162    public static final Block furnaceBurning = (new BlockFurnace(62, true)).setHardness(3.5F).setStepSound(soundStoneFootstep).setLightValue(0.875F).setUnlocalizedName("furnace");
    163    public static final Block signPost = (new BlockSign(63, TileEntitySign.class, true)).setHardness(1.0F).setStepSound(soundWoodFootstep).setUnlocalizedName("sign").disableStats();
    164    public static final Block doorWood = (new BlockDoor(64, Material.wood)).setHardness(3.0F).setStepSound(soundWoodFootstep).setUnlocalizedName("doorWood").disableStats();
    165    public static final Block ladder = (new BlockLadder(65)).setHardness(0.4F).setStepSound(soundLadderFootstep).setUnlocalizedName("ladder");
    166    public static final Block rail = (new BlockRail(66)).setHardness(0.7F).setStepSound(soundMetalFootstep).setUnlocalizedName("rail");
    167    public static final Block stairCompactCobblestone = (new BlockStairs(67, cobblestone, 0)).setUnlocalizedName("stairsStone");
    168    public static final Block signWall = (new BlockSign(68, TileEntitySign.class, false)).setHardness(1.0F).setStepSound(soundWoodFootstep).setUnlocalizedName("sign").disableStats();
    169    public static final Block lever = (new BlockLever(69)).setHardness(0.5F).setStepSound(soundWoodFootstep).setUnlocalizedName("lever");
    170    public static final Block pressurePlateStone = (new BlockPressurePlate(70, "stone", Material.rock, EnumMobType.mobs)).setHardness(0.5F).setStepSound(soundStoneFootstep).setUnlocalizedName("pressurePlate");
    171    public static final Block doorSteel = (new BlockDoor(71, Material.iron)).setHardness(5.0F).setStepSound(soundMetalFootstep).setUnlocalizedName("doorIron").disableStats();
    172    public static final Block pressurePlatePlanks = (new BlockPressurePlate(72, "wood", Material.wood, EnumMobType.everything)).setHardness(0.5F).setStepSound(soundWoodFootstep).setUnlocalizedName("pressurePlate");
    173    public static final Block oreRedstone = (new BlockRedstoneOre(73, false)).setHardness(3.0F).setResistance(5.0F).setStepSound(soundStoneFootstep).setUnlocalizedName("oreRedstone").setCreativeTab(CreativeTabs.tabBlock);
    174    public static final Block oreRedstoneGlowing = (new BlockRedstoneOre(74, true)).setLightValue(0.625F).setHardness(3.0F).setResistance(5.0F).setStepSound(soundStoneFootstep).setUnlocalizedName("oreRedstone");
    175    public static final Block torchRedstoneIdle = (new BlockRedstoneTorch(75, false)).setHardness(0.0F).setStepSound(soundWoodFootstep).setUnlocalizedName("notGate");
    176    public static final Block torchRedstoneActive = (new BlockRedstoneTorch(76, true)).setHardness(0.0F).setLightValue(0.5F).setStepSound(soundWoodFootstep).setUnlocalizedName("notGate").setCreativeTab(CreativeTabs.tabRedstone);
    177    public static final Block stoneButton = (new BlockButtonStone(77)).setHardness(0.5F).setStepSound(soundStoneFootstep).setUnlocalizedName("button");
    178    public static final Block snow = (new BlockSnow(78)).setHardness(0.1F).setStepSound(soundSnowFootstep).setUnlocalizedName("snow").setLightOpacity(0);
    179    public static final Block ice = (new BlockIce(79)).setHardness(0.5F).setLightOpacity(3).setStepSound(soundGlassFootstep).setUnlocalizedName("ice");
    180    public static final Block blockSnow = (new BlockSnowBlock(80)).setHardness(0.2F).setStepSound(soundSnowFootstep).setUnlocalizedName("snow");
    181    public static final Block cactus = (new BlockCactus(81)).setHardness(0.4F).setStepSound(soundClothFootstep).setUnlocalizedName("cactus");
    182    public static final Block blockClay = (new BlockClay(82)).setHardness(0.6F).setStepSound(soundGravelFootstep).setUnlocalizedName("clay");
    183    public static final Block reed = (new BlockReed(83)).setHardness(0.0F).setStepSound(soundGrassFootstep).setUnlocalizedName("reeds").disableStats();
    184    public static final Block jukebox = (new BlockJukeBox(84)).setHardness(2.0F).setResistance(10.0F).setStepSound(soundStoneFootstep).setUnlocalizedName("jukebox");
    185    public static final Block fence = (new BlockFence(85, "wood", Material.wood)).setHardness(2.0F).setResistance(5.0F).setStepSound(soundWoodFootstep).setUnlocalizedName("fence");
    186    public static final Block pumpkin = (new BlockPumpkin(86, false)).setHardness(1.0F).setStepSound(soundWoodFootstep).setUnlocalizedName("pumpkin");
    187    public static final Block netherrack = (new BlockNetherrack(87)).setHardness(0.4F).setStepSound(soundStoneFootstep).setUnlocalizedName("hellrock");
    188    public static final Block slowSand = (new BlockSoulSand(88)).setHardness(0.5F).setStepSound(soundSandFootstep).setUnlocalizedName("hellsand");
    189    public static final Block glowStone = (new BlockGlowStone(89, Material.glass)).setHardness(0.3F).setStepSound(soundGlassFootstep).setLightValue(1.0F).setUnlocalizedName("lightgem");
    190
    191    /** The purple teleport blocks inside the obsidian circle */
    192    public static final BlockPortal portal = (BlockPortal)(new BlockPortal(90)).setHardness(-1.0F).setStepSound(soundGlassFootstep).setLightValue(0.75F).setUnlocalizedName("portal");
    193    public static final Block pumpkinLantern = (new BlockPumpkin(91, true)).setHardness(1.0F).setStepSound(soundWoodFootstep).setLightValue(1.0F).setUnlocalizedName("litpumpkin");
    194    public static final Block cake = (new BlockCake(92)).setHardness(0.5F).setStepSound(soundClothFootstep).setUnlocalizedName("cake").disableStats();
    195    public static final BlockRedstoneRepeater redstoneRepeaterIdle = (BlockRedstoneRepeater)(new BlockRedstoneRepeater(93, false)).setHardness(0.0F).setStepSound(soundWoodFootstep).setUnlocalizedName("diode").disableStats();
    196    public static final BlockRedstoneRepeater redstoneRepeaterActive = (BlockRedstoneRepeater)(new BlockRedstoneRepeater(94, true)).setHardness(0.0F).setLightValue(0.625F).setStepSound(soundWoodFootstep).setUnlocalizedName("diode").disableStats();
    197
    198    /**
    199     * April fools secret locked chest, only spawns on new chunks on 1st April.
    200     */
    201    public static final Block lockedChest = (new BlockLockedChest(95)).setHardness(0.0F).setLightValue(1.0F).setStepSound(soundWoodFootstep).setUnlocalizedName("lockedchest").setTickRandomly(true);
    202    public static final Block trapdoor = (new BlockTrapDoor(96, Material.wood)).setHardness(3.0F).setStepSound(soundWoodFootstep).setUnlocalizedName("trapdoor").disableStats();
    203    public static final Block silverfish = (new BlockSilverfish(97)).setHardness(0.75F).setUnlocalizedName("monsterStoneEgg");
    204    public static final Block stoneBrick = (new BlockStoneBrick(98)).setHardness(1.5F).setResistance(10.0F).setStepSound(soundStoneFootstep).setUnlocalizedName("stonebricksmooth");
    205    public static final Block mushroomCapBrown = (new BlockMushroomCap(99, Material.wood, 0)).setHardness(0.2F).setStepSound(soundWoodFootstep).setUnlocalizedName("mushroom");
    206    public static final Block mushroomCapRed = (new BlockMushroomCap(100, Material.wood, 1)).setHardness(0.2F).setStepSound(soundWoodFootstep).setUnlocalizedName("mushroom");
    207    public static final Block fenceIron = (new BlockPane(101, "fenceIron", "fenceIron", Material.iron, true)).setHardness(5.0F).setResistance(10.0F).setStepSound(soundMetalFootstep).setUnlocalizedName("fenceIron");
    208    public static final Block thinGlass = (new BlockPane(102, "glass", "thinglass_top", Material.glass, false)).setHardness(0.3F).setStepSound(soundGlassFootstep).setUnlocalizedName("thinGlass");
    209    public static final Block melon = (new BlockMelon(103)).setHardness(1.0F).setStepSound(soundWoodFootstep).setUnlocalizedName("melon");
    210    public static final Block pumpkinStem = (new BlockStem(104, pumpkin)).setHardness(0.0F).setStepSound(soundWoodFootstep).setUnlocalizedName("pumpkinStem");
    211    public static final Block melonStem = (new BlockStem(105, melon)).setHardness(0.0F).setStepSound(soundWoodFootstep).setUnlocalizedName("pumpkinStem");
    212    public static final Block vine = (new BlockVine(106)).setHardness(0.2F).setStepSound(soundGrassFootstep).setUnlocalizedName("vine");
    213    public static final Block fenceGate = (new BlockFenceGate(107)).setHardness(2.0F).setResistance(5.0F).setStepSound(soundWoodFootstep).setUnlocalizedName("fenceGate");
    214    public static final Block stairsBrick = (new BlockStairs(108, brick, 0)).setUnlocalizedName("stairsBrick");
    215    public static final Block stairsStoneBrickSmooth = (new BlockStairs(109, stoneBrick, 0)).setUnlocalizedName("stairsStoneBrickSmooth");
    216    public static final BlockMycelium mycelium = (BlockMycelium)(new BlockMycelium(110)).setHardness(0.6F).setStepSound(soundGrassFootstep).setUnlocalizedName("mycel");
    217    public static final Block waterlily = (new BlockLilyPad(111)).setHardness(0.0F).setStepSound(soundGrassFootstep).setUnlocalizedName("waterlily");
    218    public static final Block netherBrick = (new Block(112, Material.rock)).setHardness(2.0F).setResistance(10.0F).setStepSound(soundStoneFootstep).setUnlocalizedName("netherBrick").setCreativeTab(CreativeTabs.tabBlock);
    219    public static final Block netherFence = (new BlockFence(113, "netherBrick", Material.rock)).setHardness(2.0F).setResistance(10.0F).setStepSound(soundStoneFootstep).setUnlocalizedName("netherFence");
    220    public static final Block stairsNetherBrick = (new BlockStairs(114, netherBrick, 0)).setUnlocalizedName("stairsNetherBrick");
    221    public static final Block netherStalk = (new BlockNetherStalk(115)).setUnlocalizedName("netherStalk");
    222    public static final Block enchantmentTable = (new BlockEnchantmentTable(116)).setHardness(5.0F).setResistance(2000.0F).setUnlocalizedName("enchantmentTable");
    223    public static final Block brewingStand = (new BlockBrewingStand(117)).setHardness(0.5F).setLightValue(0.125F).setUnlocalizedName("brewingStand");
    224    public static final BlockCauldron cauldron = (BlockCauldron)(new BlockCauldron(118)).setHardness(2.0F).setUnlocalizedName("cauldron");
    225    public static final Block endPortal = (new BlockEndPortal(119, Material.portal)).setHardness(-1.0F).setResistance(6000000.0F);
    226    public static final Block endPortalFrame = (new BlockEndPortalFrame(120)).setStepSound(soundGlassFootstep).setLightValue(0.125F).setHardness(-1.0F).setUnlocalizedName("endPortalFrame").setResistance(6000000.0F).setCreativeTab(CreativeTabs.tabDecorations);
    227
    228    /** The rock found in The End. */
    229    public static final Block whiteStone = (new Block(121, Material.rock)).setHardness(3.0F).setResistance(15.0F).setStepSound(soundStoneFootstep).setUnlocalizedName("whiteStone").setCreativeTab(CreativeTabs.tabBlock);
    230    public static final Block dragonEgg = (new BlockDragonEgg(122)).setHardness(3.0F).setResistance(15.0F).setStepSound(soundStoneFootstep).setLightValue(0.125F).setUnlocalizedName("dragonEgg");
    231    public static final Block redstoneLampIdle = (new BlockRedstoneLight(123, false)).setHardness(0.3F).setStepSound(soundGlassFootstep).setUnlocalizedName("redstoneLight").setCreativeTab(CreativeTabs.tabRedstone);
    232    public static final Block redstoneLampActive = (new BlockRedstoneLight(124, true)).setHardness(0.3F).setStepSound(soundGlassFootstep).setUnlocalizedName("redstoneLight");
    233    public static final BlockHalfSlab woodDoubleSlab = (BlockHalfSlab)(new BlockWoodSlab(125, true)).setHardness(2.0F).setResistance(5.0F).setStepSound(soundWoodFootstep).setUnlocalizedName("woodSlab");
    234    public static final BlockHalfSlab woodSingleSlab = (BlockHalfSlab)(new BlockWoodSlab(126, false)).setHardness(2.0F).setResistance(5.0F).setStepSound(soundWoodFootstep).setUnlocalizedName("woodSlab");
    235    public static final Block cocoaPlant = (new BlockCocoa(127)).setHardness(0.2F).setResistance(5.0F).setStepSound(soundWoodFootstep).setUnlocalizedName("cocoa");
    236    public static final Block stairsSandStone = (new BlockStairs(128, sandStone, 0)).setUnlocalizedName("stairsSandStone");
    237    public static final Block oreEmerald = (new BlockOre(129)).setHardness(3.0F).setResistance(5.0F).setStepSound(soundStoneFootstep).setUnlocalizedName("oreEmerald");
    238    public static final Block enderChest = (new BlockEnderChest(130)).setHardness(22.5F).setResistance(1000.0F).setStepSound(soundStoneFootstep).setUnlocalizedName("enderChest").setLightValue(0.5F);
    239    public static final BlockTripWireSource tripWireSource = (BlockTripWireSource)(new BlockTripWireSource(131)).setUnlocalizedName("tripWireSource");
    240    public static final Block tripWire = (new BlockTripWire(132)).setUnlocalizedName("tripWire");
    241    public static final Block blockEmerald = (new BlockOreStorage(133)).setHardness(5.0F).setResistance(10.0F).setStepSound(soundMetalFootstep).setUnlocalizedName("blockEmerald");
    242    public static final Block stairsWoodSpruce = (new BlockStairs(134, planks, 1)).setUnlocalizedName("stairsWoodSpruce");
    243    public static final Block stairsWoodBirch = (new BlockStairs(135, planks, 2)).setUnlocalizedName("stairsWoodBirch");
    244    public static final Block stairsWoodJungle = (new BlockStairs(136, planks, 3)).setUnlocalizedName("stairsWoodJungle");
    245    public static final Block commandBlock = (new BlockCommandBlock(137)).setUnlocalizedName("commandBlock");
    246    public static final BlockBeacon beacon = (BlockBeacon)(new BlockBeacon(138)).setUnlocalizedName("beacon").setLightValue(1.0F);
    247    public static final Block cobblestoneWall = (new BlockWall(139, cobblestone)).setUnlocalizedName("cobbleWall");
    248    public static final Block flowerPot = (new BlockFlowerPot(140)).setHardness(0.0F).setStepSound(soundPowderFootstep).setUnlocalizedName("flowerPot");
    249    public static final Block carrot = (new BlockCarrot(141)).setUnlocalizedName("carrots");
    250    public static final Block potato = (new BlockPotato(142)).setUnlocalizedName("potatoes");
    251    public static final Block woodenButton = (new BlockButtonWood(143)).setHardness(0.5F).setStepSound(soundWoodFootstep).setUnlocalizedName("button");
    252    public static final Block skull = (new BlockSkull(144)).setHardness(1.0F).setStepSound(soundStoneFootstep).setUnlocalizedName("skull");
    253    public static final Block anvil = (new BlockAnvil(145)).setHardness(5.0F).setStepSound(soundAnvilFootstep).setResistance(2000.0F).setUnlocalizedName("anvil");
    254    public static final Block field_94347_ck = (new BlockChest(146, 1)).setHardness(2.5F).setStepSound(soundWoodFootstep).setUnlocalizedName("chestTrap");
    255    public static final Block field_94348_cl = (new BlockPressurePlateWeighted(147, "blockGold", Material.iron, 64)).setHardness(0.5F).setStepSound(soundWoodFootstep).setUnlocalizedName("weightedPlate_light");
    256    public static final Block field_94345_cm = (new BlockPressurePlateWeighted(148, "blockIron", Material.iron, 640)).setHardness(0.5F).setStepSound(soundWoodFootstep).setUnlocalizedName("weightedPlate_heavy");
    257    public static final BlockComparator field_94346_cn = (BlockComparator)(new BlockComparator(149, false)).setHardness(0.0F).setStepSound(soundWoodFootstep).setUnlocalizedName("comparator").disableStats();
    258    public static final BlockComparator field_94343_co = (BlockComparator)(new BlockComparator(150, true)).setHardness(0.0F).setLightValue(0.625F).setStepSound(soundWoodFootstep).setUnlocalizedName("comparator").disableStats();
    259    public static final BlockDaylightDetector field_94344_cp = (BlockDaylightDetector)(new BlockDaylightDetector(151)).setHardness(0.2F).setStepSound(soundWoodFootstep).setUnlocalizedName("daylightDetector");
    260    public static final Block field_94341_cq = (new BlockPoweredOre(152)).setHardness(5.0F).setResistance(10.0F).setStepSound(soundMetalFootstep).setUnlocalizedName("blockRedstone");
    261    public static final Block field_94342_cr = (new BlockOre(153)).setHardness(3.0F).setResistance(5.0F).setStepSound(soundStoneFootstep).setUnlocalizedName("netherquartz");
    262    public static final BlockHopper field_94340_cs = (BlockHopper)(new BlockHopper(154)).setHardness(3.0F).setResistance(8.0F).setStepSound(soundWoodFootstep).setUnlocalizedName("hopper");
    263    public static final Block field_94339_ct = (new BlockQuartz(155)).setStepSound(soundStoneFootstep).setHardness(0.8F).setUnlocalizedName("quartzBlock");
    264    public static final Block field_94338_cu = (new BlockStairs(156, field_94339_ct, 0)).setUnlocalizedName("stairsQuartz");
    265    public static final Block field_94337_cv = (new BlockRailPowered(157)).setHardness(0.7F).setStepSound(soundMetalFootstep).setUnlocalizedName("activatorRail");
    266    public static final Block field_96469_cy = (new BlockDropper(158)).setHardness(3.5F).setStepSound(soundStoneFootstep).setUnlocalizedName("dropper");
    267
    268    /** ID of the block. */
    269    public final int blockID;
    270
    271    /** Indicates how many hits it takes to break a block. */
    272    protected float blockHardness;
    273
    274    /** Indicates the blocks resistance to explosions. */
    275    protected float blockResistance;
    276
    277    /**
    278     * set to true when Block's constructor is called through the chain of super()'s. Note: Never used
    279     */
    280    protected boolean blockConstructorCalled = true;
    281
    282    /**
    283     * If this field is true, the block is counted for statistics (mined or placed)
    284     */
    285    protected boolean enableStats = true;
    286
    287    /**
    288     * Flags whether or not this block is of a type that needs random ticking. Ref-counted by ExtendedBlockStorage in
    289     * order to broadly cull a chunk from the random chunk update list for efficiency's sake.
    290     */
    291    protected boolean needsRandomTick;
    292
    293    /** true if the Block contains a Tile Entity */
    294    protected boolean isBlockContainer;
    295
    296    /** minimum X for the block bounds (local coordinates) */
    297    protected double minX;
    298
    299    /** minimum Y for the block bounds (local coordinates) */
    300    protected double minY;
    301
    302    /** minimum Z for the block bounds (local coordinates) */
    303    protected double minZ;
    304
    305    /** maximum X for the block bounds (local coordinates) */
    306    protected double maxX;
    307
    308    /** maximum Y for the block bounds (local coordinates) */
    309    protected double maxY;
    310
    311    /** maximum Z for the block bounds (local coordinates) */
    312    protected double maxZ;
    313
    314    /** Sound of stepping on the block */
    315    public StepSound stepSound;
    316    public float blockParticleGravity;
    317
    318    /** Block material definition. */
    319    public final Material blockMaterial;
    320
    321    /**
    322     * Determines how much velocity is maintained while moving on top of this block
    323     */
    324    public float slipperiness;
    325
    326    /** The unlocalized name of this block. */
    327    private String unlocalizedName;
    328    @SideOnly(Side.CLIENT)
    329    protected Icon field_94336_cN;
    330
    331    public Block(int par1, Material par2Material)
    332    {
    333        this.stepSound = soundPowderFootstep;
    334        this.blockParticleGravity = 1.0F;
    335        this.slipperiness = 0.6F;
    336
    337        if (blocksList[par1] != null)
    338        {
    339            throw new IllegalArgumentException("Slot " + par1 + " is already occupied by " + blocksList[par1] + " when adding " + this);
    340        }
    341        else
    342        {
    343            this.blockMaterial = par2Material;
    344            blocksList[par1] = this;
    345            this.blockID = par1;
    346            this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
    347            opaqueCubeLookup[par1] = this.isOpaqueCube();
    348            lightOpacity[par1] = this.isOpaqueCube() ? 255 : 0;
    349            canBlockGrass[par1] = !par2Material.getCanBlockGrass();
    350        }
    351    }
    352
    353    /**
    354     * This method is called on a block after all other blocks gets already created. You can use it to reference and
    355     * configure something on the block that needs the others ones.
    356     */
    357    protected void initializeBlock() {}
    358
    359    /**
    360     * Sets the footstep sound for the block. Returns the object for convenience in constructing.
    361     */
    362    public Block setStepSound(StepSound par1StepSound)
    363    {
    364        this.stepSound = par1StepSound;
    365        return this;
    366    }
    367
    368    /**
    369     * Sets how much light is blocked going through this block. Returns the object for convenience in constructing.
    370     */
    371    public Block setLightOpacity(int par1)
    372    {
    373        lightOpacity[this.blockID] = par1;
    374        return this;
    375    }
    376
    377    /**
    378     * Sets the amount of light emitted by a block from 0.0f to 1.0f (converts internally to 0-15). Returns the object
    379     * for convenience in constructing.
    380     */
    381    public Block setLightValue(float par1)
    382    {
    383        lightValue[this.blockID] = (int)(15.0F * par1);
    384        return this;
    385    }
    386
    387    /**
    388     * Sets the the blocks resistance to explosions. Returns the object for convenience in constructing.
    389     */
    390    public Block setResistance(float par1)
    391    {
    392        this.blockResistance = par1 * 3.0F;
    393        return this;
    394    }
    395
    396    public static boolean isNormalCube(int par0)
    397    {
    398        Block block = blocksList[par0];
    399        return block == null ? false : block.blockMaterial.isOpaque() && block.renderAsNormalBlock() && !block.canProvidePower();
    400    }
    401
    402    /**
    403     * If this block doesn't render as an ordinary block it will return False (examples: signs, buttons, stairs, etc)
    404     */
    405    public boolean renderAsNormalBlock()
    406    {
    407        return true;
    408    }
    409
    410    public boolean getBlocksMovement(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
    411    {
    412        return !this.blockMaterial.blocksMovement();
    413    }
    414
    415    /**
    416     * The type of render function that is called for this block
    417     */
    418    public int getRenderType()
    419    {
    420        return 0;
    421    }
    422
    423    /**
    424     * Sets how many hits it takes to break a block.
    425     */
    426    public Block setHardness(float par1)
    427    {
    428        this.blockHardness = par1;
    429
    430        if (this.blockResistance < par1 * 5.0F)
    431        {
    432            this.blockResistance = par1 * 5.0F;
    433        }
    434
    435        return this;
    436    }
    437
    438    /**
    439     * This method will make the hardness of the block equals to -1, and the block is indestructible.
    440     */
    441    public Block setBlockUnbreakable()
    442    {
    443        this.setHardness(-1.0F);
    444        return this;
    445    }
    446
    447    /**
    448     * Returns the block hardness at a location. Args: world, x, y, z
    449     */
    450    public float getBlockHardness(World par1World, int par2, int par3, int par4)
    451    {
    452        return this.blockHardness;
    453    }
    454
    455    /**
    456     * Sets whether this block type will receive random update ticks
    457     */
    458    public Block setTickRandomly(boolean par1)
    459    {
    460        this.needsRandomTick = par1;
    461        return this;
    462    }
    463
    464    /**
    465     * Returns whether or not this block is of a type that needs random ticking. Called for ref-counting purposes by
    466     * ExtendedBlockStorage in order to broadly cull a chunk from the random chunk update list for efficiency's sake.
    467     */
    468    public boolean getTickRandomly()
    469    {
    470        return this.needsRandomTick;
    471    }
    472
    473    @Deprecated //Forge: New Metadata sensitive version.
    474    public boolean hasTileEntity()
    475    {
    476        return hasTileEntity(0);
    477    }
    478
    479    /**
    480     * Sets the bounds of the block.  minX, minY, minZ, maxX, maxY, maxZ
    481     */
    482    public final void setBlockBounds(float par1, float par2, float par3, float par4, float par5, float par6)
    483    {
    484        this.minX = (double)par1;
    485        this.minY = (double)par2;
    486        this.minZ = (double)par3;
    487        this.maxX = (double)par4;
    488        this.maxY = (double)par5;
    489        this.maxZ = (double)par6;
    490    }
    491
    492    @SideOnly(Side.CLIENT)
    493
    494    /**
    495     * How bright to render this block based on the light its receiving. Args: iBlockAccess, x, y, z
    496     */
    497    public float getBlockBrightness(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
    498    {
    499        return par1IBlockAccess.getBrightness(par2, par3, par4, getLightValue(par1IBlockAccess, par2, par3, par4));
    500    }
    501
    502    @SideOnly(Side.CLIENT)
    503
    504    /**
    505     * Goes straight to getLightBrightnessForSkyBlocks for Blocks, does some fancy computing for Fluids
    506     */
    507    public int getMixedBrightnessForBlock(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
    508    {
    509        return par1IBlockAccess.getLightBrightnessForSkyBlocks(par2, par3, par4, getLightValue(par1IBlockAccess, par2, par3, par4));
    510    }
    511
    512    @SideOnly(Side.CLIENT)
    513
    514    /**
    515     * Returns true if the given side of this block type should be rendered, if the adjacent block is at the given
    516     * coordinates.  Args: blockAccess, x, y, z, side
    517     */
    518    public boolean shouldSideBeRendered(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5)
    519    {
    520        return par5 == 0 && this.minY > 0.0D ? true : (par5 == 1 && this.maxY < 1.0D ? true : (par5 == 2 && this.minZ > 0.0D ? true : (par5 == 3 && this.maxZ < 1.0D ? true : (par5 == 4 && this.minX > 0.0D ? true : (par5 == 5 && this.maxX < 1.0D ? true : !par1IBlockAccess.isBlockOpaqueCube(par2, par3, par4))))));
    521    }
    522
    523    /**
    524     * Returns Returns true if the given side of this block type should be rendered (if it's solid or not), if the
    525     * adjacent block is at the given coordinates. Args: blockAccess, x, y, z, side
    526     */
    527    public boolean isBlockSolid(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5)
    528    {
    529        return par1IBlockAccess.getBlockMaterial(par2, par3, par4).isSolid();
    530    }
    531
    532    @SideOnly(Side.CLIENT)
    533
    534    /**
    535     * Retrieves the block texture to use based on the display side. Args: iBlockAccess, x, y, z, side
    536     */
    537    public Icon getBlockTexture(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5)
    538    {
    539        return this.getBlockTextureFromSideAndMetadata(par5, par1IBlockAccess.getBlockMetadata(par2, par3, par4));
    540    }
    541
    542    @SideOnly(Side.CLIENT)
    543
    544    /**
    545     * From the specified side and block metadata retrieves the blocks texture. Args: side, metadata
    546     */
    547    public Icon getBlockTextureFromSideAndMetadata(int par1, int par2)
    548    {
    549        return this.field_94336_cN;
    550    }
    551
    552    /**
    553     * Adds all intersecting collision boxes to a list. (Be sure to only add boxes to the list if they intersect the
    554     * mask.) Parameters: World, X, Y, Z, mask, list, colliding entity
    555     */
    556    public void addCollisionBoxesToList(World par1World, int par2, int par3, int par4, AxisAlignedBB par5AxisAlignedBB, List par6List, Entity par7Entity)
    557    {
    558        AxisAlignedBB axisalignedbb1 = this.getCollisionBoundingBoxFromPool(par1World, par2, par3, par4);
    559
    560        if (axisalignedbb1 != null && par5AxisAlignedBB.intersectsWith(axisalignedbb1))
    561        {
    562            par6List.add(axisalignedbb1);
    563        }
    564    }
    565
    566    @SideOnly(Side.CLIENT)
    567
    568    /**
    569     * Returns the block texture based on the side being looked at.  Args: side
    570     */
    571    public final Icon getBlockTextureFromSide(int par1)
    572    {
    573        return this.getBlockTextureFromSideAndMetadata(par1, 0);
    574    }
    575
    576    @SideOnly(Side.CLIENT)
    577
    578    /**
    579     * Returns the bounding box of the wired rectangular prism to render.
    580     */
    581    public AxisAlignedBB getSelectedBoundingBoxFromPool(World par1World, int par2, int par3, int par4)
    582    {
    583        return AxisAlignedBB.getAABBPool().getAABB((double)par2 + this.minX, (double)par3 + this.minY, (double)par4 + this.minZ, (double)par2 + this.maxX, (double)par3 + this.maxY, (double)par4 + this.maxZ);
    584    }
    585
    586    /**
    587     * Returns a bounding box from the pool of bounding boxes (this means this box can change after the pool has been
    588     * cleared to be reused)
    589     */
    590    public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4)
    591    {
    592        return AxisAlignedBB.getAABBPool().getAABB((double)par2 + this.minX, (double)par3 + this.minY, (double)par4 + this.minZ, (double)par2 + this.maxX, (double)par3 + this.maxY, (double)par4 + this.maxZ);
    593    }
    594
    595    /**
    596     * Is this block (a) opaque and (b) a full 1m cube?  This determines whether or not to render the shared face of two
    597     * adjacent blocks and also whether the player can attach torches, redstone wire, etc to this block.
    598     */
    599    public boolean isOpaqueCube()
    600    {
    601        return true;
    602    }
    603
    604    /**
    605     * Returns whether this block is collideable based on the arguments passed in Args: blockMetaData, unknownFlag
    606     */
    607    public boolean canCollideCheck(int par1, boolean par2)
    608    {
    609        return this.isCollidable();
    610    }
    611
    612    /**
    613     * Returns if this block is collidable (only used by Fire). Args: x, y, z
    614     */
    615    public boolean isCollidable()
    616    {
    617        return true;
    618    }
    619
    620    /**
    621     * Ticks the block if it's been scheduled
    622     */
    623    public void updateTick(World par1World, int par2, int par3, int par4, Random par5Random) {}
    624
    625    @SideOnly(Side.CLIENT)
    626
    627    /**
    628     * A randomly called display update to be able to add particles or other items for display
    629     */
    630    public void randomDisplayTick(World par1World, int par2, int par3, int par4, Random par5Random) {}
    631
    632    /**
    633     * Called right before the block is destroyed by a player.  Args: world, x, y, z, metaData
    634     */
    635    public void onBlockDestroyedByPlayer(World par1World, int par2, int par3, int par4, int par5) {}
    636
    637    /**
    638     * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are
    639     * their own) Args: x, y, z, neighbor blockID
    640     */
    641    public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) {}
    642
    643    /**
    644     * How many world ticks before ticking
    645     */
    646    public int tickRate(World par1World)
    647    {
    648        return 10;
    649    }
    650
    651    /**
    652     * Called whenever the block is added into the world. Args: world, x, y, z
    653     */
    654    public void onBlockAdded(World par1World, int par2, int par3, int par4) {}
    655
    656    /**
    657     * ejects contained items into the world, and notifies neighbours of an update, as appropriate
    658     */
    659    public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6)
    660    {
    661        if (hasTileEntity(par6) && !(this instanceof BlockContainer))
    662        {
    663            par1World.removeBlockTileEntity(par2, par3, par4);
    664        }
    665    }
    666
    667    /**
    668     * Returns the quantity of items to drop on block destruction.
    669     */
    670    public int quantityDropped(Random par1Random)
    671    {
    672        return 1;
    673    }
    674
    675    /**
    676     * Returns the ID of the items to drop on destruction.
    677     */
    678    public int idDropped(int par1, Random par2Random, int par3)
    679    {
    680        return this.blockID;
    681    }
    682
    683    /**
    684     * Gets the hardness of block at the given coordinates in the given world, relative to the ability of the given
    685     * EntityPlayer.
    686     */
    687    public float getPlayerRelativeBlockHardness(EntityPlayer par1EntityPlayer, World par2World, int par3, int par4, int par5)
    688    {
    689        float f = this.getBlockHardness(par2World, par3, par4, par5);
    690        return ForgeHooks.blockStrength(this, par1EntityPlayer, par2World, par3, par4, par5);
    691    }
    692
    693    /**
    694     * Drops the specified block items
    695     */
    696    public final void dropBlockAsItem(World par1World, int par2, int par3, int par4, int par5, int par6)
    697    {
    698        this.dropBlockAsItemWithChance(par1World, par2, par3, par4, par5, 1.0F, par6);
    699    }
    700
    701    /**
    702     * Drops the block items with a specified chance of dropping the specified items
    703     */
    704    public void dropBlockAsItemWithChance(World par1World, int par2, int par3, int par4, int par5, float par6, int par7)
    705    {
    706        if (!par1World.isRemote)
    707        {
    708            ArrayList<ItemStack> items = getBlockDropped(par1World, par2, par3, par4, par5, par7);
    709
    710            for (ItemStack item : items)
    711            {
    712                if (par1World.rand.nextFloat() <= par6)
    713                {
    714                    this.dropBlockAsItem_do(par1World, par2, par3, par4, item);
    715                }
    716            }
    717        }
    718    }
    719
    720    /**
    721     * Spawns EntityItem in the world for the given ItemStack if the world is not remote.
    722     */
    723    protected void dropBlockAsItem_do(World par1World, int par2, int par3, int par4, ItemStack par5ItemStack)
    724    {
    725        if (!par1World.isRemote && par1World.getGameRules().getGameRuleBooleanValue("doTileDrops"))
    726        {
    727            float f = 0.7F;
    728            double d0 = (double)(par1World.rand.nextFloat() * f) + (double)(1.0F - f) * 0.5D;
    729            double d1 = (double)(par1World.rand.nextFloat() * f) + (double)(1.0F - f) * 0.5D;
    730            double d2 = (double)(par1World.rand.nextFloat() * f) + (double)(1.0F - f) * 0.5D;
    731            EntityItem entityitem = new EntityItem(par1World, (double)par2 + d0, (double)par3 + d1, (double)par4 + d2, par5ItemStack);
    732            entityitem.delayBeforeCanPickup = 10;
    733            par1World.spawnEntityInWorld(entityitem);
    734        }
    735    }
    736
    737    /**
    738     * called by spawner, ore, redstoneOre blocks
    739     */
    740    protected void dropXpOnBlockBreak(World par1World, int par2, int par3, int par4, int par5)
    741    {
    742        if (!par1World.isRemote)
    743        {
    744            while (par5 > 0)
    745            {
    746                int i1 = EntityXPOrb.getXPSplit(par5);
    747                par5 -= i1;
    748                par1World.spawnEntityInWorld(new EntityXPOrb(par1World, (double)par2 + 0.5D, (double)par3 + 0.5D, (double)par4 + 0.5D, i1));
    749            }
    750        }
    751    }
    752
    753    /**
    754     * Determines the damage on the item the block drops. Used in cloth and wood.
    755     */
    756    public int damageDropped(int par1)
    757    {
    758        return 0;
    759    }
    760
    761    /**
    762     * Returns how much this block can resist explosions from the passed in entity.
    763     */
    764    public float getExplosionResistance(Entity par1Entity)
    765    {
    766        return this.blockResistance / 5.0F;
    767    }
    768
    769    /**
    770     * Ray traces through the blocks collision from start vector to end vector returning a ray trace hit. Args: world,
    771     * x, y, z, startVec, endVec
    772     */
    773    public MovingObjectPosition collisionRayTrace(World par1World, int par2, int par3, int par4, Vec3 par5Vec3, Vec3 par6Vec3)
    774    {
    775        this.setBlockBoundsBasedOnState(par1World, par2, par3, par4);
    776        par5Vec3 = par5Vec3.addVector((double)(-par2), (double)(-par3), (double)(-par4));
    777        par6Vec3 = par6Vec3.addVector((double)(-par2), (double)(-par3), (double)(-par4));
    778        Vec3 vec32 = par5Vec3.getIntermediateWithXValue(par6Vec3, this.minX);
    779        Vec3 vec33 = par5Vec3.getIntermediateWithXValue(par6Vec3, this.maxX);
    780        Vec3 vec34 = par5Vec3.getIntermediateWithYValue(par6Vec3, this.minY);
    781        Vec3 vec35 = par5Vec3.getIntermediateWithYValue(par6Vec3, this.maxY);
    782        Vec3 vec36 = par5Vec3.getIntermediateWithZValue(par6Vec3, this.minZ);
    783        Vec3 vec37 = par5Vec3.getIntermediateWithZValue(par6Vec3, this.maxZ);
    784
    785        if (!this.isVecInsideYZBounds(vec32))
    786        {
    787            vec32 = null;
    788        }
    789
    790        if (!this.isVecInsideYZBounds(vec33))
    791        {
    792            vec33 = null;
    793        }
    794
    795        if (!this.isVecInsideXZBounds(vec34))
    796        {
    797            vec34 = null;
    798        }
    799
    800        if (!this.isVecInsideXZBounds(vec35))
    801        {
    802            vec35 = null;
    803        }
    804
    805        if (!this.isVecInsideXYBounds(vec36))
    806        {
    807            vec36 = null;
    808        }
    809
    810        if (!this.isVecInsideXYBounds(vec37))
    811        {
    812            vec37 = null;
    813        }
    814
    815        Vec3 vec38 = null;
    816
    817        if (vec32 != null && (vec38 == null || par5Vec3.squareDistanceTo(vec32) < par5Vec3.squareDistanceTo(vec38)))
    818        {
    819            vec38 = vec32;
    820        }
    821
    822        if (vec33 != null && (vec38 == null || par5Vec3.squareDistanceTo(vec33) < par5Vec3.squareDistanceTo(vec38)))
    823        {
    824            vec38 = vec33;
    825        }
    826
    827        if (vec34 != null && (vec38 == null || par5Vec3.squareDistanceTo(vec34) < par5Vec3.squareDistanceTo(vec38)))
    828        {
    829            vec38 = vec34;
    830        }
    831
    832        if (vec35 != null && (vec38 == null || par5Vec3.squareDistanceTo(vec35) < par5Vec3.squareDistanceTo(vec38)))
    833        {
    834            vec38 = vec35;
    835        }
    836
    837        if (vec36 != null && (vec38 == null || par5Vec3.squareDistanceTo(vec36) < par5Vec3.squareDistanceTo(vec38)))
    838        {
    839            vec38 = vec36;
    840        }
    841
    842        if (vec37 != null && (vec38 == null || par5Vec3.squareDistanceTo(vec37) < par5Vec3.squareDistanceTo(vec38)))
    843        {
    844            vec38 = vec37;
    845        }
    846
    847        if (vec38 == null)
    848        {
    849            return null;
    850        }
    851        else
    852        {
    853            byte b0 = -1;
    854
    855            if (vec38 == vec32)
    856            {
    857                b0 = 4;
    858            }
    859
    860            if (vec38 == vec33)
    861            {
    862                b0 = 5;
    863            }
    864
    865            if (vec38 == vec34)
    866            {
    867                b0 = 0;
    868            }
    869
    870            if (vec38 == vec35)
    871            {
    872                b0 = 1;
    873            }
    874
    875            if (vec38 == vec36)
    876            {
    877                b0 = 2;
    878            }
    879
    880            if (vec38 == vec37)
    881            {
    882                b0 = 3;
    883            }
    884
    885            return new MovingObjectPosition(par2, par3, par4, b0, vec38.addVector((double)par2, (double)par3, (double)par4));
    886        }
    887    }
    888
    889    /**
    890     * Checks if a vector is within the Y and Z bounds of the block.
    891     */
    892    private boolean isVecInsideYZBounds(Vec3 par1Vec3)
    893    {
    894        return par1Vec3 == null ? false : par1Vec3.yCoord >= this.minY && par1Vec3.yCoord <= this.maxY && par1Vec3.zCoord >= this.minZ && par1Vec3.zCoord <= this.maxZ;
    895    }
    896
    897    /**
    898     * Checks if a vector is within the X and Z bounds of the block.
    899     */
    900    private boolean isVecInsideXZBounds(Vec3 par1Vec3)
    901    {
    902        return par1Vec3 == null ? false : par1Vec3.xCoord >= this.minX && par1Vec3.xCoord <= this.maxX && par1Vec3.zCoord >= this.minZ && par1Vec3.zCoord <= this.maxZ;
    903    }
    904
    905    /**
    906     * Checks if a vector is within the X and Y bounds of the block.
    907     */
    908    private boolean isVecInsideXYBounds(Vec3 par1Vec3)
    909    {
    910        return par1Vec3 == null ? false : par1Vec3.xCoord >= this.minX && par1Vec3.xCoord <= this.maxX && par1Vec3.yCoord >= this.minY && par1Vec3.yCoord <= this.maxY;
    911    }
    912
    913    /**
    914     * Called upon the block being destroyed by an explosion
    915     */
    916    public void onBlockDestroyedByExplosion(World par1World, int par2, int par3, int par4, Explosion par5Explosion) {}
    917
    918    public boolean func_94331_a(World par1World, int par2, int par3, int par4, int par5, ItemStack par6ItemStack)
    919    {
    920        return this.canPlaceBlockOnSide(par1World, par2, par3, par4, par5);
    921    }
    922
    923    @SideOnly(Side.CLIENT)
    924
    925    /**
    926     * Returns which pass should this block be rendered on. 0 for solids and 1 for alpha
    927     */
    928    public int getRenderBlockPass()
    929    {
    930        return 0;
    931    }
    932
    933    /**
    934     * checks to see if you can place this block can be placed on that side of a block: BlockLever overrides
    935     */
    936    public boolean canPlaceBlockOnSide(World par1World, int par2, int par3, int par4, int par5)
    937    {
    938        return this.canPlaceBlockAt(par1World, par2, par3, par4);
    939    }
    940
    941    /**
    942     * Checks to see if its valid to put this block at the specified coordinates. Args: world, x, y, z
    943     */
    944    public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4)
    945    {
    946        int l = par1World.getBlockId(par2, par3, par4);
    947        return l == 0 || blocksList[l].blockMaterial.isReplaceable();
    948    }
    949
    950    /**
    951     * Called upon block activation (right click on the block.)
    952     */
    953    public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9)
    954    {
    955        return false;
    956    }
    957
    958    /**
    959     * Called whenever an entity is walking on top of this block. Args: world, x, y, z, entity
    960     */
    961    public void onEntityWalking(World par1World, int par2, int par3, int par4, Entity par5Entity) {}
    962
    963    /**
    964     * Called when a block is placed using its ItemBlock. Args: World, X, Y, Z, side, hitX, hitY, hitZ, block metadata
    965     */
    966    public int onBlockPlaced(World par1World, int par2, int par3, int par4, int par5, float par6, float par7, float par8, int par9)
    967    {
    968        return par9;
    969    }
    970
    971    /**
    972     * Called when the block is clicked by a player. Args: x, y, z, entityPlayer
    973     */
    974    public void onBlockClicked(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer) {}
    975
    976    /**
    977     * Can add to the passed in vector for a movement vector to be applied to the entity. Args: x, y, z, entity, vec3d
    978     */
    979    public void velocityToAddToEntity(World par1World, int par2, int par3, int par4, Entity par5Entity, Vec3 par6Vec3) {}
    980
    981    /**
    982     * Updates the blocks bounds based on its current state. Args: world, x, y, z
    983     */
    984    public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {}
    985
    986    /**
    987     * returns the block bounderies minX value
    988     */
    989    public final double getBlockBoundsMinX()
    990    {
    991        return this.minX;
    992    }
    993
    994    /**
    995     * returns the block bounderies maxX value
    996     */
    997    public final double getBlockBoundsMaxX()
    998    {
    999        return this.maxX;
    1000    }
    1001
    1002    /**
    1003     * returns the block bounderies minY value
    1004     */
    1005    public final double getBlockBoundsMinY()
    1006    {
    1007        return this.minY;
    1008    }
    1009
    1010    /**
    1011     * returns the block bounderies maxY value
    1012     */
    1013    public final double getBlockBoundsMaxY()
    1014    {
    1015        return this.maxY;
    1016    }
    1017
    1018    /**
    1019     * returns the block bounderies minZ value
    1020     */
    1021    public final double getBlockBoundsMinZ()
    1022    {
    1023        return this.minZ;
    1024    }
    1025
    1026    /**
    1027     * returns the block bounderies maxZ value
    1028     */
    1029    public final double getBlockBoundsMaxZ()
    1030    {
    1031        return this.maxZ;
    1032    }
    1033
    1034    @SideOnly(Side.CLIENT)
    1035    public int getBlockColor()
    1036    {
    1037        return 16777215;
    1038    }
    1039
    1040    @SideOnly(Side.CLIENT)
    1041
    1042    /**
    1043     * Returns the color this block should be rendered. Used by leaves.
    1044     */
    1045    public int getRenderColor(int par1)
    1046    {
    1047        return 16777215;
    1048    }
    1049
    1050    /**
    1051     * Returns true if the block is emitting indirect/weak redstone power on the specified side. If isBlockNormalCube
    1052     * returns true, standard redstone propagation rules will apply instead and this will not be called. Args: World, X,
    1053     * Y, Z, side. Note that the side is reversed - eg it is 1 (up) when checking the bottom of the block.
    1054     */
    1055    public int isProvidingWeakPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5)
    1056    {
    1057        return 0;
    1058    }
    1059
    1060    @SideOnly(Side.CLIENT)
    1061
    1062    /**
    1063     * Returns a integer with hex for 0xrrggbb with this color multiplied against the blocks color. Note only called
    1064     * when first determining what to render.
    1065     */
    1066    public int colorMultiplier(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
    1067    {
    1068        return 16777215;
    1069    }
    1070
    1071    /**
    1072     * Can this block provide power. Only wire currently seems to have this change based on its state.
    1073     */
    1074    public boolean canProvidePower()
    1075    {
    1076        return false;
    1077    }
    1078
    1079    /**
    1080     * Triggered whenever an entity collides with this block (enters into the block). Args: world, x, y, z, entity
    1081     */
    1082    public void onEntityCollidedWithBlock(World par1World, int par2, int par3, int par4, Entity par5Entity) {}
    1083
    1084    /**
    1085     * Returns true if the block is emitting direct/strong redstone power on the specified side. Args: World, X, Y, Z,
    1086     * side. Note that the side is reversed - eg it is 1 (up) when checking the bottom of the block.
    1087     */
    1088    public int isProvidingStrongPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5)
    1089    {
    1090        return 0;
    1091    }
    1092
    1093    /**
    1094     * Sets the block's bounds for rendering it as an item
    1095     */
    1096    public void setBlockBoundsForItemRender() {}
    1097
    1098    /**
    1099     * Called when the player destroys a block with an item that can harvest it. (i, j, k) are the coordinates of the
    1100     * block and l is the block's subtype/damage.
    1101     */
    1102    public void harvestBlock(World par1World, EntityPlayer par2EntityPlayer, int par3, int par4, int par5, int par6)
    1103    {
    1104        par2EntityPlayer.addStat(StatList.mineBlockStatArray[this.blockID], 1);
    1105        par2EntityPlayer.addExhaustion(0.025F);
    1106
    1107        if (this.canSilkHarvest(par1World, par2EntityPlayer, par3, par4, par5, par6) && EnchantmentHelper.getSilkTouchModifier(par2EntityPlayer))
    1108        {
    1109            ItemStack itemstack = this.createStackedBlock(par6);
    1110
    1111            if (itemstack != null)
    1112            {
    1113                this.dropBlockAsItem_do(par1World, par3, par4, par5, itemstack);
    1114            }
    1115        }
    1116        else
    1117        {
    1118            int i1 = EnchantmentHelper.getFortuneModifier(par2EntityPlayer);
    1119            this.dropBlockAsItem(par1World, par3, par4, par5, par6, i1);
    1120        }
    1121    }
    1122
    1123    private int silk_check_meta = -1; //Dirty hack to stop us from needing to special case the silk check hook.
    1124    /**
    1125     * Return true if a player with Silk Touch can harvest this block directly, and not its normal drops.
    1126     */
    1127    protected boolean canSilkHarvest()
    1128    {
    1129        return this.renderAsNormalBlock() && !this.hasTileEntity(silk_check_meta);
    1130    }
    1131
    1132    /**
    1133     * Returns an item stack containing a single instance of the current block type. 'i' is the block's subtype/damage
    1134     * and is ignored for blocks which do not support subtypes. Blocks which cannot be harvested should return null.
    1135     */
    1136    protected ItemStack createStackedBlock(int par1)
    1137    {
    1138        int j = 0;
    1139
    1140        if (this.blockID >= 0 && this.blockID < Item.itemsList.length && Item.itemsList[this.blockID].getHasSubtypes())
    1141        {
    1142            j = par1;
    1143        }
    1144
    1145        return new ItemStack(this.blockID, 1, j);
    1146    }
    1147
    1148    /**
    1149     * Returns the usual quantity dropped by the block plus a bonus of 1 to 'i' (inclusive).
    1150     */
    1151    public int quantityDroppedWithBonus(int par1, Random par2Random)
    1152    {
    1153        return this.quantityDropped(par2Random);
    1154    }
    1155
    1156    /**
    1157     * Can this block stay at this position.  Similar to canPlaceBlockAt except gets checked often with plants.
    1158     */
    1159    public boolean canBlockStay(World par1World, int par2, int par3, int par4)
    1160    {
    1161        return true;
    1162    }
    1163
    1164    /**
    1165     * Called when the block is placed in the world.
    1166     */
    1167    public void onBlockPlacedBy(World par1World, int par2, int par3, int par4, EntityLiving par5EntityLiving, ItemStack par6ItemStack) {}
    1168
    1169    /**
    1170     * Called after a block is placed
    1171     */
    1172    public void onPostBlockPlaced(World par1World, int par2, int par3, int par4, int par5) {}
    1173
    1174    /**
    1175     * Sets the unlocalized name of the block to the string passed as a parameter, prefixed by "tile."
    1176     */
    1177    public Block setUnlocalizedName(String par1Str)
    1178    {
    1179        this.unlocalizedName = par1Str;
    1180        return this;
    1181    }
    1182
    1183    /**
    1184     * Gets the localized name of this block. Used for the statistics page.
    1185     */
    1186    public String getLocalizedName()
    1187    {
    1188        return StatCollector.translateToLocal(this.getUnlocalizedName() + ".name");
    1189    }
    1190
    1191    /**
    1192     * Returns the unlocalized name of this block.
    1193     */
    1194    public String getUnlocalizedName()
    1195    {
    1196        return "tile." + this.unlocalizedName;
    1197    }
    1198
    1199    @SideOnly(Side.CLIENT)
    1200    public String func_94330_A()
    1201    {
    1202        return this.unlocalizedName;
    1203    }
    1204
    1205    /**
    1206     * Called when the block receives a BlockEvent - see World.addBlockEvent. By default, passes it on to the tile
    1207     * entity at this location. Args: world, x, y, z, blockID, EventID, event parameter
    1208     */
    1209    public boolean onBlockEventReceived(World par1World, int par2, int par3, int par4, int par5, int par6)
    1210    {
    1211        return false;
    1212    }
    1213
    1214    /**
    1215     * Return the state of blocks statistics flags - if the block is counted for mined and placed.
    1216     */
    1217    public boolean getEnableStats()
    1218    {
    1219        return this.enableStats;
    1220    }
    1221
    1222    /**
    1223     * Disable statistics for the block, the block will no count for mined or placed.
    1224     */
    1225    protected Block disableStats()
    1226    {
    1227        this.enableStats = false;
    1228        return this;
    1229    }
    1230
    1231    /**
    1232     * Returns the mobility information of the block, 0 = free, 1 = can't push but can move over, 2 = total immobility
    1233     * and stop pistons
    1234     */
    1235    public int getMobilityFlag()
    1236    {
    1237        return this.blockMaterial.getMaterialMobility();
    1238    }
    1239
    1240    @SideOnly(Side.CLIENT)
    1241
    1242    /**
    1243     * Returns the default ambient occlusion value based on block opacity
    1244     */
    1245    public float getAmbientOcclusionLightValue(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
    1246    {
    1247        return par1IBlockAccess.isBlockNormalCube(par2, par3, par4) ? 0.2F : 1.0F;
    1248    }
    1249
    1250    /**
    1251     * Block's chance to react to an entity falling on it.
    1252     */
    1253    public void onFallenUpon(World par1World, int par2, int par3, int par4, Entity par5Entity, float par6) {}
    1254
    1255    @SideOnly(Side.CLIENT)
    1256
    1257    /**
    1258     * only called by clickMiddleMouseButton , and passed to inventory.setCurrentItem (along with isCreative)
    1259     */
    1260    public int idPicked(World par1World, int par2, int par3, int par4)
    1261    {
    1262        return this.blockID;
    1263    }
    1264
    1265    /**
    1266     * Get the block's damage value (for use with pick block).
    1267     */
    1268    public int getDamageValue(World par1World, int par2, int par3, int par4)
    1269    {
    1270        return this.damageDropped(par1World.getBlockMetadata(par2, par3, par4));
    1271    }
    1272
    1273    @SideOnly(Side.CLIENT)
    1274
    1275    /**
    1276     * returns a list of blocks with the same ID, but different meta (eg: wood returns 4 blocks)
    1277     */
    1278    public void getSubBlocks(int par1, CreativeTabs par2CreativeTabs, List par3List)
    1279    {
    1280        par3List.add(new ItemStack(par1, 1, 0));
    1281    }
    1282
    1283    /**
    1284     * Sets the CreativeTab to display this block on.
    1285     */
    1286    public Block setCreativeTab(CreativeTabs par1CreativeTabs)
    1287    {
    1288        this.displayOnCreativeTab = par1CreativeTabs;
    1289        return this;
    1290    }
    1291
    1292    /**
    1293     * Called when the block is attempted to be harvested
    1294     */
    1295    public void onBlockHarvested(World par1World, int par2, int par3, int par4, int par5, EntityPlayer par6EntityPlayer) {}
    1296
    1297    @SideOnly(Side.CLIENT)
    1298
    1299    /**
    1300     * Returns the CreativeTab to display the given block on.
    1301     */
    1302    public CreativeTabs getCreativeTabToDisplayOn()
    1303    {
    1304        return this.displayOnCreativeTab;
    1305    }
    1306
    1307    /**
    1308     * Called when this block is set (with meta data).
    1309     */
    1310    public void onSetBlockIDWithMetaData(World par1World, int par2, int par3, int par4, int par5) {}
    1311
    1312    /**
    1313     * currently only used by BlockCauldron to incrament meta-data during rain
    1314     */
    1315    public void fillWithRain(World par1World, int par2, int par3, int par4) {}
    1316
    1317    @SideOnly(Side.CLIENT)
    1318    public boolean func_82505_u_()
    1319    {
    1320        return false;
    1321    }
    1322
    1323    public boolean func_82506_l()
    1324    {
    1325        return true;
    1326    }
    1327
    1328    /**
    1329     * Return whether this block can drop from an explosion.
    1330     */
    1331    public boolean canDropFromExplosion(Explosion par1Explosion)
    1332    {
    1333        return true;
    1334    }
    1335
    1336    public boolean func_94334_h(int par1)
    1337    {
    1338        return this.blockID == par1;
    1339    }
    1340
    1341    public static boolean func_94329_b(int par0, int par1)
    1342    {
    1343        return par0 == par1 ? true : (par0 != 0 && par1 != 0 && blocksList[par0] != null && blocksList[par1] != null ? blocksList[par0].func_94334_h(par1) : false);
    1344    }
    1345
    1346    public boolean func_96468_q_()
    1347    {
    1348        return false;
    1349    }
    1350
    1351    public int func_94328_b_(World par1World, int par2, int par3, int par4, int par5)
    1352    {
    1353        return 0;
    1354    }
    1355
    1356    @SideOnly(Side.CLIENT)
    1357    public void func_94332_a(IconRegister par1IconRegister)
    1358    {
    1359        this.field_94336_cN = par1IconRegister.func_94245_a(this.unlocalizedName);
    1360    }
    1361
    1362    @SideOnly(Side.CLIENT)
    1363    public String func_94327_t_()
    1364    {
    1365        return null;
    1366    }
    1367
    1368    static
    1369    {
    1370        Item.itemsList[cloth.blockID] = (new ItemCloth(cloth.blockID - 256)).setUnlocalizedName("cloth");
    1371        Item.itemsList[wood.blockID] = (new ItemMultiTextureTile(wood.blockID - 256, wood, BlockLog.woodType)).setUnlocalizedName("log");
    1372        Item.itemsList[planks.blockID] = (new ItemMultiTextureTile(planks.blockID - 256, planks, BlockWood.woodType)).setUnlocalizedName("wood");
    1373        Item.itemsList[silverfish.blockID] = (new ItemMultiTextureTile(silverfish.blockID - 256, silverfish, BlockSilverfish.silverfishStoneTypes)).setUnlocalizedName("monsterStoneEgg");
    1374        Item.itemsList[stoneBrick.blockID] = (new ItemMultiTextureTile(stoneBrick.blockID - 256, stoneBrick, BlockStoneBrick.STONE_BRICK_TYPES)).setUnlocalizedName("stonebricksmooth");
    1375        Item.itemsList[sandStone.blockID] = (new ItemMultiTextureTile(sandStone.blockID - 256, sandStone, BlockSandStone.SAND_STONE_TYPES)).setUnlocalizedName("sandStone");
    1376        Item.itemsList[field_94339_ct.blockID] = (new ItemMultiTextureTile(field_94339_ct.blockID - 256, field_94339_ct, BlockQuartz.field_94420_a)).setUnlocalizedName("quartzBlock");
    1377        Item.itemsList[stoneSingleSlab.blockID] = (new ItemSlab(stoneSingleSlab.blockID - 256, stoneSingleSlab, stoneDoubleSlab, false)).setUnlocalizedName("stoneSlab");
    1378        Item.itemsList[stoneDoubleSlab.blockID] = (new ItemSlab(stoneDoubleSlab.blockID - 256, stoneSingleSlab, stoneDoubleSlab, true)).setUnlocalizedName("stoneSlab");
    1379        Item.itemsList[woodSingleSlab.blockID] = (new ItemSlab(woodSingleSlab.blockID - 256, woodSingleSlab, woodDoubleSlab, false)).setUnlocalizedName("woodSlab");
    1380        Item.itemsList[woodDoubleSlab.blockID] = (new ItemSlab(woodDoubleSlab.blockID - 256, woodSingleSlab, woodDoubleSlab, true)).setUnlocalizedName("woodSlab");
    1381        Item.itemsList[sapling.blockID] = (new ItemMultiTextureTile(sapling.blockID - 256, sapling, BlockSapling.WOOD_TYPES)).setUnlocalizedName("sapling");
    1382        Item.itemsList[leaves.blockID] = (new ItemLeaves(leaves.blockID - 256)).setUnlocalizedName("leaves");
    1383        Item.itemsList[vine.blockID] = new ItemColored(vine.blockID - 256, false);
    1384        Item.itemsList[tallGrass.blockID] = (new ItemColored(tallGrass.blockID - 256, true)).setBlockNames(new String[] {"shrub", "grass", "fern"});
    1385        Item.itemsList[snow.blockID] = new ItemSnow(snow.blockID - 256, snow);
    1386        Item.itemsList[waterlily.blockID] = new ItemLilyPad(waterlily.blockID - 256);
    1387        Item.itemsList[pistonBase.blockID] = new ItemPiston(pistonBase.blockID - 256);
    1388        Item.itemsList[pistonStickyBase.blockID] = new ItemPiston(pistonStickyBase.blockID - 256);
    1389        Item.itemsList[cobblestoneWall.blockID] = (new ItemMultiTextureTile(cobblestoneWall.blockID - 256, cobblestoneWall, BlockWall.types)).setUnlocalizedName("cobbleWall");
    1390        Item.itemsList[anvil.blockID] = (new ItemAnvilBlock(anvil)).setUnlocalizedName("anvil");
    1391
    1392        for (int i = 0; i < 256; ++i)
    1393        {
    1394            if (blocksList[i] != null)
    1395            {
    1396                if (Item.itemsList[i] == null)
    1397                {
    1398                    Item.itemsList[i] = new ItemBlock(i - 256);
    1399                    blocksList[i].initializeBlock();
    1400                }
    1401
    1402                boolean flag = false;
    1403
    1404                if (i > 0 && blocksList[i].getRenderType() == 10)
    1405                {
    1406                    flag = true;
    1407                }
    1408
    1409                if (i > 0 && blocksList[i] instanceof BlockHalfSlab)
    1410                {
    1411                    flag = true;
    1412                }
    1413
    1414                if (i == tilledField.blockID)
    1415                {
    1416                    flag = true;
    1417                }
    1418
    1419                if (canBlockGrass[i])
    1420                {
    1421                    flag = true;
    1422                }
    1423
    1424                if (lightOpacity[i] == 0)
    1425                {
    1426                    flag = true;
    1427                }
    1428
    1429                useNeighborBrightness[i] = flag;
    1430            }
    1431        }
    1432
    1433        canBlockGrass[0] = true;
    1434        StatList.initBreakableStats();
    1435    }
    1436
    1437    /* =================================================== FORGE START =====================================*/
    1438    /**
    1439     * Get a light value for the block at the specified coordinates, normal ranges are between 0 and 15
    1440     *
    1441     * @param world The current world
    1442     * @param x X Position
    1443     * @param y Y position
    1444     * @param z Z position
    1445     * @return The light value
    1446     */
    1447    public int getLightValue(IBlockAccess world, int x, int y, int z)
    1448    {
    1449        Block block = blocksList[world.getBlockId(x, y, z)];
    1450        if (block != null && block != this)
    1451        {
    1452            return block.getLightValue(world, x, y, z);
    1453        }
    1454        return lightValue[blockID];
    1455    }
    1456
    1457    /**
    1458     * Checks if a player or entity can use this block to 'climb' like a ladder.
    1459     *
    1460     * @param world The current world
    1461     * @param x X Position
    1462     * @param y Y position
    1463     * @param z Z position
    1464     * @return True if the block should act like a ladder
    1465     */
    1466    public boolean isLadder(World world, int x, int y, int z)
    1467    {
    1468        return false;
    1469    }
    1470
    1471    /**
    1472     * Return true if the block is a normal, solid cube.  This
    1473     * determines indirect power state, entity ejection from blocks, and a few
    1474     * others.
    1475     *
    1476     * @param world The current world
    1477     * @param x X Position
    1478     * @param y Y position
    1479     * @param z Z position
    1480     * @return True if the block is a full cube
    1481     */
    1482    public boolean isBlockNormalCube(World world, int x, int y, int z)
    1483    {
    1484        return blockMaterial.isOpaque() && renderAsNormalBlock() && !canProvidePower();
    1485    }
    1486
    1487    /**
    1488     * Checks if the block is a solid face on the given side, used by placement logic.
    1489     *
    1490     * @param world The current world
    1491     * @param x X Position
    1492     * @param y Y position
    1493     * @param z Z position
    1494     * @param side The side to check
    1495     * @return True if the block is solid on the specified side.
    1496     */
    1497    public boolean isBlockSolidOnSide(World world, int x, int y, int z, ForgeDirection side)
    1498    {
    1499        int meta = world.getBlockMetadata(x, y, z);
    1500        if (this instanceof BlockHalfSlab)
    1501        {
    1502            return (((meta & 8) == 8 && (side == UP)) || isOpaqueCube());
    1503        }
    1504        else if (this instanceof BlockFarmland)
    1505        {
    1506            return (side != DOWN && side != UP);
    1507        }
    1508        else if (this instanceof BlockStairs)
    1509        {
    1510            boolean flipped = ((meta & 4) != 0);
    1511            return ((meta & 3) + side.ordinal() == 5) || (side == UP && flipped);
    1512        }
    1513        else if (this instanceof BlockHopper && side == UP)
    1514        {
    1515            return true;
    1516        }
    1517        else if (this instanceof BlockPoweredOre)
    1518        {
    1519            return true;
    1520        }
    1521        return isBlockNormalCube(world, x, y, z);
    1522    }
    1523
    1524    /**
    1525     * Determines if a new block can be replace the space occupied by this one,
    1526     * Used in the player's placement code to make the block act like water, and lava.
    1527     *
    1528     * @param world The current world
    1529     * @param x X Position
    1530     * @param y Y position
    1531     * @param z Z position
    1532     * @return True if the block is replaceable by another block
    1533     */
    1534    public boolean isBlockReplaceable(World world, int x, int y, int z)
    1535    {
    1536        return false;
    1537    }
    1538
    1539    /**
    1540     * Determines if this block should set fire and deal fire damage
    1541     * to entities coming into contact with it.
    1542     *
    1543     * @param world The current world
    1544     * @param x X Position
    1545     * @param y Y position
    1546     * @param z Z position
    1547     * @return True if the block should deal damage
    1548     */
    1549    public boolean isBlockBurning(World world, int x, int y, int z)
    1550    {
    1551        return false;
    1552    }
    1553
    1554    /**
    1555     * Determines this block should be treated as an air block
    1556     * by the rest of the code. This method is primarily
    1557     * useful for creating pure logic-blocks that will be invisible
    1558     * to the player and otherwise interact as air would.
    1559     *
    1560     * @param world The current world
    1561     * @param x X Position
    1562     * @param y Y position
    1563     * @param z Z position
    1564     * @return True if the block considered air
    1565     */
    1566    public boolean isAirBlock(World world, int x, int y, int z)
    1567    {
    1568        return false;
    1569    }
    1570
    1571    /**
    1572     * Determines if the player can harvest this block, obtaining it's drops when the block is destroyed.
    1573     *
    1574     * @param player The player damaging the block, may be null
    1575     * @param meta The block's current metadata
    1576     * @return True to spawn the drops
    1577     */
    1578    public boolean canHarvestBlock(EntityPlayer player, int meta)
    1579    {
    1580        return ForgeHooks.canHarvestBlock(this, player, meta);
    1581    }
    1582
    1583    /**
    1584     * Called when a player removes a block.  This is responsible for
    1585     * actually destroying the block, and the block is intact at time of call.
    1586     * This is called regardless of whether the player can harvest the block or
    1587     * not.
    1588     *
    1589     * Return true if the block is actually destroyed.
    1590     *
    1591     * Note: When used in multiplayer, this is called on both client and
    1592     * server sides!
    1593     *
    1594     * @param world The current world
    1595     * @param player The player damaging the block, may be null
    1596     * @param x X Position
    1597     * @param y Y position
    1598     * @param z Z position
    1599     * @return True if the block is actually destroyed.
    1600     */
    1601    public boolean removeBlockByPlayer(World world, EntityPlayer player, int x, int y, int z)
    1602    {
    1603        return world.func_94571_i(x, y, z);
    1604    }
    1605
    1606    /**
    1607     * Called when a new CreativeContainer is opened, populate the list
    1608     * with all of the items for this block you want a player in creative mode
    1609     * to have access to.
    1610     *
    1611     * @param itemList The list of items to display on the creative inventory.
    1612     */
    1613    public void addCreativeItems(ArrayList itemList)
    1614    {
    1615    }
    1616
    1617    /**
    1618     * Chance that fire will spread and consume this block.
    1619     * 300 being a 100% chance, 0, being a 0% chance.
    1620     *
    1621     * @param world The current world
    1622     * @param x The blocks X position
    1623     * @param y The blocks Y position
    1624     * @param z The blocks Z position
    1625     * @param metadata The blocks current metadata
    1626     * @param face The face that the fire is coming from
    1627     * @return A number ranging from 0 to 300 relating used to determine if the block will be consumed by fire
    1628     */
    1629    public int getFlammability(IBlockAccess world, int x, int y, int z, int metadata, ForgeDirection face)
    1630    {
    1631        return blockFlammability[blockID];
    1632    }
    1633
    1634    /**
    1635     * Called when fire is updating, checks if a block face can catch fire.
    1636     *
    1637     *
    1638     * @param world The current world
    1639     * @param x The blocks X position
    1640     * @param y The blocks Y position
    1641     * @param z The blocks Z position
    1642     * @param metadata The blocks current metadata
    1643     * @param face The face that the fire is coming from
    1644     * @return True if the face can be on fire, false otherwise.
    1645     */
    1646    public boolean isFlammable(IBlockAccess world, int x, int y, int z, int metadata, ForgeDirection face)
    1647    {
    1648        return getFlammability(world, x, y, z, metadata, face) > 0;
    1649    }
    1650
    1651    /**
    1652     * Called when fire is updating on a neighbor block.
    1653     * The higher the number returned, the faster fire will spread around this block.
    1654     *
    1655     * @param world The current world
    1656     * @param x The blocks X position
    1657     * @param y The blocks Y position
    1658     * @param z The blocks Z position
    1659     * @param metadata The blocks current metadata
    1660     * @param face The face that the fire is coming from
    1661     * @return A number that is used to determine the speed of fire growth around the block
    1662     */
    1663    public int getFireSpreadSpeed(World world, int x, int y, int z, int metadata, ForgeDirection face)
    1664    {
    1665        return blockFireSpreadSpeed[blockID];
    1666    }
    1667
    1668    /**
    1669     * Currently only called by fire when it is on top of this block.
    1670     * Returning true will prevent the fire from naturally dying during updating.
    1671     * Also prevents firing from dying from rain.
    1672     *
    1673     * @param world The current world
    1674     * @param x The blocks X position
    1675     * @param y The blocks Y position
    1676     * @param z The blocks Z position
    1677     * @param metadata The blocks current metadata
    1678     * @param side The face that the fire is coming from
    1679     * @return True if this block sustains fire, meaning it will never go out.
    1680     */
    1681    public boolean isFireSource(World world, int x, int y, int z, int metadata, ForgeDirection side)
    1682    {
    1683        if (blockID == Block.netherrack.blockID && side == UP)
    1684        {
    1685            return true;
    1686        }
    1687        if ((world.provider instanceof WorldProviderEnd) && blockID == Block.bedrock.blockID && side == UP)
    1688        {
    1689            return true;
    1690        }
    1691        return false;
    1692    }
    1693
    1694    /**
    1695     * Called by BlockFire to setup the burn values of vanilla blocks.
    1696     * @param id The block id
    1697     * @param encouragement How much the block encourages fire to spread
    1698     * @param flammability how easy a block is to catch fire
    1699     */
    1700    public static void setBurnProperties(int id, int encouragement, int flammability)
    1701    {
    1702        blockFireSpreadSpeed[id] = encouragement;
    1703        blockFlammability[id] = flammability;
    1704    }
    1705
    1706    private boolean isTileProvider = this instanceof ITileEntityProvider;
    1707    /**
    1708     * Called throughout the code as a replacement for block instanceof BlockContainer
    1709     * Moving this to the Block base class allows for mods that wish to extend vinella
    1710     * blocks, and also want to have a tile entity on that block, may.
    1711     *
    1712     * Return true from this function to specify this block has a tile entity.
    1713     *
    1714     * @param metadata Metadata of the current block
    1715     * @return True if block has a tile entity, false otherwise
    1716     */
    1717    public boolean hasTileEntity(int metadata)
    1718    {
    1719        return isTileProvider;
    1720    }
    1721
    1722    /**
    1723     * Called throughout the code as a replacement for ITileEntityProvider.createNewTileEntity
    1724     * Return the same thing you would from that function.
    1725     * This will fall back to ITileEntityProvider.createNewTileEntity(World) if this block is a ITileEntityProvider
    1726     *
    1727     * @param metadata The Metadata of the current block
    1728     * @return A instance of a class extending TileEntity
    1729     */
    1730    public TileEntity createTileEntity(World world, int metadata)
    1731    {
    1732        if (isTileProvider)
    1733        {
    1734            return ((ITileEntityProvider)this).createNewTileEntity(world);
    1735        }
    1736        return null;
    1737    }
    1738
    1739    /**
    1740     * Metadata and fortune sensitive version, this replaces the old (int meta, Random rand)
    1741     * version in 1.1.
    1742     *
    1743     * @param meta Blocks Metadata
    1744     * @param fortune Current item fortune level
    1745     * @param random Random number generator
    1746     * @return The number of items to drop
    1747     */
    1748    public int quantityDropped(int meta, int fortune, Random random)
    1749    {
    1750        return quantityDroppedWithBonus(fortune, random);
    1751    }
    1752
    1753    /**
    1754     * This returns a complete list of items dropped from this block.
    1755     *
    1756     * @param world The current world
    1757     * @param x X Position
    1758     * @param y Y Position
    1759     * @param z Z Position
    1760     * @param metadata Current metadata
    1761     * @param fortune Breakers fortune level
    1762     * @return A ArrayList containing all items this block drops
    1763     */
    1764    public ArrayList<ItemStack> getBlockDropped(World world, int x, int y, int z, int metadata, int fortune)
    1765    {
    1766        ArrayList<ItemStack> ret = new ArrayList<ItemStack>();
    1767
    1768        int count = quantityDropped(metadata, fortune, world.rand);
    1769        for(int i = 0; i < count; i++)
    1770        {
    1771            int id = idDropped(metadata, world.rand, fortune);
    1772            if (id > 0)
    1773            {
    1774                ret.add(new ItemStack(id, 1, damageDropped(metadata)));
    1775            }
    1776        }
    1777        return ret;
    1778    }
    1779
    1780    /**
    1781     * Return true from this function if the player with silk touch can harvest this block directly, and not it's normal drops.
    1782     *
    1783     * @param world The world
    1784     * @param player The player doing the harvesting
    1785     * @param x X Position
    1786     * @param y Y Position
    1787     * @param z Z Position
    1788     * @param metadata The metadata
    1789     * @return True if the block can be directly harvested using silk touch
    1790     */
    1791    public boolean canSilkHarvest(World world, EntityPlayer player, int x, int y, int z, int metadata)
    1792    {
    1793        silk_check_meta = metadata;
    1794        boolean ret = this.canSilkHarvest();
    1795        silk_check_meta = 0;
    1796        return ret;
    1797    }
    1798
    1799    /**
    1800     * Determines if a specified mob type can spawn on this block, returning false will
    1801     * prevent any mob from spawning on the block.
    1802     *
    1803     * @param type The Mob Category Type
    1804     * @param world The current world
    1805     * @param x The X Position
    1806     * @param y The Y Position
    1807     * @param z The Z Position
    1808     * @return True to allow a mob of the specified category to spawn, false to prevent it.
    1809     */
    1810    public boolean canCreatureSpawn(EnumCreatureType type, World world, int x, int y, int z)
    1811    {
    1812        int meta = world.getBlockMetadata(x, y, z);
    1813        if (this instanceof BlockStep)
    1814        {
    1815            return (((meta & 8) == 8) || isOpaqueCube());
    1816        }
    1817        else if (this instanceof BlockStairs)
    1818        {
    1819            return ((meta & 4) != 0);
    1820        }
    1821        return isBlockSolidOnSide(world, x, y, z, UP);
    1822    }
    1823
    1824    /**
    1825     * Determines if this block is classified as a Bed, Allowing
    1826     * players to sleep in it, though the block has to specifically
    1827     * perform the sleeping functionality in it's activated event.
    1828     *
    1829     * @param world The current world
    1830     * @param x X Position
    1831     * @param y Y Position
    1832     * @param z Z Position
    1833     * @param player The player or camera entity, null in some cases.
    1834     * @return True to treat this as a bed
    1835     */
    1836    public boolean isBed(World world, int x, int y, int z, EntityLiving player)
    1837    {
    1838        return blockID == Block.bed.blockID;
    1839    }
    1840
    1841    /**
    1842     * Returns the position that the player is moved to upon
    1843     * waking up, or respawning at the bed.
    1844     *
    1845     * @param world The current world
    1846     * @param x X Position
    1847     * @param y Y Position
    1848     * @param z Z Position
    1849     * @param player The player or camera entity, null in some cases.
    1850     * @return The spawn position
    1851     */
    1852    public ChunkCoordinates getBedSpawnPosition(World world, int x, int y, int z, EntityPlayer player)
    1853    {
    1854        return BlockBed.getNearestEmptyChunkCoordinates(world, x, y, z, 0);
    1855    }
    1856
    1857    /**
    1858     * Called when a user either starts or stops sleeping in the bed.
    1859     *
    1860     * @param world The current world
    1861     * @param x X Position
    1862     * @param y Y Position
    1863     * @param z Z Position
    1864     * @param player The player or camera entity, null in some cases.
    1865     * @param occupied True if we are occupying the bed, or false if they are stopping use of the bed
    1866     */
    1867    public void setBedOccupied(World world, int x, int y, int z, EntityPlayer player, boolean occupied)
    1868    {
    1869        BlockBed.setBedOccupied(world,  x, y, z, occupied);
    1870    }
    1871
    1872    /**
    1873     * Returns the direction of the block. Same values that
    1874     * are returned by BlockDirectional
    1875     *
    1876     * @param world The current world
    1877     * @param x X Position
    1878     * @param y Y Position
    1879     * @param z Z Position
    1880     * @return Bed direction
    1881     */
    1882    public int getBedDirection(IBlockAccess world, int x, int y, int z)
    1883    {
    1884        return BlockBed.getDirection(world.getBlockMetadata(x,  y, z));
    1885    }
    1886
    1887    /**
    1888     * Determines if the current block is the foot half of the bed.
    1889     *
    1890     * @param world The current world
    1891     * @param x X Position
    1892     * @param y Y Position
    1893     * @param z Z Position
    1894     * @return True if the current block is the foot side of a bed.
    1895     */
    1896    public boolean isBedFoot(IBlockAccess world, int x, int y, int z)
    1897    {
    1898        return BlockBed.isBlockHeadOfBed(world.getBlockMetadata(x,  y, z));
    1899    }
    1900
    1901    /**
    1902     * Called when a leaf should start its decay process.
    1903     *
    1904     * @param world The current world
    1905     * @param x X Position
    1906     * @param y Y Position
    1907     * @param z Z Position
    1908     */
    1909    public void beginLeavesDecay(World world, int x, int y, int z){}
    1910
    1911    /**
    1912     * Determines if this block can prevent leaves connected to it from decaying.
    1913     *
    1914     * @param world The current world
    1915     * @param x X Position
    1916     * @param y Y Position
    1917     * @param z Z Position
    1918     * @return true if the presence this block can prevent leaves from decaying.
    1919     */
    1920    public boolean canSustainLeaves(World world, int x, int y, int z)
    1921    {
    1922        return false;
    1923    }
    1924
    1925    /**
    1926     * Determines if this block is considered a leaf block, used to apply the leaf decay and generation system.
    1927     *
    1928     * @param world The current world
    1929     * @param x X Position
    1930     * @param y Y Position
    1931     * @param z Z Position
    1932     * @return true if this block is considered leaves.
    1933     */
    1934    public boolean isLeaves(World world, int x, int y, int z)
    1935    {
    1936        return false;
    1937    }
    1938
    1939    /**
    1940     * Used during tree growth to determine if newly generated leaves can replace this block.
    1941     *
    1942     * @param world The current world
    1943     * @param x X Position
    1944     * @param y Y Position
    1945     * @param z Z Position
    1946     * @return true if this block can be replaced by growing leaves.
    1947     */
    1948    public boolean canBeReplacedByLeaves(World world, int x, int y, int z)
    1949    {
    1950        return !Block.opaqueCubeLookup[this.blockID];
    1951    }
    1952
    1953    /**
    1954     *
    1955     * @param world The current world
    1956     * @param x X Position
    1957     * @param y Y Position
    1958     * @param z Z Position
    1959     * @return  true if the block is wood (logs)
    1960     */
    1961    public boolean isWood(World world, int x, int y, int z)
    1962    {
    1963         return false;
    1964    }
    1965
    1966    /**
    1967     * Determines if the current block is replaceable by Ore veins during world generation.
    1968     *
    1969     * @param world The current world
    1970     * @param x X Position
    1971     * @param y Y Position
    1972     * @param z Z Position
    1973     * @param target The generic target block the gen is looking for, Standards define stone
    1974     *      for overworld generation, and neatherack for the nether.
    1975     * @return True to allow this block to be replaced by a ore
    1976     */
    1977    public boolean isGenMineableReplaceable(World world, int x, int y, int z, int target)
    1978    {
    1979        return blockID == target;
    1980    }
    1981
    1982    /**
    1983     * Location sensitive version of getExplosionRestance
    1984     *
    1985     * @param par1Entity The entity that caused the explosion
    1986     * @param world The current world
    1987     * @param x X Position
    1988     * @param y Y Position
    1989     * @param z Z Position
    1990     * @param explosionX Explosion source X Position
    1991     * @param explosionY Explosion source X Position
    1992     * @param explosionZ Explosion source X Position
    1993     * @return The amount of the explosion absorbed.
    1994     */
    1995    public float getExplosionResistance(Entity par1Entity, World world, int x, int y, int z, double explosionX, double explosionY, double explosionZ)
    1996    {
    1997        return getExplosionResistance(par1Entity);
    1998    }
    1999
    2000    /**
    2001     * Determine if this block can make a redstone connection on the side provided,
    2002     * Useful to control which sides are inputs and outputs for redstone wires.
    2003     *
    2004     * Side:
    2005     *  -1: UP
    2006     *   0: NORTH
    2007     *   1: EAST
    2008     *   2: SOUTH
    2009     *   3: WEST
    2010     *
    2011     * @param world The current world
    2012     * @param x X Position
    2013     * @param y Y Position
    2014     * @param z Z Position
    2015     * @param side The side that is trying to make the connection
    2016     * @return True to make the connection
    2017     */
    2018    public boolean canConnectRedstone(IBlockAccess world, int x, int y, int z, int side)
    2019    {
    2020        return Block.blocksList[blockID].canProvidePower() && side != -1;
    2021    }
    2022
    2023    /**
    2024     * Determines if a torch can be placed on the top surface of this block.
    2025     * Useful for creating your own block that torches can be on, such as fences.
    2026     *
    2027     * @param world The current world
    2028     * @param x X Position
    2029     * @param y Y Position
    2030     * @param z Z Position
    2031     * @return True to allow the torch to be placed
    2032     */
    2033    public boolean canPlaceTorchOnTop(World world, int x, int y, int z)
    2034    {
    2035        if (world.doesBlockHaveSolidTopSurface(x, y, z))
    2036        {
    2037            return true;
    2038        }
    2039        else
    2040        {
    2041            int id = world.getBlockId(x, y, z);
    2042            return id == Block.fence.blockID || id == Block.netherFence.blockID || id == Block.glass.blockID || id == Block.cobblestoneWall.blockID;
    2043        }
    2044    }
    2045
    2046
    2047    /**
    2048     * Determines if this block should render in this pass.
    2049     *
    2050     * @param pass The pass in question
    2051     * @return True to render
    2052     */
    2053    public boolean canRenderInPass(int pass)
    2054    {
    2055        return pass == getRenderBlockPass();
    2056    }
    2057
    2058    /**
    2059     * Called when a user uses the creative pick block button on this block
    2060     *
    2061     * @param target The full target the player is looking at
    2062     * @return A ItemStack to add to the player's inventory, Null if nothing should be added.
    2063     */
    2064    public ItemStack getPickBlock(MovingObjectPosition target, World world, int x, int y, int z)
    2065    {
    2066        int id = idPicked(world, x, y, z);
    2067
    2068        if (id == 0)
    2069        {
    2070            return null;
    2071        }
    2072
    2073        Item item = Item.itemsList[id];
    2074        if (item == null)
    2075        {
    2076            return null;
    2077        }
    2078
    2079        return new ItemStack(id, 1, getDamageValue(world, x, y, z));
    2080    }
    2081
    2082    /**
    2083     * Used by getTopSolidOrLiquidBlock while placing biome decorations, villages, etc
    2084     * Also used to determine if the player can spawn on this block.
    2085     *
    2086     * @return False to disallow spawning
    2087     */
    2088    public boolean isBlockFoliage(World world, int x, int y, int z)
    2089    {
    2090        return false;
    2091    }
    2092
    2093    /**
    2094     * Spawn a digging particle effect in the world, this is a wrapper
    2095     * around EffectRenderer.addBlockHitEffects to allow the block more
    2096     * control over the particles. Useful when you have entirely different
    2097     * texture sheets for different sides/locations in the world.
    2098     *
    2099     * @param world The current world
    2100     * @param target The target the player is looking at {x/y/z/side/sub}
    2101     * @param effectRenderer A reference to the current effect renderer.
    2102     * @return True to prevent vanilla digging particles form spawning.
    2103     */
    2104    @SideOnly(Side.CLIENT)
    2105    public boolean addBlockHitEffects(World worldObj, MovingObjectPosition target, EffectRenderer effectRenderer)
    2106    {
    2107        return false;
    2108    }
    2109
    2110    /**
    2111     * Spawn particles for when the block is destroyed. Due to the nature
    2112     * of how this is invoked, the x/y/z locations are not always guaranteed
    2113     * to host your block. So be sure to do proper sanity checks before assuming
    2114     * that the location is this block.
    2115     *
    2116     * @param world The current world
    2117     * @param x X position to spawn the particle
    2118     * @param y Y position to spawn the particle
    2119     * @param z Z position to spawn the particle
    2120     * @param meta The metadata for the block before it was destroyed.
    2121     * @param effectRenderer A reference to the current effect renderer.
    2122     * @return True to prevent vanilla break particles from spawning.
    2123     */
    2124    @SideOnly(Side.CLIENT)
    2125    public boolean addBlockDestroyEffects(World world, int x, int y, int z, int meta, EffectRenderer effectRenderer)
    2126    {
    2127        return false;
    2128    }
    2129
    2130    /**
    2131     * Determines if this block can support the passed in plant, allowing it to be planted and grow.
    2132     * Some examples:
    2133     *   Reeds check if its a reed, or if its sand/dirt/grass and adjacent to water
    2134     *   Cacti checks if its a cacti, or if its sand
    2135     *   Nether types check for soul sand
    2136     *   Crops check for tilled soil
    2137     *   Caves check if it's a colid surface
    2138     *   Plains check if its grass or dirt
    2139     *   Water check if its still water
    2140     *
    2141     * @param world The current world
    2142     * @param x X Position
    2143     * @param y Y Position
    2144     * @param z Z position
    2145     * @param direction The direction relative to the given position the plant wants to be, typically its UP
    2146     * @param plant The plant that wants to check
    2147     * @return True to allow the plant to be planted/stay.
    2148     */
    2149    public boolean canSustainPlant(World world, int x, int y, int z, ForgeDirection direction, IPlantable plant)
    2150    {
    2151        int plantID = plant.getPlantID(world, x, y + 1, z);
    2152        EnumPlantType plantType = plant.getPlantType(world, x, y + 1, z);
    2153
    2154        if (plantID == cactus.blockID && blockID == cactus.blockID)
    2155        {
    2156            return true;
    2157        }
    2158
    2159        if (plantID == reed.blockID && blockID == reed.blockID)
    2160        {
    2161            return true;
    2162        }
    2163
    2164        if (plant instanceof BlockFlower && ((BlockFlower)plant).canThisPlantGrowOnThisBlockID(blockID))
    2165        {
    2166            return true;
    2167        }
    2168
    2169        switch (plantType)
    2170        {
    2171            case Desert: return blockID == sand.blockID;
    2172            case Nether: return blockID == slowSand.blockID;
    2173            case Crop:   return blockID == tilledField.blockID;
    2174            case Cave:   return isBlockSolidOnSide(world, x, y, z, UP);
    2175            case Plains: return blockID == grass.blockID || blockID == dirt.blockID;
    2176            case Water:  return world.getBlockMaterial(x, y, z) == Material.water && world.getBlockMetadata(x, y, z) == 0;
    2177            case Beach:
    2178                boolean isBeach = (blockID == Block.grass.blockID || blockID == Block.dirt.blockID || blockID == Block.sand.blockID);
    2179                boolean hasWater = (world.getBlockMaterial(x - 1, y, z    ) == Material.water ||
    2180                                    world.getBlockMaterial(x + 1, y, z    ) == Material.water ||
    2181                                    world.getBlockMaterial(x,     y, z - 1) == Material.water ||
    2182                                    world.getBlockMaterial(x,     y, z + 1) == Material.water);
    2183                return isBeach && hasWater;
    2184        }
    2185
    2186        return false;
    2187    }
    2188
    2189    /**
    2190     * Called when a plant grows on this block, only implemented for saplings using the WorldGen*Trees classes right now.
    2191     * Modder may implement this for custom plants.
    2192     * This does not use ForgeDirection, because large/huge trees can be located in non-representable direction,
    2193     * so the source location is specified.
    2194     * Currently this just changes the block to dirt if it was grass.
    2195     *
    2196     * Note: This happens DURING the generation, the generation may not be complete when this is called.
    2197     *
    2198     * @param world Current world
    2199     * @param x Soil X
    2200     * @param y Soil Y
    2201     * @param z Soil Z
    2202     * @param sourceX Plant growth location X
    2203     * @param sourceY Plant growth location Y
    2204     * @param sourceZ Plant growth location Z
    2205     */
    2206    public void onPlantGrow(World world, int x, int y, int z, int sourceX, int sourceY, int sourceZ)
    2207    {
    2208        if (blockID == grass.blockID)
    2209        {
    2210            world.setBlockAndMetadataWithNotify(x, y, z, dirt.blockID, 0, 2);
    2211        }
    2212    }
    2213
    2214    /**
    2215     * Checks if this soil is fertile, typically this means that growth rates
    2216     * of plants on this soil will be slightly sped up.
    2217     * Only vanilla case is tilledField when it is within range of water.
    2218     *
    2219     * @param world The current world
    2220     * @param x X Position
    2221     * @param y Y Position
    2222     * @param z Z position
    2223     * @return True if the soil should be considered fertile.
    2224     */
    2225    public boolean isFertile(World world, int x, int y, int z)
    2226    {
    2227        if (blockID == tilledField.blockID)
    2228        {
    2229            return world.getBlockMetadata(x, y, z) > 0;
    2230        }
    2231
    2232        return false;
    2233    }
    2234
    2235    /**
    2236     * Location aware and overrideable version of the lightOpacity array,
    2237     * return the number to subtract from the light value when it passes through this block.
    2238     *
    2239     * This is not guaranteed to have the tile entity in place before this is called, so it is
    2240     * Recommended that you have your tile entity call relight after being placed if you
    2241     * rely on it for light info.
    2242     *
    2243     * @param world The current world
    2244     * @param x X Position
    2245     * @param y Y Position
    2246     * @param z Z position
    2247     * @return The amount of light to block, 0 for air, 255 for fully opaque.
    2248     */
    2249    public int getLightOpacity(World world, int x, int y, int z)
    2250    {
    2251        return lightOpacity[blockID];
    2252    }
    2253
    2254    /**
    2255     * Determines if this block is destroyed when a ender dragon tries to fly through it.
    2256     * The block will be set to 0, nothing will drop.
    2257     *
    2258     * @param world The current world
    2259     * @param x X Position
    2260     * @param y Y Position
    2261     * @param z Z position
    2262     * @return True to allow the ender dragon to destroy this block
    2263     */
    2264    public boolean canDragonDestroy(World world, int x, int y, int z)
    2265    {
    2266        return blockID != obsidian.blockID && blockID != whiteStone.blockID && blockID != bedrock.blockID;
    2267    }
    2268
    2269    /**
    2270     * Determines if this block can be used as the base of a beacon.
    2271     *
    2272     * @param world The current world
    2273     * @param x X Position
    2274     * @param y Y Position
    2275     * @param z Z position
    2276     * @param beaconX Beacons X Position
    2277     * @param beaconY Beacons Y Position
    2278     * @param beaconZ Beacons Z Position
    2279     * @return True, to support the beacon, and make it active with this block.
    2280     */
    2281    public boolean isBeaconBase(World worldObj, int x, int y, int z, int beaconX, int beaconY, int beaconZ)
    2282    {
    2283        return (blockID == blockEmerald.blockID || blockID == blockGold.blockID || blockID == blockDiamond.blockID || blockID == blockSteel.blockID);
    2284    }
    2285}