Skip to content

Commit

Permalink
Move EventBusSubscriber to top-level and cleanup Bindings suppliers (
Browse files Browse the repository at this point in the history
…#118)

* Move EventBusSubscriber to top-level and cleanup Bindings suppliers

* Inline I18nParser into IBindingsProvider

* Rename FORGE bus to GAME bus

* Add EBS snippet in javadoc
  • Loading branch information
Technici4n authored Apr 20, 2024
1 parent 4b4447a commit fa57788
Show file tree
Hide file tree
Showing 9 changed files with 113 additions and 105 deletions.
31 changes: 17 additions & 14 deletions loader/src/main/java/net/neoforged/fml/Bindings.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,38 @@

package net.neoforged.fml;

import cpw.mods.modlauncher.util.ServiceLoaderUtils;
import java.util.ServiceLoader;
import java.util.function.Supplier;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.fml.config.IConfigEvent;
import net.neoforged.fml.loading.FMLLoader;
import org.jetbrains.annotations.ApiStatus;

@ApiStatus.Internal
public class Bindings {
private static final Bindings INSTANCE = new Bindings();
private static final IBindingsProvider provider;

private final IBindingsProvider provider;

private Bindings() {
final var providers = ServiceLoaderUtils.streamServiceLoader(() -> ServiceLoader.load(FMLLoader.getGameLayer(), IBindingsProvider.class), sce -> {}).toList();
static {
var providers = ServiceLoader.load(FMLLoader.getGameLayer(), IBindingsProvider.class)
.stream().toList();
if (providers.size() != 1) {
throw new IllegalStateException("Could not find bindings provider");
}
this.provider = providers.get(0);
provider = providers.get(0).get();
}

public static IEventBus getGameBus() {
return provider.getGameBus();
}

public static Supplier<IEventBus> getForgeBus() {
return INSTANCE.provider.getForgeBusSupplier();
public static String parseMessage(String i18nMessage, Object... args) {
return provider.parseMessage(i18nMessage, args);
}

public static Supplier<I18NParser> getMessageParser() {
return INSTANCE.provider.getMessageParser();
public static String stripControlCodes(String toStrip) {
return provider.stripControlCodes(toStrip);
}

public static Supplier<IConfigEvent.ConfigConfig> getConfigConfiguration() {
return INSTANCE.provider.getConfigConfiguration();
public static IConfigEvent.ConfigConfig getConfigConfiguration() {
return provider.getConfigConfiguration();
}
}
12 changes: 0 additions & 12 deletions loader/src/main/java/net/neoforged/fml/I18NParser.java

This file was deleted.

11 changes: 7 additions & 4 deletions loader/src/main/java/net/neoforged/fml/IBindingsProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,17 @@

package net.neoforged.fml;

import java.util.function.Supplier;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.fml.config.IConfigEvent;
import org.jetbrains.annotations.ApiStatus;

@ApiStatus.Internal
public interface IBindingsProvider {
Supplier<IEventBus> getForgeBusSupplier();
IEventBus getGameBus();

Supplier<I18NParser> getMessageParser();
String parseMessage(String i18nMessage, Object... args);

Supplier<IConfigEvent.ConfigConfig> getConfigConfiguration();
String stripControlCodes(String toStrip);

IConfigEvent.ConfigConfig getConfigConfiguration();
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public Object[] getContext() {

public String formatToString() {
// TODO: cleanup null here - this requires moving all indices in the translations
return Bindings.getMessageParser().get().parseMessage(i18nMessage, Streams.concat(Stream.of(modInfo, null, getCause()), context.stream()).toArray());
return Bindings.parseMessage(i18nMessage, Streams.concat(Stream.of(modInfo, null, getCause()), context.stream()).toArray());
}

@Override
Expand All @@ -66,6 +66,6 @@ public IModInfo getModInfo() {
}

public String getCleanMessage() {
return Bindings.getMessageParser().get().stripControlCodes(formatToString());
return Bindings.stripControlCodes(formatToString());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public ModLoadingWarning(final IModInfo modInfo, final String i18nMessage, Objec

public String formatToString() {
// TODO: cleanup null here - this requires moving all indices in the translations
return Bindings.getMessageParser().get().parseMessage(i18nMessage, Streams.concat(Stream.of(modInfo, null), context.stream()).toArray());
return Bindings.parseMessage(i18nMessage, Streams.concat(Stream.of(modInfo, null), context.stream()).toArray());
}

static Stream<ModLoadingWarning> fromEarlyException(final EarlyLoadingException e) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/

package net.neoforged.fml.common;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.ModContainer;

// @formatter:off - spotless doesn't like @
/**
* Annotate a class which will be subscribed to an Event Bus at mod construction time. Defaults to subscribing the current modid to the {@code NeoForge#EVENT_BUS} on both sides.
*
* <p>Annotated classes will be scanned for <b>static</b> methods that have the {@link SubscribeEvent} annotation.
* For example:
*
* {@snippet :
* @EventBusSubscriber
* public class MyEventHandler {
* @SubscribeEvent
* private static void onSomeEvent(SomeEvent event) {
* // SomeEvent handler here
* }
*
* @SubscribeEvent
* private static void onAnotherEvent(AnotherEvent event) {
* // AnotherEvent handler here
* }
* }
* }
*
* @see Bus
*/
// @formatter:on
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface EventBusSubscriber {
/**
* Specify targets to load this event subscriber on. Can be used to avoid loading Client specific events on a dedicated server, for example.
*
* @return an array of Dist to load this event subscriber on
*/
Dist[] value() default { Dist.CLIENT, Dist.DEDICATED_SERVER };

/**
* Optional value, only necessary if this annotation is not on the same class that has a @Mod annotation. Needed to prevent early classloading of classes not owned by your mod.
*
* @return a modid
*/
String modid() default "";

/**
* Specify an alternative bus to listen to
*
* @return the bus you wish to listen to
*/
Bus bus() default Bus.GAME;

enum Bus {
/**
* The main NeoForge Event Bus, used after the game has started up.
*
* <p>See {@code NeoForge#EVENT_BUS}</p>
*/
GAME,
/**
* The mod-specific Event bus, used during startup.
*
* @see ModContainer#getEventBus()
*/
MOD,
}
}
66 changes: 0 additions & 66 deletions loader/src/main/java/net/neoforged/fml/common/Mod.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,6 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.function.Supplier;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.fml.Bindings;
import net.neoforged.fml.ModContainer;
import net.neoforged.fml.javafmlmod.FMLJavaModLoadingContext;

/**
* This defines a Mod to FML.
Expand All @@ -33,64 +27,4 @@
* By default, you will have a resource domain that matches the modid. All these uses require that constraints are imposed on the format of the modid.
*/
String value();

/**
* Annotate a class which will be subscribed to an Event Bus at mod construction time.
* Defaults to subscribing the current modid to the {@code NeoForge#EVENT_BUS}
* on both sides.
*
* @see Bus
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface EventBusSubscriber {
/**
* Specify targets to load this event subscriber on. Can be used to avoid loading Client specific events
* on a dedicated server, for example.
*
* @return an array of Dist to load this event subscriber on
*/
Dist[] value() default { Dist.CLIENT, Dist.DEDICATED_SERVER };

/**
* Optional value, only necessary if this annotation is not on the same class that has a @Mod annotation.
* Needed to prevent early classloading of classes not owned by your mod.
*
* @return a modid
*/
String modid() default "";

/**
* Specify an alternative bus to listen to
*
* @return the bus you wish to listen to
*/
Bus bus() default Bus.FORGE;

enum Bus {
/**
* The main Forge Event Bus.
*
* <p>See {@code NeoForge#EVENT_BUS}</p>
*/
FORGE(Bindings.getForgeBus()),
/**
* The mod specific Event bus.
*
* @see ModContainer#getEventBus()
*/
MOD(() -> FMLJavaModLoadingContext.get().getModEventBus());

private final Supplier<IEventBus> busSupplier;

Bus(final Supplier<IEventBus> eventBusSupplier) {
this.busSupplier = eventBusSupplier;
}

@Deprecated(forRemoval = true)
public Supplier<IEventBus> bus() {
return busSupplier;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
public interface IConfigEvent {
record ConfigConfig(Function<ModConfig, IConfigEvent> loading, Function<ModConfig, IConfigEvent> reloading, @Nullable Function<ModConfig, IConfigEvent> unloading) {}

ConfigConfig CONFIGCONFIG = Bindings.getConfigConfiguration().get();
ConfigConfig CONFIGCONFIG = Bindings.getConfigConfiguration();

static IConfigEvent reloading(ModConfig modConfig) {
return CONFIGCONFIG.reloading().apply(modConfig);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import net.neoforged.bus.api.IEventBus;
import net.neoforged.fml.Bindings;
import net.neoforged.fml.ModContainer;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.fml.common.Mod;
import net.neoforged.fml.loading.FMLEnvironment;
import net.neoforged.fml.loading.moddiscovery.ModAnnotation;
Expand All @@ -26,13 +27,13 @@
import org.objectweb.asm.Type;

/**
* Automatic eventbus subscriber - reads {@link Mod.EventBusSubscriber}
* annotations and passes the class instances to the {@link Mod.EventBusSubscriber.Bus}
* Automatic eventbus subscriber - reads {@link EventBusSubscriber}
* annotations and passes the class instances to the {@link EventBusSubscriber.Bus}
* defined by the annotation. Defaults to {@code NeoForge#EVENT_BUS}
*/
public class AutomaticEventSubscriber {
private static final Logger LOGGER = LogManager.getLogger();
private static final Type AUTO_SUBSCRIBER = Type.getType(Mod.EventBusSubscriber.class);
private static final Type AUTO_SUBSCRIBER = Type.getType(EventBusSubscriber.class);
private static final Type MOD_TYPE = Type.getType(Mod.class);

public static void inject(final ModContainer mod, final ModFileScanData scanData, final ClassLoader loader) {
Expand All @@ -47,11 +48,11 @@ public static void inject(final ModContainer mod, final ModFileScanData scanData
final EnumSet<Dist> sides = sidesValue.stream().map(eh -> Dist.valueOf(eh.getValue())).collect(Collectors.toCollection(() -> EnumSet.noneOf(Dist.class)));
final String modId = (String) ad.annotationData().getOrDefault("modid", modids.getOrDefault(ad.clazz().getClassName(), mod.getModId()));
final ModAnnotation.EnumHolder busTargetHolder = (ModAnnotation.EnumHolder) ad.annotationData().getOrDefault("bus", new ModAnnotation.EnumHolder(null, "FORGE"));
final Mod.EventBusSubscriber.Bus busTarget = Mod.EventBusSubscriber.Bus.valueOf(busTargetHolder.getValue());
final EventBusSubscriber.Bus busTarget = EventBusSubscriber.Bus.valueOf(busTargetHolder.getValue());
if (Objects.equals(mod.getModId(), modId) && sides.contains(FMLEnvironment.dist)) {
try {
IEventBus bus = switch (busTarget) {
case FORGE -> Bindings.getForgeBus().get();
case GAME -> Bindings.getGameBus();
case MOD -> mod.getEventBus();
};

Expand Down

0 comments on commit fa57788

Please sign in to comment.