Skip to content

Commit

Permalink
Be more specific about @mod initializer order (#145)
Browse files Browse the repository at this point in the history
Side-agnostic initializers will always run before side-specific initializers.
  • Loading branch information
Gaming32 committed May 26, 2024
1 parent a095c6c commit c1fa963
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 2 deletions.
2 changes: 1 addition & 1 deletion loader/src/main/java/net/neoforged/fml/common/Mod.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
* <p>
* Any class found with this annotation applied will be loaded as a mod entrypoint for the mod with the given {@linkplain #value() ID}. <br>
* A mod loaded with the {@code javafml} language loader may have multiple entrypoints, but it must have <strong>at least one</strong>.
* However, a mod can have entrypoints for only one {@linkplain #dist() side}.
* Entrypoints for all {@link #dist}s are always run before entrypoints for a single {@link #dist}.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import java.lang.annotation.ElementType;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Set;
import net.neoforged.fml.ModContainer;
Expand All @@ -30,6 +31,7 @@ public ModContainer loadMod(IModInfo info, ModFileScanData modFileScanResults, M
final var modClasses = modFileScanResults.getAnnotatedBy(Mod.class, ElementType.TYPE)
.filter(data -> data.annotationData().get("value").equals(info.getModId()))
.filter(ad -> AutomaticEventSubscriber.getSides(ad.annotationData().get("dist")).contains(FMLLoader.getDist()))
.sorted(Comparator.comparingInt(ad -> -AutomaticEventSubscriber.getSides(ad.annotationData().get("dist")).size()))
.map(ad -> ad.clazz().getClassName())
.toList();
return new FMLModContainer(info, modClasses, modFileScanResults, layer);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@

public class FMLJavaModLanguageProviderTest extends LauncherTest {
// Allows us to capture events received by mods loaded in the game layer
public static List<FMLClientSetupEvent> EVENTS = new ArrayList<>();
public static final List<FMLClientSetupEvent> EVENTS = new ArrayList<>();
public static final List<String> MESSAGES = new ArrayList<>();

@AfterEach
void tearDown() {
EVENTS.clear();
MESSAGES.clear();
}

/**
Expand Down Expand Up @@ -107,6 +109,38 @@ public EntryPoint(net.neoforged.bus.api.IEventBus modEventBus) {
assertThat(EVENTS).hasSize(1);
}

@Test
void testMultipleEntrypoints() throws Exception {
installation.setupProductionClient();

var testJar = installation.writeModJar("test.jar", SimulatedInstallation.createModsToml("testmod", "1.0"));
try (var compiler = RuntimeCompiler.create(testJar)) {
compiler.builder()
.addClass("testmod.EntryPoint", """
@net.neoforged.fml.common.Mod("testmod")
public class EntryPoint {
public EntryPoint() {
net.neoforged.fml.javafmlmod.FMLJavaModLanguageProviderTest.MESSAGES.add("common");
}
}
""")
.addClass("testmod.ClientEntryPoint", """
@net.neoforged.fml.common.Mod(value = "testmod", dist = net.neoforged.api.distmarker.Dist.CLIENT)
public class ClientEntryPoint {
public ClientEntryPoint() {
net.neoforged.fml.javafmlmod.FMLJavaModLanguageProviderTest.MESSAGES.add("client");
}
}
""")
.compile();
}

var result = launch("forgeclient");
loadMods(result);

assertThat(MESSAGES).isEqualTo(List.of("common", "client"));
}

@Test
void testErrorDuringEventDispatch() throws Exception {
installation.setupProductionClient();
Expand Down

0 comments on commit c1fa963

Please sign in to comment.