Optionally supply FMLJavaModLoadingContext as a param to mod constructors (backport of #10074 to 1.20.1) (#10100)

Co-authored-by: RealMangoRage <andrew333awesome@outlook.com>
This commit is contained in:
Paint_Ninja 2024-09-12 14:06:42 +01:00 committed by GitHub
parent e615774a0e
commit 29986615fe
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 59 additions and 65 deletions

View file

@ -8,9 +8,7 @@ package net.minecraftforge.fml;
import com.mojang.logging.LogUtils;
import net.minecraftforge.fml.config.IConfigSpec;
import net.minecraftforge.fml.config.ModConfig;
import net.minecraftforge.fml.loading.FMLLoader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.function.BiPredicate;
import java.util.function.Supplier;
@ -19,28 +17,45 @@ public class ModLoadingContext
{
private static final Logger LOGGER = LogUtils.getLogger();
private static final ThreadLocal<ModLoadingContext> context = ThreadLocal.withInitial(ModLoadingContext::new);
private ModContainer activeContainer;
private Object languageExtension;
private ModLoadingStage stage;
/**
* @deprecated Use the context provided by your language loader in your mod's constructor.
*/
@Deprecated(forRemoval = true, since = "1.21.1")
public static ModLoadingContext get() {
return context.get();
}
private ModContainer activeContainer;
/**
* @deprecated Going to be moved to ForgeHooks for internal use.
*/
@Deprecated(forRemoval = true, since = "1.21.1")
public void setActiveContainer(final ModContainer container) {
this.activeContainer = container;
this.languageExtension = container == null ? null : container.contextExtension.get();
}
/**
* Going to be moved to ForgeHooks for internal use.
* @deprecated Override/Use {@link ModLoadingContext#getContainer()}
*/
@Deprecated(forRemoval = true, since = "1.21.1")
public ModContainer getActiveContainer() {
return activeContainer == null ? ModList.get().getModContainerById("minecraft").orElseThrow(()->new RuntimeException("Where is minecraft???!")) : activeContainer;
}
@Deprecated(forRemoval = true, since = "1.21.1")
public String getActiveNamespace() {
return activeContainer == null ? "minecraft" : activeContainer.getNamespace();
}
public ModContainer getContainer() {
return getActiveContainer();
}
/**
* Register an {@link IExtensionPoint} with the mod container.
* @param point The extension point to register
@ -48,7 +63,7 @@ public class ModLoadingContext
* @param <T> The type signature of the extension operator
*/
public <T extends Record & IExtensionPoint<T>> void registerExtensionPoint(Class<? extends IExtensionPoint<T>> point, Supplier<T> extension) {
getActiveContainer().registerExtensionPoint(point, extension);
getContainer().registerExtensionPoint(point, extension);
}
/**
@ -57,7 +72,7 @@ public class ModLoadingContext
* @param displayTest The {@link IExtensionPoint.DisplayTest} to register
*/
public void registerDisplayTest(IExtensionPoint.DisplayTest displayTest) {
getActiveContainer().registerDisplayTest(() -> displayTest);
getContainer().registerDisplayTest(() -> displayTest);
}
/**
@ -66,7 +81,7 @@ public class ModLoadingContext
* @param displayTest The {@link Supplier<IExtensionPoint.DisplayTest>} to register
*/
public void registerDisplayTest(Supplier<IExtensionPoint.DisplayTest> displayTest) {
getActiveContainer().registerDisplayTest(displayTest);
getContainer().registerDisplayTest(displayTest);
}
/**
@ -76,7 +91,7 @@ public class ModLoadingContext
* @see IExtensionPoint.DisplayTest#DisplayTest(String, BiPredicate)
*/
public void registerDisplayTest(String version, BiPredicate<String, Boolean> remoteVersionTest) {
getActiveContainer().registerDisplayTest(new IExtensionPoint.DisplayTest(version, remoteVersionTest));
getContainer().registerDisplayTest(new IExtensionPoint.DisplayTest(version, remoteVersionTest));
}
/**
@ -86,29 +101,29 @@ public class ModLoadingContext
* @see IExtensionPoint.DisplayTest#DisplayTest(Supplier, BiPredicate)
*/
public void registerDisplayTest(Supplier<String> suppliedVersion, BiPredicate<String, Boolean> remoteVersionTest) {
getActiveContainer().registerDisplayTest(new IExtensionPoint.DisplayTest(suppliedVersion, remoteVersionTest));
getContainer().registerDisplayTest(new IExtensionPoint.DisplayTest(suppliedVersion, remoteVersionTest));
}
public void registerConfig(ModConfig.Type type, IConfigSpec<?> spec) {
if (spec.isEmpty())
{
// This handles the case where a mod tries to register a config, without any options configured inside it.
LOGGER.debug("Attempted to register an empty config for type {} on mod {}", type, getActiveContainer().getModId());
LOGGER.debug("Attempted to register an empty config for type {} on mod {}", type, getContainer().getModId());
return;
}
getActiveContainer().addConfig(new ModConfig(type, spec, getActiveContainer()));
getContainer().addConfig(new ModConfig(type, spec, getContainer()));
}
public void registerConfig(ModConfig.Type type, IConfigSpec<?> spec, String fileName) {
if (spec.isEmpty())
{
// This handles the case where a mod tries to register a config, without any options configured inside it.
LOGGER.debug("Attempted to register an empty config for type {} on mod {} using file name {}", type, getActiveContainer().getModId(), fileName);
LOGGER.debug("Attempted to register an empty config for type {} on mod {} using file name {}", type, getContainer().getModId(), fileName);
return;
}
getActiveContainer().addConfig(new ModConfig(type, spec, getActiveContainer(), fileName));
getContainer().addConfig(new ModConfig(type, spec, getContainer(), fileName));
}

View file

@ -8,7 +8,7 @@ package net.minecraftforge.fml.javafmlmod;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.fml.ModLoadingContext;
public class FMLJavaModLoadingContext
public class FMLJavaModLoadingContext extends ModLoadingContext
{
private final FMLModContainer container;
@ -24,11 +24,18 @@ public class FMLJavaModLoadingContext
return container.getEventBus();
}
@Override
public FMLModContainer getContainer() {
return container;
}
/**
* Helper to get the right instance from the {@link ModLoadingContext} correctly.
* @return The FMLJavaMod language specific extension from the ModLoadingContext
*
* @deprecated use {@link FMLJavaModLoadingContext} in your mod constructor
*/
@Deprecated(forRemoval = true, since = "1.21.1")
public static FMLJavaModLoadingContext get() {
return ModLoadingContext.get().extension();
}

View file

@ -21,6 +21,7 @@ import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.MarkerManager;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Objects;
import java.util.Optional;
@ -33,6 +34,7 @@ public class FMLModContainer extends ModContainer
private final IEventBus eventBus;
private Object modInstance;
private final Class<?> modClass;
private final FMLJavaModLoadingContext context = new FMLJavaModLoadingContext(this);
public FMLModContainer(IModInfo info, String className, ModFileScanData modFileScanResults, ModuleLayer gameLayer)
{
@ -42,8 +44,7 @@ public class FMLModContainer extends ModContainer
activityMap.put(ModLoadingStage.CONSTRUCT, this::constructMod);
this.eventBus = BusBuilder.builder().setExceptionHandler(this::onEventFailed).setTrackPhases(false).markerType(IModBusEvent.class).useModLauncher().build();
this.configHandler = Optional.of(ce->this.eventBus.post(ce.self()));
final FMLJavaModLoadingContext contextExtension = new FMLJavaModLoadingContext(this);
this.contextExtension = () -> contextExtension;
this.contextExtension = () -> context;
try
{
var layer = gameLayer.findModule(info.getOwningFile().moduleName()).orElseThrow();
@ -67,7 +68,13 @@ public class FMLModContainer extends ModContainer
try
{
LOGGER.trace(LOADING, "Loading mod instance {} of type {}", getModId(), modClass.getName());
this.modInstance = modClass.getDeclaredConstructor().newInstance();
Constructor<?> constructor;
try {
constructor = modClass.getDeclaredConstructor(context.getClass());
} catch (NoSuchMethodException | SecurityException exception) {
constructor = modClass.getDeclaredConstructor();
}
this.modInstance = constructor.getParameterCount() == 0 ? constructor.newInstance() : constructor.newInstance(context);
LOGGER.trace(LOADING, "Loaded mod instance {} of type {}", getModId(), modClass.getName());
}
catch (Throwable e)

View file

@ -18,7 +18,6 @@ import net.minecraftforge.event.BuildCreativeModeTabContentsEvent;
import net.minecraftforge.event.server.ServerStartingEvent;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.ModLoadingContext;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.config.ModConfig;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
@ -61,9 +60,9 @@ public class ExampleMod
output.accept(EXAMPLE_ITEM.get()); // Add the example item to the tab. For your own tabs, this method is preferred over the event
}).build());
public ExampleMod()
public ExampleMod(FMLJavaModLoadingContext context)
{
IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
IEventBus modEventBus = context.getModEventBus();
// Register the commonSetup method for modloading
modEventBus.addListener(this::commonSetup);
@ -82,7 +81,7 @@ public class ExampleMod
modEventBus.addListener(this::addCreative);
// Register our mod's ForgeConfigSpec so that Forge can create and load the config file for us
ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, Config.SPEC);
context.registerConfig(ModConfig.Type.COMMON, Config.SPEC);
}
private void commonSetup(final FMLCommonSetupEvent event)

