From d7b8ab9d0acb5ea94084918bce674e9bb1ba368c Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Sun, 12 Jan 2025 14:29:10 -0700 Subject: [PATCH] Multi-project example --- .gitignore | 2 + build.gradle.kts | 85 ++++++++++--------- buildSrc/build.gradle.kts | 7 ++ .../src/main/kotlin/my-conventions.gradle.kts | 28 ++++++ gradle.properties | 6 ++ paper_1_17_1/build.gradle.kts | 10 +++ .../hooks/paper_1_17_1/PaperHooks1_17_1.java | 12 +++ paper_1_19_4/build.gradle.kts | 10 +++ .../hooks/paper_1_19_4/PaperHooks1_19_4.java | 12 +++ paper_1_21_4/build.gradle.kts | 17 ++++ .../hooks/paper_1_21_4/PaperHooks1_21_4.java | 12 +++ paper_hooks/build.gradle.kts | 7 ++ .../main/java/my/plugin/hooks/PaperHooks.java | 46 ++++++++++ settings.gradle.kts | 5 ++ .../testplugin/PluginBrigadierCommand.java | 69 --------------- .../paperweight/testplugin/TestPlugin.java | 75 ---------------- src/main/java/my/plugin/MyPlugin.java | 15 ++++ 17 files changed, 233 insertions(+), 185 deletions(-) create mode 100644 buildSrc/build.gradle.kts create mode 100644 buildSrc/src/main/kotlin/my-conventions.gradle.kts create mode 100644 paper_1_17_1/build.gradle.kts create mode 100644 paper_1_17_1/src/main/java/my/plugin/hooks/paper_1_17_1/PaperHooks1_17_1.java create mode 100644 paper_1_19_4/build.gradle.kts create mode 100644 paper_1_19_4/src/main/java/my/plugin/hooks/paper_1_19_4/PaperHooks1_19_4.java create mode 100644 paper_1_21_4/build.gradle.kts create mode 100644 paper_1_21_4/src/main/java/my/plugin/hooks/paper_1_21_4/PaperHooks1_21_4.java create mode 100644 paper_hooks/build.gradle.kts create mode 100644 paper_hooks/src/main/java/my/plugin/hooks/PaperHooks.java delete mode 100644 src/main/java/io/papermc/paperweight/testplugin/PluginBrigadierCommand.java delete mode 100644 src/main/java/io/papermc/paperweight/testplugin/TestPlugin.java create mode 100644 src/main/java/my/plugin/MyPlugin.java diff --git a/.gitignore b/.gitignore index 621429a8..4c1b1d2e 100644 --- a/.gitignore +++ b/.gitignore @@ -117,6 +117,8 @@ buildNumber.properties # Common working directory run/ +run1_19_4/ +run1_17_1/ build .gradle /*.jar diff --git a/build.gradle.kts b/build.gradle.kts index 3ba67eed..9342b14b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,61 +1,64 @@ import xyz.jpenilla.resourcefactory.bukkit.BukkitPluginYaml +import xyz.jpenilla.runpaper.task.RunServer plugins { - `java-library` - id("io.papermc.paperweight.userdev") version "2.0.0-beta.13" - id("xyz.jpenilla.run-paper") version "2.3.1" // Adds runServer and runMojangMappedServer tasks for testing + `my-conventions` + id("io.papermc.paperweight.userdev") version "2.0.0-beta.13" apply false + id("xyz.jpenilla.run-paper") version "2.3.1" // Adds runServer task for testing id("xyz.jpenilla.resource-factory-bukkit-convention") version "1.2.0" // Generates plugin.yml based on the Gradle config + id("com.gradleup.shadow") version "8.3.5" } -group = "io.papermc.paperweight" -version = "1.0.0-SNAPSHOT" -description = "Test plugin for paperweight-userdev" +java.disableAutoTargetJvm() // Allow consuming JVM 21 projects (i.e. paper_1_21_4) even though our release is 17 -java { - // Configure the java toolchain. This allows gradle to auto-provision JDK 21 on systems that only have JDK 11 installed for example. - toolchain.languageVersion = JavaLanguageVersion.of(21) -} +dependencies { + compileOnly("io.papermc.paper:paper-api:1.17.1-R0.1-SNAPSHOT") + + implementation(project(":paper_hooks")) -// For 1.20.4 or below, or when you care about supporting Spigot on >=1.20.5: -/* -paperweight.reobfArtifactConfiguration = io.papermc.paperweight.userdev.ReobfArtifactConfiguration.REOBF_PRODUCTION + // Shade the reobf variant + runtimeOnly(project(":paper_1_17_1", configuration = "reobf")) + runtimeOnly(project(":paper_1_19_4", configuration = "reobf")) + + // For Paper 1.20.5+, we don't need to use the reobf variant. + // If you still support spigot, you will need to use the reobf variant, + // and remove the Mojang-mapped metadata from the manifest below. + runtimeOnly(project(":paper_1_21_4")) +} tasks.assemble { - dependsOn(tasks.reobfJar) + dependsOn(tasks.shadowJar) } - */ -dependencies { - paperweight.paperDevBundle("1.21.4-R0.1-SNAPSHOT") - // paperweight.foliaDevBundle("1.21.4-R0.1-SNAPSHOT") - // paperweight.devBundle("com.example.paperfork", "1.21.4-R0.1-SNAPSHOT") -} - -tasks { - compileJava { - // Set the release flag. This configures what version bytecode the compiler will emit, as well as what JDK APIs are usable. - // See https://openjdk.java.net/jeps/247 for more information. - options.release = 21 - } - javadoc { - options.encoding = Charsets.UTF_8.name() // We want UTF-8 for everything - } - - // Only relevant for 1.20.4 or below, or when you care about supporting Spigot on >=1.20.5: - /* - reobfJar { - // This is an example of how you might change the output location for reobfJar. It's recommended not to do this - // for a variety of reasons, however it's asked frequently enough that an example of how to do it is included here. - outputJar = layout.buildDirectory.file("libs/PaperweightTestPlugin-${project.version}.jar") - } - */ +tasks.jar { + manifest.attributes( + "paperweight-mappings-namespace" to "mojang", + ) } // Configure plugin.yml generation // - name, version, and description are inherited from the Gradle project. bukkitPluginYaml { - main = "io.papermc.paperweight.testplugin.TestPlugin" + main = "my.plugin.MyPlugin" load = BukkitPluginYaml.PluginLoadOrder.STARTUP authors.add("Author") - apiVersion = "1.21.4" + apiVersion = "1.17" +} + +tasks.runServer { + minecraftVersion("1.21.4") +} + +tasks.register("run1_17_1", RunServer::class) { + minecraftVersion("1.17.1") + pluginJars.from(tasks.shadowJar.flatMap { it.archiveFile }) + runDirectory = layout.projectDirectory.dir("run1_17_1") + systemProperties["Paper.IgnoreJavaVersion"] = true +} + +tasks.register("run1_19_4", RunServer::class) { + minecraftVersion("1.19.4") + pluginJars.from(tasks.shadowJar.flatMap { it.archiveFile }) + runDirectory = layout.projectDirectory.dir("run1_19_4") + systemProperties["Paper.IgnoreJavaVersion"] = true } diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts new file mode 100644 index 00000000..52b9cc0a --- /dev/null +++ b/buildSrc/build.gradle.kts @@ -0,0 +1,7 @@ +plugins { + `kotlin-dsl` +} + +repositories { + gradlePluginPortal() +} diff --git a/buildSrc/src/main/kotlin/my-conventions.gradle.kts b/buildSrc/src/main/kotlin/my-conventions.gradle.kts new file mode 100644 index 00000000..35dae3bf --- /dev/null +++ b/buildSrc/src/main/kotlin/my-conventions.gradle.kts @@ -0,0 +1,28 @@ +import org.gradle.jvm.toolchain.JavaLanguageVersion +import org.gradle.kotlin.dsl.maven +import org.gradle.kotlin.dsl.repositories + +plugins { + `java-library` +} + +java { + // Configure the java toolchain. This allows gradle to auto-provision JDK 21 on systems that only have JDK 17 installed for example. + // If you need to compile to for example JVM 8 or 17 bytecode, adjust the 'release' option below and keep the toolchain at 21. + toolchain.languageVersion = JavaLanguageVersion.of(21) +} + +repositories { + maven("https://repo.papermc.io/repository/maven-public/") +} + +tasks { + withType().configureEach { + // Set the release flag. This configures what version bytecode the compiler will emit, as well as what JDK APIs are usable. + // See https://openjdk.java.net/jeps/247 for more information. + options.release = 17 + } + withType().configureEach { + options.encoding = Charsets.UTF_8.name() // We want UTF-8 for everything + } +} diff --git a/gradle.properties b/gradle.properties index 20c6ff63..78e641ef 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,9 @@ +# Project meta +group = io.papermc.paperweight +version = 1.0.0-SNAPSHOT +description = Test plugin for paperweight-userdev + +# Gradle configuration org.gradle.parallel=true org.gradle.caching=true org.gradle.configuration-cache=true diff --git a/paper_1_17_1/build.gradle.kts b/paper_1_17_1/build.gradle.kts new file mode 100644 index 00000000..86449aaf --- /dev/null +++ b/paper_1_17_1/build.gradle.kts @@ -0,0 +1,10 @@ +plugins { + `my-conventions` + id("io.papermc.paperweight.userdev") +} + +dependencies { + implementation(project(":paper_hooks")) + + paperweight.paperDevBundle("1.17.1-R0.1-SNAPSHOT") +} diff --git a/paper_1_17_1/src/main/java/my/plugin/hooks/paper_1_17_1/PaperHooks1_17_1.java b/paper_1_17_1/src/main/java/my/plugin/hooks/paper_1_17_1/PaperHooks1_17_1.java new file mode 100644 index 00000000..0842543b --- /dev/null +++ b/paper_1_17_1/src/main/java/my/plugin/hooks/paper_1_17_1/PaperHooks1_17_1.java @@ -0,0 +1,12 @@ +package my.plugin.hooks.paper_1_17_1; + +import my.plugin.hooks.PaperHooks; +import net.minecraft.SharedConstants; +import org.slf4j.Logger; + +public class PaperHooks1_17_1 implements PaperHooks { + @Override + public void doSomething(final Logger logger) { + logger.info(SharedConstants.getCurrentVersion().getName()); + } +} diff --git a/paper_1_19_4/build.gradle.kts b/paper_1_19_4/build.gradle.kts new file mode 100644 index 00000000..2f36b64a --- /dev/null +++ b/paper_1_19_4/build.gradle.kts @@ -0,0 +1,10 @@ +plugins { + `my-conventions` + id("io.papermc.paperweight.userdev") +} + +dependencies { + implementation(project(":paper_hooks")) + + paperweight.paperDevBundle("1.19.4-R0.1-SNAPSHOT") +} diff --git a/paper_1_19_4/src/main/java/my/plugin/hooks/paper_1_19_4/PaperHooks1_19_4.java b/paper_1_19_4/src/main/java/my/plugin/hooks/paper_1_19_4/PaperHooks1_19_4.java new file mode 100644 index 00000000..312771fb --- /dev/null +++ b/paper_1_19_4/src/main/java/my/plugin/hooks/paper_1_19_4/PaperHooks1_19_4.java @@ -0,0 +1,12 @@ +package my.plugin.hooks.paper_1_19_4; + +import my.plugin.hooks.PaperHooks; +import net.minecraft.SharedConstants; +import org.slf4j.Logger; + +public class PaperHooks1_19_4 implements PaperHooks { + @Override + public void doSomething(final Logger logger) { + logger.info(SharedConstants.getCurrentVersion().getName()); + } +} diff --git a/paper_1_21_4/build.gradle.kts b/paper_1_21_4/build.gradle.kts new file mode 100644 index 00000000..13ab4df2 --- /dev/null +++ b/paper_1_21_4/build.gradle.kts @@ -0,0 +1,17 @@ +plugins { + `my-conventions` + id("io.papermc.paperweight.userdev") +} + +dependencies { + implementation(project(":paper_hooks")) + + paperweight.paperDevBundle("1.21.4-R0.1-SNAPSHOT") + // paperweight.foliaDevBundle("1.21.4-R0.1-SNAPSHOT") + // paperweight.devBundle("com.example.paperfork", "1.21.4-R0.1-SNAPSHOT") +} + +tasks.withType().configureEach { + // Override release for newer MC + options.release = 21 +} diff --git a/paper_1_21_4/src/main/java/my/plugin/hooks/paper_1_21_4/PaperHooks1_21_4.java b/paper_1_21_4/src/main/java/my/plugin/hooks/paper_1_21_4/PaperHooks1_21_4.java new file mode 100644 index 00000000..4f4c4b4b --- /dev/null +++ b/paper_1_21_4/src/main/java/my/plugin/hooks/paper_1_21_4/PaperHooks1_21_4.java @@ -0,0 +1,12 @@ +package my.plugin.hooks.paper_1_21_4; + +import my.plugin.hooks.PaperHooks; +import net.minecraft.SharedConstants; +import org.slf4j.Logger; + +public class PaperHooks1_21_4 implements PaperHooks { + @Override + public void doSomething(final Logger logger) { + logger.info(SharedConstants.getCurrentVersion().getName()); + } +} diff --git a/paper_hooks/build.gradle.kts b/paper_hooks/build.gradle.kts new file mode 100644 index 00000000..34bdba8a --- /dev/null +++ b/paper_hooks/build.gradle.kts @@ -0,0 +1,7 @@ +plugins { + `my-conventions` +} + +dependencies { + compileOnly("io.papermc.paper:paper-api:1.17.1-R0.1-SNAPSHOT") +} diff --git a/paper_hooks/src/main/java/my/plugin/hooks/PaperHooks.java b/paper_hooks/src/main/java/my/plugin/hooks/PaperHooks.java new file mode 100644 index 00000000..7d961bfc --- /dev/null +++ b/paper_hooks/src/main/java/my/plugin/hooks/PaperHooks.java @@ -0,0 +1,46 @@ +package my.plugin.hooks; + +import java.lang.reflect.Method; +import org.bukkit.Bukkit; +import org.jetbrains.annotations.Nullable; +import org.slf4j.Logger; + +public interface PaperHooks { + void doSomething(Logger logger); + + static PaperHooks get() { + return Holder.INSTANCE; + } + + final class Holder { + private static final PaperHooks INSTANCE; + + static { + final PaperHooks hooks; + String minecraftVersion = minecraftVersionFromServerBuildInfo(); + if (minecraftVersion == null) { + minecraftVersion = Bukkit.getServer().getMinecraftVersion(); + } + // You probably want to do something smarter here + try { + final String underscored = minecraftVersion.replace(".", "_"); + hooks = (PaperHooks) Class.forName("my.plugin.hooks.paper_" + underscored + ".PaperHooks" + underscored).getDeclaredConstructors()[0].newInstance(); + } catch (final ReflectiveOperationException e) { + throw new RuntimeException("Could not create PaperHooks for " + minecraftVersion, e); + } + INSTANCE = hooks; + } + + // For bootstrap-time compatibility on applicable versions + private static @Nullable String minecraftVersionFromServerBuildInfo() { + try { + final Class cls = Class.forName("io.papermc.paper.ServerBuildInfo"); + final Method method = cls.getMethod("minecraftVersionId"); + final Object instance = cls.getMethod("buildInfo").invoke(null); + return (String) method.invoke(instance); + } catch (final Throwable e) { + return null; + } + } + } +} diff --git a/settings.gradle.kts b/settings.gradle.kts index 56a75ece..de0698fa 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -3,3 +3,8 @@ plugins { } rootProject.name = "paperweight-test-plugin" + +include("paper_hooks") +include("paper_1_17_1") +include("paper_1_19_4") +include("paper_1_21_4") diff --git a/src/main/java/io/papermc/paperweight/testplugin/PluginBrigadierCommand.java b/src/main/java/io/papermc/paperweight/testplugin/PluginBrigadierCommand.java deleted file mode 100644 index df3d8d1b..00000000 --- a/src/main/java/io/papermc/paperweight/testplugin/PluginBrigadierCommand.java +++ /dev/null @@ -1,69 +0,0 @@ -package io.papermc.paperweight.testplugin; - -import com.mojang.brigadier.CommandDispatcher; -import com.mojang.brigadier.ParseResults; -import com.mojang.brigadier.StringReader; -import com.mojang.brigadier.builder.LiteralArgumentBuilder; -import java.util.List; -import java.util.function.Consumer; -import com.mojang.brigadier.suggestion.Suggestion; -import net.minecraft.commands.CommandSourceStack; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.command.PluginIdentifiableCommand; -import org.bukkit.craftbukkit.CraftServer; -import org.bukkit.craftbukkit.command.VanillaCommandWrapper; -import org.bukkit.plugin.Plugin; -import org.checkerframework.checker.nullness.qual.NonNull; -import org.checkerframework.checker.nullness.qual.Nullable; -import org.checkerframework.framework.qual.DefaultQualifier; - -@DefaultQualifier(NonNull.class) -final class PluginBrigadierCommand extends Command implements PluginIdentifiableCommand { - private final Consumer> command; - private final Plugin plugin; - - PluginBrigadierCommand( - final Plugin plugin, - final String name, - final Consumer> command - ) { - super(name); - this.plugin = plugin; - this.command = command; - } - - @Override - public boolean execute(final CommandSender sender, final String commandLabel, final String[] args) { - final String joined = String.join(" ", args); - final String argsString = joined.isBlank() ? "" : " " + joined; - ((CraftServer) Bukkit.getServer()).getServer().getCommands().performPrefixedCommand( - VanillaCommandWrapper.getListener(sender), - commandLabel + argsString, - commandLabel - ); - return true; - } - - @Override - public List tabComplete(final CommandSender sender, final String alias, final String[] args, final @Nullable Location location) { - final String joined = String.join(" ", args); - final String argsString = joined.isBlank() ? "" : joined; - final CommandDispatcher dispatcher = ((CraftServer) Bukkit.getServer()).getServer().getCommands().getDispatcher(); - final ParseResults results = dispatcher.parse(new StringReader(alias + " " + argsString), VanillaCommandWrapper.getListener(sender)); - return dispatcher.getCompletionSuggestions(results) - .thenApply(result -> result.getList().stream().map(Suggestion::getText).toList()) - .join(); - } - - @Override - public Plugin getPlugin() { - return this.plugin; - } - - Consumer> command() { - return this.command; - } -} diff --git a/src/main/java/io/papermc/paperweight/testplugin/TestPlugin.java b/src/main/java/io/papermc/paperweight/testplugin/TestPlugin.java deleted file mode 100644 index 6ed25ea3..00000000 --- a/src/main/java/io/papermc/paperweight/testplugin/TestPlugin.java +++ /dev/null @@ -1,75 +0,0 @@ -package io.papermc.paperweight.testplugin; - -import com.destroystokyo.paper.brigadier.BukkitBrigadierCommandSource; -import com.destroystokyo.paper.event.brigadier.CommandRegisteredEvent; -import com.mojang.brigadier.Command; -import com.mojang.brigadier.builder.LiteralArgumentBuilder; -import com.mojang.brigadier.tree.LiteralCommandNode; -import java.util.Collection; -import java.util.function.Consumer; -import net.minecraft.ChatFormatting; -import net.minecraft.commands.CommandSourceStack; -import net.minecraft.commands.arguments.EntityArgument; -import net.minecraft.network.chat.ClickEvent; -import net.minecraft.network.chat.Component; -import net.minecraft.server.level.ServerPlayer; -import org.bukkit.craftbukkit.CraftServer; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.plugin.java.JavaPlugin; -import org.checkerframework.checker.nullness.qual.NonNull; -import org.checkerframework.framework.qual.DefaultQualifier; - -import static net.kyori.adventure.text.Component.text; -import static net.kyori.adventure.text.format.NamedTextColor.BLUE; -import static net.minecraft.commands.Commands.argument; -import static net.minecraft.commands.Commands.literal; -import static net.minecraft.commands.arguments.EntityArgument.players; - -@DefaultQualifier(NonNull.class) -public final class TestPlugin extends JavaPlugin implements Listener { - @Override - public void onEnable() { - this.getServer().getPluginManager().registerEvents(this, this); - - this.registerPluginBrigadierCommand( - "paperweight", - literal -> literal.requires(stack -> stack.getBukkitSender().hasPermission("paperweight")) - .then(literal("hello") - .executes(ctx -> { - ctx.getSource().getBukkitSender().sendMessage(text("Hello!", BLUE)); - return Command.SINGLE_SUCCESS; - })) - .then(argument("players", players()) - .executes(ctx -> { - final Collection players = EntityArgument.getPlayers(ctx, "players"); - for (final ServerPlayer player : players) { - player.sendSystemMessage( - Component.literal("Hello from Paperweight test plugin!") - .withStyle(ChatFormatting.ITALIC, ChatFormatting.GREEN) - .withStyle(style -> style.withClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/paperweight @a"))) - ); - } - return players.size(); - })) - ); - } - - private PluginBrigadierCommand registerPluginBrigadierCommand(final String label, final Consumer> command) { - final PluginBrigadierCommand pluginBrigadierCommand = new PluginBrigadierCommand(this, label, command); - this.getServer().getCommandMap().register(this.getName(), pluginBrigadierCommand); - ((CraftServer) this.getServer()).syncCommands(); - return pluginBrigadierCommand; - } - - @SuppressWarnings({"rawtypes", "unchecked"}) - @EventHandler - public void onCommandRegistered(final CommandRegisteredEvent event) { - if (!(event.getCommand() instanceof PluginBrigadierCommand pluginBrigadierCommand)) { - return; - } - final LiteralArgumentBuilder node = literal(event.getCommandLabel()); - pluginBrigadierCommand.command().accept(node); - event.setLiteral((LiteralCommandNode) node.build()); - } -} diff --git a/src/main/java/my/plugin/MyPlugin.java b/src/main/java/my/plugin/MyPlugin.java new file mode 100644 index 00000000..e6d6d18c --- /dev/null +++ b/src/main/java/my/plugin/MyPlugin.java @@ -0,0 +1,15 @@ +package my.plugin; + +import my.plugin.hooks.PaperHooks; +import org.bukkit.event.Listener; +import org.bukkit.plugin.java.JavaPlugin; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.framework.qual.DefaultQualifier; + +@DefaultQualifier(NonNull.class) +public final class MyPlugin extends JavaPlugin implements Listener { + @Override + public void onEnable() { + PaperHooks.get().doSomething(this.getSLF4JLogger()); + } +}