    001    package cpw.mods.fml.common.registry;
    002
    003    import java.util.List;
    004    import java.util.Map;
    005    import java.util.Random;
    006    import java.util.Set;
    007    import java.util.concurrent.CountDownLatch;
    008    import java.util.logging.Level;
    009
    010    import net.minecraft.entity.item.EntityItem;
    011    import net.minecraft.entity.player.EntityPlayer;
    012    import net.minecraft.inventory.IInventory;
    013    import net.minecraft.item.Item;
    014    import net.minecraft.item.ItemBlock;
    015    import net.minecraft.item.ItemStack;
    016    import net.minecraft.item.crafting.CraftingManager;
    017    import net.minecraft.item.crafting.FurnaceRecipes;
    018    import net.minecraft.item.crafting.IRecipe;
    019    import net.minecraft.nbt.NBTTagCompound;
    020    import net.minecraft.nbt.NBTTagList;
    021    import net.minecraft.tileentity.TileEntity;
    022    import net.minecraft.world.World;
    023    import net.minecraft.world.WorldType;
    024    import net.minecraft.world.biome.BiomeGenBase;
    025    import net.minecraft.world.chunk.IChunkProvider;
    026
    027    import com.google.common.base.Function;
    028    import com.google.common.collect.ArrayListMultimap;
    029    import com.google.common.collect.Lists;
    030    import com.google.common.collect.MapDifference;
    031    import com.google.common.collect.Maps;
    032    import com.google.common.collect.Multimap;
    033    import com.google.common.collect.Multimaps;
    034    import com.google.common.collect.Sets;
    035    import com.google.common.collect.Sets.SetView;
    036
    037    import cpw.mods.fml.common.FMLLog;
    038    import cpw.mods.fml.common.ICraftingHandler;
    039    import cpw.mods.fml.common.IDispenseHandler;
    040    import cpw.mods.fml.common.IDispenserHandler;
    041    import cpw.mods.fml.common.IFuelHandler;
    042    import cpw.mods.fml.common.IPickupNotifier;
    043    import cpw.mods.fml.common.IPlayerTracker;
    044    import cpw.mods.fml.common.IWorldGenerator;
    045    import cpw.mods.fml.common.Loader;
    046    import cpw.mods.fml.common.LoaderException;
    047    import cpw.mods.fml.common.LoaderState;
    048    import cpw.mods.fml.common.Mod.Block;
    049    import cpw.mods.fml.common.ModContainer;
    050
    051    public class GameRegistry
    052    {
    053        private static Multimap<ModContainer, BlockProxy> blockRegistry = ArrayListMultimap.create();
    054        private static Set<IWorldGenerator> worldGenerators = Sets.newHashSet();
    055        private static List<IFuelHandler> fuelHandlers = Lists.newArrayList();
    056        private static List<ICraftingHandler> craftingHandlers = Lists.newArrayList();
    057        private static List<IPickupNotifier> pickupHandlers = Lists.newArrayList();
    058        private static List<IPlayerTracker> playerTrackers = Lists.newArrayList();
    059
    060        /**
    061         * Register a world generator - something that inserts new block types into the world
    062         *
    063         * @param generator
    064         */
    065        public static void registerWorldGenerator(IWorldGenerator generator)
    066        {
    067            worldGenerators.add(generator);
    068        }
    069
    070        /**
    071         * Callback hook for world gen - if your mod wishes to add extra mod related generation to the world
    072         * call this
    073         *
    074         * @param chunkX
    075         * @param chunkZ
    076         * @param world
    077         * @param chunkGenerator
    078         * @param chunkProvider
    079         */
    080        public static void generateWorld(int chunkX, int chunkZ, World world, IChunkProvider chunkGenerator, IChunkProvider chunkProvider)
    081        {
    082            long worldSeed = world.getSeed();
    083            Random fmlRandom = new Random(worldSeed);
    084            long xSeed = fmlRandom.nextLong() >> 2 + 1L;
    085            long zSeed = fmlRandom.nextLong() >> 2 + 1L;
    086            fmlRandom.setSeed((xSeed * chunkX + zSeed * chunkZ) ^ worldSeed);
    087
    088            for (IWorldGenerator generator : worldGenerators)
    089            {
    090                generator.generate(fmlRandom, chunkX, chunkZ, world, chunkGenerator, chunkProvider);
    091            }
    092        }
    093
    094        /**
    095         * Deprecated without replacement. Use vanilla DispenserRegistry code
    096         *
    097         * @param handler
    098         */
    099        @Deprecated
    100        public static void registerDispenserHandler(IDispenserHandler handler)
    101        {
    102        }
    103        /**
    104         * Deprecated without replacement. Use vanilla DispenserRegistry code
    105         *
    106         * @param handler
    107         */
    108        @Deprecated
    109        public static void registerDispenserHandler(final IDispenseHandler handler)
    110        {
    111        }
    112
    113
    114        /**
    115         *
    116         * Deprecated without replacement, use vanilla DispenserRegistry code
    117         *
    118         * @param world
    119         * @param x
    120         * @param y
    121         * @param z
    122         * @param xVelocity
    123         * @param zVelocity
    124         * @param item
    125         */
    126        @Deprecated
    127        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)
    128        {
    129            return -1;
    130        }
    131        /**
    132         * Internal method for creating an @Block instance
    133         * @param container
    134         * @param type
    135         * @param annotation
    136         * @throws Exception
    137         */
    138        public static Object buildBlock(ModContainer container, Class<?> type, Block annotation) throws Exception
    139        {
    140            Object o = type.getConstructor(int.class).newInstance(findSpareBlockId());
    141            registerBlock((net.minecraft.block.Block) o);
    142            return o;
    143        }
    144
    145        /**
    146         * Private and not yet working properly
    147         *
    148         * @return
    149         */
    150        private static int findSpareBlockId()
    151        {
    152            return BlockTracker.nextBlockId();
    153        }
    154
    155        /**
    156         * Register an item with the item registry with a custom name : this allows for easier server->client resolution
    157         *
    158         * @param item The item to register
    159         * @param name The mod-unique name of the item
    160         */
    161        public static void registerItem(net.minecraft.item.Item item, String name)
    162        {
    163            registerItem(item, name, null);
    164        }
    165
    166        /**
    167         * Register the specified Item with a mod specific name : overrides the standard type based name
    168         * @param item The item to register
    169         * @param name The mod-unique name to register it as - null will remove a custom name
    170         * @param modId An optional modId that will "own" this block - generally used by multi-mod systems
    171         * where one mod should "own" all the blocks of all the mods, null defaults to the active mod
    172         */
    173        public static void registerItem(net.minecraft.item.Item item, String name, String modId)
    174        {
    175            GameData.setName(item, name, modId);
    176        }
    177
    178        /**
    179         * Register a block with the world
    180         *
    181         */
    182        @Deprecated
    183        public static void registerBlock(net.minecraft.block.Block block)
    184        {
    185            registerBlock(block, ItemBlock.class);
    186        }
    187
    188
    189        /**
    190         * Register a block with the specified mod specific name : overrides the standard type based name
    191         * @param block The block to register
    192         * @param name The mod-unique name to register it as
    193         */
    194        public static void registerBlock(net.minecraft.block.Block block, String name)
    195        {
    196            registerBlock(block, ItemBlock.class, name);
    197        }
    198
    199        /**
    200         * Register a block with the world, with the specified item class
    201         *
    202         * Deprecated in favour of named versions
    203         *
    204         * @param block The block to register
    205         * @param itemclass The item type to register with it
    206         */
    207        @Deprecated
    208        public static void registerBlock(net.minecraft.block.Block block, Class<? extends ItemBlock> itemclass)
    209        {
    210            registerBlock(block, itemclass, null);
    211        }
    212        /**
    213         * Register a block with the world, with the specified item class and block name
    214         * @param block The block to register
    215         * @param itemclass The item type to register with it
    216         * @param name The mod-unique name to register it with
    217         */
    218        public static void registerBlock(net.minecraft.block.Block block, Class<? extends ItemBlock> itemclass, String name)
    219        {
    220            registerBlock(block, itemclass, name, null);
    221        }
    222        /**
    223         * Register a block with the world, with the specified item class, block name and owning modId
    224         * @param block The block to register
    225         * @param itemclass The iterm type to register with it
    226         * @param name The mod-unique name to register it with
    227         * @param modId The modId that will own the block name. null defaults to the active modId
    228         */
    229        public static void registerBlock(net.minecraft.block.Block block, Class<? extends ItemBlock> itemclass, String name, String modId)
    230        {
    231            if (Loader.instance().isInState(LoaderState.CONSTRUCTING))
    232            {
    233                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());
    234            }
    235            try
    236            {
    237                assert block != null : "registerBlock: block cannot be null";
    238                assert itemclass != null : "registerBlock: itemclass cannot be null";
    239                int blockItemId = block.blockID - 256;
    240                Item i = itemclass.getConstructor(int.class).newInstance(blockItemId);
    241                GameRegistry.registerItem(i,name, modId);
    242            }
    243            catch (Exception e)
    244            {
    245                FMLLog.log(Level.SEVERE, e, "Caught an exception during block registration");
    246                throw new LoaderException(e);
    247            }
    248            blockRegistry.put(Loader.instance().activeModContainer(), (BlockProxy) block);
    249        }
    250
    251        public static void addRecipe(ItemStack output, Object... params)
    252        {
    253            CraftingManager.getInstance().addRecipe(output, params);
    254        }
    255
    256        public static void addShapelessRecipe(ItemStack output, Object... params)
    257        {
    258            CraftingManager.getInstance().addShapelessRecipe(output, params);
    259        }
    260
    261        public static void addRecipe(IRecipe recipe)
    262        {
    263            CraftingManager.getInstance().getRecipeList().add(recipe);
    264        }
    265
    266        public static void addSmelting(int input, ItemStack output, float xp)
    267        {
    268            FurnaceRecipes.smelting().addSmelting(input, output, xp);
    269        }
    270
    271        public static void registerTileEntity(Class<? extends TileEntity> tileEntityClass, String id)
    272        {
    273            TileEntity.addMapping(tileEntityClass, id);
    274        }
    275
    276        public static void addBiome(BiomeGenBase biome)
    277        {
    278            WorldType.DEFAULT.addNewBiome(biome);
    279        }
    280
    281        public static void removeBiome(BiomeGenBase biome)
    282        {
    283            WorldType.DEFAULT.removeBiome(biome);
    284        }
    285
    286        public static void registerFuelHandler(IFuelHandler handler)
    287        {
    288            fuelHandlers.add(handler);
    289        }
    290        public static int getFuelValue(ItemStack itemStack)
    291        {
    292            int fuelValue = 0;
    293            for (IFuelHandler handler : fuelHandlers)
    294            {
    295                fuelValue = Math.max(fuelValue, handler.getBurnTime(itemStack));
    296            }
    297            return fuelValue;
    298        }
    299
    300        public static void registerCraftingHandler(ICraftingHandler handler)
    301        {
    302            craftingHandlers.add(handler);
    303        }
    304
    305        public static void onItemCrafted(EntityPlayer player, ItemStack item, IInventory craftMatrix)
    306        {
    307            for (ICraftingHandler handler : craftingHandlers)
    308            {
    309                handler.onCrafting(player, item, craftMatrix);
    310            }
    311        }
    312
    313        public static void onItemSmelted(EntityPlayer player, ItemStack item)
    314        {
    315            for (ICraftingHandler handler : craftingHandlers)
    316            {
    317                handler.onSmelting(player, item);
    318            }
    319        }
    320
    321        public static void registerPickupHandler(IPickupNotifier handler)
    322        {
    323            pickupHandlers.add(handler);
    324        }
    325
    326        public static void onPickupNotification(EntityPlayer player, EntityItem item)
    327        {
    328            for (IPickupNotifier notify : pickupHandlers)
    329            {
    330                notify.notifyPickup(item, player);
    331            }
    332        }
    333
    334        public static void registerPlayerTracker(IPlayerTracker tracker)
    335        {
    336            playerTrackers.add(tracker);
    337        }
    338
    339        public static void onPlayerLogin(EntityPlayer player)
    340        {
    341            for(IPlayerTracker tracker : playerTrackers)
    342                tracker.onPlayerLogin(player);
    343        }
    344
    345        public static void onPlayerLogout(EntityPlayer player)
    346        {
    347            for(IPlayerTracker tracker : playerTrackers)
    348                tracker.onPlayerLogout(player);
    349        }
    350
    351        public static void onPlayerChangedDimension(EntityPlayer player)
    352        {
    353            for(IPlayerTracker tracker : playerTrackers)
    354                tracker.onPlayerChangedDimension(player);
    355        }
    356
    357        public static void onPlayerRespawn(EntityPlayer player)
    358        {
    359            for(IPlayerTracker tracker : playerTrackers)
    360                tracker.onPlayerRespawn(player);
    361        }
    362
    363    }