Add support for paper-plugin.yml - #30
Conversation
|
@TheMeinerLP @rainbowdashlabs Could you coordinate/agree on one of the two PRs adding support for the |
* Improve handling of gradle domain object container * Improve handling of gradle domain object container * Improve readme * Fix typos * Add group for plugin yml into gradle * Fix group for plugin yml into gradle * Add version check for paper plugins
* Improve handling of gradle domain object container * Improve handling of gradle domain object container * Improve readme * Fix typos * Add group for plugin yml into gradle * Fix group for plugin yml into gradle * Add version check for paper plugins * Add code generator for paper plugins * Ignore libs for paper-plugin yml * Rename dependencies to depends to avoid conflicts * Add check for substring * Fix string validation * Improve generation of help classes * Add option to enable code generation * Add license * Add process trigger * Fix process trigger * Add package name for generation --------- Co-authored-by: Florian Fülling <46890129+RainbowDashLabs@users.noreply.github.com>
|
@stephan-gh We combined our two PRs. @TheMeinerLP did great work on the dynamic class generation to provide libraries and repositories inside the plugin. The plugin is ready for review and I checked that it works on paper servers. I also updated the readme to include information about the paper module. |
|
Can you add also for normal "bukkit" plugins the folia support ? |
|
I did this in #31 since it is not scope of this PR |
Since this feature is required for paper anyway, I would include it since it is somehow a fixed dependency. There are of course a lot of points still to improve, but I would prefer to stick to the initial scope of the PR which is simply "add support for paper plugins" and not "add a plugin for library exporting". Stuff I would set on my list for future goals of this gradle plugin would be:
But that is future stuff and I would prefer to tackle this in future PRs. |
This sounds good and is likely indeed a good idea to speed up the review!
But I'm confused about this part: How come is the library functionality a fixed dependency of the Paper plugin? The main purpose of plugin-yml is to generate the plugin description file ( The way I understand it the same applies to Paper: They offer an API to load additional libraries but plugins are free to implement the library selection in any way they like. We can offer help with this, by generating a custom It's probably easiest if we do it like you suggested, focus on "adding support for paper plugins" first. But then Paper should be set up like Nukkit and don't offer the "library exporting" at all in the first step. |
|
That might be the viewpoint from a development side. However I would also take a look at all this from the majority of the user side. Nearly every person person usually has the normal plugin yml. Adding a version replacement is not that much work. However most of the people decide to use this plugin once they want to load libraries. Imo that is the main selling point of this plugin. For me as well. It is simply a feature that users of the bukkit and in the future the paper module expect. I dont know what capabilities nukkit has, but from my view it doesnt seem to be important, otherwise this feature would exist already. My approach would be to implement a generic approach to create such a file for any platform by simply extending a barebone class which allows this. This would then be added for the required platforms and enabled those who are supposed to use it to use it properly. Making this a general dependency might cause some other issues:
But also honestly I grew a bit tired of this PR already. The first suggestions were reasonable, but I feel like we are starting to argue a lot about personal preferences. |
I'm not sure why this implementation detail needs to be exposed to the user. Sharing the json generation code between platforms is already easy — we already have generic-icity between the different platform types in the form of However, it may be justified if specifying the Anyways, I like the current state of the PR, and would also be fine with any small tweak to the idea. Should emphasize that the differences between these approaches are very minor and may not be consequential. (But on the other hand I guess there is time to debate and get it right the first time, since Paper Plugins are still an alpha feature of PaperMC.) |
For me the reason I made this plugin is that I was "annoyed" by having to write several subtly different template YAML files with placeholders for version, description, author, website. This is also why the plugin tries to fill out those automatically with information from the Gradle project. I haven't used the "library exporting" feature much myself. However, I understand how this can be very useful as well and I think it's perfectly fine if everyone finds different value in using the plugin. The difficult part for libraries on Paper is that we don't have a "standard" solution to work with. The various options we have already discussed, i.e.
make it obvious that this part is very subjective and everyone has slightly different personal preferences. Perhaps some project setups work better with the code generation approach, while for others the JSON file is more simple. Ideally I would like plugin-yml to be as "impartial" as possible. The core functionality right now is defined exactly by the specification of the plugin-y(a)ml files, with convenient integration into Gradle where appropriate. For Bukkit/Bungee, we can output Providing opinionated defaults for convenience of most users is also nice, but in my opinion those should be clearly separated and optional. And this is the part I'm not entirely sure about yet. If Bukkit/Bungee did not already have the library functionality I probably would have suggested "implement this in a separate plugin + project" right from the start, since it goes beyond generating the plugin-y(a)ml file. And this would not be a bad thing at all - Gradle has a flexible plugin architecture that allows combining plugin-yml with any number of other plugins. We do however have that functionality for Bukkit/Bungee, and I also understand the argument that people coming from Bukkit expect the same functionality to work on Paper. It's not that easy though because Paper is simply different, and people still need to copy the example code, set up the loader correctly etc. Otherwise they will just find the I perfectly understand if you find my thoughts a bit "overengineered", but for me personally a clear separation of the purposes and responsibilities on the design level is important. I believe this makes the end result easier to understand and also easier to maintain (which will be my job). TL;DR: I probably just need some more time to think about this and maybe experiment with some options myself. -> As mentioned before I suggest we focus on the |
This is a bit cleaner for the implementation and allows Nukkit to use the mechanism as well. The generated files are now called "<type>-libraries.json" (e.g. "paper-libraries.json") to avoid conflicts when used for more than just Paper.
|
I'm still not fully sure if supporting libraries for Paper is in scope for plugin-yml.. If someone wants more features than just the simple However, after playing with the changes a bit locally it seems easy enough to support generating the JSON file. I made some minor refactoring to the changes:
Could you look through the commits I pushed and look and/or test that this is still okay? Any feedback is welcome. Thanks. |
|
I ported a plugin to use it and it seems to work well. Make sure README.md is changed back to Here: d66b3da4ff0a31f1d61675981181e43b0e33bb39 diff --git a/README.md b/README.md
index 252d86f..0a2776a 100644
--- a/README.md
+++ b/README.md
@@ -276,11 +276,11 @@ paper {
apiVersion = "1.19"
// Other possible properties from plugin.yml (optional)
- load = PaperPluginDescription.PluginLoadOrder.STARTUP // or POSTWORLD
+ load = BukkitPluginDescription.PluginLoadOrder.STARTUP // or POSTWORLD
authors = listOf("Notch", "Notch2")
prefix = "TEST"
- defaultPermission = PaperPluginDescription.Permission.Default.OP // TRUE, FALSE, OP or NOT_OP
+ defaultPermission = BukkitPluginDescription.Permission.Default.OP // TRUE, FALSE, OP or NOT_OP
provides = listOf("TestPluginOldName", "TestPlug")
depends {Should it have a Kotlin example for the loader as well? |
Thanks for noticing this!
Hm you mean the |
In theory, could the loader be written without requiring the kotlin standard library? Not actually sure how heavily tied kotlin is to its standard library. If it does try to pull in a bunch of stuff no matter what, then yeah, shouldn't bother adding a README example. |
|
Heads up that Paper might be changing the Anyways, I've been using this pull request for a bit and it seems to work great. No complaints so far! |
|
Sorry for the long delay. Didnt really had time to test this. No objections from my side. This seems to be functional and working. |
|
Here is the 1.20 update on
|
|
Here is a version that supports the new @Minecrell @rainbowdashlabs @stephan-gh @TheMeinerLP what do you think? Here is the syntax: kotlin paper {
[...]
bootstrapDependencies {
// Required dependency during bootstrap
register("WorldEdit")
// During bootstrap, load BeforePlugin's bootstrap code before ours
register("BeforePlugin") {
required = false
load = PaperPluginDescription.RelativeLoadOrder.BEFORE
}
// During bootstrap, load AfterPlugin's bootstrap code after ours
register("AfterPlugin") {
required = false
load = PaperPluginDescription.RelativeLoadOrder.AFTER
}
}
serverDependencies {
// During server run time, require LuckPerms, add it to the classpath, and load it before us
register("LuckPerms") {
load = PaperPluginDescription.RelativeLoadOrder.BEFORE
}
// During server run time, require WorldEdit, add it to the classpath, and load it before us
register("WorldEdit") {
load = PaperPluginDescription.RelativeLoadOrder.BEFORE
}
// Optional dependency, add it to classpath if it is available
register("ProtocolLib") {
required = false
}
// During server run time, optionally depend on Essentials but do not add it to the classpath
register("Essentials") {
required = false
joinClasspath = false
}
}
}groovy paper {
[...]
bootstrapDependencies {
// Required dependency during bootstrap
'WorldEdit' {}
// During bootstrap, load BeforePlugin's bootstrap code before ours
'BeforePlugin' {
load = PaperPluginDescription.RelativeLoadOrder.BEFORE
required = false
joinClasspath = false
}
// During bootstrap, load AfterPlugin's bootstrap code after ours
'AfterPlugin' {
load = PaperPluginDescription.RelativeLoadOrder.AFTER
required = false
joinClasspath = false
}
}
serverDependencies {
// During server run time, require LuckPerms, add it to the classpath, and load it before us
'LuckPerms' {
load = PaperPluginDescription.RelativeLoadOrder.BEFORE
}
// During server run time, require WorldEdit, add it to the classpath, and load it before us
'WorldEdit' {
load = PaperPluginDescription.RelativeLoadOrder.BEFORE
}
// Optional dependency, add it to classpath if it is available
'ProtocolLib' {
required = false
}
// During server run time, optionally depend on Essentials but do not add it to the classpath
'Essentials' {
required = false
joinClasspath = false
}
}
} |
|
@lordofpipes Thanks! I merged the previous state for now, can you make a new PR with the needed changes? |
|
Here: #34 |
I finally finished my implementation. I saw the other PR too late, so here is my proposal as well.
What I changed:
I thought about using the BukkitPlugin as a parent, but there are just too many differences and I would probably expect that there will be more differences in the future. Maybe a further refactoring could still extract common classes.
I also thought about extracting the command and permission class to reuse those declarations for spigot and paper plugins. Maybe you have an opinion on this.
I also removed the
YAMLGenerator.Feature.INDENT_ARRAYSbecause it renders object like this:instead of this
Not sure what the reason was behind it, but I am quite certain it wont break something. Of course both cases are valid yaml, but I see no gain from the setting.
dependencies and loaders are defined like this:
depends { register("WorldEdit") { required = true } register("Essentials") { required = true } } loadBefore { register("BrokenPlugin") { bootstrap = true } }Paper Libraries work different. The library field in paper was removed, therefore no straight way of importing classes exist. Instead a file called
plugin-libraries.jsonis generated when enabled.paper { generatePluginLibraries = true }This file can be loaded from resources.
Fixes #27