View file

@ -414,7 +414,7 @@ public class ForgeMod
enableMilkFluid = true;
}
public ForgeMod()
public ForgeMod(FMLJavaModLoadingContext context)
{
LOGGER.info(FORGEMOD,"Forge mod loading, version {}, for MC {} with MCP {}", ForgeVersion.getVersion(), MCPVersion.getMCVersion(), MCPVersion.getMCPVersion());
ForgeSnapshotsMod.logStartupWarning();
@ -430,7 +430,7 @@ public class ForgeMod
CrashReportCallables.registerCrashCallable("FML", ForgeVersion::getSpec);
CrashReportCallables.registerCrashCallable("Forge", ()->ForgeVersion.getGroup()+":"+ForgeVersion.getVersion());
final IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
final IEventBus modEventBus = context.getModEventBus();
// Forge-provided datapack registries
modEventBus.addListener((DataPackRegistryEvent.NewRegistry event) -> {
event.dataPackRegistry(ForgeRegistries.Keys.BIOME_MODIFIERS, BiomeModifier.DIRECT_CODEC);
@ -452,13 +452,13 @@ public class ForgeMod
VANILLA_FLUID_TYPES.register(modEventBus);
MinecraftForge.EVENT_BUS.addListener(this::serverStopping);
MinecraftForge.EVENT_BUS.addListener(this::missingSoundMapping);
ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, ForgeConfig.clientSpec);
ModLoadingContext.get().registerConfig(ModConfig.Type.SERVER, ForgeConfig.serverSpec);
ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, ForgeConfig.commonSpec);
context.registerConfig(ModConfig.Type.CLIENT, ForgeConfig.clientSpec);
context.registerConfig(ModConfig.Type.SERVER, ForgeConfig.serverSpec);
context.registerConfig(ModConfig.Type.COMMON, ForgeConfig.commonSpec);
modEventBus.register(ForgeConfig.class);
ForgeDeferredRegistriesSetup.setup(modEventBus);
// Forge does not display problems when the remote is not matching.
ModLoadingContext.get().registerExtensionPoint(IExtensionPoint.DisplayTest.class, ()->new IExtensionPoint.DisplayTest(()->"ANY", (remote, isServer)-> true));
context.registerDisplayTest(IExtensionPoint.DisplayTest.IGNORE_ALL_VERSION);
StartupMessageManager.addModMessage("Forge version "+ForgeVersion.getVersion());
MinecraftForge.EVENT_BUS.addListener(VillagerTradingManager::loadTrades);

View file

@ -27,12 +27,10 @@ import java.util.function.Function;
public class MinecraftForge
{
/**
* The core Forge EventBusses, all events for Forge will be fired on these,
* you should use this to register all your listeners.
* This replaces every register*Handler() function in the old version of Forge.
* TERRAIN_GEN_BUS for terrain gen events
* ORE_GEN_BUS for ore gen events
* EVENT_BUS for everything else
* The EventBus for all the Forge Events.
*
* Events marked with {@link net.minecraftforge.fml.event.IModBusEvent}
* belong on the ModBus and not this bus
*/
public static final IEventBus EVENT_BUS = BusBuilder.builder().startShutdown().useModLauncher().build();
@ -82,36 +80,4 @@ public class MinecraftForge
() -> new ConfigScreenHandler.ConfigScreenFactory(screenFunction)
);
}
/*
public static void preloadCrashClasses(ASMDataTable table, String modID, Set<String> classes)
{
//Find all ICrashReportDetail's handlers and preload them.
List<String> all = Lists.newArrayList();
for (ASMData asm : table.getAll(ICrashReportDetail.class.getName().replace('.', '/')))
all.add(asm.getClassName());
for (ASMData asm : table.getAll(ICrashCallable.class.getName().replace('.', '/')))
all.add(asm.getClassName());
all.retainAll(classes);
if (all.size() == 0)
return;
ForgeMod.log.debug("Preloading CrashReport Classes");
Collections.sort(all); //Sort it because I like pretty output ;)
for (String name : all)
{
ForgeMod.log.debug("\t{}", name);
try
{
Class.forName(name.replace('/', '.'), false, MinecraftForge.class.getClassLoader());
}
catch (Exception e)
{
LOGGER.error("Could not find class for name '{}'.", name, e);
}
}
}
*/
}