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 }