001 package cpw.mods.fml.common.registry;
002
003 import java.util.ArrayList;
004 import java.util.List;
005 import java.util.Map;
006 import java.util.Random;
007
008 import net.minecraft.src.ComponentVillageStartPiece;
009 import net.minecraft.src.EntityVillager;
010 import net.minecraft.src.Item;
011 import net.minecraft.src.MapGenVillage;
012 import net.minecraft.src.MerchantRecipeList;
013 import net.minecraft.src.StructureVillagePieceWeight;
014 import net.minecraft.src.StructureVillagePieces;
015 import net.minecraft.src.Tuple;
016
017 import com.google.common.collect.ArrayListMultimap;
018 import com.google.common.collect.Lists;
019 import com.google.common.collect.Maps;
020 import com.google.common.collect.Multimap;
021
022 import cpw.mods.fml.common.FMLLog;
023
024 /**
025 * Registry for villager trading control
026 *
027 * @author cpw
028 *
029 */
030 public class VillagerRegistry
031 {
032 private static final VillagerRegistry INSTANCE = new VillagerRegistry();
033
034 private Multimap<Integer, IVillageTradeHandler> tradeHandlers = ArrayListMultimap.create();
035 private Map<Class<?>, IVillageCreationHandler> villageCreationHandlers = Maps.newHashMap();
036 private Map<Integer, String> newVillagers = Maps.newHashMap();
037 private List<Integer> newVillagerIds = Lists.newArrayList();
038
039 /**
040 * Allow access to the {@link StructureVillagePieces} array controlling new village
041 * creation so you can insert your own new village pieces
042 *
043 * @author cpw
044 *
045 */
046 public interface IVillageCreationHandler
047 {
048 /**
049 * Called when {@link MapGenVillage} is creating a new village
050 *
051 * @param random
052 * @param i
053 */
054 StructureVillagePieceWeight getVillagePieceWeight(Random random, int i);
055
056 /**
057 * The class of the root structure component to add to the village
058 */
059 Class<?> getComponentClass();
060
061
062 /**
063 * Build an instance of the village component {@link StructureVillagePieces}
064 * @param villagePiece
065 * @param startPiece
066 * @param pieces
067 * @param random
068 * @param p1
069 * @param p2
070 * @param p3
071 * @param p4
072 * @param p5
073 */
074 Object buildComponent(StructureVillagePieceWeight villagePiece, ComponentVillageStartPiece startPiece, List pieces, Random random, int p1,
075 int p2, int p3, int p4, int p5);
076 }
077
078 /**
079 * Allow access to the {@link MerchantRecipeList} for a villager type for manipulation
080 *
081 * @author cpw
082 *
083 */
084 public interface IVillageTradeHandler
085 {
086 /**
087 * Called to allow changing the content of the {@link MerchantRecipeList} for the villager
088 * supplied during creation
089 *
090 * @param villager
091 * @param recipeList
092 */
093 void manipulateTradesForVillager(EntityVillager villager, MerchantRecipeList recipeList, Random random);
094 }
095
096 public static VillagerRegistry instance()
097 {
098 return INSTANCE;
099 }
100
101 /**
102 * Register a new skin for a villager type
103 *
104 * @param villagerId
105 * @param villagerSkin
106 */
107 public void registerVillagerType(int villagerId, String villagerSkin)
108 {
109 if (newVillagers.containsKey(villagerId))
110 {
111 FMLLog.severe("Attempt to register duplicate villager id %d", villagerId);
112 throw new RuntimeException();
113 }
114 newVillagers.put(villagerId, villagerSkin);
115 newVillagerIds.add(villagerId);
116 }
117
118 /**
119 * Register a new village creation handler
120 *
121 * @param handler
122 */
123 public void registerVillageCreationHandler(IVillageCreationHandler handler)
124 {
125 villageCreationHandlers.put(handler.getComponentClass(), handler);
126 }
127
128 /**
129 * Register a new villager trading handler for the specified villager type
130 *
131 * @param villagerId
132 * @param handler
133 */
134 public void registerVillageTradeHandler(int villagerId, IVillageTradeHandler handler)
135 {
136 tradeHandlers.put(villagerId, handler);
137 }
138
139 /**
140 * Callback to setup new villager types
141 *
142 * @param villagerType
143 * @param defaultSkin
144 */
145 public static String getVillagerSkin(int villagerType, String defaultSkin)
146 {
147 if (instance().newVillagers.containsKey(villagerType))
148 {
149 return instance().newVillagers.get(villagerType);
150 }
151 return defaultSkin;
152 }
153
154 /**
155 * Callback to handle trade setup for villagers
156 *
157 * @param recipeList
158 * @param villager
159 * @param villagerType
160 * @param random
161 */
162 public static void manageVillagerTrades(MerchantRecipeList recipeList, EntityVillager villager, int villagerType, Random random)
163 {
164 for (IVillageTradeHandler handler : instance().tradeHandlers.get(villagerType))
165 {
166 handler.manipulateTradesForVillager(villager, recipeList, random);
167 }
168 }
169
170 public static void addExtraVillageComponents(ArrayList components, Random random, int i)
171 {
172 List<StructureVillagePieceWeight> parts = components;
173 for (IVillageCreationHandler handler : instance().villageCreationHandlers.values())
174 {
175 parts.add(handler.getVillagePieceWeight(random, i));
176 }
177 }
178
179 public static Object getVillageComponent(StructureVillagePieceWeight villagePiece, ComponentVillageStartPiece startPiece, List pieces, Random random,
180 int p1, int p2, int p3, int p4, int p5)
181 {
182 return instance().villageCreationHandlers.get(villagePiece.villagePieceClass).buildComponent(villagePiece, startPiece, pieces, random, p1, p2, p3, p4, p5);
183 }
184
185
186 public static void addEmeraldBuyRecipe(EntityVillager villager, MerchantRecipeList list, Random random, Item item, float chance, int min, int max)
187 {
188 if (min > 0 && max > 0)
189 {
190 EntityVillager.villagerStockList.put(item.shiftedIndex, new Tuple(min, max));
191 }
192 villager.addMerchantItem(list, item.getMaxDamage(), random, chance);
193 }
194
195 public static void addEmeraldSellRecipe(EntityVillager villager, MerchantRecipeList list, Random random, Item item, float chance, int min, int max)
196 {
197 if (min > 0 && max > 0)
198 {
199 EntityVillager.blacksmithSellingList.put(item.shiftedIndex, new Tuple(min, max));
200 }
201 villager.addBlacksmithItem(list, item.getMaxDamage(), random, chance);
202 }
203
204 public static void applyRandomTrade(EntityVillager villager, Random rand)
205 {
206 int extra = instance().newVillagerIds.size();
207 int trade = rand.nextInt(5 + extra);
208 villager.setProfession(trade < 5 ? trade : instance().newVillagerIds.get(trade - 5));
209 }
210 }