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;
+ }
}