LibJF/src/main/java/io/gitlab/jfronny/libjf/entry/DynamicEntry.java

69 lines
3.2 KiB
Java
Raw Normal View History

package io.gitlab.jfronny.libjf.entry;
import it.unimi.dsi.fastutil.objects.ReferenceArrayList;
import net.fabricmc.loader.ModContainer;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.metadata.EntrypointMetadata;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.function.Consumer;
public class DynamicEntry {
/**
* Execute an entrypoint.
*
* @param name the name of the entrypoint to execute.
* @param entrypointType the entrypoint type.
* @param onExecute entrypoint execution callback with an instance of the entrypoint type.
* @param <T> the entrypoint type.
*/
public static <T> void execute(final String name, final Class<T> entrypointType, final Consumer<ConsumableEntrypoint<T>> onExecute) {
final List<ConsumableEntrypoint<T>> targets = new ArrayList<>();
final ReferenceArrayList<EntrypointContainer> entrypoints = getEntrypointTargets(name);
for (final EntrypointContainer entrypoint : entrypoints) {
try {
targets.add(new ConsumableEntrypoint<>(
entrypointType.cast(Class.forName(entrypoint.entrypoint).getConstructor().newInstance()),
entrypoint.mod
));
} catch (final ClassNotFoundException exception) {
throw new IllegalArgumentException(String.format("class %s specified in the %s entrypoint of mod %s does not exist", entrypoint.entrypoint, name, entrypoint.mod), exception);
} catch (final IllegalAccessException | InstantiationException | NoSuchMethodException exception) {
throw new IllegalStateException(String.format("class %s specified in the %s entrypoint of mod %s cannot be instantiated", entrypoint.entrypoint, name, entrypoint.mod), exception);
} catch (final InvocationTargetException exception) {
throw new RuntimeException(String.format("an error was encountered during the instantiation of the %s entrypoint class %s", name, entrypoint.entrypoint), exception);
}
}
for (ConsumableEntrypoint<T> target : targets) {
onExecute.accept(target);
}
}
private static ReferenceArrayList<EntrypointContainer> getEntrypointTargets(final String entrypoint) {
final ReferenceArrayList<EntrypointContainer> entrypoints = ReferenceArrayList.wrap(new EntrypointContainer[1], 0);
for (final ModContainer mod : (Collection<ModContainer>) (Object) FabricLoader.getInstance().getAllMods()) {
final List<EntrypointMetadata> modEntrypoints = mod.getInfo().getEntrypoints(entrypoint);
if (modEntrypoints != null) {
for (final EntrypointMetadata metadata : modEntrypoints) {
entrypoints.add(new EntrypointContainer(metadata.getValue(), mod.getMetadata().getId()));
}
}
}
return entrypoints;
}
record EntrypointContainer(String entrypoint, String mod) {
}
public record ConsumableEntrypoint<T>(T instance, String modId) {
}
}