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

Locator rewrite #112

Merged
merged 39 commits into from
May 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
7d74dc6
Rewrite the mod discovery process with a focus on better end-to-end r…
Matyrobbrt Apr 9, 2024
881efa4
Tests
shartte Apr 20, 2024
967a72e
Replicate normalization from SJH
shartte Apr 20, 2024
2ea6679
Replicate normalization from SJH
shartte Apr 20, 2024
5b3b774
improv
shartte Apr 20, 2024
0f7a846
improv
shartte Apr 20, 2024
07488c7
Better mod classes support
shartte Apr 21, 2024
484896b
Better mod classes support
shartte Apr 21, 2024
c6f9789
Fix support for ML plugins/services
shartte Apr 21, 2024
970b098
Add back method to get at the loading issues in case there's no fatal…
shartte Apr 21, 2024
aecf471
Add back method to add more issues.
shartte Apr 21, 2024
371762b
Slightly refactored how ModLoader keeps tracks of errors & loading st…
shartte Apr 22, 2024
0a054b7
Fix modular classpath issues for userdev
shartte Apr 22, 2024
d1a20f3
Used the wrong CL
shartte Apr 22, 2024
f9e5e1e
Better handling for union fs paths.
shartte Apr 22, 2024
b065b45
Read from legacyClassPath again
shartte Apr 22, 2024
eebdb85
Read from legacyClassPath again
shartte Apr 22, 2024
0766291
Read from legacyClassPath again
shartte Apr 22, 2024
3d0c13a
BSL will load client-extra as a module :-|
shartte Apr 22, 2024
f09744a
Fix how Userdev works
shartte Apr 22, 2024
399fe82
Reworked how locators handle files
shartte Apr 25, 2024
f6dfea0
Fix dependency reading
shartte Apr 25, 2024
8d5f31a
Implement attribute merging.
shartte Apr 25, 2024
a4e36f4
Fix system mod file flag and locator settings.
shartte Apr 25, 2024
db4f60a
Switch launch handler to a consumer pattern.
shartte Apr 26, 2024
986b544
Fix JIJ double-loading
shartte Apr 26, 2024
fc2e315
More translation fixes.
shartte Apr 27, 2024
bfb81cf
More translation fixes.
shartte Apr 27, 2024
fca7c3b
More tests and more error handling.
shartte Apr 27, 2024
0ae7ede
More tests and more error handling.
shartte Apr 27, 2024
a8d23c4
Add Javadoc to DiscoveryPipeline
shartte Apr 27, 2024
6072338
Fix maven coordinate parsing
shartte Apr 28, 2024
fea3307
Reorganized packages
shartte Apr 29, 2024
907d956
Added priority
shartte Apr 29, 2024
45df3d9
Removed ISystemModSource
shartte Apr 29, 2024
1ffc42e
Unified on NeoForge capitalization
shartte Apr 29, 2024
a0a8b4f
Review comments
shartte Apr 29, 2024
21fcf79
Update SJH
Matyrobbrt May 1, 2024
d65af2f
Update NeoForgeDevProvider.java
Matyrobbrt May 1, 2024
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
3 changes: 2 additions & 1 deletion .github/workflows/build-prs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@ jobs:
uses: neoforged/actions/.github/workflows/build-prs.yml@main
with:
java: 21
gradle_tasks: test
# --info allows seeing STDOUT of tests
gradle_tasks: check --info
jar_compatibility: true
11 changes: 11 additions & 0 deletions .run/Template JUnit.run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<component name="ProjectRunConfigurationManager">
<configuration default="true" type="JUnit" factoryName="JUnit">
<option name="MAIN_CLASS_NAME" value="" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="class" />
<option name="VM_PARAMETERS" value="-ea --add-opens=java.base/java.lang.invoke=ALL-UNNAMED" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>
31 changes: 31 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Fancy Mod Loader

