Separate plugin types #10

Merged
owlsys merged 14 commits from ecorous/plugin-types into main 2024-06-16 17:13:54 -04:00
3 changed files with 99 additions and 80 deletions
Showing only changes of commit a3aab3d87c - Show all commits

View file

@ -1,6 +1,6 @@
plugins {
java
id("dev.frogmc.phytotelma") version "0.0.1-alpha.6"
id("dev.frogmc.phytotelma") version "0.0.1-alpha.7"
}
repositories {
@ -20,7 +20,7 @@ dependencies {
}
phytotelma {
minecraft("1.20.6")
minecraft("1.21", "1.20.6")
}
java {

View file

@ -18,8 +18,6 @@ import dev.frogmc.frogloader.api.plugin.FrogGamePlugin;
import dev.frogmc.frogloader.api.plugin.FrogModProvider;
import dev.frogmc.frogloader.impl.gui.LoaderGui;
import dev.frogmc.frogloader.impl.launch.MixinClassLoader;
import dev.frogmc.frogloader.impl.mixin.AWProcessor;
import dev.frogmc.frogloader.impl.mod.BuiltinExtensions;
import dev.frogmc.frogloader.impl.mod.ModUtil;
import dev.frogmc.frogloader.impl.util.CrashReportGenerator;
import dev.frogmc.frogloader.impl.util.SystemProperties;
@ -27,40 +25,32 @@ import lombok.Getter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spongepowered.asm.mixin.MixinEnvironment;
import org.spongepowered.asm.mixin.Mixins;
public class FrogLoaderImpl implements FrogLoader {
private static final boolean DEV_ENV = Boolean.getBoolean(SystemProperties.DEVELOPMENT);
private static final Logger LOGGER = LoggerFactory.getLogger("FrogLoader");
@Getter
private static FrogLoaderImpl instance;
@Getter
private final String[] args;
@Getter
private final Env env;
private final Logger LOGGER = LoggerFactory.getLogger("FrogLoader");
@Getter
private FrogGamePlugin gamePlugin;
@Getter
private final Collection<FrogModProvider> modProviders = new ArrayList<>();
@Getter
private final Path gameDir, configDir;
@Getter
private final Collection<Path> modsDirs = new HashSet<>();
@Getter
private final MixinClassLoader classloader;
@Getter
private final Gson gson = new Gson();
private final Map<String, Map<String, ModProperties>> mods = new HashMap<>();
@Getter
private FrogGamePlugin gamePlugin;
@Getter
private String gameVersion;
private final Map<String, Map<String, ModProperties>> mods = new HashMap<>();
private Collection<String> modIds = new ArrayList<>();
@ -81,8 +71,8 @@ public class FrogLoaderImpl implements FrogLoader {
}
try {
discoverGamePlugins();
discoverModProviders();
loadGamePlugin();
loadModProviders();
modProviders.stream().map(FrogModProvider::loadDirectory).map(gameDir::resolve).forEach(modsDirs::add);
advanceMixinState();
modIds = collectModIds();
@ -114,59 +104,8 @@ public class FrogLoaderImpl implements FrogLoader {
}
}
private void discoverModProviders() {
LOGGER.info("Discovering mod providers...");
for (FrogModProvider plugin : ServiceLoader.load(FrogModProvider.class)) {
LOGGER.debug("Found mod provider: {}", plugin.getClass().getName());
if (!plugin.isApplicable()) {
continue;
}
try {
LOGGER.debug("Initialising mod provider: {}", plugin.id());
Map<String, ModProperties> modsFromProvider = new HashMap<>();
Collection<ModProperties> loadedMods = plugin.loadMods(Discovery.find(gameDir.resolve(plugin.loadDirectory()), plugin::isDirectoryApplicable, plugin::isFileApplicable));
initModMixins(loadedMods);
AWProcessor.load(loadedMods);
loadedMods.forEach(m -> modsFromProvider.put(m.id(), m));
LOGGER.debug("Loaded {} mod(s) from provider: {}", modsFromProvider.size(), plugin.id());
mods.put(plugin.id(), modsFromProvider);
modIds.addAll(modsFromProvider.keySet());
modProviders.add(plugin);
} catch (Throwable e) {
LOGGER.error("Error during plugin initialisation: ", e);
}
}
}
@SuppressWarnings({"rawtypes", "unchecked"})
private void initModMixins(Collection<ModProperties> loadedMods) {
loadedMods.forEach(props -> {
Object o = props.extensions().get(BuiltinExtensions.MIXIN_CONFIG);
if (o instanceof String name) {
Mixins.addConfiguration(name);
} else if (o instanceof Collection l) {
((Collection<String>) l).forEach(Mixins::addConfiguration);
}
});
}
private void discoverGamePlugins() {
LOGGER.info("Discovering game plugins...");
ServiceLoader<FrogGamePlugin> loader = ServiceLoader.load(FrogGamePlugin.class);
loader.stream().map(ServiceLoader.Provider::get).forEach(p -> LOGGER.info("Found game plugin: {}", p.getClass().getName()));
FrogGamePlugin[] applicablePlugins = ServiceLoader.load(FrogGamePlugin.class).stream().map(ServiceLoader.Provider::get).filter(FrogGamePlugin::isApplicable).toArray(FrogGamePlugin[]::new);
if (applicablePlugins.length > 1) {
throw new IllegalStateException("Multiple applicable game plugins found!");
} else if (applicablePlugins.length == 0) {
throw new IllegalStateException("No applicable game plugin found!");
}
FrogGamePlugin plugin = applicablePlugins[0]; // we can skip the loop as we always will only have one element
try {
plugin.init(this);
private void loadGamePlugin() {
FrogGamePlugin plugin = PluginLoader.discoverGamePlugins();
gameVersion = plugin.queryVersion();
ModProperties gameMod = plugin.getGameMod();
if (gameMod != null) {
@ -174,11 +113,10 @@ public class FrogLoaderImpl implements FrogLoader {
modIds.add(gameMod.id());
}
gamePlugin = plugin;
} catch (Throwable e) {
LOGGER.error("Error during plugin initialisation: ", e);
throw new RuntimeException(e);
}
private void loadModProviders() {
PluginLoader.discoverModProviders(gameDir, mods, modIds, modProviders);
}
public String getArgument(String name) {

View file

@ -0,0 +1,81 @@
package dev.frogmc.frogloader.impl;
import java.nio.file.Path;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.ServiceLoader;
import dev.frogmc.frogloader.api.FrogLoader;
import dev.frogmc.frogloader.api.mod.ModProperties;
import dev.frogmc.frogloader.api.plugin.FrogGamePlugin;
import dev.frogmc.frogloader.api.plugin.FrogModProvider;
import dev.frogmc.frogloader.impl.mixin.AWProcessor;
import dev.frogmc.frogloader.impl.mod.BuiltinExtensions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spongepowered.asm.mixin.Mixins;
public class PluginLoader {
private static final Logger LOGGER = LoggerFactory.getLogger("FrogLoader/Plugins");
public static void discoverModProviders(Path gameDir, Map<String, Map<String, ModProperties>> mods, Collection<String> modIds, Collection<FrogModProvider> modProviders) {
LOGGER.info("Discovering mod providers...");
for (FrogModProvider plugin : ServiceLoader.load(FrogModProvider.class)) {
LOGGER.debug("Found mod provider: {}", plugin.getClass().getName());
if (!plugin.isApplicable()) {
continue;
}
try {
LOGGER.debug("Initialising mod provider: {}", plugin.id());
Map<String, ModProperties> modsFromProvider = new HashMap<>();
Collection<ModProperties> loadedMods = plugin.loadMods(Discovery.find(gameDir.resolve(plugin.loadDirectory()), plugin::isDirectoryApplicable, plugin::isFileApplicable));
initializeModMixins(loadedMods);
AWProcessor.load(loadedMods);
loadedMods.forEach(m -> modsFromProvider.put(m.id(), m));
LOGGER.debug("Loaded {} mod(s) from provider: {}", modsFromProvider.size(), plugin.id());
mods.put(plugin.id(), modsFromProvider);
modIds.addAll(modsFromProvider.keySet());
modProviders.add(plugin);
} catch (Throwable e) {
LOGGER.error("Error during plugin initialisation: ", e);
}
}
}
@SuppressWarnings({"rawtypes", "unchecked"})
private static void initializeModMixins(Collection<ModProperties> loadedMods) {
loadedMods.forEach(props -> {
Object o = props.extensions().get(BuiltinExtensions.MIXIN_CONFIG);
if (o instanceof String name) {
Mixins.addConfiguration(name);
} else if (o instanceof Collection l) {
((Collection<String>) l).forEach(Mixins::addConfiguration);
}
});
}
public static FrogGamePlugin discoverGamePlugins() {
LOGGER.info("Discovering game plugins...");
ServiceLoader<FrogGamePlugin> loader = ServiceLoader.load(FrogGamePlugin.class);
loader.stream().map(ServiceLoader.Provider::get).forEach(p -> LOGGER.info("Found game plugin: {}", p.getClass().getName()));
FrogGamePlugin[] applicablePlugins = ServiceLoader.load(FrogGamePlugin.class).stream().map(ServiceLoader.Provider::get).filter(FrogGamePlugin::isApplicable).toArray(FrogGamePlugin[]::new);
if (applicablePlugins.length > 1) {
throw new IllegalStateException("Multiple applicable game plugins found!");
} else if (applicablePlugins.length == 0) {
throw new IllegalStateException("No applicable game plugin found!");
}
FrogGamePlugin plugin = applicablePlugins[0]; // we can skip the loop as we always will only have one element
try {
plugin.init(FrogLoader.getInstance());
return plugin;
} catch (Throwable e) {
LOGGER.error("Error during plugin initialisation: ", e);
throw new RuntimeException(e);
}
}
}