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    }