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