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.
This commit is contained in:
LexManos committed 2016-10-08 16:30:53 -07:00
1 parent c0db34796b
commit bc303074f6
6 files changed
+93 -30

No files matched your search

@@ -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<T extends IForgeRegistryEntry<T>> extends GenericEvent<T>
public class RegistryEvent<T extends IForgeRegistryEntry<T>> extends GenericEvent<T> implements IContextSetter
{
RegistryEvent(Class<T> clazz) {
super(clazz);
@@ -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<ModAnnotation.EnumHolder> sidesEnum = (List<ModAnnotation.EnumHolder>)targ.getAnnotationInfo().get("value");
EnumSet<Side> sides = DEFAULT;
@@ -1144,4 +1144,9 @@ public class Loader
{
return modController != null ? modController.getState() : LoaderState.NOINIT;
}
public void setActiveModContainer(ModContainer container)
{
this.modController.forceActiveContainer(container);
}
}
@@ -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<IEventListener> others = listeners.get(target);
if (others == null)
@@ -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 {}