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