001 package cpw.mods.fml.common.registry; 002 003 import java.util.List; 004 import java.util.Random; 005 import java.util.Set; 006 import java.util.logging.Level; 007 008 import net.minecraft.src.BiomeGenBase; 009 import net.minecraft.src.CraftingManager; 010 import net.minecraft.src.EntityItem; 011 import net.minecraft.src.EntityPlayer; 012 import net.minecraft.src.FurnaceRecipes; 013 import net.minecraft.src.IChunkProvider; 014 import net.minecraft.src.IInventory; 015 import net.minecraft.src.IRecipe; 016 import net.minecraft.src.ItemBlock; 017 import net.minecraft.src.ItemStack; 018 import net.minecraft.src.TileEntity; 019 import net.minecraft.src.World; 020 import net.minecraft.src.WorldType; 021 022 import com.google.common.collect.ArrayListMultimap; 023 import com.google.common.collect.Lists; 024 import com.google.common.collect.Multimap; 025 import com.google.common.collect.Sets; 026 027 import cpw.mods.fml.common.FMLLog; 028 import cpw.mods.fml.common.ICraftingHandler; 029 import cpw.mods.fml.common.IDispenseHandler; 030 import cpw.mods.fml.common.IFuelHandler; 031 import cpw.mods.fml.common.IPickupNotifier; 032 import cpw.mods.fml.common.IPlayerTracker; 033 import cpw.mods.fml.common.IWorldGenerator; 034 import cpw.mods.fml.common.Loader; 035 import cpw.mods.fml.common.LoaderException; 036 import cpw.mods.fml.common.LoaderState; 037 import cpw.mods.fml.common.Mod.Block; 038 import cpw.mods.fml.common.ModContainer; 039 040 public class GameRegistry 041 { 042 private static Multimap<ModContainer, BlockProxy> blockRegistry = ArrayListMultimap.create(); 043 private static Multimap<ModContainer, ItemProxy> itemRegistry = ArrayListMultimap.create(); 044 private static Set<IWorldGenerator> worldGenerators = Sets.newHashSet(); 045 private static List<IFuelHandler> fuelHandlers = Lists.newArrayList(); 046 private static List<ICraftingHandler> craftingHandlers = Lists.newArrayList(); 047 private static List<IDispenseHandler> dispenserHandlers = Lists.newArrayList(); 048 private static List<IPickupNotifier> pickupHandlers = Lists.newArrayList(); 049 private static List<IPlayerTracker> playerTrackers = Lists.newArrayList(); 050 051 /** 052 * Register a world generator - something that inserts new block types into the world 053 * 054 * @param generator 055 */ 056 public static void registerWorldGenerator(IWorldGenerator generator) 057 { 058 worldGenerators.add(generator); 059 } 060 061 /** 062 * Callback hook for world gen - if your mod wishes to add extra mod related generation to the world 063 * call this 064 * 065 * @param chunkX 066 * @param chunkZ 067 * @param world 068 * @param chunkGenerator 069 * @param chunkProvider 070 */ 071 public static void generateWorld(int chunkX, int chunkZ, World world, IChunkProvider chunkGenerator, IChunkProvider chunkProvider) 072 { 073 long worldSeed = world.getSeed(); 074 Random fmlRandom = new Random(worldSeed); 075 long xSeed = fmlRandom.nextLong() >> 2 + 1L; 076 long zSeed = fmlRandom.nextLong() >> 2 + 1L; 077 fmlRandom.setSeed((xSeed * chunkX + zSeed * chunkZ) ^ worldSeed); 078 079 for (IWorldGenerator generator : worldGenerators) 080 { 081 generator.generate(fmlRandom, chunkX, chunkZ, world, chunkGenerator, chunkProvider); 082 } 083 } 084 085 /** 086 * Register a handler for dispensers 087 * 088 * @param handler 089 */ 090 public static void registerDispenserHandler(IDispenseHandler handler) 091 { 092 dispenserHandlers.add(handler); 093 } 094 095 096 /** 097 * Callback hook for dispenser activities - if you add a block and want mods to be able 098 * to extend their dispenser related activities to it call this 099 * 100 * @param world 101 * @param x 102 * @param y 103 * @param z 104 * @param xVelocity 105 * @param zVelocity 106 * @param item 107 * @return 108 */ 109 public static int tryDispense(World world, double x, double y, double z, int xVelocity, int zVelocity, ItemStack item, Random random, double entX, double entY, double entZ) 110 { 111 for (IDispenseHandler handler : dispenserHandlers) 112 { 113 int dispensed = handler.dispense(x, y, z, xVelocity, zVelocity, world, item, random, entX, entY, entZ); 114 if (dispensed>-1) 115 { 116 return dispensed; 117 } 118 } 119 return -1; 120 } 121 /** 122 * Internal method for creating an @Block instance 123 * @param container 124 * @param type 125 * @param annotation 126 * @return 127 * @throws Exception 128 */ 129 public static Object buildBlock(ModContainer container, Class<?> type, Block annotation) throws Exception 130 { 131 Object o = type.getConstructor(int.class).newInstance(findSpareBlockId()); 132 registerBlock((net.minecraft.src.Block) o); 133 return o; 134 } 135 136 /** 137 * Private and not yet working properly 138 * 139 * @return 140 */ 141 private static int findSpareBlockId() 142 { 143 return BlockTracker.nextBlockId(); 144 } 145 146 /** 147 * Register a block with the world 148 * 149 */ 150 public static void registerBlock(net.minecraft.src.Block block) 151 { 152 registerBlock(block, ItemBlock.class); 153 } 154 155 /** 156 * Register a block with the world, with the specified item class 157 * 158 * @param block 159 * @param itemclass 160 */ 161 public static void registerBlock(net.minecraft.src.Block block, Class<? extends ItemBlock> itemclass) 162 { 163 if (Loader.instance().isInState(LoaderState.CONSTRUCTING)) 164 { 165 FMLLog.warning("The mod %s is attempting to register a block whilst it it being constructed. This is bad modding practice - please use a proper mod lifecycle event.", Loader.instance().activeModContainer()); 166 } 167 try 168 { 169 assert block != null : "registerBlock: block cannot be null"; 170 assert itemclass != null : "registerBlock: itemclass cannot be null"; 171 int blockItemId = block.blockID - 256; 172 itemclass.getConstructor(int.class).newInstance(blockItemId); 173 } 174 catch (Exception e) 175 { 176 FMLLog.log(Level.SEVERE, e, "Caught an exception during block registration"); 177 throw new LoaderException(e); 178 } 179 blockRegistry.put(Loader.instance().activeModContainer(), (BlockProxy) block); 180 } 181 182 public static void addRecipe(ItemStack output, Object... params) 183 { 184 CraftingManager.getInstance().addRecipe(output, params); 185 } 186 187 public static void addShapelessRecipe(ItemStack output, Object... params) 188 { 189 CraftingManager.getInstance().addShapelessRecipe(output, params); 190 } 191 192 public static void addRecipe(IRecipe recipe) 193 { 194 CraftingManager.getInstance().getRecipeList().add(recipe); 195 } 196 197 public static void addSmelting(int input, ItemStack output, float xp) 198 { 199 FurnaceRecipes.smelting().addSmelting(input, output, xp); 200 } 201 202 public static void registerTileEntity(Class<? extends TileEntity> tileEntityClass, String id) 203 { 204 TileEntity.addMapping(tileEntityClass, id); 205 } 206 207 public static void addBiome(BiomeGenBase biome) 208 { 209 WorldType.DEFAULT.addNewBiome(biome); 210 } 211 212 public static void removeBiome(BiomeGenBase biome) 213 { 214 WorldType.DEFAULT.removeBiome(biome); 215 } 216 217 public static void registerFuelHandler(IFuelHandler handler) 218 { 219 fuelHandlers.add(handler); 220 } 221 public static int getFuelValue(ItemStack itemStack) 222 { 223 int fuelValue = 0; 224 for (IFuelHandler handler : fuelHandlers) 225 { 226 fuelValue = Math.max(fuelValue, handler.getBurnTime(itemStack)); 227 } 228 return fuelValue; 229 } 230 231 public static void registerCraftingHandler(ICraftingHandler handler) 232 { 233 craftingHandlers.add(handler); 234 } 235 236 public static void onItemCrafted(EntityPlayer player, ItemStack item, IInventory craftMatrix) 237 { 238 for (ICraftingHandler handler : craftingHandlers) 239 { 240 handler.onCrafting(player, item, craftMatrix); 241 } 242 } 243 244 public static void onItemSmelted(EntityPlayer player, ItemStack item) 245 { 246 for (ICraftingHandler handler : craftingHandlers) 247 { 248 handler.onSmelting(player, item); 249 } 250 } 251 252 public static void registerPickupHandler(IPickupNotifier handler) 253 { 254 pickupHandlers.add(handler); 255 } 256 257 public static void onPickupNotification(EntityPlayer player, EntityItem item) 258 { 259 for (IPickupNotifier notify : pickupHandlers) 260 { 261 notify.notifyPickup(item, player); 262 } 263 } 264 265 public static void registerPlayerTracker(IPlayerTracker tracker) 266 { 267 playerTrackers.add(tracker); 268 } 269 270 public static void onPlayerLogin(EntityPlayer player) 271 { 272 for(IPlayerTracker tracker : playerTrackers) 273 tracker.onPlayerLogin(player); 274 } 275 276 public static void onPlayerLogout(EntityPlayer player) 277 { 278 for(IPlayerTracker tracker : playerTrackers) 279 tracker.onPlayerLogout(player); 280 } 281 282 public static void onPlayerChangedDimension(EntityPlayer player) 283 { 284 for(IPlayerTracker tracker : playerTrackers) 285 tracker.onPlayerChangedDimension(player); 286 } 287 288 public static void onPlayerRespawn(EntityPlayer player) 289 { 290 for(IPlayerTracker tracker : playerTrackers) 291 tracker.onPlayerRespawn(player); 292 } 293 }