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