    001    package net.minecraftforge.common;
    002
    003    import java.util.*;
    004
    005    import net.minecraft.item.ItemStack;
    006    import net.minecraft.util.WeightedRandomChestContent;
    007    import net.minecraft.world.WorldServer;
    008    import net.minecraft.world.gen.structure.*;
    009
    010    public class ChestGenHooks
    011    {
    012        //Currently implemented categories for chests/dispensers, Dungeon loot is still in DungeonHooks
    013        public static final String MINESHAFT_CORRIDOR       = "mineshaftCorridor";
    014        public static final String PYRAMID_DESERT_CHEST     = "pyramidDesertyChest";
    015        public static final String PYRAMID_JUNGLE_CHEST     = "pyramidJungleChest";
    016        public static final String PYRAMID_JUNGLE_DISPENSER = "pyramidJungleDispenser";
    017        public static final String STRONGHOLD_CORRIDOR      = "strongholdCorridor";
    018        public static final String STRONGHOLD_LIBRARY       = "strongholdLibrary";
    019        public static final String STRONGHOLD_CROSSING      = "strongholdCrossing";
    020        public static final String VILLAGE_BLACKSMITH       = "villageBlacksmith";
    021        public static final String BONUS_CHEST              = "bonusChest";
    022
    023        private static final HashMap<String, ChestGenHooks> chestInfo = new HashMap<String, ChestGenHooks>();
    024        private static boolean hasInit = false;
    025        static
    026        {
    027            init();
    028        }
    029
    030        private static void init()
    031        {
    032            if (hasInit)
    033            {
    034                return;
    035            }
    036            addInfo(MINESHAFT_CORRIDOR,       StructureMineshaftPieces.mineshaftChestContents,                         3,  7);
    037            addInfo(PYRAMID_DESERT_CHEST,     ComponentScatteredFeatureDesertPyramid.itemsToGenerateInTemple,          2,  7);
    038            addInfo(PYRAMID_JUNGLE_CHEST,     ComponentScatteredFeatureJunglePyramid.junglePyramidsChestContents,      2,  7);
    039            addInfo(PYRAMID_JUNGLE_DISPENSER, ComponentScatteredFeatureJunglePyramid.junglePyramidsDispenserContents,  2,  2);
    040            addInfo(STRONGHOLD_CORRIDOR,      ComponentStrongholdChestCorridor.strongholdChestContents,                2,  4);
    041            addInfo(STRONGHOLD_LIBRARY,       ComponentStrongholdLibrary.strongholdLibraryChestContents,               1,  5);
    042            addInfo(STRONGHOLD_CROSSING,      ComponentStrongholdRoomCrossing.strongholdRoomCrossingChestContents,     1,  5);
    043            addInfo(VILLAGE_BLACKSMITH,       ComponentVillageHouse2.villageBlacksmithChestContents,                   3,  9);
    044            addInfo(BONUS_CHEST,              WorldServer.bonusChestContent,                                          10, 10);
    045        }
    046
    047        private static void addInfo(String category, WeightedRandomChestContent[] items, int min, int max)
    048        {
    049            chestInfo.put(category, new ChestGenHooks(category, items, min, max));
    050        }
    051
    052        /**
    053         * Retrieves, or creates the info class for the specified category.
    054         *
    055         * @param category The category name
    056         * @return A instance of ChestGenHooks for the specified category.
    057         */
    058        public static ChestGenHooks getInfo(String category)
    059        {
    060            if (!chestInfo.containsKey(category))
    061            {
    062                chestInfo.put(category, new ChestGenHooks(category));
    063            }
    064            return chestInfo.get(category);
    065        }
    066
    067        /**
    068         * Generates an array of items based on the input min/max count.
    069         * If the stack can not hold the total amount, it will be split into
    070         * stacks of size 1.
    071         *
    072         * @param rand A random number generator
    073         * @param source Source item stack
    074         * @param min Minimum number of items
    075         * @param max Maximum number of items
    076         * @return An array containing the generated item stacks
    077         */
    078        public static ItemStack[] generateStacks(Random rand, ItemStack source, int min, int max)
    079        {
    080            int count = min + (rand.nextInt(max - min + 1));
    081
    082            ItemStack[] ret;
    083            if (source.getItem() == null)
    084            {
    085                ret = new ItemStack[0];
    086            }
    087            else if (count > source.getItem().getItemStackLimit())
    088            {
    089                ret = new ItemStack[count];
    090                for (int x = 0; x < count; x++)
    091                {
    092                    ret[x] = source.copy();
    093                    ret[x].stackSize = 1;
    094                }
    095            }
    096            else
    097            {
    098                ret = new ItemStack[1];
    099                ret[0] = source.copy();
    100                ret[0].stackSize = count;
    101            }
    102            return ret;
    103        }
    104
    105        //shortcut functions, See the non-static versions below
    106        public static WeightedRandomChestContent[] getItems(String category){ return getInfo(category).getItems(); }
    107        public static int getCount(String category, Random rand){ return getInfo(category).getCount(rand); }
    108        public static void addItem(String category, WeightedRandomChestContent item){ getInfo(category).addItem(item); }
    109        public static void removeItem(String category, ItemStack item){ getInfo(category).removeItem(item); }
    110
    111        private String category;
    112        private int countMin = 0;
    113        private int countMax = 0;
    114        private ArrayList<WeightedRandomChestContent> contents = new ArrayList<WeightedRandomChestContent>();
    115
    116        public ChestGenHooks(String category)
    117        {
    118            this.category = category;
    119        }
    120
    121        public ChestGenHooks(String category, WeightedRandomChestContent[] items, int min, int max)
    122        {
    123            this(category);
    124            for (WeightedRandomChestContent item : items)
    125            {
    126                contents.add(item);
    127            }
    128            countMin = min;
    129            countMax = max;
    130        }
    131
    132        /**
    133         * Adds a new entry into the possible items to generate.
    134         *
    135         * @param item The item to add.
    136         */
    137        public void addItem(WeightedRandomChestContent item)
    138        {
    139            contents.add(item);
    140        }
    141
    142        /**
    143         * Removes all items that match the input item stack, Only metadata and item ID are checked.
    144         * If the input item has a metadata of -1, all metadatas will match.
    145         *
    146         * @param item The item to check
    147         */
    148        public void removeItem(ItemStack item)
    149        {
    150            Iterator<WeightedRandomChestContent> itr = contents.iterator();
    151            while(itr.hasNext())
    152            {
    153                WeightedRandomChestContent cont = itr.next();
    154                if (item.isItemEqual(cont.itemStack) || (item.getItemDamage() == -1 && item.itemID == cont.itemStack.itemID))
    155                {
    156                    itr.remove();
    157                }
    158            }
    159        }
    160
    161        /**
    162         * Gets an array of all random objects that are associated with this category.
    163         *
    164         * @return The random objects
    165         */
    166        public WeightedRandomChestContent[] getItems()
    167        {
    168            return contents.toArray(new WeightedRandomChestContent[contents.size()]);
    169        }
    170
    171        /**
    172         * Gets a random number between countMin and countMax.
    173         *
    174         * @param rand A RNG
    175         * @return A random number where countMin <= num <= countMax
    176         */
    177        public int getCount(Random rand)
    178        {
    179            return countMin < countMax ? countMin + rand.nextInt(countMax - countMin) : countMin;
    180        }
    181
    182        //Accessors
    183        public int getMin(){ return countMin; }
    184        public int getMax(){ return countMax; }
    185        public void setMin(int value){ countMin = value; }
    186        public void setMax(int value){ countMax = value; }
    187    }