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