diff --git a/ScalaLoader-Common/src/main/java/xyz/janboerman/scalaloader/plugin/ScalaPluginDescription.java b/ScalaLoader-Common/src/main/java/xyz/janboerman/scalaloader/plugin/ScalaPluginDescription.java index f85a6fa5..09e42e1f 100644 --- a/ScalaLoader-Common/src/main/java/xyz/janboerman/scalaloader/plugin/ScalaPluginDescription.java +++ b/ScalaLoader-Common/src/main/java/xyz/janboerman/scalaloader/plugin/ScalaPluginDescription.java @@ -38,6 +38,7 @@ public class ScalaPluginDescription { private final LinkedHashSet hardDependencies = new LinkedHashSet<>(); private final LinkedHashSet softDependencies = new LinkedHashSet<>(); { addSoftDepend("ScalaLoader"); } private final LinkedHashSet inverseDependencies = new LinkedHashSet<>(); + //TODO paperplugin-style dependencies? private final LinkedHashSet provides = new LinkedHashSet<>(); private final LinkedHashSet mavenDependencies = new LinkedHashSet<>(); private PermissionDefault permissionDefault = null; @@ -493,9 +494,9 @@ public void readFromPluginYamlData(Map pluginYaml) { addContributor(contrib.toString()); website((String) pluginYaml.get("website")); prefix((String) pluginYaml.get("prefix")); - String load = (String) pluginYaml.get("load"); - if (load != null && this.loadOrder == null) - loadOrder(PluginLoadOrder.valueOf(load)); + String pluginLoadOrder = (String) pluginYaml.get("load"); + if (pluginLoadOrder != null && this.loadOrder == null) + loadOrder(PluginLoadOrder.valueOf(pluginLoadOrder)); String defaultPermissionDefault = (String) pluginYaml.get("default-permission"); if (defaultPermissionDefault != null && this.permissionDefault == null) permissionDefault(PermissionDefault.getByName(defaultPermissionDefault)); @@ -514,13 +515,22 @@ public void readFromPluginYamlData(Map pluginYaml) { for (String inverseDep : inverseDepend) if (inverseDep != null) addLoadBefore(inverseDep); - List> paperDependencies = (List>) pluginYaml.get("dependencies"); - if (paperDependencies != null) - for (Map paperDependency : paperDependencies) - if (Boolean.parseBoolean(paperDependency.get("required").toString())) - addHardDepend(paperDependency.get("name").toString()); - else - addSoftDepend(paperDependency.get("name").toString()); + + Object paperDependencies = pluginYaml.get("dependencies"); + if (paperDependencies instanceof List) { + List> paperDeps = (List) paperDependencies; + if (paperDependencies != null) + for (Map paperDependency : paperDeps) + if (Boolean.parseBoolean(paperDependency.get("required").toString())) + addHardDepend(paperDependency.get("name").toString()); + else + addSoftDepend(paperDependency.get("name").toString()); + } else if (paperDependencies instanceof Map) { + //TODO might want to track paper plugin dependencies separately in ScalaPluginDescription or ScalaPluginMeta + Map map = (Map) paperDependencies; + addPaperDependency(this, (Map>) map.get("bootstrap")); + addPaperDependency(this, (Map>) map.get("server")); + } List> paperLoadBefores = (List>) pluginYaml.get("load-before"); if (paperLoadBefores != null) for (Map paperLoadBefore : paperLoadBefores) @@ -529,6 +539,7 @@ public void readFromPluginYamlData(Map pluginYaml) { if (paperLoadAfters != null) for (Map paperLoadAfter : paperLoadAfters) addSoftDepend(paperLoadAfter.get("name").toString()); + List provides = (List) pluginYaml.get("provides"); if (provides != null) provides(provides.toArray(new String[0])); @@ -561,6 +572,29 @@ public void readFromPluginYamlData(Map pluginYaml) { } } + private static void addPaperDependency(ScalaPluginDescription receiver, Map> dependencies) { + for (Map.Entry> entry : dependencies.entrySet()) { + String pluginName = entry.getKey(); + Map dependencyConfig = entry.getValue(); + String load = dependencyConfig.getOrDefault("load", "OMIT").toString(); + boolean required = (Boolean) dependencyConfig.getOrDefault("required", true); + boolean joinClassPath = (Boolean) dependencyConfig.getOrDefault("join-classpath", true); + if (!required) { + if (joinClassPath) { + receiver.addSoftDepend(pluginName); + } else { + receiver.addLoadBefore(pluginName); + } + } else { + switch (load) { + case "BEFORE": receiver.addHardDepend(pluginName); break; + case "AFTER": receiver.addLoadBefore(pluginName); break; + case "OMIT": receiver.addSoftDepend(pluginName); break; + } + } + } + } + private static Permission makePermission(String name, Map properties) { Permission perm = new Permission(name); diff --git a/ScalaLoader-Paper/src/main/java/xyz/janboerman/scalaloader/paper/ScalaLoader.java b/ScalaLoader-Paper/src/main/java/xyz/janboerman/scalaloader/paper/ScalaLoader.java index 080db585..113d4a84 100644 --- a/ScalaLoader-Paper/src/main/java/xyz/janboerman/scalaloader/paper/ScalaLoader.java +++ b/ScalaLoader-Paper/src/main/java/xyz/janboerman/scalaloader/paper/ScalaLoader.java @@ -4,6 +4,7 @@ import com.google.common.graph.GraphBuilder; import com.google.common.graph.MutableGraph; import io.papermc.paper.plugin.bootstrap.PluginBootstrap; +import io.papermc.paper.plugin.bootstrap.PluginProviderContext; import org.bukkit.Server; import org.bukkit.command.CommandMap; import org.bukkit.event.EventHandler; @@ -11,7 +12,6 @@ import org.bukkit.event.server.ServerLoadEvent; import org.bukkit.event.server.ServerLoadEvent.LoadType; import org.bukkit.plugin.PluginLoadOrder; -import org.bukkit.plugin.UnknownDependencyException; import org.bukkit.plugin.java.JavaPlugin; import org.objectweb.asm.ClassReader; import org.yaml.snakeyaml.Yaml; @@ -29,6 +29,7 @@ import xyz.janboerman.scalaloader.dependency.PluginYamlLibraryLoader; import xyz.janboerman.scalaloader.event.EventBus; import xyz.janboerman.scalaloader.event.plugin.ScalaPluginEnableEvent; +import xyz.janboerman.scalaloader.paper.plugin.ScalaPluginBootstrapContext; import xyz.janboerman.scalaloader.plugin.PluginScalaVersion; import xyz.janboerman.scalaloader.plugin.ScalaCompatMap; import xyz.janboerman.scalaloader.plugin.ScalaPluginDescription; @@ -62,6 +63,7 @@ import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; @@ -295,14 +297,14 @@ private void loadScalaPlugins(File[] files) { ScalaPluginDescription description = descriptions.get(file); //TODO check dependencies. if not available, might want to try to load the ScalaPlugin again once Paper's own JavaPlugin loading process has finished. - ScalaPluginProviderContext context = new ScalaPluginProviderContext(file, description); + ScalaPluginProviderContext context = makeScalaPluginProviderContext(file, description); //used to be just new ScalaPluginProviderContext(file, description) var optionalBootstrap = getBootstrap(description, descriptionPlugins.get(file).descriptionClassLoader()); if (optionalBootstrap.isEmpty()) continue; PluginBootstrap bootstrapper = optionalBootstrap.get(); ScalaPluginLoader loader = new ScalaPluginLoader(); ScalaPluginClasspathBuilder pluginClasspathBuilder = new ScalaPluginClasspathBuilder(context); - bootstrapper.bootstrap(context); + bootstrap(bootstrapper, context); //used to be just boostrapper.bootstrap(context), but PluginBootstrap#bootstrap(PluginProviderContext) got changed to PluginBootstrap#bootstrap(BootstrapContext). loader.classloader(pluginClasspathBuilder); var optionalPlugin = buildPlugin(pluginName, file, context, scanResult, loader, bootstrapper, pluginClasspathBuilder); @@ -317,6 +319,44 @@ private void loadScalaPlugins(File[] files) { } + private static ScalaPluginProviderContext makeScalaPluginProviderContext(File file, ScalaPluginDescription description) { + try { + Class.forName("io.papermc.paper.plugin.bootstrap.BootstrapContext"); + return new ScalaPluginBootstrapContext(file, description); + } catch (ClassNotFoundException e) { + return new ScalaPluginProviderContext(file, description); + } + } + + private static void bootstrap(PluginBootstrap bootstrapper, ScalaPluginProviderContext context) { + Method bootstrap = null; + RuntimeException ex = new RuntimeException("could not bootstrap plugin using bootstrapper: " + bootstrapper + " and context " + context); + + try { + Class bootstrapContextClazz = Class.forName("io.papermc.paper.plugin.bootstrap.BootstrapContext"); + bootstrap = PluginBootstrap.class.getMethod("bootstrap", bootstrapContextClazz); + } catch (ReflectiveOperationException e1) { + ex.addSuppressed(e1); + + try { + bootstrap = PluginBootstrap.class.getMethod("bootstrap", PluginProviderContext.class); + } catch (ReflectiveOperationException e2) { + ex.addSuppressed(e2); + } + } + + if (bootstrap != null) { + try { + bootstrap.invoke(bootstrapper, context); + return; + } catch (IllegalAccessException | InvocationTargetException e) { + ex.addSuppressed(e); + } + } + + throw ex; + } + private void enableScalaPlugins(PluginLoadOrder loadOrder) { for (ScalaPlugin plugin : getScalaPlugins()) { if (!plugin.isEnabled() && plugin.getPluginMeta().getLoadOrder() == loadOrder) { diff --git a/ScalaLoader-Paper/src/main/java/xyz/janboerman/scalaloader/paper/plugin/ScalaPluginBootstrap.java b/ScalaLoader-Paper/src/main/java/xyz/janboerman/scalaloader/paper/plugin/ScalaPluginBootstrap.java index c9612df3..e4f33ea3 100644 --- a/ScalaLoader-Paper/src/main/java/xyz/janboerman/scalaloader/paper/plugin/ScalaPluginBootstrap.java +++ b/ScalaLoader-Paper/src/main/java/xyz/janboerman/scalaloader/paper/plugin/ScalaPluginBootstrap.java @@ -1,5 +1,6 @@ package xyz.janboerman.scalaloader.paper.plugin; +import io.papermc.paper.plugin.bootstrap.BootstrapContext; import io.papermc.paper.plugin.bootstrap.PluginBootstrap; import io.papermc.paper.plugin.bootstrap.PluginProviderContext; import org.jetbrains.annotations.NotNull; @@ -14,7 +15,7 @@ */ public class ScalaPluginBootstrap implements PluginBootstrap { - @Override + /*@Override*/ public void bootstrap(@NotNull PluginProviderContext context) { //context provides access to: // - configuration (ScalaPluginMeta) @@ -27,6 +28,11 @@ public void bootstrap(@NotNull PluginProviderContext context) { scalaPluginMeta.description.setScalaVersion(compatMap.getLatestVersion(scalaPluginMeta.getScalaVersion()).getVersionString()); } + @Override + public void bootstrap(@NotNull BootstrapContext context) { + bootstrap((PluginProviderContext) context); + } + @Override public @NotNull ScalaPlugin createPlugin(@NotNull PluginProviderContext context) { ScalaPluginProviderContext scalaContext = (ScalaPluginProviderContext) context; diff --git a/ScalaLoader-Paper/src/main/java/xyz/janboerman/scalaloader/paper/plugin/ScalaPluginBootstrapContext.java b/ScalaLoader-Paper/src/main/java/xyz/janboerman/scalaloader/paper/plugin/ScalaPluginBootstrapContext.java new file mode 100644 index 00000000..20d79e69 --- /dev/null +++ b/ScalaLoader-Paper/src/main/java/xyz/janboerman/scalaloader/paper/plugin/ScalaPluginBootstrapContext.java @@ -0,0 +1,12 @@ +package xyz.janboerman.scalaloader.paper.plugin; + +import io.papermc.paper.plugin.bootstrap.BootstrapContext; +import xyz.janboerman.scalaloader.plugin.ScalaPluginDescription; + +import java.io.File; + +public class ScalaPluginBootstrapContext extends ScalaPluginProviderContext implements BootstrapContext { + public ScalaPluginBootstrapContext(File pluginJarFile, ScalaPluginDescription description) { + super(pluginJarFile, description); + } +} diff --git a/ScalaLoader-Paper/src/main/java/xyz/janboerman/scalaloader/paper/plugin/ScalaPluginMeta.java b/ScalaLoader-Paper/src/main/java/xyz/janboerman/scalaloader/paper/plugin/ScalaPluginMeta.java index e8affd6c..dbf774e1 100644 --- a/ScalaLoader-Paper/src/main/java/xyz/janboerman/scalaloader/paper/plugin/ScalaPluginMeta.java +++ b/ScalaLoader-Paper/src/main/java/xyz/janboerman/scalaloader/paper/plugin/ScalaPluginMeta.java @@ -1,6 +1,8 @@ package xyz.janboerman.scalaloader.paper.plugin; import io.papermc.paper.plugin.provider.configuration.PaperPluginMeta; +import io.papermc.paper.plugin.provider.configuration.type.DependencyConfiguration; +import io.papermc.paper.plugin.provider.configuration.type.DependencyConfiguration.LoadOrder; import org.bukkit.permissions.Permission; import org.bukkit.permissions.PermissionDefault; import org.bukkit.plugin.PluginLoadOrder; @@ -19,6 +21,7 @@ public class ScalaPluginMeta extends PaperPluginMeta /*implements PluginMeta*/ { + //TODO separate paper plugin dependency configuration? final ScalaPluginDescription description; public ScalaPluginMeta(ScalaPluginDescription description) { @@ -77,6 +80,36 @@ public ScalaPluginMeta(ScalaPluginDescription description) { return Compat.listCopy(description.getProvides()); } + //TODO track new paper-style dependency configuration separately? + @Override + public Map getServerDependencies() { + Map res = new HashMap<>(); + + for (String pluginName : getPluginDependencies()) { + res.put(pluginName, new DependencyConfiguration(LoadOrder.BEFORE, true, true)); + } + for (String pluginName : getPluginSoftDependencies()) { + res.put(pluginName, new DependencyConfiguration(LoadOrder.OMIT, false, true)); + } + for (String pluginName : getLoadBeforePlugins()) { + res.put(pluginName, new DependencyConfiguration(LoadOrder.AFTER, true, true)); + } + + return res; + } + + //TODO track new paper-style dependency configuration separately? + @Override + public Map getBoostrapDependencies() { + Map res = new HashMap<>(); + + for (String pluginName : getPluginDependencies()) { + res.put(pluginName, new DependencyConfiguration(LoadOrder.BEFORE, true, true)); + } + + return res; + } + @Override public @NotNull List getAuthors() { return description.getAuthors();