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