The mod loader used by [NeoForge](https://github.com/neoforged/NeoForge).

## Extension Points

### Mod File Candidate Locators

Responsible for locating potential mod files. Filesystem locations, virtual jars or even full mod-files can be reported to the discovery pipeline for inclusion in the mod loading process.
The pipeline also offers a way for locators to add issues (warnings & errors) that will later be shown to the user when mod loading concludes.

Interface: `net.neoforged.neoforgespi.locating.IModFileCandidateLocator`

Resolved via Java ServiceLoader.

You can construct a basic locator to scan a folder for mods by using `IModFileCandidateLocator.forFolder`. This can be
useful if your locator generates a folder on-disk and wants to delegate to default behavior for it (For example used
by [ServerPackLocator](https://github.com/marchermans/serverpacklocator/)).

### Mod File Readers

Responsible for creating a `IModFile` for mod file candidates.

The default implementation will resolve the type of the mod file by inspecting the Jar manifest or the mod metadata
file (`neoforge.mods.toml`) and return an `IModFile` instance if this succeeds.

Interface: `net.neoforged.neoforgespi.locating.IModFileReader`

Resolved via Java ServiceLoader.

Mod file instances can be created using the static methods on `IModFile`.
6 changes: 3 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,6 @@ allprojects {
name = 'Minecraft'
url = 'https://libraries.minecraft.net'
}

// TODO remove
mavenLocal()
}

dependencyUpdates.rejectVersionIf { isNonStable(it.candidate.version) }
Expand All @@ -69,6 +66,9 @@ allprojects {

test {
useJUnitPlatform()

// Needed by UnionFS
jvmArgs("--add-opens=java.base/java.lang.invoke=ALL-UNNAMED")
}
}

Expand Down
3 changes: 1 addition & 2 deletions earlydisplay/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ dependencies {
implementation("net.sf.jopt-simple:jopt-simple:${jopt_simple_version}")

testImplementation("org.junit.jupiter:junit-jupiter-api:${jupiter_version}")
testImplementation("org.powermock:powermock-core:${powermock_version}")


testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${jupiter_version}")
testRuntimeOnly("org.slf4j:slf4j-jdk14:${slf4j_api_version}")
testRuntimeOnly("org.lwjgl:lwjgl::${lwjglNatives}")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@
import java.util.stream.Collectors;
import joptsimple.OptionParser;
import net.neoforged.fml.loading.FMLConfig;
import net.neoforged.fml.loading.FMLLoader;
import net.neoforged.fml.loading.FMLPaths;
import net.neoforged.fml.loading.ImmediateWindowHandler;
import net.neoforged.fml.loading.progress.StartupNotificationManager;
Expand Down Expand Up @@ -600,7 +599,7 @@ public <T> Supplier<T> loadingOverlay(final Supplier<?> mc, final Supplier<?> ri
public void updateModuleReads(final ModuleLayer layer) {
var fm = layer.findModule("neoforge").orElseThrow();
getClass().getModule().addReads(fm);
var clz = FMLLoader.getGameLayer().findModule("neoforge").map(l -> Class.forName(l, "net.neoforged.neoforge.client.loading.NeoForgeLoadingOverlay")).orElseThrow();
var clz = Class.forName(fm, "net.neoforged.neoforge.client.loading.NeoForgeLoadingOverlay");
var methods = Arrays.stream(clz.getMethods()).filter(m -> Modifier.isStatic(m.getModifiers())).collect(Collectors.toMap(Method::getName, Function.identity()));
loadingOverlay = methods.get("newInstance");
}
Expand Down
10 changes: 5 additions & 5 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,19 @@ accesstransformers_version=10.0.1
coremods_version=7.0.3
eventbus_version=7.0.16
modlauncher_version=10.1.10
securejarhandler_version=2.1.31
securejarhandler_version=3.0.4
bootstraplauncher_version=1.1.8
asm_version=9.5
mixin_version=0.12.5+mixin.0.8.5
mixin_version=0.13.1+mixin.0.8.5
terminalconsoleappender_version=1.2.0
nightconfig_version=3.6.4
jetbrains_annotations_version=24.0.1
slf4j_api_version=1.8.0-beta4
apache_maven_artifact_version=3.8.5
jarjar_version=0.4.0
jarjar_version=0.4.1
lwjgl_version=3.3.1
jupiter_version=5.8.2
powermock_version=2.0.9
jupiter_version=5.10.2
mockito_version=5.11.0

mojang_logging_version=1.1.1
log4j_version=2.19.0
Expand Down
10 changes: 4 additions & 6 deletions loader/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,11 @@ dependencies {
testCompileOnly("org.jetbrains:annotations:${jetbrains_annotations_version}")
testRuntimeOnly("cpw.mods:bootstraplauncher:${bootstraplauncher_version}")
testRuntimeOnly("org.apache.logging.log4j:log4j-core:$log4j_version")
testRuntimeOnly("net.neoforged:JarJarFileSystems:$jarjar_version")
testImplementation("org.junit.jupiter:junit-jupiter-api:$jupiter_version")
testImplementation("org.powermock:powermock-core:$powermock_version")
testImplementation("org.hamcrest:hamcrest-core:2.2+")
testImplementation("org.junit.jupiter:junit-jupiter-params:$jupiter_version")
testImplementation("org.mockito:mockito-junit-jupiter:$mockito_version")
testImplementation("org.assertj:assertj-core:3.25.3")
testImplementation("org.junit.jupiter:junit-jupiter-engine:$jupiter_version")
}

Expand All @@ -68,7 +70,3 @@ spotless {
bumpThisNumberIfACustomStepChanges(1)
}
}

test {
useJUnitPlatform()
}
26 changes: 0 additions & 26 deletions loader/src/main/java/net/neoforged/fml/LoadingFailedException.java

This file was deleted.

4 changes: 2 additions & 2 deletions loader/src/main/java/net/neoforged/fml/ModContainer.java
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ public final <T extends Event & IModBusEvent> void acceptEvent(T 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, "fml.modloading.errorduringevent", t, e.getClass().getName());
throw new ModLoadingException(ModLoadingIssue.error("fml.modloading.errorduringevent", e.getClass().getName()).withAffectedMod(modInfo).withCause(t));
}
}

Expand All @@ -204,7 +204,7 @@ public final <T extends Event & IModBusEvent> void acceptEvent(EventPriority pha
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, "fml.modloading.errorduringevent", t, e.getClass().getName());
throw new ModLoadingException(ModLoadingIssue.error("fml.modloading.errorduringevent", e.getClass().getName()).withAffectedMod(modInfo).withCause(t));
}
}
}
20 changes: 4 additions & 16 deletions loader/src/main/java/net/neoforged/fml/ModList.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinWorkerThread;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
Expand All @@ -32,15 +30,12 @@
import net.neoforged.neoforgespi.language.IModInfo;
import net.neoforged.neoforgespi.language.ModFileScanData;
import net.neoforged.neoforgespi.locating.IModFile;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

