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 }