    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) && ItemStack.areItemStackTagsEqual(stack, 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    }