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