Move Registry Events to the mod event bus.

Add infrastructure to allow parallel or synchronous dispatch of
mod events, and pass-through of events to the dispatch system.

Signed-off-by: cpw <cpw+github@weeksfamily.ca>
This commit is contained in:
cpw 2019-01-19 23:26:25 -05:00
parent ff2e35c243
commit f4d2d1a24b
No known key found for this signature in database
GPG key ID: 8EB3DF749553B1B7
9 changed files with 162 additions and 88 deletions

View file

@ -260,7 +260,7 @@ project(':forge') {
installer 'org.ow2.asm:asm-tree:6.2' installer 'org.ow2.asm:asm-tree:6.2'
installer 'cpw.mods:modlauncher:0.6.0' installer 'cpw.mods:modlauncher:0.6.0'
installer 'net.minecraftforge:accesstransformers:0.14.+:shadowed' installer 'net.minecraftforge:accesstransformers:0.14.+:shadowed'
installer 'net.minecraftforge:eventbus:0.3.+:service' installer 'net.minecraftforge:eventbus:0.6.+:service'
installer 'net.minecraftforge:forgespi:0.2.+' installer 'net.minecraftforge:forgespi:0.2.+'
installer 'net.minecraftforge:coremods:0.2.+' installer 'net.minecraftforge:coremods:0.2.+'
installer 'com.electronwill.night-config:core:3.4.2' installer 'com.electronwill.night-config:core:3.4.2'

View file

@ -39,7 +39,8 @@ import static net.minecraftforge.fml.Logging.LOADING;
/** /**
* Automatic eventbus subscriber - reads {@link net.minecraftforge.fml.common.Mod.EventBusSubscriber} * Automatic eventbus subscriber - reads {@link net.minecraftforge.fml.common.Mod.EventBusSubscriber}
* annotations and passes the class instances to the {@link net.minecraftforge.common.MinecraftForge.EVENT_BUS} * annotations and passes the class instances to the {@link net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus}
* defined by the annotation. Defaults to {@link MinecraftForge#EVENT_BUS}
*/ */
public class AutomaticEventSubscriber public class AutomaticEventSubscriber
{ {
@ -60,10 +61,11 @@ public class AutomaticEventSubscriber
final EnumSet<Dist> sides = sidesValue.stream().map(eh -> Dist.valueOf(eh.getValue())). final EnumSet<Dist> sides = sidesValue.stream().map(eh -> Dist.valueOf(eh.getValue())).
collect(Collectors.toCollection(() -> EnumSet.noneOf(Dist.class))); collect(Collectors.toCollection(() -> EnumSet.noneOf(Dist.class)));
final String modId = (String)ad.getAnnotationData().getOrDefault("modId", mod.getModId()); final String modId = (String)ad.getAnnotationData().getOrDefault("modId", mod.getModId());
final Mod.EventBusSubscriber.Bus busTarget = (Mod.EventBusSubscriber.Bus)ad.getAnnotationData().getOrDefault("bus", Mod.EventBusSubscriber.Bus.FORGE);
if (Objects.equals(mod.getModId(), modId) && sides.contains(FMLEnvironment.dist)) { if (Objects.equals(mod.getModId(), modId) && sides.contains(FMLEnvironment.dist)) {
try try
{ {
MinecraftForge.EVENT_BUS.register(Class.forName(ad.getClassType().getClassName(), true, loader)); busTarget.bus().get().register(Class.forName(ad.getClassType().getClassName(), true, loader));
} }
catch (ClassNotFoundException e) catch (ClassNotFoundException e)
{ {

View file

@ -19,40 +19,72 @@
package net.minecraftforge.fml; package net.minecraftforge.fml;
import net.minecraftforge.eventbus.api.Event;
import net.minecraftforge.fml.event.lifecycle.ModLifecycleEvent; import net.minecraftforge.fml.event.lifecycle.ModLifecycleEvent;
import net.minecraftforge.fml.javafmlmod.FMLModContainer; import net.minecraftforge.fml.javafmlmod.FMLModContainer;
import net.minecraftforge.forgespi.language.ILifecycleEvent; import net.minecraftforge.forgespi.language.ILifecycleEvent;
import java.util.List; import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier; import java.util.function.Supplier;
public enum LifecycleEventProvider public enum LifecycleEventProvider
{ {
CONSTRUCT(()->new LifecycleEvent(ModLoadingStage.CONSTRUCT)), CONSTRUCT(()->new LifecycleEvent(ModLoadingStage.CONSTRUCT)),
CREATE_REGISTRIES(()->new LifecycleEvent(ModLoadingStage.CREATE_REGISTRIES), ModList.inlineDispatcher),
LOAD_REGISTRIES(()->new LifecycleEvent(ModLoadingStage.LOAD_REGISTRIES, LifecycleEvent.Progression.STAY), ModList.inlineDispatcher),
SETUP(()->new LifecycleEvent(ModLoadingStage.COMMON_SETUP)), SETUP(()->new LifecycleEvent(ModLoadingStage.COMMON_SETUP)),
SIDED_SETUP(()->new LifecycleEvent(ModLoadingStage.SIDED_SETUP)), SIDED_SETUP(()->new LifecycleEvent(ModLoadingStage.SIDED_SETUP)),
ENQUEUE_IMC(()->new LifecycleEvent(ModLoadingStage.ENQUEUE_IMC)), ENQUEUE_IMC(()->new LifecycleEvent(ModLoadingStage.ENQUEUE_IMC)),
PROCESS_IMC(()->new LifecycleEvent(ModLoadingStage.PROCESS_IMC)), PROCESS_IMC(()->new LifecycleEvent(ModLoadingStage.PROCESS_IMC)),
COMPLETE(()->new LifecycleEvent(ModLoadingStage.COMPLETE)); COMPLETE(()->new LifecycleEvent(ModLoadingStage.COMPLETE));
public void dispatch(Consumer<List<ModLoadingException>> errorHandler) {
ModList.get().dispatchLifeCycleEvent(this.event.get(), errorHandler);
}
private final Supplier<? extends LifecycleEvent> event; private final Supplier<? extends LifecycleEvent> event;
private final BiConsumer<LifecycleEvent, Consumer<List<ModLoadingException>>> eventDispatcher;
private Supplier<Event> customEventSupplier;
private LifecycleEvent.Progression progression = LifecycleEvent.Progression.NEXT;
LifecycleEventProvider(Supplier<? extends LifecycleEvent> e) LifecycleEventProvider(Supplier<? extends LifecycleEvent> e)
{ {
event = e; this(e, ModList.parallelDispatcher);
}
LifecycleEventProvider(Supplier<? extends LifecycleEvent> e, BiConsumer<LifecycleEvent, Consumer<List<ModLoadingException>>> eventDispatcher)
{
this.event = e;
this.eventDispatcher = eventDispatcher;
}
public void setCustomEventSupplier(Supplier<Event> eventSupplier) {
this.customEventSupplier = eventSupplier;
}
public void changeProgression(LifecycleEvent.Progression progression) {
this.progression = progression;
}
public void dispatch(Consumer<List<ModLoadingException>> errorHandler) {
final LifecycleEvent lifecycleEvent = this.event.get();
lifecycleEvent.setCustomEventSupplier(this.customEventSupplier);
lifecycleEvent.changeProgression(this.progression);
this.eventDispatcher.accept(lifecycleEvent, errorHandler);
} }
public static class LifecycleEvent implements ILifecycleEvent<LifecycleEvent> { public static class LifecycleEvent implements ILifecycleEvent<LifecycleEvent> {
private final ModLoadingStage stage; private final ModLoadingStage stage;
private Supplier<Event> customEventSupplier;
public LifecycleEvent(ModLoadingStage stage) private Progression progression;
LifecycleEvent(final ModLoadingStage stage)
{ {
this(stage, Progression.NEXT);
}
LifecycleEvent(final ModLoadingStage stage, final Progression progression) {
this.stage = stage; this.stage = stage;
this.progression = progression;
} }
public ModLoadingStage fromStage() public ModLoadingStage fromStage()
@ -62,12 +94,42 @@ public enum LifecycleEventProvider
public ModLoadingStage toStage() public ModLoadingStage toStage()
{ {
return ModLoadingStage.values()[this.stage.ordinal()+1]; return progression.apply(this.stage);
} }
public ModLifecycleEvent buildModEvent(FMLModContainer fmlModContainer) public void setCustomEventSupplier(Supplier<Event> customEventSupplier) {
this.customEventSupplier = customEventSupplier;
}
public void changeProgression(Progression p) {
this.progression = p;
}
public Event getOrBuildEvent(FMLModContainer fmlModContainer)
{ {
if (customEventSupplier!=null) return customEventSupplier.get();
return stage.getModEvent(fmlModContainer); return stage.getModEvent(fmlModContainer);
} }
@Override
public String toString() {
return "LifecycleEvent:"+stage;
}
public enum Progression {
NEXT((current)-> ModLoadingStage.values()[current.ordinal()+1]),
STAY(Function.identity());
private final Function<ModLoadingStage, ModLoadingStage> edge;
Progression(Function<ModLoadingStage, ModLoadingStage> edge) {
this.edge = edge;
}
public ModLoadingStage apply(ModLoadingStage in) {
return this.edge.apply(in);
}
}
} }
} }

View file

@ -35,6 +35,7 @@ import java.util.Optional;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool; import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.FutureTask; import java.util.concurrent.FutureTask;
import java.util.function.BiConsumer;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -74,6 +75,10 @@ public class ModList
return INSTANCE; return INSTANCE;
} }
static BiConsumer<LifecycleEventProvider.LifecycleEvent, Consumer<List<ModLoadingException>>> inlineDispatcher = (event, errors) -> ModList.get().dispatchSynchronousEvent(event, errors);
static BiConsumer<LifecycleEventProvider.LifecycleEvent, Consumer<List<ModLoadingException>>> parallelDispatcher = (event, errors) -> ModList.get().dispatchParallelEvent(event, errors);
public static ModList get() { public static ModList get() {
return INSTANCE; return INSTANCE;
} }
@ -83,13 +88,19 @@ public class ModList
return modFiles; return modFiles;
} }
public ModFileInfo getModFileById(String modid) public ModFileInfo getModFileById(String modid)
{ {
return this.fileById.get(modid); return this.fileById.get(modid);
} }
public void dispatchLifeCycleEvent(LifecycleEventProvider.LifecycleEvent lifecycleEvent, final Consumer<List<ModLoadingException>> errorHandler) { private void dispatchSynchronousEvent(LifecycleEventProvider.LifecycleEvent lifecycleEvent, final Consumer<List<ModLoadingException>> errorHandler) {
LOGGER.info(LOADING, "Dispatching synchronous event {}", lifecycleEvent);
FMLLoader.getLanguageLoadingProvider().forEach(lp->lp.consumeLifecycleEvent(()->lifecycleEvent));
this.mods.forEach(m->m.transitionState(lifecycleEvent, errorHandler));
FMLLoader.getLanguageLoadingProvider().forEach(lp->lp.consumeLifecycleEvent(()->lifecycleEvent));
}
private void dispatchParallelEvent(LifecycleEventProvider.LifecycleEvent lifecycleEvent, final Consumer<List<ModLoadingException>> errorHandler) {
LOGGER.info(LOADING, "Dispatching parallel event {}", lifecycleEvent);
FMLLoader.getLanguageLoadingProvider().forEach(lp->lp.consumeLifecycleEvent(()->lifecycleEvent)); FMLLoader.getLanguageLoadingProvider().forEach(lp->lp.consumeLifecycleEvent(()->lifecycleEvent));
DeferredWorkQueue.clear(); DeferredWorkQueue.clear();
try try
@ -104,7 +115,7 @@ public class ModList
FMLLoader.getLanguageLoadingProvider().forEach(lp->lp.consumeLifecycleEvent(()->lifecycleEvent)); FMLLoader.getLanguageLoadingProvider().forEach(lp->lp.consumeLifecycleEvent(()->lifecycleEvent));
} }
public void setLoadedMods(final List<ModContainer> modContainers) void setLoadedMods(final List<ModContainer> modContainers)
{ {
this.mods = modContainers; this.mods = modContainers;
this.indexedMods = modContainers.stream().collect(Collectors.toMap(ModContainer::getModId, Function.identity())); this.indexedMods = modContainers.stream().collect(Collectors.toMap(ModContainer::getModId, Function.identity()));

View file

@ -123,10 +123,10 @@ public class ModLoader
} }
modList.setLoadedMods(modContainerStream.collect(Collectors.toList())); modList.setLoadedMods(modContainerStream.collect(Collectors.toList()));
dispatchAndHandleError(LifecycleEventProvider.CONSTRUCT); dispatchAndHandleError(LifecycleEventProvider.CONSTRUCT);
GameData.fireCreateRegistryEvents(); GameData.fireCreateRegistryEvents(LifecycleEventProvider.CREATE_REGISTRIES, this::dispatchAndHandleError);
ObjectHolderRegistry.findObjectHolders(); ObjectHolderRegistry.findObjectHolders();
CapabilityManager.INSTANCE.injectCapabilities(modList.getAllScanData()); CapabilityManager.INSTANCE.injectCapabilities(modList.getAllScanData());
GameData.fireRegistryEvents(); GameData.fireRegistryEvents(rl->true, LifecycleEventProvider.LOAD_REGISTRIES, this::dispatchAndHandleError);
dispatchAndHandleError(LifecycleEventProvider.SETUP); dispatchAndHandleError(LifecycleEventProvider.SETUP);
DistExecutor.runWhenOn(Dist.CLIENT, ModLoader::fireClientEvents); DistExecutor.runWhenOn(Dist.CLIENT, ModLoader::fireClientEvents);
dispatchAndHandleError(LifecycleEventProvider.SIDED_SETUP); dispatchAndHandleError(LifecycleEventProvider.SIDED_SETUP);

View file

@ -29,13 +29,14 @@ public enum ModLoadingStage
ERROR(null), ERROR(null),
VALIDATE(null), VALIDATE(null),
CONSTRUCT(null), CONSTRUCT(null),
CREATE_REGISTRIES(null),
LOAD_REGISTRIES(null),
COMMON_SETUP(()-> FMLCommonSetupEvent::new), COMMON_SETUP(()-> FMLCommonSetupEvent::new),
SIDED_SETUP(SidedProvider.SIDED_SETUP_EVENT::get), SIDED_SETUP(SidedProvider.SIDED_SETUP_EVENT::get),
ENQUEUE_IMC(()-> InterModEnqueueEvent::new), ENQUEUE_IMC(()-> InterModEnqueueEvent::new),
PROCESS_IMC(()-> InterModProcessEvent::new), PROCESS_IMC(()-> InterModProcessEvent::new),
COMPLETE(()-> FMLLoadCompleteEvent::new), COMPLETE(()-> FMLLoadCompleteEvent::new),
DONE(null); DONE(null);
private final Supplier<Function<ModContainer, ModLifecycleEvent>> modLifecycleEventFunction; private final Supplier<Function<ModContainer, ModLifecycleEvent>> modLifecycleEventFunction;
ModLoadingStage(Supplier<Function<ModContainer, ModLifecycleEvent>> modLifecycleEventFunction) ModLoadingStage(Supplier<Function<ModContainer, ModLifecycleEvent>> modLifecycleEventFunction)

View file

@ -23,26 +23,19 @@ import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import java.util.function.Supplier;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.fml.event.lifecycle.FMLFingerprintViolationEvent; import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.event.lifecycle.InterModProcessEvent; import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.event.server.FMLServerAboutToStartEvent;
import net.minecraftforge.fml.event.server.FMLServerStartedEvent;
import net.minecraftforge.fml.event.server.FMLServerStartingEvent;
import net.minecraftforge.fml.event.server.FMLServerStoppedEvent;
import net.minecraftforge.fml.event.server.FMLServerStoppingEvent;
import net.minecraftforge.fml.event.lifecycle.ModLifecycleEvent; import net.minecraftforge.fml.event.lifecycle.ModLifecycleEvent;
import net.minecraftforge.fml.event.lifecycle.InterModEnqueueEvent; import net.minecraftforge.fml.javafmlmod.FMLModLoadingContext;
import net.minecraftforge.fml.common.registry.GameRegistry;
/** /**
* This defines a Mod to FML. * This defines a Mod to FML.
* Any class found with this annotation applied will be loaded as a Mod. The instance that is loaded will * Any class found with this annotation applied will be loaded as a Mod. The instance that is loaded will
* represent the mod to other Mods in the system. It will be sent various subclasses of {@link ModLifecycleEvent} * represent the mod to other Mods in the system. It will be sent various subclasses of {@link ModLifecycleEvent}
* at pre-defined times during the loading of the game, based on where you have applied the {@link EventHandler} * at pre-defined times during the loading of the game.
* annotation.
*/ */
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE) @Target(ElementType.TYPE)
@ -56,63 +49,60 @@ public @interface Mod
* By default, you will have a resource domain that matches the modid. All these uses require that constraints are imposed on the format of the modid. * By default, you will have a resource domain that matches the modid. All these uses require that constraints are imposed on the format of the modid.
*/ */
String value(); String value();
/**
* Marks the associated method as handling an FML lifecycle event.
* The method must have a single parameter, one of the following types. This annotation
* replaces the multiple different annotations that previously were used.
*
* Current event classes. This first section is standard lifecycle events. They are dispatched
* at various phases as the game starts. Each event should have information useful to that
* phase of the lifecycle. They are fired in this order.
*
* These suggestions are mostly just suggestions on what to do in each event.
* <ul>
* <li> {@link FMLCommonSetupEvent} : Run before anything else. Read your config, create blocks,
* items, etc, and register them with the {@link GameRegistry}.</li>
* <li> {@link InterModEnqueueEvent} : Do your mod setup. Build whatever data structures you care about. Register recipes,
* send {@link FMLInterModComms} messages to other mods.</li>
* <li> {@link InterModProcessEvent} : Handle interaction with other mods, complete your setup based on this.</li>
* </ul>
* <p>These are the server lifecycle events. They are fired whenever a server is running, or about to run. Each time a server
* starts they will be fired in this sequence.
* <ul>
* <li> {@link FMLServerAboutToStartEvent} : Use if you need to handle something before the server has even been created.</li>
* <li> {@link FMLServerStartingEvent} : Do stuff you need to do to set up the server. register commands, tweak the server.</li>
* <li> {@link FMLServerStartedEvent} : Do what you need to with the running server.</li>
* <li> {@link FMLServerStoppingEvent} : Do what you need to before the server has started it's shutdown sequence.</li>
* <li> {@link FMLServerStoppedEvent} : Do whatever cleanup you need once the server has shutdown. Generally only useful
* on the integrated server.</li>
* </ul>
* The second set of events are more specialized, for receiving notification of specific
* information.
* <ul>
* <li> {@link FMLFingerprintViolationEvent} : Sent just before {@link FMLCommonSetupEvent}
* if something is wrong with your mod signature</li>
* <li> {@link IMCEvent} : Sent just after {@link InterModEnqueueEvent} if you have IMC messages waiting
* from other mods</li>
* </ul>
*
* @author cpw
*
*/
@Deprecated
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface EventHandler{}
/** /**
* A class which will be subscribed to {@link net.minecraftforge.common.MinecraftForge.EVENT_BUS} at mod construction time. * Annotate a class which will be subscribed to an Event Bus at mod construction time.
* Defaults to subscribing the current modid to the {@link MinecraftForge#EVENT_BUS}
* on both sides.
*
* @see Bus
*/ */
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE) @Target(ElementType.TYPE)
@interface EventBusSubscriber { @interface EventBusSubscriber {
/**
* Specify targets to load this event subscriber on. Can be used to avoid loading Client specific events
* on a dedicated server, for example.
*
* @return an array of Dist to load this event subscriber on
*/
Dist[] value() default { Dist.CLIENT, Dist.DEDICATED_SERVER }; Dist[] value() default { Dist.CLIENT, Dist.DEDICATED_SERVER };
/** /**
* Optional value, only nessasary if tis annotation is not on the same class that has a @Mod annotation. * Optional value, only necessary if this annotation is not on the same class that has a @Mod annotation.
* Needed to prevent early classloading of classes not owned by your mod. * Needed to prevent early classloading of classes not owned by your mod.
* @return * @return a modid
*/ */
String modid() default ""; String modid() default "";
/**
* Specify an alternative bus to listen to
*
* @return the bus you wish to listen to
*/
Bus bus() default Bus.FORGE;
enum Bus {
/**
* The main Forge Event Bus.
* @see MinecraftForge#EVENT_BUS
*/
FORGE(()-> MinecraftForge.EVENT_BUS),
/**
* The mod specific Event bus.
* @see FMLModLoadingContext#getModEventBus()
*/
MOD(()-> FMLModLoadingContext.get().getModEventBus());
private final Supplier<IEventBus> busSupplier;
Bus(final Supplier<IEventBus> eventBusSupplier) {
this.busSupplier = eventBusSupplier;
}
public Supplier<IEventBus> bus() {
return busSupplier;
}
}
} }
} }

