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.isHarvestable())
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))
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 }