diff --git a/src/main/java/net/minecraftforge/event/RegistryEvent.java b/src/main/java/net/minecraftforge/event/RegistryEvent.java index a1967e5b7d..50d09ab092 100644 --- a/src/main/java/net/minecraftforge/event/RegistryEvent.java +++ b/src/main/java/net/minecraftforge/event/RegistryEvent.java @@ -22,6 +22,7 @@ package net.minecraftforge.event; import net.minecraft.util.ResourceLocation; import net.minecraftforge.fml.common.eventhandler.Event; import net.minecraftforge.fml.common.eventhandler.GenericEvent; +import net.minecraftforge.fml.common.eventhandler.IContextSetter; import net.minecraftforge.fml.common.registry.IForgeRegistry; import net.minecraftforge.fml.common.registry.IForgeRegistryEntry; import net.minecraftforge.fml.common.registry.PersistentRegistryManager; @@ -30,7 +31,7 @@ import net.minecraftforge.fml.common.registry.PersistentRegistryManager; /** * RegistryEvent supertype. */ -public class RegistryEvent> extends GenericEvent +public class RegistryEvent> extends GenericEvent implements IContextSetter { RegistryEvent(Class clazz) { super(clazz); diff --git a/src/main/java/net/minecraftforge/fml/common/AutomaticEventSubscriber.java b/src/main/java/net/minecraftforge/fml/common/AutomaticEventSubscriber.java index 81df043008..230abe471b 100644 --- a/src/main/java/net/minecraftforge/fml/common/AutomaticEventSubscriber.java +++ b/src/main/java/net/minecraftforge/fml/common/AutomaticEventSubscriber.java @@ -22,6 +22,7 @@ package net.minecraftforge.fml.common; import com.google.common.base.Strings; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fml.common.discovery.ASMDataTable; +import net.minecraftforge.fml.common.discovery.ASMDataTable.ASMData; import net.minecraftforge.fml.common.discovery.asm.ModAnnotation; import net.minecraftforge.fml.relauncher.Side; import org.apache.logging.log4j.Level; @@ -50,6 +51,24 @@ public class AutomaticEventSubscriber { try { + //Filter out handlers for things that arnt this mod. + //Perhaps find a way to make this more generic for multiple mods + //from the same source.... + boolean register = true; + for (ASMData a : data.getAll(Mod.class.getName())) + { + if (a.getClassName().equals(targ.getClassName())) + { + if (!mod.getModId().equals(a.getAnnotationInfo().get("modid"))) + { + register = false; + break; + } + } + } + if (!register) + continue; + //noinspection unchecked List sidesEnum = (List)targ.getAnnotationInfo().get("value"); EnumSet sides = DEFAULT; diff --git a/src/main/java/net/minecraftforge/fml/common/Loader.java b/src/main/java/net/minecraftforge/fml/common/Loader.java index 3f43f781d7..763dffeaf5 100644 --- a/src/main/java/net/minecraftforge/fml/common/Loader.java +++ b/src/main/java/net/minecraftforge/fml/common/Loader.java @@ -1144,4 +1144,9 @@ public class Loader { return modController != null ? modController.getState() : LoaderState.NOINIT; } + + public void setActiveModContainer(ModContainer container) + { + this.modController.forceActiveContainer(container); + } } diff --git a/src/main/java/net/minecraftforge/fml/common/eventhandler/EventBus.java b/src/main/java/net/minecraftforge/fml/common/eventhandler/EventBus.java index 651e3d4637..f3c36c1244 100644 --- a/src/main/java/net/minecraftforge/fml/common/eventhandler/EventBus.java +++ b/src/main/java/net/minecraftforge/fml/common/eventhandler/EventBus.java @@ -122,15 +122,32 @@ public class EventBus implements IEventExceptionHandler } } - private void register(Class eventType, Object target, Method method, ModContainer owner) + private void register(Class eventType, Object target, Method method, final ModContainer owner) { try { Constructor ctr = eventType.getConstructor(); ctr.setAccessible(true); Event event = (Event)ctr.newInstance(); - ASMEventHandler listener = new ASMEventHandler(target, method, owner, IGenericEvent.class.isAssignableFrom(eventType)); - event.getListenerList().register(busID, listener.getPriority(), listener); + final ASMEventHandler asm = new ASMEventHandler(target, method, owner, IGenericEvent.class.isAssignableFrom(eventType)); + + IEventListener listener = asm; + if (IContextSetter.class.isAssignableFrom(eventType)) + { + listener = new IEventListener() + { + @Override + public void invoke(Event event) + { + ModContainer old = Loader.instance().activeModContainer(); + Loader.instance().setActiveModContainer(owner); + asm.invoke(event); + Loader.instance().setActiveModContainer(old); + } + }; + } + + event.getListenerList().register(busID, asm.getPriority(), listener); ArrayList others = listeners.get(target); if (others == null) diff --git a/src/main/java/net/minecraftforge/fml/common/eventhandler/IContextSetter.java b/src/main/java/net/minecraftforge/fml/common/eventhandler/IContextSetter.java new file mode 100644 index 0000000000..eab39993ed --- /dev/null +++ b/src/main/java/net/minecraftforge/fml/common/eventhandler/IContextSetter.java @@ -0,0 +1,7 @@ +package net.minecraftforge.fml.common.eventhandler; + +//Instructs event handlers to set the active mod container. +//This has a major performance impact so use sparingly. +//Note: The context IS NOT thread aware as this would be ungodly slow. +//So This should ONLY be used for Forge mod lifecycle events. +public interface IContextSetter {} diff --git a/src/test/java/net/minecraftforge/debug/ForgeBlockStatesLoaderDebug.java b/src/test/java/net/minecraftforge/debug/ForgeBlockStatesLoaderDebug.java index 98399ed326..f89dbbe84c 100644 --- a/src/test/java/net/minecraftforge/debug/ForgeBlockStatesLoaderDebug.java +++ b/src/test/java/net/minecraftforge/debug/ForgeBlockStatesLoaderDebug.java @@ -5,25 +5,21 @@ import java.util.Map.Entry; import net.minecraft.block.Block; import net.minecraft.block.BlockWall; -import net.minecraft.block.material.Material; -import net.minecraft.block.properties.PropertyEnum; -import net.minecraft.block.state.BlockStateContainer; import net.minecraft.block.state.IBlockState; import net.minecraft.client.renderer.block.statemap.IStateMapper; import net.minecraft.client.renderer.block.statemap.StateMap; import net.minecraft.client.renderer.block.model.ModelResourceLocation; import net.minecraft.init.Blocks; import net.minecraft.item.Item; -import net.minecraft.item.ItemBlock; import net.minecraft.item.ItemMultiTexture; import net.minecraft.item.ItemStack; -import net.minecraft.util.IStringSerializable; import net.minecraftforge.client.model.ModelLoader; +import net.minecraftforge.event.RegistryEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod.EventHandler; import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; -import net.minecraftforge.fml.common.registry.GameData; -import net.minecraftforge.fml.common.registry.GameRegistry; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.registry.GameRegistry.ObjectHolder; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; @@ -31,21 +27,45 @@ import com.google.common.base.Function; import com.google.common.collect.Maps; @Mod(modid = ForgeBlockStatesLoaderDebug.MODID, name = "ForgeBlockStatesLoader", version = "1.0") +@Mod.EventBusSubscriber public class ForgeBlockStatesLoaderDebug { public static final String MODID = "forgeblockstatesloader"; public static final String ASSETS = "forgeblockstatesloader:"; - //public static final Block blockCustom = new CustomMappedBlock(); - public static final String nameCustomWall = "custom_wall"; - public static final BlockWall blockCustomWall = new BlockWall(Blocks.COBBLESTONE); - public static final ItemMultiTexture itemCustomWall = (ItemMultiTexture)new ItemMultiTexture(blockCustomWall, blockCustomWall, new Function() + @ObjectHolder(MODID) + public static class BLOCKS { + public static final BlockWall custom_wall = null; + } + + @ObjectHolder(MODID) + public static class ITEMS { + public static final ItemMultiTexture custom_wall = null; + } + + @SubscribeEvent + public static void registerBlocks(RegistryEvent.Register event) { - @Override - public String apply(ItemStack stack) - { - return BlockWall.EnumType.byMetadata(stack.getMetadata()).getUnlocalizedName(); - } - }).setRegistryName(nameCustomWall); + event.getRegistry().registerAll( + new BlockWall(Blocks.COBBLESTONE).setUnlocalizedName(MODID + ".customWall").setRegistryName(MODID, "custom_wall") + ); + } + + @SubscribeEvent + public static void registerItems(RegistryEvent.Register event) + { + event.getRegistry().registerAll( + new ItemMultiTexture(BLOCKS.custom_wall, BLOCKS.custom_wall, new Function() + { + @Override + public String apply(ItemStack stack) + { + return BlockWall.EnumType.byMetadata(stack.getMetadata()).getUnlocalizedName(); + } + }).setRegistryName(BLOCKS.custom_wall.getRegistryName()) + ); + } + + //public static final Block blockCustom = new CustomMappedBlock(); @EventHandler public void preInit(FMLPreInitializationEvent event) @@ -53,11 +73,6 @@ public class ForgeBlockStatesLoaderDebug { //blockCustom.setUnlocalizedName(MODID + ".customBlock").setRegistryName("customBlock"); //GameRegistry.registerBlock(blockCustom); - blockCustomWall.setUnlocalizedName(MODID + ".customWall").setRegistryName(nameCustomWall); - GameRegistry.register(blockCustomWall); - GameRegistry.register(itemCustomWall); - GameData.getBlockItemMap().put(blockCustomWall, itemCustomWall); - if (event.getSide() == Side.CLIENT) preInitClient(event); } @@ -67,7 +82,7 @@ public class ForgeBlockStatesLoaderDebug { { //ModelLoader.setCustomStateMapper(blockCustom, new StateMap.Builder().withName(CustomMappedBlock.VARIANT).build()); - ModelLoader.setCustomStateMapper(blockCustomWall, new IStateMapper() + ModelLoader.setCustomStateMapper(BLOCKS.custom_wall, new IStateMapper() { StateMap stateMap = new StateMap.Builder().withName(BlockWall.VARIANT).withSuffix("_wall").build(); @Override @@ -85,9 +100,8 @@ public class ForgeBlockStatesLoaderDebug { return newMap; } }); - Item customWallItem = Item.getItemFromBlock(blockCustomWall); - ModelLoader.setCustomModelResourceLocation(customWallItem, 0, new ModelResourceLocation(ASSETS + "cobblestone_wall", "inventory")); - ModelLoader.setCustomModelResourceLocation(customWallItem, 1, new ModelResourceLocation(ASSETS + "mossy_cobblestone_wall", "inventory")); + ModelLoader.setCustomModelResourceLocation(ITEMS.custom_wall, 0, new ModelResourceLocation(ASSETS + "cobblestone_wall", "inventory")); + ModelLoader.setCustomModelResourceLocation(ITEMS.custom_wall, 1, new ModelResourceLocation(ASSETS + "mossy_cobblestone_wall", "inventory")); } // this block is never actually used, it's only needed for the error message on load to see the variant it maps to