From 1a28facc56ace71d8d237747244430493720851d Mon Sep 17 00:00:00 2001 From: Paul Reilly Date: Sat, 11 Mar 2023 18:36:15 -0600 Subject: [PATCH] Made some adjustments; still more to do. --- discord/pom.xml | 6 ++ .../java/me/totalfreedom/discord/Bot.java | 22 ----- .../java/me/totalfreedom/discord/TFD4J.java | 4 + .../discord/react/DisposableBukkitTask.java | 35 +++++++ .../react/ReactiveBukkitScheduler.java | 96 +++++++++++++++++++ 5 files changed, 141 insertions(+), 22 deletions(-) create mode 100644 discord/src/main/java/me/totalfreedom/discord/react/DisposableBukkitTask.java create mode 100644 discord/src/main/java/me/totalfreedom/discord/react/ReactiveBukkitScheduler.java diff --git a/discord/pom.xml b/discord/pom.xml index ac5f5992..42af766e 100644 --- a/discord/pom.xml +++ b/discord/pom.xml @@ -36,5 +36,11 @@ 3.5.1 provided + + me.totalfreedom + commons + 2023.02 + compile + \ No newline at end of file diff --git a/discord/src/main/java/me/totalfreedom/discord/Bot.java b/discord/src/main/java/me/totalfreedom/discord/Bot.java index 43c4eb1e..542b8a8f 100644 --- a/discord/src/main/java/me/totalfreedom/discord/Bot.java +++ b/discord/src/main/java/me/totalfreedom/discord/Bot.java @@ -39,28 +39,6 @@ public class Bot public void initialize() { if (client == null) throw new IllegalStateException(); - - final CommandHandler handler = new CommandHandler(client.getRestClient()); - - /* Call our code to handle creating/deleting/editing our global slash commands. - We have to hard code our list of command files since iterating over a list of files in a resource directory - is overly complicated for such a simple demo and requires handling for both IDE and .jar packaging. - Using SpringBoot we can avoid all of this and use their resource pattern matcher to do this for us. - */ - try - { - handler.registerCommand(new HelpCommand()); - handler.registerCommand(new ListCommand()); - handler.registerCommand(new TPSCommand()); - } - catch (Exception e) - { - Bukkit.getLogger().severe("Error trying to register global slash commands.\n" + e.getMessage()); - } - //Register our slash command listener - client.on(ChatInputInteractionEvent.class, handler::handle) - .then(client.onDisconnect()); - //.block(); // We use .block() as there is not another non-daemon thread and the jvm would close otherwise. } public String formatBotTag() { diff --git a/discord/src/main/java/me/totalfreedom/discord/TFD4J.java b/discord/src/main/java/me/totalfreedom/discord/TFD4J.java index 721bc18f..e152000c 100644 --- a/discord/src/main/java/me/totalfreedom/discord/TFD4J.java +++ b/discord/src/main/java/me/totalfreedom/discord/TFD4J.java @@ -1,5 +1,6 @@ package me.totalfreedom.discord; +import discord4j.core.event.domain.interaction.ChatInputInteractionEvent; import me.totalfreedom.discord.command.HelpCommand; import me.totalfreedom.discord.command.ListCommand; import me.totalfreedom.discord.command.TPSCommand; @@ -50,6 +51,9 @@ public class TFD4J extends JavaPlugin this.ch.registerCommand(new ListCommand()); this.ch.registerCommand(new TPSCommand()); + this.getBot().getClient().on(ChatInputInteractionEvent.class, ch::handle) + .subscribe(); + slf4j().info("Commands successfully registered! Providing context to TFM..."); Context context = new Context<>(tfd4jcommons); bot.getTFM().getCommons().ag.setDiscordContext(context); diff --git a/discord/src/main/java/me/totalfreedom/discord/react/DisposableBukkitTask.java b/discord/src/main/java/me/totalfreedom/discord/react/DisposableBukkitTask.java new file mode 100644 index 00000000..b3c3cf12 --- /dev/null +++ b/discord/src/main/java/me/totalfreedom/discord/react/DisposableBukkitTask.java @@ -0,0 +1,35 @@ +package me.totalfreedom.discord.react; + +import org.bukkit.scheduler.BukkitTask; +import reactor.core.Disposable; + +/** + * This class is a wrapper for a BukkitTask that implements the Disposable interface. + * This is so we can schedule non-blocking tasks asynchronously on the Bukkit Scheduler. + *

+ * From SimplexSS + * + * @param task The task to wrap. + */ +public record DisposableBukkitTask(BukkitTask task) implements Disposable +{ + /** + * Disposes of the task upstream on the Bukkit scheduler. + */ + @Override + public void dispose() + { + task.cancel(); + } + + /** + * Checks if the task is cancelled. + * + * @return true if the task is cancelled, false otherwise. + */ + @Override + public boolean isDisposed() + { + return task.isCancelled(); + } +} diff --git a/discord/src/main/java/me/totalfreedom/discord/react/ReactiveBukkitScheduler.java b/discord/src/main/java/me/totalfreedom/discord/react/ReactiveBukkitScheduler.java new file mode 100644 index 00000000..538d4846 --- /dev/null +++ b/discord/src/main/java/me/totalfreedom/discord/react/ReactiveBukkitScheduler.java @@ -0,0 +1,96 @@ +package me.totalfreedom.discord.react; + +import java.util.concurrent.TimeUnit; +import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.scheduler.BukkitScheduler; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import reactor.core.Disposable; +import reactor.core.scheduler.Scheduler; + +/** + * An abstraction layer over the {@link BukkitScheduler} to allow for the use as a {@link Scheduler}. + * This will allow us to perform non-blocking operations on the main server thread. + * + * @author SimplexDevelopment + */ +public final class ReactiveBukkitScheduler + implements Scheduler, Scheduler.Worker { + /** + * The plugin instance. + */ + private final JavaPlugin plugin; + /** + * The bukkit scheduler. + */ + private final BukkitScheduler scheduler; + + public ReactiveBukkitScheduler(JavaPlugin plugin) { + this.plugin = plugin; + this.scheduler = plugin.getServer().getScheduler(); + } + + /** + * Delegates to the {@link BukkitScheduler}. + * + * @param task The task to delegate. + * @return A disposable that can be used to cancel the task. + */ + @Override + public @NotNull Disposable schedule(@NotNull Runnable task) { + return new DisposableBukkitTask(scheduler.runTask(plugin, task)); + } + + /** + * Delegates to the {@link BukkitScheduler} with a delay. + * + * @param task The task to delegate + * @param delay The amount of time to wait before running the task + * @param unit Unused parameter in this implementation. + * Regardless of what value you use, this parameter will never be called. + * @return A disposable that can be used to cancel the task. + */ + @Override + public @NotNull Disposable schedule(@NotNull Runnable task, long delay, @Deprecated @Nullable TimeUnit unit) { + return new DisposableBukkitTask(scheduler.runTaskLater(plugin, task, delay)); + } + + /** + * Delegates to the {@link BukkitScheduler} with a delay and a period. + * The initial delay may be 0L, but the period must be greater than 0L. + * + * @param task The task to delegate. + * @param initialDelay The amount of time to wait before running the task. + * @param period The amount of time to wait between each execution of the task. + * @param unit Unused parameter in this implementation. + * Regardless of what value you use, this parameter will never be called. + * @return A disposable that can be used to cancel the task. + */ + @Override + public @NotNull Disposable schedulePeriodically(@NotNull Runnable task, long initialDelay, long period, @Deprecated @Nullable TimeUnit unit) { + if (period <= 0L) { + throw new IllegalArgumentException("Period must be greater than 0L"); + } + + return new DisposableBukkitTask(scheduler.runTaskTimer(plugin, task, initialDelay, period)); + } + + /** + * A new {@link Worker}. + * + * @return This class instance, as it implements {@link Worker}. + */ + @Override + public @NotNull Scheduler.Worker createWorker() { + return this; + } + + /** + * This method does nothing and is unused. + */ + @Override + @Deprecated + public void dispose() { + // This method does nothing and is only here because it's being overridden from a parent. + } +}