diff --git a/core/src/main/java/net/neoforged/fml/ModContainer.java b/core/src/main/java/net/neoforged/fml/ModContainer.java index 0b3312b0..dfaef7ed 100644 --- a/core/src/main/java/net/neoforged/fml/ModContainer.java +++ b/core/src/main/java/net/neoforged/fml/ModContainer.java @@ -5,12 +5,18 @@ package net.neoforged.fml; +import net.neoforged.bus.api.BusBuilder; import net.neoforged.bus.api.Event; +import net.neoforged.bus.api.EventPriority; +import net.neoforged.bus.api.IEventBus; import net.neoforged.fml.config.IConfigEvent; import net.neoforged.fml.config.ModConfig; import net.neoforged.fml.event.IModBusEvent; import net.neoforged.fml.loading.progress.ProgressMeter; import net.neoforged.neoforgespi.language.IModInfo; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.jetbrains.annotations.Nullable; import java.util.EnumMap; import java.util.HashMap; @@ -24,6 +30,8 @@ import java.util.function.Consumer; import java.util.function.Supplier; +import static net.neoforged.fml.Logging.LOADING; + /** * The container that wraps around mods in the system. *

@@ -39,6 +47,8 @@ public abstract class ModContainer { + private static final Logger LOGGER = LogManager.getLogger(); + protected final String modId; protected final String namespace; protected final IModInfo modInfo; @@ -167,8 +177,49 @@ public void dispatchConfigEvent(IConfigEvent event) { public abstract Object getMod(); /** - * Accept an arbitrary event for processing by the mod. Probably posted to an event bus in the lower level container. + * {@return the event bus for this mod, if available} + * + *

Not all mods have an event bus! + * + * @implNote For custom mod container implementations, the event bus must be built with + * {@link BusBuilder#allowPerPhasePost()} or posting via {@link #acceptEvent(EventPriority, Event)} will throw! + */ + @Nullable + public abstract IEventBus getEventBus(); + + /** + * Accept an arbitrary event for processing by the mod. Posted to {@link #getEventBus()}. * @param e Event to accept */ - protected void acceptEvent(T e) {} + protected final void acceptEvent(T e) { + IEventBus bus = getEventBus(); + if (bus == null) return; + + try { + LOGGER.trace(LOADING, "Firing event for modid {} : {}", this.getModId(), e); + bus.post(e); + LOGGER.trace(LOADING, "Fired event for modid {} : {}", this.getModId(), e); + } catch (Throwable t) { + LOGGER.error(LOADING,"Caught exception during event {} dispatch for modid {}", e, this.getModId(), t); + throw new ModLoadingException(modInfo, modLoadingStage, "fml.modloading.errorduringevent", t); + } + } + + /** + * Accept an arbitrary event for processing by the mod. Posted to {@link #getEventBus()}. + * @param e Event to accept + */ + protected final void acceptEvent(EventPriority phase, T e) { + IEventBus bus = getEventBus(); + if (bus == null) return; + + try { + LOGGER.trace(LOADING, "Firing event for phase {} for modid {} : {}", phase, this.getModId(), e); + bus.post(phase, e); + LOGGER.trace(LOADING, "Fired event for phase {} for modid {} : {}", phase, this.getModId(), e); + } catch (Throwable t) { + LOGGER.error(LOADING,"Caught exception during event {} dispatch for modid {}", e, this.getModId(), t); + throw new ModLoadingException(modInfo, modLoadingStage, "fml.modloading.errorduringevent", t); + } + } } diff --git a/core/src/main/java/net/neoforged/fml/ModList.java b/core/src/main/java/net/neoforged/fml/ModList.java index c5c36dcf..e2d416fc 100644 --- a/core/src/main/java/net/neoforged/fml/ModList.java +++ b/core/src/main/java/net/neoforged/fml/ModList.java @@ -223,6 +223,10 @@ public void forEachModContainer(BiConsumer modContainerCon indexedMods.forEach(modContainerConsumer); } + public List getSortedMods() { + return sortedContainers; + } + public void forEachModInOrder(Consumer containerConsumer) { this.sortedContainers.forEach(containerConsumer); } diff --git a/core/src/main/java/net/neoforged/fml/ModLoader.java b/core/src/main/java/net/neoforged/fml/ModLoader.java index b4808b78..07e20ef1 100644 --- a/core/src/main/java/net/neoforged/fml/ModLoader.java +++ b/core/src/main/java/net/neoforged/fml/ModLoader.java @@ -7,6 +7,8 @@ import com.google.common.collect.ImmutableList; import net.neoforged.bus.api.Event; +import net.neoforged.bus.api.EventPriority; +import net.neoforged.bus.api.IEventBus; import net.neoforged.fml.event.IModBusEvent; import net.neoforged.fml.loading.FMLEnvironment; import net.neoforged.fml.loading.FMLLoader; @@ -23,6 +25,7 @@ import net.neoforged.neoforgespi.locating.IModFile; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.jetbrains.annotations.Nullable; import java.util.*; import java.util.concurrent.CompletableFuture; @@ -315,7 +318,18 @@ public void runEventGenerator(Function mc.acceptEvent(generator.apply(mc))); + + // Construct events + List modContainers = ModList.get().getSortedMods(); + List events = new ArrayList<>(modContainers.size()); + ModList.get().forEachModInOrder(mc -> events.add(generator.apply(mc))); + + // Post them + for (EventPriority phase : EventPriority.values()) { + for (int i = 0; i < modContainers.size(); i++) { + modContainers.get(i).acceptEvent(phase, events.get(i)); + } + } } public void postEvent(T e) { @@ -323,14 +337,12 @@ public void postEvent(T e) { LOGGER.error("Cowardly refusing to send event {} to a broken mod state", e.getClass().getName()); return; } - ModList.get().forEachModInOrder(mc -> mc.acceptEvent(e)); + for (EventPriority phase : EventPriority.values()) { + ModList.get().forEachModInOrder(mc -> mc.acceptEvent(phase, e)); + } } public T postEventWithReturn(T e) { - if (!loadingStateValid) { - LOGGER.error("Cowardly refusing to send event {} to a broken mod state", e.getClass().getName()); - return e; - } - ModList.get().forEachModInOrder(mc -> mc.acceptEvent(e)); + postEvent(e); return e; } public void postEventWrapContainerInModOrder(T event) { @@ -341,11 +353,13 @@ public void postEventWithWrapInModOrder(T e, Bi LOGGER.error("Cowardly refusing to send event {} to a broken mod state", e.getClass().getName()); return; } - ModList.get().forEachModInOrder(mc -> { - pre.accept(mc, e); - mc.acceptEvent(e); - post.accept(mc, e); - }); + for (EventPriority phase : EventPriority.values()) { + ModList.get().forEachModInOrder(mc -> { + pre.accept(mc, e); + mc.acceptEvent(phase, e); + post.accept(mc, e); + }); + } } public List getWarnings() @@ -378,5 +392,10 @@ public boolean matches(final Object mod) { public Object getMod() { return null; } + + @Override + public @Nullable IEventBus getEventBus() { + return null; + } } } diff --git a/languages/java/src/main/java/net/neoforged/fml/javafmlmod/FMLModContainer.java b/languages/java/src/main/java/net/neoforged/fml/javafmlmod/FMLModContainer.java index c30f86a6..8a88cdb2 100644 --- a/languages/java/src/main/java/net/neoforged/fml/javafmlmod/FMLModContainer.java +++ b/languages/java/src/main/java/net/neoforged/fml/javafmlmod/FMLModContainer.java @@ -43,7 +43,11 @@ public FMLModContainer(IModInfo info, String className, ModFileScanData modFileS LOGGER.debug(LOADING,"Creating FMLModContainer instance for {}", className); this.scanResults = modFileScanResults; activityMap.put(ModLoadingStage.CONSTRUCT, this::constructMod); - this.eventBus = BusBuilder.builder().setExceptionHandler(this::onEventFailed).markerType(IModBusEvent.class).build(); + this.eventBus = BusBuilder.builder() + .setExceptionHandler(this::onEventFailed) + .markerType(IModBusEvent.class) + .allowPerPhasePost() + .build(); this.configHandler = Optional.of(ce->this.eventBus.post(ce.self())); final FMLJavaModLoadingContext contextExtension = new FMLJavaModLoadingContext(this); this.contextExtension = () -> contextExtension; @@ -139,20 +143,9 @@ public Object getMod() return modInstance; } + @Override public IEventBus getEventBus() { return this.eventBus; } - - @Override - protected void acceptEvent(final T e) { - try { - LOGGER.trace(LOADING, "Firing event for modid {} : {}", this.getModId(), e); - this.eventBus.post(e); - LOGGER.trace(LOADING, "Fired event for modid {} : {}", this.getModId(), e); - } catch (Throwable t) { - LOGGER.error(LOADING,"Caught exception during event {} dispatch for modid {}", e, this.getModId(), t); - throw new ModLoadingException(modInfo, modLoadingStage, "fml.modloading.errorduringevent", t); - } - } } diff --git a/languages/lowcode/src/main/java/net/neoforged/fml/lowcodemod/LowCodeModContainer.java b/languages/lowcode/src/main/java/net/neoforged/fml/lowcodemod/LowCodeModContainer.java index 810d2ac3..437851d7 100644 --- a/languages/lowcode/src/main/java/net/neoforged/fml/lowcodemod/LowCodeModContainer.java +++ b/languages/lowcode/src/main/java/net/neoforged/fml/lowcodemod/LowCodeModContainer.java @@ -6,12 +6,12 @@ package net.neoforged.fml.lowcodemod; import com.mojang.logging.LogUtils; -import net.neoforged.bus.api.Event; +import net.neoforged.bus.api.IEventBus; import net.neoforged.fml.IExtensionPoint; import net.neoforged.fml.ModContainer; -import net.neoforged.fml.event.IModBusEvent; import net.neoforged.neoforgespi.language.IModInfo; import net.neoforged.neoforgespi.language.ModFileScanData; +import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import static net.neoforged.fml.loading.LogMarkers.LOADING; @@ -45,7 +45,7 @@ public Object getMod() } @Override - protected void acceptEvent(final T e) - { + public @Nullable IEventBus getEventBus() { + return null; } } diff --git a/languages/minecraft/src/main/java/net/neoforged/fml/mclanguageprovider/MinecraftModContainer.java b/languages/minecraft/src/main/java/net/neoforged/fml/mclanguageprovider/MinecraftModContainer.java index be467100..9f0cc0a5 100644 --- a/languages/minecraft/src/main/java/net/neoforged/fml/mclanguageprovider/MinecraftModContainer.java +++ b/languages/minecraft/src/main/java/net/neoforged/fml/mclanguageprovider/MinecraftModContainer.java @@ -5,8 +5,10 @@ package net.neoforged.fml.mclanguageprovider; +import net.neoforged.bus.api.IEventBus; import net.neoforged.fml.ModContainer; import net.neoforged.neoforgespi.language.IModInfo; +import org.jetbrains.annotations.Nullable; import java.util.Objects; @@ -27,4 +29,9 @@ public boolean matches(final Object mod) { public Object getMod() { return MCMODINSTANCE; } + + @Override + public @Nullable IEventBus getEventBus() { + return null; + } }