001 package net.minecraft.item; 002 003 import cpw.mods.fml.relauncher.Side; 004 import cpw.mods.fml.relauncher.SideOnly; 005 import java.util.ArrayList; 006 import java.util.HashMap; 007 import java.util.Iterator; 008 import java.util.LinkedHashMap; 009 import java.util.List; 010 import java.util.Map; 011 import net.minecraft.creativetab.CreativeTabs; 012 import net.minecraft.entity.player.EntityPlayer; 013 import net.minecraft.entity.projectile.EntityPotion; 014 import net.minecraft.nbt.NBTTagCompound; 015 import net.minecraft.nbt.NBTTagList; 016 import net.minecraft.potion.Potion; 017 import net.minecraft.potion.PotionEffect; 018 import net.minecraft.potion.PotionHelper; 019 import net.minecraft.util.StatCollector; 020 import net.minecraft.world.World; 021 022 public class ItemPotion extends Item 023 { 024 /** maps potion damage values to lists of effect names */ 025 private HashMap effectCache = new HashMap(); 026 private static final Map field_77835_b = new LinkedHashMap(); 027 028 public ItemPotion(int par1) 029 { 030 super(par1); 031 this.setMaxStackSize(1); 032 this.setHasSubtypes(true); 033 this.setMaxDamage(0); 034 this.setCreativeTab(CreativeTabs.tabBrewing); 035 } 036 037 /** 038 * Returns a list of potion effects for the specified itemstack. 039 */ 040 public List getEffects(ItemStack par1ItemStack) 041 { 042 if (par1ItemStack.hasTagCompound() && par1ItemStack.getTagCompound().hasKey("CustomPotionEffects")) 043 { 044 ArrayList var6 = new ArrayList(); 045 NBTTagList var3 = par1ItemStack.getTagCompound().getTagList("CustomPotionEffects"); 046 047 for (int var4 = 0; var4 < var3.tagCount(); ++var4) 048 { 049 NBTTagCompound var5 = (NBTTagCompound)var3.tagAt(var4); 050 var6.add(PotionEffect.readCustomPotionEffectFromNBT(var5)); 051 } 052 053 return var6; 054 } 055 else 056 { 057 List var2 = (List)this.effectCache.get(Integer.valueOf(par1ItemStack.getItemDamage())); 058 059 if (var2 == null) 060 { 061 var2 = PotionHelper.getPotionEffects(par1ItemStack.getItemDamage(), false); 062 this.effectCache.put(Integer.valueOf(par1ItemStack.getItemDamage()), var2); 063 } 064 065 return var2; 066 } 067 } 068 069 /** 070 * Returns a list of effects for the specified potion damage value. 071 */ 072 public List getEffects(int par1) 073 { 074 List var2 = (List)this.effectCache.get(Integer.valueOf(par1)); 075 076 if (var2 == null) 077 { 078 var2 = PotionHelper.getPotionEffects(par1, false); 079 this.effectCache.put(Integer.valueOf(par1), var2); 080 } 081 082 return var2; 083 } 084 085 public ItemStack onFoodEaten(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer) 086 { 087 if (!par3EntityPlayer.capabilities.isCreativeMode) 088 { 089 --par1ItemStack.stackSize; 090 } 091 092 if (!par2World.isRemote) 093 { 094 List var4 = this.getEffects(par1ItemStack); 095 096 if (var4 != null) 097 { 098 Iterator var5 = var4.iterator(); 099 100 while (var5.hasNext()) 101 { 102 PotionEffect var6 = (PotionEffect)var5.next(); 103 par3EntityPlayer.addPotionEffect(new PotionEffect(var6)); 104 } 105 } 106 } 107 108 if (!par3EntityPlayer.capabilities.isCreativeMode) 109 { 110 if (par1ItemStack.stackSize <= 0) 111 { 112 return new ItemStack(Item.glassBottle); 113 } 114 115 par3EntityPlayer.inventory.addItemStackToInventory(new ItemStack(Item.glassBottle)); 116 } 117 118 return par1ItemStack; 119 } 120 121 /** 122 * How long it takes to use or consume an item 123 */ 124 public int getMaxItemUseDuration(ItemStack par1ItemStack) 125 { 126 return 32; 127 } 128 129 /** 130 * returns the action that specifies what animation to play when the items is being used 131 */ 132 public EnumAction getItemUseAction(ItemStack par1ItemStack) 133 { 134 return EnumAction.drink; 135 } 136 137 /** 138 * Called whenever this item is equipped and the right mouse button is pressed. Args: itemStack, world, entityPlayer 139 */ 140 public ItemStack onItemRightClick(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer) 141 { 142 if (isSplash(par1ItemStack.getItemDamage())) 143 { 144 if (!par3EntityPlayer.capabilities.isCreativeMode) 145 { 146 --par1ItemStack.stackSize; 147 } 148 149 par2World.playSoundAtEntity(par3EntityPlayer, "random.bow", 0.5F, 0.4F / (itemRand.nextFloat() * 0.4F + 0.8F)); 150 151 if (!par2World.isRemote) 152 { 153 par2World.spawnEntityInWorld(new EntityPotion(par2World, par3EntityPlayer, par1ItemStack)); 154 } 155 156 return par1ItemStack; 157 } 158 else 159 { 160 par3EntityPlayer.setItemInUse(par1ItemStack, this.getMaxItemUseDuration(par1ItemStack)); 161 return par1ItemStack; 162 } 163 } 164 165 /** 166 * Callback for item usage. If the item does something special on right clicking, he will have one of those. Return 167 * True if something happen and false if it don't. This is for ITEMS, not BLOCKS 168 */ 169 public boolean onItemUse(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, World par3World, int par4, int par5, int par6, int par7, float par8, float par9, float par10) 170 { 171 return false; 172 } 173 174 @SideOnly(Side.CLIENT) 175 176 /** 177 * Gets an icon index based on an item's damage value 178 */ 179 public int getIconFromDamage(int par1) 180 { 181 return isSplash(par1) ? 154 : 140; 182 } 183 184 @SideOnly(Side.CLIENT) 185 186 /** 187 * Gets an icon index based on an item's damage value and the given render pass 188 */ 189 public int getIconFromDamageForRenderPass(int par1, int par2) 190 { 191 return par2 == 0 ? 141 : super.getIconFromDamageForRenderPass(par1, par2); 192 } 193 194 /** 195 * returns wether or not a potion is a throwable splash potion based on damage value 196 */ 197 public static boolean isSplash(int par0) 198 { 199 return (par0 & 16384) != 0; 200 } 201 202 @SideOnly(Side.CLIENT) 203 public int getColorFromDamage(int par1) 204 { 205 return PotionHelper.func_77915_a(par1, false); 206 } 207 208 @SideOnly(Side.CLIENT) 209 public int getColorFromItemStack(ItemStack par1ItemStack, int par2) 210 { 211 return par2 > 0 ? 16777215 : this.getColorFromDamage(par1ItemStack.getItemDamage()); 212 } 213 214 @SideOnly(Side.CLIENT) 215 public boolean requiresMultipleRenderPasses() 216 { 217 return true; 218 } 219 220 @SideOnly(Side.CLIENT) 221 public boolean isEffectInstant(int par1) 222 { 223 List var2 = this.getEffects(par1); 224 225 if (var2 != null && !var2.isEmpty()) 226 { 227 Iterator var3 = var2.iterator(); 228 PotionEffect var4; 229 230 do 231 { 232 if (!var3.hasNext()) 233 { 234 return false; 235 } 236 237 var4 = (PotionEffect)var3.next(); 238 } 239 while (!Potion.potionTypes[var4.getPotionID()].isInstant()); 240 241 return true; 242 } 243 else 244 { 245 return false; 246 } 247 } 248 249 public String getItemDisplayName(ItemStack par1ItemStack) 250 { 251 if (par1ItemStack.getItemDamage() == 0) 252 { 253 return StatCollector.translateToLocal("item.emptyPotion.name").trim(); 254 } 255 else 256 { 257 String var2 = ""; 258 259 if (isSplash(par1ItemStack.getItemDamage())) 260 { 261 var2 = StatCollector.translateToLocal("potion.prefix.grenade").trim() + " "; 262 } 263 264 List var3 = Item.potion.getEffects(par1ItemStack); 265 String var4; 266 267 if (var3 != null && !var3.isEmpty()) 268 { 269 var4 = ((PotionEffect)var3.get(0)).getEffectName(); 270 var4 = var4 + ".postfix"; 271 return var2 + StatCollector.translateToLocal(var4).trim(); 272 } 273 else 274 { 275 var4 = PotionHelper.func_77905_c(par1ItemStack.getItemDamage()); 276 return StatCollector.translateToLocal(var4).trim() + " " + super.getItemDisplayName(par1ItemStack); 277 } 278 } 279 } 280 281 @SideOnly(Side.CLIENT) 282 283 /** 284 * allows items to add custom lines of information to the mouseover description 285 */ 286 public void addInformation(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, List par3List, boolean par4) 287 { 288 if (par1ItemStack.getItemDamage() != 0) 289 { 290 List var5 = Item.potion.getEffects(par1ItemStack); 291 292 if (var5 != null && !var5.isEmpty()) 293 { 294 Iterator var9 = var5.iterator(); 295 296 while (var9.hasNext()) 297 { 298 PotionEffect var7 = (PotionEffect)var9.next(); 299 String var8 = StatCollector.translateToLocal(var7.getEffectName()).trim(); 300 301 if (var7.getAmplifier() > 0) 302 { 303 var8 = var8 + " " + StatCollector.translateToLocal("potion.potency." + var7.getAmplifier()).trim(); 304 } 305 306 if (var7.getDuration() > 20) 307 { 308 var8 = var8 + " (" + Potion.getDurationString(var7) + ")"; 309 } 310 311 if (Potion.potionTypes[var7.getPotionID()].isBadEffect()) 312 { 313 par3List.add("\u00a7c" + var8); 314 } 315 else 316 { 317 par3List.add("\u00a77" + var8); 318 } 319 } 320 } 321 else 322 { 323 String var6 = StatCollector.translateToLocal("potion.empty").trim(); 324 par3List.add("\u00a77" + var6); 325 } 326 } 327 } 328 329 @SideOnly(Side.CLIENT) 330 public boolean hasEffect(ItemStack par1ItemStack) 331 { 332 List var2 = this.getEffects(par1ItemStack); 333 return var2 != null && !var2.isEmpty(); 334 } 335 336 @SideOnly(Side.CLIENT) 337 338 /** 339 * returns a list of items with the same ID, but different meta (eg: dye returns 16 items) 340 */ 341 public void getSubItems(int par1, CreativeTabs par2CreativeTabs, List par3List) 342 { 343 super.getSubItems(par1, par2CreativeTabs, par3List); 344 345 if (field_77835_b.isEmpty()) 346 { 347 for (int var4 = 0; var4 <= 32767; ++var4) 348 { 349 List var5 = PotionHelper.getPotionEffects(var4, false); 350 351 if (var5 != null && !var5.isEmpty()) 352 { 353 field_77835_b.put(var5, Integer.valueOf(var4)); 354 } 355 } 356 } 357 358 Iterator var6 = field_77835_b.values().iterator(); 359 360 while (var6.hasNext()) 361 { 362 int var7 = ((Integer)var6.next()).intValue(); 363 par3List.add(new ItemStack(par1, 1, var7)); 364 } 365 } 366 }