Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update to simpler mod loading from latest FML #774

Merged
merged 5 commits into from
Apr 18, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ accesstransformers_version=10.0.1
coremods_version=6.0.4
eventbus_version=7.2.0
modlauncher_version=10.1.10
securejarhandler_version=2.1.24
securejarhandler_version=2.1.31
bootstraplauncher_version=1.1.2
asm_version=9.5
installer_version=2.1.+
Expand All @@ -31,7 +31,7 @@ jetbrains_annotations_version=24.0.1
slf4j_api_version=2.0.7
apache_maven_artifact_version=3.8.5
jarjar_version=0.4.0
fancy_mod_loader_version=3.0.10
fancy_mod_loader_version=3.0.12
mojang_logging_version=1.1.1
log4j_version=2.22.1
guava_version=31.1.2-jre
Expand Down
2 changes: 1 addition & 1 deletion patches/net/minecraft/client/renderer/Sheets.java.patch
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
+ }
+
+ static {
+ if (net.neoforged.fml.ModLoader.isLoadingStateValid() && !net.neoforged.fml.ModLoader.get().hasCompletedState("LOAD_REGISTRIES")) {
+ if (net.neoforged.fml.ModLoader.isLoadingStateValid() && !net.neoforged.neoforge.internal.CommonModLoader.areRegistriesLoaded()) {
+ com.mojang.logging.LogUtils.getLogger().error(
+ "net.minecraft.client.renderer.Sheets loaded too early, modded registry-based materials may not work correctly",
+ new IllegalStateException("net.minecraft.client.renderer.Sheets loaded too early")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
import net.minecraft.server.packs.repository.PackSource;
import net.minecraft.server.packs.resources.IoSupplier;
import net.minecraft.util.FormattedCharSequence;
import net.neoforged.fml.ModContainer;
import net.neoforged.fml.ModList;
import net.neoforged.fml.VersionChecker;
import net.neoforged.fml.loading.FMLPaths;
Expand Down Expand Up @@ -402,7 +401,7 @@ public void upload() {

lines.add(I18nExtension.getDisplayName(selectedMod));
lines.add(I18nExtension.parseMessage("fml.menu.mods.info.version", MavenVersionStringHelper.artifactVersionToString(selectedMod.getVersion())));
lines.add(I18nExtension.parseMessage("fml.menu.mods.info.idstate", selectedMod.getModId(), ModList.get().getModContainerById(selectedMod.getModId()).map(ModContainer::getCurrentState).map(Object::toString).orElse("NONE")));
lines.add(I18nExtension.parseMessage("fml.menu.mods.info.idstate", selectedMod.getModId(), "LOADED")); // TODO: remove mod loading stages from here too

selectedMod.getConfig().getConfigElement("credits").ifPresent(credits -> lines.add(I18nExtension.parseMessage("fml.menu.mods.info.credits", credits)));
selectedMod.getConfig().getConfigElement("authors").ifPresent(authors -> lines.add(I18nExtension.parseMessage("fml.menu.mods.info.authors", authors)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,15 @@
import net.neoforged.neoforge.common.NeoForgeConfig;
import net.neoforged.neoforge.common.util.LogicalSidedProvider;
import net.neoforged.neoforge.internal.BrandingControl;
import net.neoforged.neoforge.internal.CommonModLoader;
import net.neoforged.neoforge.logging.CrashReportExtender;
import net.neoforged.neoforge.resource.ResourcePackLoader;
import net.neoforged.neoforge.server.LanguageHook;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

@OnlyIn(Dist.CLIENT)
public class ClientModLoader {
public class ClientModLoader extends CommonModLoader {
private static final Logger LOGGER = LogManager.getLogger();
private static boolean loading;
private static Minecraft mc;
Expand All @@ -53,7 +54,7 @@ public static void begin(final Minecraft minecraft, final PackRepository default
ClientModLoader.mc = minecraft;
LogicalSidedProvider.setClient(() -> minecraft);
LanguageHook.loadBuiltinLanguages();
createRunnableWithCatch(() -> ModLoader.get().gatherAndInitializeMods(ModWorkManager.syncExecutor(), ModWorkManager.parallelExecutor(), ImmediateWindowHandler::renderTick)).run();
createRunnableWithCatch(() -> begin(ImmediateWindowHandler::renderTick)).run();
if (error == null) {
ResourcePackLoader.populatePackRepository(defaultResourcePacks, PackType.CLIENT_RESOURCES);
DataPackConfig.DEFAULT.addModPacks(ResourcePackLoader.getDataPackNames());
Expand All @@ -63,9 +64,9 @@ public static void begin(final Minecraft minecraft, final PackRepository default
}

private static CompletableFuture<Void> onResourceReload(final PreparableReloadListener.PreparationBarrier stage, final ResourceManager resourceManager, final ProfilerFiller prepareProfiler, final ProfilerFiller executeProfiler, final Executor asyncExecutor, final Executor syncExecutor) {
return CompletableFuture.runAsync(createRunnableWithCatch(() -> startModLoading(ModWorkManager.wrappedExecutor(syncExecutor), asyncExecutor)), ModWorkManager.parallelExecutor())
return CompletableFuture.runAsync(createRunnableWithCatch(() -> startModLoading(syncExecutor, asyncExecutor)), ModWorkManager.parallelExecutor())
.thenCompose(stage::wait)
.thenRunAsync(() -> finishModLoading(ModWorkManager.wrappedExecutor(syncExecutor), asyncExecutor), ModWorkManager.parallelExecutor());
.thenRunAsync(() -> finishModLoading(syncExecutor, asyncExecutor), ModWorkManager.parallelExecutor());
}

private static Runnable createRunnableWithCatch(Runnable r) {
Expand All @@ -79,12 +80,12 @@ private static Runnable createRunnableWithCatch(Runnable r) {
};
}

private static void startModLoading(ModWorkManager.DrivenExecutor syncExecutor, Executor parallelExecutor) {
createRunnableWithCatch(() -> ModLoader.get().loadMods(syncExecutor, parallelExecutor, ImmediateWindowHandler::renderTick)).run();
private static void startModLoading(Executor syncExecutor, Executor parallelExecutor) {
createRunnableWithCatch(() -> load(syncExecutor, parallelExecutor)).run();
}

private static void finishModLoading(ModWorkManager.DrivenExecutor syncExecutor, Executor parallelExecutor) {
createRunnableWithCatch(() -> ModLoader.get().finishMods(syncExecutor, parallelExecutor, ImmediateWindowHandler::renderTick)).run();
private static void finishModLoading(Executor syncExecutor, Executor parallelExecutor) {
createRunnableWithCatch(() -> finish(syncExecutor, parallelExecutor)).run();
loading = false;
loadingComplete = true;
// reload game settings on main thread
Expand Down
4 changes: 1 addition & 3 deletions src/main/java/net/neoforged/neoforge/common/NeoForgeMod.java
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@
import net.neoforged.fml.CrashReportCallables;
import net.neoforged.fml.ModContainer;
import net.neoforged.fml.ModLoader;
import net.neoforged.fml.ModLoadingStage;
import net.neoforged.fml.ModLoadingWarning;
import net.neoforged.fml.StartupMessageManager;
import net.neoforged.fml.VersionChecker;
Expand Down Expand Up @@ -615,8 +614,7 @@ public NeoForgeMod(IEventBus modEventBus, Dist dist, ModContainer container) {
if (isPRBuild(container.getModInfo().getVersion().toString())) {
isPRBuild = true;
ModLoader.get().addWarning(new ModLoadingWarning(
container.getModInfo(), ModLoadingStage.CONSTRUCT,
"loadwarning.neoforge.prbuild"));
container.getModInfo(), "loadwarning.neoforge.prbuild"));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@
import net.minecraft.data.registries.VanillaRegistries;
import net.minecraft.server.Bootstrap;
import net.neoforged.fml.ModLoader;
import net.neoforged.fml.ModWorkManager;
import net.neoforged.neoforge.client.ClientHooks;
import net.neoforged.neoforge.common.data.ExistingFileHelper;
import net.neoforged.neoforge.data.event.GatherDataEvent;
import net.neoforged.neoforge.internal.CommonModLoader;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class DatagenModLoader {
public class DatagenModLoader extends CommonModLoader {
private static final Logger LOGGER = LogManager.getLogger();
private static GatherDataEvent.DataGeneratorConfig dataGeneratorConfig;
private static ExistingFileHelper existingFileHelper;
Expand All @@ -40,7 +40,7 @@ public static void begin(final Set<String> mods, final Path path, final Collecti
LOGGER.info("Initializing Data Gatherer for mods {}", mods);
runningDataGen = true;
Bootstrap.bootStrap();
ModLoader.get().gatherAndInitializeMods(ModWorkManager.syncExecutor(), ModWorkManager.parallelExecutor(), () -> {});
begin(() -> {});
CompletableFuture<HolderLookup.Provider> lookupProvider = CompletableFuture.supplyAsync(VanillaRegistries::createLookup, Util.backgroundExecutor());
dataGeneratorConfig = new GatherDataEvent.DataGeneratorConfig(mods, path, inputs, lookupProvider, serverGenerators,
clientGenerators, devToolGenerators, reportsGenerator, structureValidator, flat);
Expand Down
85 changes: 85 additions & 0 deletions src/main/java/net/neoforged/neoforge/internal/CommonModLoader.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* Copyright (c) NeoForged and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/

package net.neoforged.neoforge.internal;

import java.util.concurrent.Executor;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.fml.ModList;
import net.neoforged.fml.ModLoader;
import net.neoforged.fml.ModWorkManager;
import net.neoforged.fml.config.ConfigTracker;
import net.neoforged.fml.config.ModConfig;
import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent;
import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent;
import net.neoforged.fml.event.lifecycle.FMLDedicatedServerSetupEvent;
import net.neoforged.fml.event.lifecycle.FMLLoadCompleteEvent;
import net.neoforged.fml.event.lifecycle.InterModEnqueueEvent;
import net.neoforged.fml.event.lifecycle.InterModProcessEvent;
import net.neoforged.fml.loading.FMLEnvironment;
import net.neoforged.fml.loading.FMLPaths;
import net.neoforged.neoforge.network.registration.NetworkRegistry;
import net.neoforged.neoforge.registries.GameData;
import net.neoforged.neoforge.registries.RegistryManager;

/**
* Internal class for handling the steps of mod loading that are common for client, data and server runs.
*/
public abstract class CommonModLoader {
private static boolean registriesLoaded = false;

public static boolean areRegistriesLoaded() {
return registriesLoaded;
}

protected static void begin(Runnable periodicTask) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment when this is called? Or when it should be called?
Especially to explain why we have begin and load and why are they split?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a vague comment - the current separation is only an artifact of how we do part of the mod loading inside a reload listener (which introduces its own set of problems btw...). I don't really want to encode it because we have discussed a potential rework of the client mod init timings.

var syncExecutor = ModWorkManager.syncExecutor();

ModLoader.get().gatherAndInitializeMods(syncExecutor, ModWorkManager.parallelExecutor(), periodicTask);
Technici4n marked this conversation as resolved.
Show resolved Hide resolved

ModLoader.get().runInitTask("Registry initialization", syncExecutor, periodicTask, () -> {
RegistryManager.postNewRegistryEvent();
GameData.unfreezeData();
GameData.postRegisterEvents();
GameData.freezeData();
registriesLoaded = true;
});
}

protected static void load(Executor syncExecutor, Executor parallelExecutor) {
Technici4n marked this conversation as resolved.
Show resolved Hide resolved
Runnable periodicTask = () -> {}; // no need to pass something else for now
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why?


if (!ModLoader.isLoadingStateValid()) {
Technici4n marked this conversation as resolved.
Show resolved Hide resolved
return;
}

ModLoader.get().runInitTask("Config loading", syncExecutor, periodicTask, () -> {
if (FMLEnvironment.dist == Dist.CLIENT) {
ConfigTracker.INSTANCE.loadConfigs(ModConfig.Type.CLIENT, FMLPaths.CONFIGDIR.get());
}
ConfigTracker.INSTANCE.loadConfigs(ModConfig.Type.COMMON, FMLPaths.CONFIGDIR.get());
});

ModLoader.get().dispatchParallelEvent("Common setup", syncExecutor, parallelExecutor, periodicTask, FMLCommonSetupEvent::new);
ModLoader.get().dispatchParallelEvent("Sided setup", syncExecutor, parallelExecutor, periodicTask,
FMLEnvironment.dist.isClient() ? FMLClientSetupEvent::new : FMLDedicatedServerSetupEvent::new);

ModLoader.get().runInitTask("Registration events", syncExecutor, periodicTask, RegistrationEvents::init);
}

protected static void finish(Executor syncExecutor, Executor parallelExecutor) {
Technici4n marked this conversation as resolved.
Show resolved Hide resolved
Runnable periodicTask = () -> {}; // no need to pass something else for now
Technici4n marked this conversation as resolved.
Show resolved Hide resolved

if (!ModLoader.isLoadingStateValid()) {
Technici4n marked this conversation as resolved.
Show resolved Hide resolved
return;
}

ModLoader.get().dispatchParallelEvent("Enqueue IMC", syncExecutor, parallelExecutor, periodicTask, InterModEnqueueEvent::new);
ModLoader.get().dispatchParallelEvent("Process IMC", syncExecutor, parallelExecutor, periodicTask, InterModProcessEvent::new);
ModLoader.get().dispatchParallelEvent("Complete loading of %d mods".formatted(ModList.get().size()), syncExecutor, parallelExecutor, periodicTask, FMLLoadCompleteEvent::new);

ModLoader.get().runInitTask("Network registry lock", syncExecutor, periodicTask, NetworkRegistry.getInstance()::setup);
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* SPDX-License-Identifier: LGPL-2.1-only
*/

@ApiStatus.Internal
@FieldsAreNonnullByDefault
@MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault
Expand All @@ -11,3 +12,4 @@
import javax.annotation.ParametersAreNonnullByDefault;
import net.minecraft.FieldsAreNonnullByDefault;
import net.minecraft.MethodsReturnNonnullByDefault;
import org.jetbrains.annotations.ApiStatus;
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
import net.minecraft.world.flag.FeatureFlagSet;
import net.neoforged.fml.ModList;
import net.neoforged.fml.ModLoader;
import net.neoforged.fml.ModLoadingStage;
import net.neoforged.fml.ModLoadingWarning;
import net.neoforged.neoforge.event.AddPackFindersEvent;
import net.neoforged.neoforgespi.language.IModFileInfo;
Expand Down Expand Up @@ -117,7 +116,7 @@ private static void packFinder(Map<IModFile, Pack.ResourcesSupplier> modResource
MOD_PACK_SELECTION_CONFIG);

if (modPack == null) {
ModLoader.get().addWarning(new ModLoadingWarning(mod, ModLoadingStage.ERROR, "fml.modloading.brokenresources", e.getKey()));
ModLoader.get().addWarning(new ModLoadingWarning(mod, "fml.modloading.brokenresources", e.getKey()));
continue;
}
} else {
Expand All @@ -135,7 +134,7 @@ private static void packFinder(Map<IModFile, Pack.ResourcesSupplier> modResource
}
} catch (IOException exception) {
LOGGER.error("Failed to read pack.mcmeta file of mod {}", mod.getModId(), exception);
ModLoader.get().addWarning(new ModLoadingWarning(mod, ModLoadingStage.ERROR, "fml.modloading.brokenresources", e.getKey()));
ModLoader.get().addWarning(new ModLoadingWarning(mod, "fml.modloading.brokenresources", e.getKey()));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@
import net.neoforged.fml.ModWorkManager;
import net.neoforged.neoforge.common.NeoForge;
import net.neoforged.neoforge.common.util.LogicalSidedProvider;
import net.neoforged.neoforge.internal.CommonModLoader;
import net.neoforged.neoforge.logging.CrashReportExtender;
import net.neoforged.neoforge.server.LanguageHook;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class ServerModLoader {
public class ServerModLoader extends CommonModLoader {
private static final Logger LOGGER = LogManager.getLogger();
private static boolean hasErrors = false;

Expand All @@ -29,9 +30,9 @@ public static void load() {
});
LanguageHook.loadBuiltinLanguages();
try {
ModLoader.get().gatherAndInitializeMods(ModWorkManager.syncExecutor(), ModWorkManager.parallelExecutor(), () -> {});
ModLoader.get().loadMods(ModWorkManager.syncExecutor(), ModWorkManager.parallelExecutor(), () -> {});
ModLoader.get().finishMods(ModWorkManager.syncExecutor(), ModWorkManager.parallelExecutor(), () -> {});
begin(() -> {});
load(ModWorkManager.syncExecutor(), ModWorkManager.parallelExecutor());
finish(ModWorkManager.syncExecutor(), ModWorkManager.parallelExecutor());
} catch (LoadingFailedException error) {
ServerModLoader.hasErrors = true;
// In case its not loaded properly
Expand Down

This file was deleted.

2 changes: 1 addition & 1 deletion src/main/resources/assets/neoforge/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
"fml.modloading.failedtoloadmod":"{0,modinfo,name} ({0,modinfo,id}) has failed to load correctly\n\u00a77{2,exc,msg}",
"fml.modloading.feature.missing": "{0,modinfo,name} ({0,modinfo,id}) is missing a feature it requires to run\n§7It requires {3,featurebound} but {4} is available",
"fml.modloading.uncaughterror":"An uncaught parallel processing error has occurred.\n\u00a77{2,exc,msg}",
"fml.modloading.errorduringevent":"{0,modinfo,name} ({0,modinfo,id}) encountered an error during the {1,lower} event phase\n\u00a77{2,exc,msg}",
"fml.modloading.errorduringevent":"{0,modinfo,name} ({0,modinfo,id}) encountered an error while dispatching the {3} event\n\u00a77{2,exc,msg}",
"fml.modloading.failedtoloadforge": "Failed to load NeoForge",

"fml.modloading.missingdependency": "Mod \u00a7e{4}\u00a7r requires \u00a76{3}\u00a7r \u00a7o{5,vr}\u00a7r\n\u00a77Currently, \u00a76{3}\u00a7r\u00a77 is \u00a7o{6,i18n,fml.messages.artifactversion.ornotinstalled}§r\n{7,optional,§7Reason for the dependency: §r}",
Expand Down
Loading