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