69 lines
3.2 KiB
Java
69 lines
3.2 KiB
Java
|
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) {
|
||
|
}
|
||
|
}
|