Skip to content

Commit

Permalink
Merge branch 'main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
Technici4n authored Nov 2, 2023
2 parents edf452a + da93135 commit dfc24e6
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 66 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;
}
}
}
Empty file modified gradlew
100644 → 100755
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

package net.neoforged.fml.javafmlmod;

import net.neoforged.api.distmarker.Dist;
import net.neoforged.bus.EventBusErrorMessage;
import net.neoforged.bus.api.BusBuilder;
import net.neoforged.bus.api.Event;
Expand All @@ -14,6 +15,7 @@
import net.neoforged.fml.ModLoadingException;
import net.neoforged.fml.ModLoadingStage;
import net.neoforged.fml.event.IModBusEvent;
import net.neoforged.fml.loading.FMLLoader;
import net.neoforged.neoforgespi.language.IModInfo;
import net.neoforged.neoforgespi.language.ModFileScanData;
import org.apache.logging.log4j.LogManager;
Expand Down Expand Up @@ -43,7 +45,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 All @@ -70,45 +76,42 @@ private void constructMod()
try
{
LOGGER.trace(LOADING, "Loading mod instance {} of type {}", getModId(), modClass.getName());
try {
// Try noargs constructor first
this.modInstance = modClass.getDeclaredConstructor().newInstance();
} catch (NoSuchMethodException ignored) {
// Otherwise look for constructor that can accept more arguments
Map<Class<?>, Object> allowedConstructorArgs = Map.of(
IEventBus.class, eventBus,
ModContainer.class, this,
FMLModContainer.class, this);

constructorsLoop: for (var constructor : modClass.getDeclaredConstructors()) {
var parameterTypes = constructor.getParameterTypes();
Object[] constructorArgs = new Object[parameterTypes.length];
Set<Class<?>> foundArgs = new HashSet<>();

for (int i = 0; i < parameterTypes.length; i++) {
Object argInstance = allowedConstructorArgs.get(parameterTypes[i]);
if (argInstance == null) {
// Unknown argument, try next constructor method...
continue constructorsLoop;
}

if (foundArgs.contains(parameterTypes[i])) {
throw new RuntimeException("Duplicate constructor argument type: " + parameterTypes[i]);
}

foundArgs.add(parameterTypes[i]);
constructorArgs[i] = argInstance;
}

// All arguments are found
this.modInstance = constructor.newInstance(constructorArgs);
}

if (this.modInstance == null) {
throw new RuntimeException("Could not find mod constructor. Allowed optional argument classes: " +
var constructors = modClass.getConstructors();
if (constructors.length != 1) {
throw new RuntimeException("Mod class must have exactly 1 public constructor, found " + constructors.length);
}
var constructor = constructors[0];

// Allowed arguments for injection via constructor
Map<Class<?>, Object> allowedConstructorArgs = Map.of(
IEventBus.class, eventBus,
ModContainer.class, this,
FMLModContainer.class, this,
Dist.class, FMLLoader.getDist());

var parameterTypes = constructor.getParameterTypes();
Object[] constructorArgs = new Object[parameterTypes.length];
Set<Class<?>> foundArgs = new HashSet<>();

for (int i = 0; i < parameterTypes.length; i++) {
Object argInstance = allowedConstructorArgs.get(parameterTypes[i]);
if (argInstance == null) {
throw new RuntimeException("Mod constructor has unsupported argument " + parameterTypes[i] + ". Allowed optional argument classes: " +
allowedConstructorArgs.keySet().stream().map(Class::getSimpleName).collect(Collectors.joining(", ")));
}

if (foundArgs.contains(parameterTypes[i])) {
throw new RuntimeException("Duplicate mod constructor argument type: " + parameterTypes[i]);
}

foundArgs.add(parameterTypes[i]);
constructorArgs[i] = argInstance;
}

// All arguments are found
this.modInstance = constructor.newInstance(constructorArgs);

LOGGER.trace(LOADING, "Loaded mod instance {} of type {}", getModId(), modClass.getName());
}
catch (Throwable e)
Expand Down Expand Up @@ -139,20 +142,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 dfc24e6

Please sign in to comment.