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.Lists; 019 import com.google.common.collect.Maps; 020 import com.google.common.collect.Multimap; 021 022 import cpw.mods.fml.common.FMLLog; 023 024 /** 025 * Registry for villager trading control 026 * 027 * @author cpw 028 * 029 */ 030 public 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 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 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 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 * Callback to handle trade setup for villagers 156 * 157 * @param recipeList 158 * @param villager 159 * @param villagerType 160 * @param random 161 */ 162 public static void manageVillagerTrades(MerchantRecipeList recipeList, EntityVillager villager, int villagerType, Random random) 163 { 164 for (IVillageTradeHandler handler : instance().tradeHandlers.get(villagerType)) 165 { 166 handler.manipulateTradesForVillager(villager, recipeList, random); 167 } 168 } 169 170 public static void addExtraVillageComponents(ArrayList components, Random random, int i) 171 { 172 List<StructureVillagePieceWeight> parts = components; 173 for (IVillageCreationHandler handler : instance().villageCreationHandlers.values()) 174 { 175 parts.add(handler.getVillagePieceWeight(random, i)); 176 } 177 } 178 179 public static Object getVillageComponent(StructureVillagePieceWeight villagePiece, ComponentVillageStartPiece startPiece, List pieces, Random random, 180 int p1, int p2, int p3, int p4, int p5) 181 { 182 return instance().villageCreationHandlers.get(villagePiece.villagePieceClass).buildComponent(villagePiece, startPiece, pieces, random, p1, p2, p3, p4, p5); 183 } 184 185 186 public static void addEmeraldBuyRecipe(EntityVillager villager, MerchantRecipeList list, Random random, Item item, float chance, int min, int max) 187 { 188 if (min > 0 && max > 0) 189 { 190 EntityVillager.villagerStockList.put(item.shiftedIndex, new Tuple(min, max)); 191 } 192 villager.addMerchantItem(list, item.getMaxDamage(), random, chance); 193 } 194 195 public static void addEmeraldSellRecipe(EntityVillager villager, MerchantRecipeList list, Random random, Item item, float chance, int min, int max) 196 { 197 if (min > 0 && max > 0) 198 { 199 EntityVillager.blacksmithSellingList.put(item.shiftedIndex, new Tuple(min, max)); 200 } 201 villager.addBlacksmithItem(list, item.getMaxDamage(), random, chance); 202 } 203 204 public static void applyRandomTrade(EntityVillager villager, Random rand) 205 { 206 int extra = instance().newVillagerIds.size(); 207 int trade = rand.nextInt(5 + extra); 208 villager.setProfession(trade < 5 ? trade : instance().newVillagerIds.get(trade - 5)); 209 } 210 }