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