diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 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 c30f86a68..6c5a4439e 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 @@ -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; @@ -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; @@ -70,45 +72,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, 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> 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, 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> 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)