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