From bc303074f6843ba13c8c71f936eb8fe3cd37c5df Mon Sep 17 00:00:00 2001 From: LexManos Date: Sat, 8 Oct 2016 16:30:53 -0700 Subject: [PATCH] Introduce IContextSetter for events. This will set the active mod container for events using the normal EventBus. Fixes improper warnings from initializing mods using the new Registry events. Modders, you should not use this as it has many performance implementations and if abused will slow down the event bus A LOT. ActiveModContainer is not thread safe. --- .../minecraftforge/event/RegistryEvent.java | 3 +- .../fml/common/AutomaticEventSubscriber.java | 19 ++++++ .../net/minecraftforge/fml/common/Loader.java | 5 ++ .../fml/common/eventhandler/EventBus.java | 23 ++++++- .../common/eventhandler/IContextSetter.java | 7 ++ .../debug/ForgeBlockStatesLoaderDebug.java | 66 +++++++++++-------- 6 files changed, 93 insertions(+), 30 deletions(-) create mode 100644 src/main/java/net/minecraftforge/fml/common/eventhandler/IContextSetter.java 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