    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.shiftedIndex, 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.shiftedIndex, 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    }