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 a1967e5b7..50d09ab09 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 81df04300..230abe471 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 3f43f781d..763dffeaf 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 651e3d463..f3c36c124 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 000000000..eab39993e --- /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 98399ed32..f89dbbe84 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