Skip to content

Commit

Permalink
Support event priorities for events posted via ModLoader
Browse files Browse the repository at this point in the history
  • Loading branch information
Technici4n committed Oct 31, 2023
1 parent e29afa5 commit a6c8464
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 31 deletions.
55 changes: 53 additions & 2 deletions core/src/main/java/net/neoforged/fml/ModContainer.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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.
* <p>
Expand All @@ -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;
Expand Down Expand Up @@ -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}
*
* <p>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 <T extends Event & IModBusEvent> void acceptEvent(T e) {}
protected final <T extends Event & IModBusEvent> 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 <T extends Event & IModBusEvent> 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);
}
}
}
4 changes: 4 additions & 0 deletions core/src/main/java/net/neoforged/fml/ModList.java
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,10 @@ public void forEachModContainer(BiConsumer<String, ModContainer> modContainerCon
indexedMods.forEach(modContainerConsumer);
}

public List<ModContainer> getSortedMods() {
return sortedContainers;
}

public void forEachModInOrder(Consumer<ModContainer> containerConsumer) {
this.sortedContainers.forEach(containerConsumer);
}
Expand Down
43 changes: 31 additions & 12 deletions core/src/main/java/net/neoforged/fml/ModLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -315,22 +318,31 @@ public <T extends Event & IModBusEvent> void runEventGenerator(Function<ModConta
LOGGER.error("Cowardly refusing to send event generator to a broken mod state");
return;
}
ModList.get().forEachModInOrder(mc -> mc.acceptEvent(generator.apply(mc)));

// Construct events
List<ModContainer> modContainers = ModList.get().getSortedMods();
List<T> 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 <T extends Event & IModBusEvent> void postEvent(T e) {
if (!loadingStateValid) {
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 extends Event & IModBusEvent> 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 <T extends Event & IModBusEvent> void postEventWrapContainerInModOrder(T event) {
Expand All @@ -341,11 +353,13 @@ public <T extends Event & IModBusEvent> 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<ModLoadingWarning> getWarnings()
Expand Down Expand Up @@ -378,5 +392,10 @@ public boolean matches(final Object mod) {
public Object getMod() {
return null;
}

@Override
public @Nullable IEventBus getEventBus() {
return null;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -139,20 +143,9 @@ public Object getMod()
return modInstance;
}

@Override
public IEventBus getEventBus()
{
return this.eventBus;
}

@Override
protected <T extends Event & IModBusEvent> 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);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -45,7 +45,7 @@ public Object getMod()
}

@Override
protected <T extends Event & IModBusEvent> void acceptEvent(final T e)
{
public @Nullable IEventBus getEventBus() {
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -27,4 +29,9 @@ public boolean matches(final Object mod) {
public Object getMod() {
return MCMODINSTANCE;
}

@Override
public @Nullable IEventBus getEventBus() {
return null;
}
}

0 comments on commit a6c8464

Please sign in to comment.