LibJF/libjf-unsafe-v0/src/main/java/io/gitlab/jfronny/libjf/unsafe/DynamicEntry.java

64 lines
3.0 KiB
Java

package io.gitlab.jfronny.libjf.unsafe;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.ModContainer;
import net.fabricmc.loader.impl.ModContainerImpl;
import net.fabricmc.loader.impl.metadata.EntrypointMetadata;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
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<>();
for (final EntrypointContainer entrypoint : getEntrypointTargets(name)) {
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 Collection<EntrypointContainer> getEntrypointTargets(final String entrypoint) {
final List<EntrypointContainer> entrypoints = new LinkedList<>();
for (final ModContainer mod : FabricLoader.getInstance().getAllMods()) {
final List<EntrypointMetadata> modEntrypoints = ((ModContainerImpl)mod).getMetadata().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) {
}
}