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 */ 122 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) 123 { 124 for (IDispenserHandler handler : dispenserHandlers) 125 { 126 int dispensed = handler.dispense(x, y, z, xVelocity, zVelocity, world, item, random, entX, entY, entZ); 127 if (dispensed>-1) 128 { 129 return dispensed; 130 } 131 } 132 return -1; 133 } 134 /** 135 * Internal method for creating an @Block instance 136 * @param container 137 * @param type 138 * @param annotation 139 * @throws Exception 140 */ 141 public static Object buildBlock(ModContainer container, Class<?> type, Block annotation) throws Exception 142 { 143 Object o = type.getConstructor(int.class).newInstance(findSpareBlockId()); 144 registerBlock((net.minecraft.src.Block) o); 145 return o; 146 } 147 148 /** 149 * Private and not yet working properly 150 * 151 * @return 152 */ 153 private static int findSpareBlockId() 154 { 155 return BlockTracker.nextBlockId(); 156 } 157 158 /** 159 * Register a block with the world 160 * 161 */ 162 public static void registerBlock(net.minecraft.src.Block block) 163 { 164 registerBlock(block, ItemBlock.class); 165 } 166 167 /** 168 * Register a block with the world, with the specified item class 169 * 170 * @param block 171 * @param itemclass 172 */ 173 public static void registerBlock(net.minecraft.src.Block block, Class<? extends ItemBlock> itemclass) 174 { 175 if (Loader.instance().isInState(LoaderState.CONSTRUCTING)) 176 { 177 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()); 178 } 179 try 180 { 181 assert block != null : "registerBlock: block cannot be null"; 182 assert itemclass != null : "registerBlock: itemclass cannot be null"; 183 int blockItemId = block.blockID - 256; 184 itemclass.getConstructor(int.class).newInstance(blockItemId); 185 } 186 catch (Exception e) 187 { 188 FMLLog.log(Level.SEVERE, e, "Caught an exception during block registration"); 189 throw new LoaderException(e); 190 } 191 blockRegistry.put(Loader.instance().activeModContainer(), (BlockProxy) block); 192 } 193 194 public static void addRecipe(ItemStack output, Object... params) 195 { 196 CraftingManager.getInstance().addRecipe(output, params); 197 } 198 199 public static void addShapelessRecipe(ItemStack output, Object... params) 200 { 201 CraftingManager.getInstance().addShapelessRecipe(output, params); 202 } 203 204 public static void addRecipe(IRecipe recipe) 205 { 206 CraftingManager.getInstance().getRecipeList().add(recipe); 207 } 208 209 public static void addSmelting(int input, ItemStack output, float xp) 210 { 211 FurnaceRecipes.smelting().addSmelting(input, output, xp); 212 } 213 214 public static void registerTileEntity(Class<? extends TileEntity> tileEntityClass, String id) 215 { 216 TileEntity.addMapping(tileEntityClass, id); 217 } 218 219 public static void addBiome(BiomeGenBase biome) 220 { 221 WorldType.DEFAULT.addNewBiome(biome); 222 } 223 224 public static void removeBiome(BiomeGenBase biome) 225 { 226 WorldType.DEFAULT.removeBiome(biome); 227 } 228 229 public static void registerFuelHandler(IFuelHandler handler) 230 { 231 fuelHandlers.add(handler); 232 } 233 public static int getFuelValue(ItemStack itemStack) 234 { 235 int fuelValue = 0; 236 for (IFuelHandler handler : fuelHandlers) 237 { 238 fuelValue = Math.max(fuelValue, handler.getBurnTime(itemStack)); 239 } 240 return fuelValue; 241 } 242 243 public static void registerCraftingHandler(ICraftingHandler handler) 244 { 245 craftingHandlers.add(handler); 246 } 247 248 public static void onItemCrafted(EntityPlayer player, ItemStack item, IInventory craftMatrix) 249 { 250 for (ICraftingHandler handler : craftingHandlers) 251 { 252 handler.onCrafting(player, item, craftMatrix); 253 } 254 } 255 256 public static void onItemSmelted(EntityPlayer player, ItemStack item) 257 { 258 for (ICraftingHandler handler : craftingHandlers) 259 { 260 handler.onSmelting(player, item); 261 } 262 } 263 264 public static void registerPickupHandler(IPickupNotifier handler) 265 { 266 pickupHandlers.add(handler); 267 } 268 269 public static void onPickupNotification(EntityPlayer player, EntityItem item) 270 { 271 for (IPickupNotifier notify : pickupHandlers) 272 { 273 notify.notifyPickup(item, player); 274 } 275 } 276 277 public static void registerPlayerTracker(IPlayerTracker tracker) 278 { 279 playerTrackers.add(tracker); 280 } 281 282 public static void onPlayerLogin(EntityPlayer player) 283 { 284 for(IPlayerTracker tracker : playerTrackers) 285 tracker.onPlayerLogin(player); 286 } 287 288 public static void onPlayerLogout(EntityPlayer player) 289 { 290 for(IPlayerTracker tracker : playerTrackers) 291 tracker.onPlayerLogout(player); 292 } 293 294 public static void onPlayerChangedDimension(EntityPlayer player) 295 { 296 for(IPlayerTracker tracker : playerTrackers) 297 tracker.onPlayerChangedDimension(player); 298 } 299 300 public static void onPlayerRespawn(EntityPlayer player) 301 { 302 for(IPlayerTracker tracker : playerTrackers) 303 tracker.onPlayerRespawn(player); 304 } 305 }