    001package cpw.mods.fml.common.registry;
    002
    003import java.util.ArrayList;
    004import java.util.List;
    005import java.util.Map;
    006import java.util.Random;
    007import java.util.Collection;
    008import java.util.Collections;
    009
    010import net.minecraft.entity.passive.EntityVillager;
    011import net.minecraft.item.Item;
    012import net.minecraft.util.Tuple;
    013import net.minecraft.village.MerchantRecipeList;
    014import net.minecraft.world.gen.structure.ComponentVillageStartPiece;
    015import net.minecraft.world.gen.structure.StructureVillagePieceWeight;
    016
    017import com.google.common.collect.ArrayListMultimap;
    018import com.google.common.collect.Lists;
    019import com.google.common.collect.Maps;
    020import com.google.common.collect.Multimap;
    021
    022import cpw.mods.fml.common.FMLLog;
    023
    024/**
    025 * Registry for villager trading control
    026 *
    027 * @author cpw
    028 *
    029 */
    030public 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 net.minecraft.world.gen.structure.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 net.minecraft.world.gen.structure.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 net.minecraft.world.gen.structure.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     * Returns a list of all added villager types
    156     *
    157     * @return newVillagerIds
    158     */
    159    public static Collection<Integer> getRegisteredVillagers()
    160    {
    161        return Collections.unmodifiableCollection(instance().newVillagerIds);
    162    }
    163    /**
    164     * Callback to handle trade setup for villagers
    165     *
    166     * @param recipeList
    167     * @param villager
    168     * @param villagerType
    169     * @param random
    170     */
    171    public static void manageVillagerTrades(MerchantRecipeList recipeList, EntityVillager villager, int villagerType, Random random)
    172    {
    173        for (IVillageTradeHandler handler : instance().tradeHandlers.get(villagerType))
    174        {
    175            handler.manipulateTradesForVillager(villager, recipeList, random);
    176        }
    177    }
    178
    179    public static void addExtraVillageComponents(ArrayList components, Random random, int i)
    180    {
    181        List<StructureVillagePieceWeight> parts = components;
    182        for (IVillageCreationHandler handler : instance().villageCreationHandlers.values())
    183        {
    184            parts.add(handler.getVillagePieceWeight(random, i));
    185        }
    186    }
    187
    188    public static Object getVillageComponent(StructureVillagePieceWeight villagePiece, ComponentVillageStartPiece startPiece, List pieces, Random random,
    189            int p1, int p2, int p3, int p4, int p5)
    190    {
    191        return instance().villageCreationHandlers.get(villagePiece.villagePieceClass).buildComponent(villagePiece, startPiece, pieces, random, p1, p2, p3, p4, p5);
    192    }
    193
    194
    195    public static void addEmeraldBuyRecipe(EntityVillager villager, MerchantRecipeList list, Random random, Item item, float chance, int min, int max)
    196    {
    197        if (min > 0 && max > 0)
    198        {
    199            EntityVillager.villagerStockList.put(item.itemID, new Tuple(min, max));
    200        }
    201        villager.addMerchantItem(list, item.getMaxDamage(), random, chance);
    202    }
    203
    204    public static void addEmeraldSellRecipe(EntityVillager villager, MerchantRecipeList list, Random random, Item item, float chance, int min, int max)
    205    {
    206        if (min > 0 && max > 0)
    207        {
    208            EntityVillager.blacksmithSellingList.put(item.itemID, new Tuple(min, max));
    209        }
    210        villager.addBlacksmithItem(list, item.getMaxDamage(), random, chance);
    211    }
    212
    213    public static void applyRandomTrade(EntityVillager villager, Random rand)
    214    {
    215        int extra = instance().newVillagerIds.size();
    216        int trade = rand.nextInt(5 + extra);
    217        villager.setProfession(trade < 5 ? trade : instance().newVillagerIds.get(trade - 5));
    218    }
    219}