View file

@ -29,7 +29,6 @@ import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.ModLoadingException; import net.minecraftforge.fml.ModLoadingException;
import net.minecraftforge.fml.ModLoadingStage; import net.minecraftforge.fml.ModLoadingStage;
import net.minecraftforge.fml.ModThreadContext; import net.minecraftforge.fml.ModThreadContext;
import net.minecraftforge.fml.event.lifecycle.ModLifecycleEvent;
import net.minecraftforge.forgespi.language.IModInfo; import net.minecraftforge.forgespi.language.IModInfo;
import net.minecraftforge.forgespi.language.ModFileScanData; import net.minecraftforge.forgespi.language.ModFileScanData;
@ -54,6 +53,8 @@ public class FMLModContainer extends ModContainer
LOGGER.debug("Creating FMLModContainer instance for {} with classLoader {} & {}", className, modClassLoader, getClass().getClassLoader()); LOGGER.debug("Creating FMLModContainer instance for {} with classLoader {} & {}", className, modClassLoader, getClass().getClassLoader());
this.scanResults = modFileScanResults; this.scanResults = modFileScanResults;
triggerMap.put(ModLoadingStage.CONSTRUCT, dummy().andThen(this::beforeEvent).andThen(this::constructMod).andThen(this::afterEvent)); triggerMap.put(ModLoadingStage.CONSTRUCT, dummy().andThen(this::beforeEvent).andThen(this::constructMod).andThen(this::afterEvent));
triggerMap.put(ModLoadingStage.CREATE_REGISTRIES, dummy().andThen(this::beforeEvent).andThen(this::fireEvent).andThen(this::afterEvent));
triggerMap.put(ModLoadingStage.LOAD_REGISTRIES, dummy().andThen(this::beforeEvent).andThen(this::fireEvent).andThen(this::afterEvent));
triggerMap.put(ModLoadingStage.COMMON_SETUP, dummy().andThen(this::beforeEvent).andThen(this::preinitMod).andThen(this::fireEvent).andThen(this::afterEvent)); triggerMap.put(ModLoadingStage.COMMON_SETUP, dummy().andThen(this::beforeEvent).andThen(this::preinitMod).andThen(this::fireEvent).andThen(this::afterEvent));
triggerMap.put(ModLoadingStage.SIDED_SETUP, dummy().andThen(this::beforeEvent).andThen(this::fireEvent).andThen(this::afterEvent)); triggerMap.put(ModLoadingStage.SIDED_SETUP, dummy().andThen(this::beforeEvent).andThen(this::fireEvent).andThen(this::afterEvent));
triggerMap.put(ModLoadingStage.ENQUEUE_IMC, dummy().andThen(this::beforeEvent).andThen(this::initMod).andThen(this::fireEvent).andThen(this::afterEvent)); triggerMap.put(ModLoadingStage.ENQUEUE_IMC, dummy().andThen(this::beforeEvent).andThen(this::initMod).andThen(this::fireEvent).andThen(this::afterEvent));
@ -96,8 +97,8 @@ public class FMLModContainer extends ModContainer
} }
private void fireEvent(LifecycleEventProvider.LifecycleEvent lifecycleEvent) { private void fireEvent(LifecycleEventProvider.LifecycleEvent lifecycleEvent) {
final ModLifecycleEvent event = lifecycleEvent.buildModEvent(this); final Event event = lifecycleEvent.getOrBuildEvent(this);
LOGGER.debug(LOADING, "Firing event for modid {} : {}", this.getModId(), event.getClass().getName()); LOGGER.info(LOADING, "Firing event for modid {} : {}", this.getModId(), event.getClass().getName());
try try
{ {
eventBus.post(event); eventBus.post(event);

View file

@ -41,6 +41,7 @@ import net.minecraft.world.biome.Biome;
import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.RegistryEvent; import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.event.RegistryEvent.MissingMappings; import net.minecraftforge.event.RegistryEvent.MissingMappings;
import net.minecraftforge.fml.LifecycleEventProvider;
import net.minecraftforge.fml.ModThreadContext; import net.minecraftforge.fml.ModThreadContext;
import net.minecraftforge.fml.StartupQuery; import net.minecraftforge.fml.StartupQuery;
import net.minecraftforge.fml.common.EnhancedRuntimeException; import net.minecraftforge.fml.common.EnhancedRuntimeException;
@ -61,6 +62,7 @@ import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -779,14 +781,17 @@ public class GameData
MinecraftForge.EVENT_BUS.post(new RegistryEvent.NewRegistry()); MinecraftForge.EVENT_BUS.post(new RegistryEvent.NewRegistry());
} }
public static void fireRegistryEvents() public static void fireCreateRegistryEvents(final LifecycleEventProvider lifecycleEventProvider, final Consumer<LifecycleEventProvider> eventDispatcher) {
{ final RegistryEvent.NewRegistry newRegistryEvent = new RegistryEvent.NewRegistry();
fireRegistryEvents(rl -> true); lifecycleEventProvider.setCustomEventSupplier(()->newRegistryEvent);
eventDispatcher.accept(lifecycleEventProvider);
} }
public static void fireRegistryEvents(Predicate<ResourceLocation> filter)
public static void fireRegistryEvents(Predicate<ResourceLocation> filter, final LifecycleEventProvider lifecycleEventProvider, final Consumer<LifecycleEventProvider> eventDispatcher)
{ {
List<ResourceLocation> keys = Lists.newArrayList(RegistryManager.ACTIVE.registries.keySet()); List<ResourceLocation> keys = Lists.newArrayList(RegistryManager.ACTIVE.registries.keySet());
Collections.sort(keys, (o1, o2) -> o1.toString().compareToIgnoreCase(o2.toString())); keys.sort((o1, o2) -> String.valueOf(o1).compareToIgnoreCase(String.valueOf(o2)));
//Move Blocks to first, and Items to second. //Move Blocks to first, and Items to second.
keys.remove(BLOCKS); keys.remove(BLOCKS);
@ -794,16 +799,18 @@ public class GameData
keys.add(0, BLOCKS); keys.add(0, BLOCKS);
keys.add(1, ITEMS); keys.add(1, ITEMS);
for (int i = 0, keysSize = keys.size(); i < keysSize; i++) {
for (ResourceLocation rl : keys) final ResourceLocation rl = keys.get(i);
{
if (!filter.test(rl)) continue; if (!filter.test(rl)) continue;
ForgeRegistry<?> reg = RegistryManager.ACTIVE.getRegistry(rl); ForgeRegistry<?> reg = RegistryManager.ACTIVE.getRegistry(rl);
reg.unfreeze(); reg.unfreeze();
MinecraftForge.EVENT_BUS.post(reg.getRegisterEvent(rl)); final RegistryEvent.Register<?> registerEvent = reg.getRegisterEvent(rl);
lifecycleEventProvider.setCustomEventSupplier(() -> registerEvent);
if (i== keysSize-1) lifecycleEventProvider.changeProgression(LifecycleEventProvider.LifecycleEvent.Progression.NEXT);
eventDispatcher.accept(lifecycleEventProvider);
reg.freeze(); reg.freeze();
LOGGER.info("{} Applying holder lookups", rl.toString()); LOGGER.info("{} Applying holder lookups", rl.toString());
ObjectHolderRegistry.applyObjectHolders(key -> rl.equals(key)); ObjectHolderRegistry.applyObjectHolders(rl::equals);
LOGGER.info("{} Holder lookups applied", rl.toString()); LOGGER.info("{} Holder lookups applied", rl.toString());
} }
} }