001package net.minecraft.block; 002 003import cpw.mods.fml.relauncher.Side; 004import cpw.mods.fml.relauncher.SideOnly; 005import java.util.Random; 006import net.minecraft.block.material.Material; 007import net.minecraft.client.renderer.texture.IconRegister; 008import net.minecraft.creativetab.CreativeTabs; 009import net.minecraft.entity.player.EntityPlayer; 010import net.minecraft.item.Item; 011import net.minecraft.item.ItemStack; 012import net.minecraft.stats.StatList; 013import net.minecraft.util.AxisAlignedBB; 014import net.minecraft.world.EnumSkyBlock; 015import net.minecraft.world.IBlockAccess; 016import net.minecraft.world.World; 017 018public class BlockSnow extends Block 019{ 020 protected BlockSnow(int par1) 021 { 022 super(par1, Material.snow); 023 this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.125F, 1.0F); 024 this.setTickRandomly(true); 025 this.setCreativeTab(CreativeTabs.tabDecorations); 026 this.func_96478_d(0); 027 } 028 029 @SideOnly(Side.CLIENT) 030 public void func_94332_a(IconRegister par1IconRegister) 031 { 032 this.field_94336_cN = par1IconRegister.func_94245_a("snow"); 033 } 034 035 /** 036 * Returns a bounding box from the pool of bounding boxes (this means this box can change after the pool has been 037 * cleared to be reused) 038 */ 039 public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4) 040 { 041 int l = par1World.getBlockMetadata(par2, par3, par4) & 7; 042 float f = 0.125F; 043 return AxisAlignedBB.getAABBPool().getAABB((double)par2 + this.minX, (double)par3 + this.minY, (double)par4 + this.minZ, (double)par2 + this.maxX, (double)((float)par3 + (float)l * f), (double)par4 + this.maxZ); 044 } 045 046 /** 047 * Is this block (a) opaque and (b) a full 1m cube? This determines whether or not to render the shared face of two 048 * adjacent blocks and also whether the player can attach torches, redstone wire, etc to this block. 049 */ 050 public boolean isOpaqueCube() 051 { 052 return false; 053 } 054 055 /** 056 * If this block doesn't render as an ordinary block it will return False (examples: signs, buttons, stairs, etc) 057 */ 058 public boolean renderAsNormalBlock() 059 { 060 return false; 061 } 062 063 /** 064 * Sets the block's bounds for rendering it as an item 065 */ 066 public void setBlockBoundsForItemRender() 067 { 068 this.func_96478_d(0); 069 } 070 071 /** 072 * Updates the blocks bounds based on its current state. Args: world, x, y, z 073 */ 074 public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) 075 { 076 this.func_96478_d(par1IBlockAccess.getBlockMetadata(par2, par3, par4)); 077 } 078 079 protected void func_96478_d(int par1) 080 { 081 int j = par1 & 7; 082 float f = (float)(2 * (1 + j)) / 16.0F; 083 this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, f, 1.0F); 084 } 085 086 /** 087 * Checks to see if its valid to put this block at the specified coordinates. Args: world, x, y, z 088 */ 089 public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4) 090 { 091 int l = par1World.getBlockId(par2, par3 - 1, par4); 092 Block block = Block.blocksList[l]; 093 if (block == null) return false; 094 if (block == this && (par1World.getBlockMetadata(par2, par3 - 1, par4) & 7) == 7) return true; 095 if (!block.isLeaves(par1World, par2, par3 - 1, par4) && !Block.blocksList[l].isOpaqueCube()) return false; 096 return par1World.getBlockMaterial(par2, par3 - 1, par4).blocksMovement(); 097 } 098 099 /** 100 * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are 101 * their own) Args: x, y, z, neighbor blockID 102 */ 103 public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) 104 { 105 this.canSnowStay(par1World, par2, par3, par4); 106 } 107 108 /** 109 * Checks if this snow block can stay at this location. 110 */ 111 private boolean canSnowStay(World par1World, int par2, int par3, int par4) 112 { 113 if (!this.canPlaceBlockAt(par1World, par2, par3, par4)) 114 { 115 par1World.func_94571_i(par2, par3, par4); 116 return false; 117 } 118 else 119 { 120 return true; 121 } 122 } 123 124 /** 125 * Called when the player destroys a block with an item that can harvest it. (i, j, k) are the coordinates of the 126 * block and l is the block's subtype/damage. 127 */ 128 public void harvestBlock(World par1World, EntityPlayer par2EntityPlayer, int par3, int par4, int par5, int par6) 129 { 130 super.harvestBlock(par1World, par2EntityPlayer, par3, par4, par5, par6); 131 par1World.func_94571_i(par3, par4, par5); 132 } 133 134 /** 135 * Returns the ID of the items to drop on destruction. 136 */ 137 public int idDropped(int par1, Random par2Random, int par3) 138 { 139 return Item.snowball.itemID; 140 } 141 142 /** 143 * Returns the quantity of items to drop on block destruction. 144 */ 145 public int quantityDropped(Random par1Random) 146 { 147 return 1; 148 } 149 150 /** 151 * Ticks the block if it's been scheduled 152 */ 153 public void updateTick(World par1World, int par2, int par3, int par4, Random par5Random) 154 { 155 if (par1World.getSavedLightValue(EnumSkyBlock.Block, par2, par3, par4) > 11) 156 { 157 par1World.func_94571_i(par2, par3, par4); 158 } 159 } 160 161 @SideOnly(Side.CLIENT) 162 163 /** 164 * Returns true if the given side of this block type should be rendered, if the adjacent block is at the given 165 * coordinates. Args: blockAccess, x, y, z, side 166 */ 167 public boolean shouldSideBeRendered(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) 168 { 169 return par5 == 1 ? true : super.shouldSideBeRendered(par1IBlockAccess, par2, par3, par4, par5); 170 } 171 172 @Override 173 public int quantityDropped(int meta, int fortune, Random random) 174 { 175 return (meta & 7) + 1; 176 } 177}