/**
* Master list of all mods - game-side version. This is classloaded in the game scope and
* can dispatch game level events as a result.
*/
public class ModList {
private static Logger LOGGER = LogManager.getLogger();
private static ModList INSTANCE;
private final List<IModFileInfo> modFiles;
private final List<IModInfo> sortedList;
Expand All @@ -58,10 +53,11 @@ private ModList(final List<ModFile> modFiles, final List<ModInfo> sortedList) {
}

private String fileToLine(IModFile mf) {
var mainMod = mf.getModInfos().getFirst();
return String.format(Locale.ENGLISH, "%-50.50s|%-30.30s|%-30.30s|%-20.20s|Manifest: %s", mf.getFileName(),
mf.getModInfos().get(0).getDisplayName(),
mf.getModInfos().get(0).getModId(),
mf.getModInfos().get(0).getVersion(),
mainMod.getDisplayName(),
mainMod.getModId(),
mainMod.getVersion(),
((ModFileInfo) mf.getModFileInfo()).getCodeSigningFingerprint().orElse("NOSIGNATURE"));
}

Expand All @@ -78,14 +74,6 @@ public static ModList get() {
return INSTANCE;
}

private static ForkJoinWorkerThread newForkJoinWorkerThread(ForkJoinPool pool) {
ForkJoinWorkerThread thread = ForkJoinPool.defaultForkJoinWorkerThreadFactory.newThread(pool);
thread.setName("modloading-worker-" + thread.getPoolIndex());
// The default sets it to the SystemClassloader, so copy the current one.
thread.setContextClassLoader(Thread.currentThread().getContextClassLoader());
return thread;
}

public List<IModFileInfo> getModFiles() {
return modFiles;
}
Expand Down
Loading
Loading