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    }