001package net.minecraft.block; 002 003import cpw.mods.fml.relauncher.Side; 004import cpw.mods.fml.relauncher.SideOnly; 005 006import java.util.ArrayList; 007import java.util.Random; 008import net.minecraft.block.material.Material; 009import net.minecraft.client.renderer.texture.IconRegister; 010import net.minecraft.entity.EntityLiving; 011import net.minecraft.entity.boss.EntityWither; 012import net.minecraft.entity.player.EntityPlayer; 013import net.minecraft.item.Item; 014import net.minecraft.item.ItemSkull; 015import net.minecraft.item.ItemStack; 016import net.minecraft.nbt.NBTTagCompound; 017import net.minecraft.tileentity.TileEntity; 018import net.minecraft.tileentity.TileEntitySkull; 019import net.minecraft.util.AxisAlignedBB; 020import net.minecraft.util.Icon; 021import net.minecraft.util.MathHelper; 022import net.minecraft.world.IBlockAccess; 023import net.minecraft.world.World; 024 025public class BlockSkull extends BlockContainer 026{ 027 protected BlockSkull(int par1) 028 { 029 super(par1, Material.circuits); 030 this.setBlockBounds(0.25F, 0.0F, 0.25F, 0.75F, 0.5F, 0.75F); 031 } 032 033 /** 034 * The type of render function that is called for this block 035 */ 036 public int getRenderType() 037 { 038 return -1; 039 } 040 041 /** 042 * Is this block (a) opaque and (b) a full 1m cube? This determines whether or not to render the shared face of two 043 * adjacent blocks and also whether the player can attach torches, redstone wire, etc to this block. 044 */ 045 public boolean isOpaqueCube() 046 { 047 return false; 048 } 049 050 /** 051 * If this block doesn't render as an ordinary block it will return False (examples: signs, buttons, stairs, etc) 052 */ 053 public boolean renderAsNormalBlock() 054 { 055 return false; 056 } 057 058 /** 059 * Updates the blocks bounds based on its current state. Args: world, x, y, z 060 */ 061 public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) 062 { 063 int l = par1IBlockAccess.getBlockMetadata(par2, par3, par4) & 7; 064 065 switch (l) 066 { 067 case 1: 068 default: 069 this.setBlockBounds(0.25F, 0.0F, 0.25F, 0.75F, 0.5F, 0.75F); 070 break; 071 case 2: 072 this.setBlockBounds(0.25F, 0.25F, 0.5F, 0.75F, 0.75F, 1.0F); 073 break; 074 case 3: 075 this.setBlockBounds(0.25F, 0.25F, 0.0F, 0.75F, 0.75F, 0.5F); 076 break; 077 case 4: 078 this.setBlockBounds(0.5F, 0.25F, 0.25F, 1.0F, 0.75F, 0.75F); 079 break; 080 case 5: 081 this.setBlockBounds(0.0F, 0.25F, 0.25F, 0.5F, 0.75F, 0.75F); 082 } 083 } 084 085 /** 086 * Returns a bounding box from the pool of bounding boxes (this means this box can change after the pool has been 087 * cleared to be reused) 088 */ 089 public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4) 090 { 091 this.setBlockBoundsBasedOnState(par1World, par2, par3, par4); 092 return super.getCollisionBoundingBoxFromPool(par1World, par2, par3, par4); 093 } 094 095 /** 096 * Called when the block is placed in the world. 097 */ 098 public void onBlockPlacedBy(World par1World, int par2, int par3, int par4, EntityLiving par5EntityLiving, ItemStack par6ItemStack) 099 { 100 int l = MathHelper.floor_double((double)(par5EntityLiving.rotationYaw * 4.0F / 360.0F) + 2.5D) & 3; 101 par1World.setBlockMetadataWithNotify(par2, par3, par4, l, 2); 102 } 103 104 /** 105 * Returns a new instance of a block's tile entity class. Called on placing the block. 106 */ 107 public TileEntity createNewTileEntity(World par1World) 108 { 109 return new TileEntitySkull(); 110 } 111 112 @SideOnly(Side.CLIENT) 113 114 /** 115 * only called by clickMiddleMouseButton , and passed to inventory.setCurrentItem (along with isCreative) 116 */ 117 public int idPicked(World par1World, int par2, int par3, int par4) 118 { 119 return Item.skull.itemID; 120 } 121 122 /** 123 * Get the block's damage value (for use with pick block). 124 */ 125 public int getDamageValue(World par1World, int par2, int par3, int par4) 126 { 127 TileEntity tileentity = par1World.getBlockTileEntity(par2, par3, par4); 128 return tileentity != null && tileentity instanceof TileEntitySkull ? ((TileEntitySkull)tileentity).getSkullType() : super.getDamageValue(par1World, par2, par3, par4); 129 } 130 131 /** 132 * Determines the damage on the item the block drops. Used in cloth and wood. 133 */ 134 public int damageDropped(int par1) 135 { 136 return par1; 137 } 138 139 /** 140 * Called when the block is attempted to be harvested 141 */ 142 public void onBlockHarvested(World par1World, int par2, int par3, int par4, int par5, EntityPlayer par6EntityPlayer) 143 { 144 if (par6EntityPlayer.capabilities.isCreativeMode) 145 { 146 par5 |= 8; 147 par1World.setBlockMetadataWithNotify(par2, par3, par4, par5, 4); 148 } 149 150 dropBlockAsItem(par1World, par2, par3, par4, par5, 0); 151 152 super.onBlockHarvested(par1World, par2, par3, par4, par5, par6EntityPlayer); 153 } 154 155 /** 156 * ejects contained items into the world, and notifies neighbours of an update, as appropriate 157 */ 158 public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6) 159 { 160 super.breakBlock(par1World, par2, par3, par4, par5, par6); 161 } 162 163 @Override 164 public ArrayList<ItemStack> getBlockDropped(World world, int x, int y, int z, int metadata, int fortune) 165 { 166 ArrayList<ItemStack> drops = new ArrayList<ItemStack>(); 167 if ((metadata & 8) == 0) 168 { 169 ItemStack itemstack = new ItemStack(Item.skull.itemID, 1, this.getDamageValue(world, x, y, z)); 170 TileEntitySkull tileentityskull = (TileEntitySkull)world.getBlockTileEntity(x, y, z); 171 172 if (tileentityskull == null) 173 { 174 return drops; 175 } 176 if (tileentityskull.getSkullType() == 3 && tileentityskull.getExtraType() != null && tileentityskull.getExtraType().length() > 0) 177 { 178 itemstack.setTagCompound(new NBTTagCompound()); 179 itemstack.getTagCompound().setString("SkullOwner", tileentityskull.getExtraType()); 180 } 181 drops.add(itemstack); 182 } 183 return drops; 184 } 185 186 /** 187 * Returns the ID of the items to drop on destruction. 188 */ 189 public int idDropped(int par1, Random par2Random, int par3) 190 { 191 return Item.skull.itemID; 192 } 193 194 /** 195 * This method attempts to create a wither at the given location and skull 196 */ 197 public void makeWither(World par1World, int par2, int par3, int par4, TileEntitySkull par5TileEntitySkull) 198 { 199 if (par5TileEntitySkull.getSkullType() == 1 && par3 >= 2 && par1World.difficultySetting > 0 && !par1World.isRemote) 200 { 201 int l = Block.slowSand.blockID; 202 int i1; 203 EntityWither entitywither; 204 int j1; 205 206 for (i1 = -2; i1 <= 0; ++i1) 207 { 208 if (par1World.getBlockId(par2, par3 - 1, par4 + i1) == l && par1World.getBlockId(par2, par3 - 1, par4 + i1 + 1) == l && par1World.getBlockId(par2, par3 - 2, par4 + i1 + 1) == l && par1World.getBlockId(par2, par3 - 1, par4 + i1 + 2) == l && this.func_82528_d(par1World, par2, par3, par4 + i1, 1) && this.func_82528_d(par1World, par2, par3, par4 + i1 + 1, 1) && this.func_82528_d(par1World, par2, par3, par4 + i1 + 2, 1)) 209 { 210 par1World.setBlockMetadataWithNotify(par2, par3, par4 + i1, 8, 2); 211 par1World.setBlockMetadataWithNotify(par2, par3, par4 + i1 + 1, 8, 2); 212 par1World.setBlockMetadataWithNotify(par2, par3, par4 + i1 + 2, 8, 2); 213 par1World.setBlock(par2, par3, par4 + i1, 0, 0, 2); 214 par1World.setBlock(par2, par3, par4 + i1 + 1, 0, 0, 2); 215 par1World.setBlock(par2, par3, par4 + i1 + 2, 0, 0, 2); 216 par1World.setBlock(par2, par3 - 1, par4 + i1, 0, 0, 2); 217 par1World.setBlock(par2, par3 - 1, par4 + i1 + 1, 0, 0, 2); 218 par1World.setBlock(par2, par3 - 1, par4 + i1 + 2, 0, 0, 2); 219 par1World.setBlock(par2, par3 - 2, par4 + i1 + 1, 0, 0, 2); 220 221 if (!par1World.isRemote) 222 { 223 entitywither = new EntityWither(par1World); 224 entitywither.setLocationAndAngles((double)par2 + 0.5D, (double)par3 - 1.45D, (double)(par4 + i1) + 1.5D, 90.0F, 0.0F); 225 entitywither.renderYawOffset = 90.0F; 226 entitywither.func_82206_m(); 227 par1World.spawnEntityInWorld(entitywither); 228 } 229 230 for (j1 = 0; j1 < 120; ++j1) 231 { 232 par1World.spawnParticle("snowballpoof", (double)par2 + par1World.rand.nextDouble(), (double)(par3 - 2) + par1World.rand.nextDouble() * 3.9D, (double)(par4 + i1 + 1) + par1World.rand.nextDouble(), 0.0D, 0.0D, 0.0D); 233 } 234 235 par1World.notifyBlockChange(par2, par3, par4 + i1, 0); 236 par1World.notifyBlockChange(par2, par3, par4 + i1 + 1, 0); 237 par1World.notifyBlockChange(par2, par3, par4 + i1 + 2, 0); 238 par1World.notifyBlockChange(par2, par3 - 1, par4 + i1, 0); 239 par1World.notifyBlockChange(par2, par3 - 1, par4 + i1 + 1, 0); 240 par1World.notifyBlockChange(par2, par3 - 1, par4 + i1 + 2, 0); 241 par1World.notifyBlockChange(par2, par3 - 2, par4 + i1 + 1, 0); 242 return; 243 } 244 } 245 246 for (i1 = -2; i1 <= 0; ++i1) 247 { 248 if (par1World.getBlockId(par2 + i1, par3 - 1, par4) == l && par1World.getBlockId(par2 + i1 + 1, par3 - 1, par4) == l && par1World.getBlockId(par2 + i1 + 1, par3 - 2, par4) == l && par1World.getBlockId(par2 + i1 + 2, par3 - 1, par4) == l && this.func_82528_d(par1World, par2 + i1, par3, par4, 1) && this.func_82528_d(par1World, par2 + i1 + 1, par3, par4, 1) && this.func_82528_d(par1World, par2 + i1 + 2, par3, par4, 1)) 249 { 250 par1World.setBlockMetadataWithNotify(par2 + i1, par3, par4, 8, 2); 251 par1World.setBlockMetadataWithNotify(par2 + i1 + 1, par3, par4, 8, 2); 252 par1World.setBlockMetadataWithNotify(par2 + i1 + 2, par3, par4, 8, 2); 253 par1World.setBlock(par2 + i1, par3, par4, 0, 0, 2); 254 par1World.setBlock(par2 + i1 + 1, par3, par4, 0, 0, 2); 255 par1World.setBlock(par2 + i1 + 2, par3, par4, 0, 0, 2); 256 par1World.setBlock(par2 + i1, par3 - 1, par4, 0, 0, 2); 257 par1World.setBlock(par2 + i1 + 1, par3 - 1, par4, 0, 0, 2); 258 par1World.setBlock(par2 + i1 + 2, par3 - 1, par4, 0, 0, 2); 259 par1World.setBlock(par2 + i1 + 1, par3 - 2, par4, 0, 0, 2); 260 261 if (!par1World.isRemote) 262 { 263 entitywither = new EntityWither(par1World); 264 entitywither.setLocationAndAngles((double)(par2 + i1) + 1.5D, (double)par3 - 1.45D, (double)par4 + 0.5D, 0.0F, 0.0F); 265 entitywither.func_82206_m(); 266 par1World.spawnEntityInWorld(entitywither); 267 } 268 269 for (j1 = 0; j1 < 120; ++j1) 270 { 271 par1World.spawnParticle("snowballpoof", (double)(par2 + i1 + 1) + par1World.rand.nextDouble(), (double)(par3 - 2) + par1World.rand.nextDouble() * 3.9D, (double)par4 + par1World.rand.nextDouble(), 0.0D, 0.0D, 0.0D); 272 } 273 274 par1World.notifyBlockChange(par2 + i1, par3, par4, 0); 275 par1World.notifyBlockChange(par2 + i1 + 1, par3, par4, 0); 276 par1World.notifyBlockChange(par2 + i1 + 2, par3, par4, 0); 277 par1World.notifyBlockChange(par2 + i1, par3 - 1, par4, 0); 278 par1World.notifyBlockChange(par2 + i1 + 1, par3 - 1, par4, 0); 279 par1World.notifyBlockChange(par2 + i1 + 2, par3 - 1, par4, 0); 280 par1World.notifyBlockChange(par2 + i1 + 1, par3 - 2, par4, 0); 281 return; 282 } 283 } 284 } 285 } 286 287 private boolean func_82528_d(World par1World, int par2, int par3, int par4, int par5) 288 { 289 if (par1World.getBlockId(par2, par3, par4) != this.blockID) 290 { 291 return false; 292 } 293 else 294 { 295 TileEntity tileentity = par1World.getBlockTileEntity(par2, par3, par4); 296 return tileentity != null && tileentity instanceof TileEntitySkull ? ((TileEntitySkull)tileentity).getSkullType() == par5 : false; 297 } 298 } 299 300 @SideOnly(Side.CLIENT) 301 302 /** 303 * When this method is called, your block should register all the icons it needs with the given IconRegister. This 304 * is the only chance you get to register icons. 305 */ 306 public void registerIcons(IconRegister par1IconRegister) {} 307 308 @SideOnly(Side.CLIENT) 309 310 /** 311 * From the specified side and block metadata retrieves the blocks texture. Args: side, metadata 312 */ 313 public Icon getBlockTextureFromSideAndMetadata(int par1, int par2) 314 { 315 return Block.slowSand.getBlockTextureFromSide(par1); 316 } 317 318 @SideOnly(Side.CLIENT) 319 public String func_94327_t_() 320 { 321 return ItemSkull.field_94587_a[0]; 322 } 323}