001 package net.minecraftforge.common; 002 003 import java.util.*; 004 import java.util.Map.Entry; 005 006 import com.google.common.collect.ArrayListMultimap; 007 import com.google.common.collect.ListMultimap; 008 009 import cpw.mods.fml.common.FMLLog; 010 import cpw.mods.fml.common.Loader; 011 012 import net.minecraft.src.*; 013 import net.minecraftforge.event.entity.item.ItemTossEvent; 014 import net.minecraftforge.event.entity.living.*; 015 import net.minecraftforge.event.entity.living.LivingEvent.*; 016 017 public class ForgeHooks 018 { 019 static class GrassEntry extends WeightedRandomItem 020 { 021 public final Block block; 022 public final int metadata; 023 public GrassEntry(Block block, int meta, int weight) 024 { 025 super(weight); 026 this.block = block; 027 this.metadata = meta; 028 } 029 } 030 031 static class SeedEntry extends WeightedRandomItem 032 { 033 public final ItemStack seed; 034 public SeedEntry(ItemStack seed, int weight) 035 { 036 super(weight); 037 this.seed = seed; 038 } 039 } 040 static final List<GrassEntry> grassList = new ArrayList<GrassEntry>(); 041 static final List<SeedEntry> seedList = new ArrayList<SeedEntry>(); 042 043 public static void plantGrass(World world, int x, int y, int z) 044 { 045 GrassEntry grass = (GrassEntry)WeightedRandom.getRandomItem(world.rand, grassList); 046 if (grass == null || grass.block == null || !grass.block.canBlockStay(world, x, y, z)) 047 { 048 return; 049 } 050 world.setBlockAndMetadataWithNotify(x, y, z, grass.block.blockID, grass.metadata); 051 } 052 053 public static ItemStack getGrassSeed(World world) 054 { 055 SeedEntry entry = (SeedEntry)WeightedRandom.getRandomItem(world.rand, seedList); 056 if (entry == null || entry.seed == null) 057 { 058 return null; 059 } 060 return entry.seed.copy(); 061 } 062 063 private static boolean toolInit = false; 064 static HashMap<Item, List> toolClasses = new HashMap<Item, List>(); 065 static HashMap<List, Integer> toolHarvestLevels = new HashMap<List, Integer>(); 066 static HashSet<List> toolEffectiveness = new HashSet<List>(); 067 068 public static boolean canHarvestBlock(Block block, EntityPlayer player, int metadata) 069 { 070 if (block.blockMaterial.isHarvestable()) 071 { 072 return true; 073 } 074 075 ItemStack stack = player.inventory.getCurrentItem(); 076 if (stack == null) 077 { 078 return player.canHarvestBlock(block); 079 } 080 081 List info = (List)toolClasses.get(stack.getItem()); 082 if (info == null) 083 { 084 return player.canHarvestBlock(block); 085 } 086 087 Object[] tmp = info.toArray(); 088 String toolClass = (String)tmp[0]; 089 int harvestLevel = (Integer)tmp[1]; 090 091 Integer blockHarvestLevel = (Integer)toolHarvestLevels.get(Arrays.asList(block, metadata, toolClass)); 092 if (blockHarvestLevel == null) 093 { 094 return player.canHarvestBlock(block); 095 } 096 097 if (blockHarvestLevel > harvestLevel) 098 { 099 return false; 100 } 101 return true; 102 } 103 104 public static float blockStrength(Block block, EntityPlayer player, World world, int x, int y, int z) 105 { 106 int metadata = world.getBlockMetadata(x, y, z); 107 float hardness = block.getBlockHardness(world, x, y, z); 108 if (hardness < 0.0F) 109 { 110 return 0.0F; 111 } 112 113 if (!canHarvestBlock(block, player, metadata)) 114 { 115 return 1.0F / hardness / 100F; 116 } 117 else 118 { 119 return player.getCurrentPlayerStrVsBlock(block, metadata) / hardness / 30F; 120 } 121 } 122 123 public static boolean isToolEffective(ItemStack stack, Block block, int metadata) 124 { 125 List toolClass = (List)toolClasses.get(stack.getItem()); 126 if (toolClass == null) 127 { 128 return false; 129 } 130 return toolEffectiveness.contains(Arrays.asList(block, metadata, (String)toolClass.get(0))); 131 } 132 133 static void initTools() 134 { 135 if (toolInit) 136 { 137 return; 138 } 139 toolInit = true; 140 141 MinecraftForge.setToolClass(Item.pickaxeWood, "pickaxe", 0); 142 MinecraftForge.setToolClass(Item.pickaxeStone, "pickaxe", 1); 143 MinecraftForge.setToolClass(Item.pickaxeSteel, "pickaxe", 2); 144 MinecraftForge.setToolClass(Item.pickaxeGold, "pickaxe", 0); 145 MinecraftForge.setToolClass(Item.pickaxeDiamond, "pickaxe", 3); 146 147 MinecraftForge.setToolClass(Item.axeWood, "axe", 0); 148 MinecraftForge.setToolClass(Item.axeStone, "axe", 1); 149 MinecraftForge.setToolClass(Item.axeSteel, "axe", 2); 150 MinecraftForge.setToolClass(Item.axeGold, "axe", 0); 151 MinecraftForge.setToolClass(Item.axeDiamond, "axe", 3); 152 153 MinecraftForge.setToolClass(Item.shovelWood, "shovel", 0); 154 MinecraftForge.setToolClass(Item.shovelStone, "shovel", 1); 155 MinecraftForge.setToolClass(Item.shovelSteel, "shovel", 2); 156 MinecraftForge.setToolClass(Item.shovelGold, "shovel", 0); 157 MinecraftForge.setToolClass(Item.shovelDiamond, "shovel", 3); 158 159 for (Block block : ItemPickaxe.blocksEffectiveAgainst) 160 { 161 MinecraftForge.setBlockHarvestLevel(block, "pickaxe", 0); 162 } 163 164 for (Block block : ItemSpade.blocksEffectiveAgainst) 165 { 166 MinecraftForge.setBlockHarvestLevel(block, "shovel", 0); 167 } 168 169 for (Block block : ItemAxe.blocksEffectiveAgainst) 170 { 171 MinecraftForge.setBlockHarvestLevel(block, "axe", 0); 172 } 173 174 MinecraftForge.setBlockHarvestLevel(Block.obsidian, "pickaxe", 3); 175 MinecraftForge.setBlockHarvestLevel(Block.oreEmerald, "pickaxe", 2); 176 MinecraftForge.setBlockHarvestLevel(Block.oreDiamond, "pickaxe", 2); 177 MinecraftForge.setBlockHarvestLevel(Block.blockDiamond, "pickaxe", 2); 178 MinecraftForge.setBlockHarvestLevel(Block.oreGold, "pickaxe", 2); 179 MinecraftForge.setBlockHarvestLevel(Block.blockGold, "pickaxe", 2); 180 MinecraftForge.setBlockHarvestLevel(Block.oreIron, "pickaxe", 1); 181 MinecraftForge.setBlockHarvestLevel(Block.blockSteel, "pickaxe", 1); 182 MinecraftForge.setBlockHarvestLevel(Block.oreLapis, "pickaxe", 1); 183 MinecraftForge.setBlockHarvestLevel(Block.blockLapis, "pickaxe", 1); 184 MinecraftForge.setBlockHarvestLevel(Block.oreRedstone, "pickaxe", 2); 185 MinecraftForge.setBlockHarvestLevel(Block.oreRedstoneGlowing, "pickaxe", 2); 186 MinecraftForge.removeBlockEffectiveness(Block.oreRedstone, "pickaxe"); 187 MinecraftForge.removeBlockEffectiveness(Block.obsidian, "pickaxe"); 188 MinecraftForge.removeBlockEffectiveness(Block.oreRedstoneGlowing, "pickaxe"); 189 } 190 191 public static String getTexture(String _default, Object obj) 192 { 193 if (obj instanceof Item) 194 { 195 return ((Item)obj).getTextureFile(); 196 } 197 else if (obj instanceof Block) 198 { 199 return ((Block)obj).getTextureFile(); 200 } 201 else 202 { 203 return _default; 204 } 205 } 206 207 public static int getTotalArmorValue(EntityPlayer player) 208 { 209 int ret = 0; 210 for (int x = 0; x < player.inventory.armorInventory.length; x++) 211 { 212 ItemStack stack = player.inventory.armorInventory[x]; 213 if (stack != null && stack.getItem() instanceof ISpecialArmor) 214 { 215 ret += ((ISpecialArmor)stack.getItem()).getArmorDisplay(player, stack, x); 216 } 217 else if (stack != null && stack.getItem() instanceof ItemArmor) 218 { 219 ret += ((ItemArmor)stack.getItem()).damageReduceAmount; 220 } 221 } 222 return ret; 223 } 224 225 static 226 { 227 grassList.add(new GrassEntry(Block.plantYellow, 0, 20)); 228 grassList.add(new GrassEntry(Block.plantRed, 0, 10)); 229 seedList.add(new SeedEntry(new ItemStack(Item.seeds), 10)); 230 initTools(); 231 } 232 233 /** 234 * Called when a player uses 'pick block', calls new Entity and Block hooks. 235 */ 236 public static boolean onPickBlock(MovingObjectPosition target, EntityPlayer player, World world) 237 { 238 ItemStack result = null; 239 boolean isCreative = player.capabilities.isCreativeMode; 240 241 if (target.typeOfHit == EnumMovingObjectType.TILE) 242 { 243 int x = target.blockX; 244 int y = target.blockY; 245 int z = target.blockZ; 246 Block var8 = Block.blocksList[world.getBlockId(x, y, z)]; 247 248 if (var8 == null) 249 { 250 return false; 251 } 252 253 result = var8.getPickBlock(target, world, x, y, z); 254 } 255 else 256 { 257 if (target.typeOfHit != EnumMovingObjectType.ENTITY || target.entityHit == null || !isCreative) 258 { 259 return false; 260 } 261 262 result = target.entityHit.getPickedResult(target); 263 } 264 265 if (result == null) 266 { 267 return false; 268 } 269 270 for (int x = 0; x < 9; x++) 271 { 272 ItemStack stack = player.inventory.getStackInSlot(x); 273 if (stack != null && stack.isItemEqual(result)) 274 { 275 player.inventory.currentItem = x; 276 return true; 277 } 278 } 279 280 if (!isCreative) 281 { 282 return false; 283 } 284 285 int slot = player.inventory.getFirstEmptyStack(); 286 if (slot < 0 || slot >= 9) 287 { 288 slot = player.inventory.currentItem; 289 } 290 291 player.inventory.setInventorySlotContents(slot, result); 292 player.inventory.currentItem = slot; 293 return true; 294 } 295 296 //Optifine Helper Functions u.u, these are here specifically for Optifine 297 //Note: When using Optfine, these methods are invoked using reflection, which 298 //incurs a major performance penalty. 299 public static void onLivingSetAttackTarget(EntityLiving entity, EntityLiving target) 300 { 301 MinecraftForge.EVENT_BUS.post(new LivingSetAttackTargetEvent(entity, target)); 302 } 303 304 public static boolean onLivingUpdate(EntityLiving entity) 305 { 306 return MinecraftForge.EVENT_BUS.post(new LivingUpdateEvent(entity)); 307 } 308 309 public static boolean onLivingAttack(EntityLiving entity, DamageSource src, int amount) 310 { 311 return MinecraftForge.EVENT_BUS.post(new LivingAttackEvent(entity, src, amount)); 312 } 313 314 public static int onLivingHurt(EntityLiving entity, DamageSource src, int amount) 315 { 316 LivingHurtEvent event = new LivingHurtEvent(entity, src, amount); 317 return (MinecraftForge.EVENT_BUS.post(event) ? 0 : event.ammount); 318 } 319 320 public static boolean onLivingDeath(EntityLiving entity, DamageSource src) 321 { 322 return MinecraftForge.EVENT_BUS.post(new LivingDeathEvent(entity, src)); 323 } 324 325 public static boolean onLivingDrops(EntityLiving entity, DamageSource source, ArrayList<EntityItem> drops, int lootingLevel, boolean recentlyHit, int specialDropValue) 326 { 327 return MinecraftForge.EVENT_BUS.post(new LivingDropsEvent(entity, source, drops, lootingLevel, recentlyHit, specialDropValue)); 328 } 329 330 public static float onLivingFall(EntityLiving entity, float distance) 331 { 332 LivingFallEvent event = new LivingFallEvent(entity, distance); 333 return (MinecraftForge.EVENT_BUS.post(event) ? 0.0f : event.distance); 334 } 335 336 public static boolean isLivingOnLadder(Block block, World world, int x, int y, int z) 337 { 338 return block != null && block.isLadder(world, x, y, z); 339 } 340 341 public static void onLivingJump(EntityLiving entity) 342 { 343 MinecraftForge.EVENT_BUS.post(new LivingJumpEvent(entity)); 344 } 345 346 public static EntityItem onPlayerTossEvent(EntityPlayer player, ItemStack item) 347 { 348 player.captureDrops = true; 349 EntityItem ret = player.dropPlayerItemWithRandomChoice(item, false); 350 player.capturedDrops.clear(); 351 player.captureDrops = false; 352 353 ItemTossEvent event = new ItemTossEvent(ret, player); 354 if (MinecraftForge.EVENT_BUS.post(event)) 355 { 356 return null; 357 } 358 359 player.joinEntityItemWithWorld(event.entityItem); 360 return event.entityItem; 361 } 362 }