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