From 34b5729e54dc24b409f592fecb78f995be47fed8 Mon Sep 17 00:00:00 2001 From: Tintinkung Date: Tue, 10 Jun 2025 05:06:01 +0700 Subject: [PATCH 1/6] feat: discord w/ discord-plotsystem-api 1.2.0 * Proper integrations for discord-plotsystem plugin * Wrote a wrapper class `at com.alpsbte.plotsystem.utils.DiscordUtil` as a singleton to manage all discord event system * DiscordUtil is designed to ever be initialized if the discord-plotsystem exist in the class path, so Plot-System plugin can stay running even if the discord feature isn't installed * Cherry picked from 33c69e774e610b5cd6c93aabe96e85f97cb294b7 --- pom.xml | 7 + .../com/alpsbte/plotsystem/PlotSystem.java | 12 + .../commands/plot/CMD_Plot_Abandon.java | 3 +- .../commands/plot/CMD_Plot_UndoSubmit.java | 2 + .../menus/review/ReviewPlotTogglesMenu.java | 3 + .../plot/generator/AbstractPlotGenerator.java | 3 +- .../plot/generator/DefaultPlotGenerator.java | 4 + .../core/system/plot/utils/PlotUtils.java | 32 ++- .../core/system/review/PlotReview.java | 3 + .../alpsbte/plotsystem/utils/DiscordUtil.java | 215 ++++++++++++++++++ src/main/resources/plugin.yml | 2 +- 11 files changed, 279 insertions(+), 7 deletions(-) create mode 100644 src/main/java/com/alpsbte/plotsystem/utils/DiscordUtil.java diff --git a/pom.xml b/pom.xml index c3e37c7f..fe2842fe 100644 --- a/pom.xml +++ b/pom.xml @@ -132,6 +132,13 @@ 2.8.12 provided + + + asia.buildtheearth.asean.discord + discord-plotsystem-api + 1.2.0 + provided + com.alpsbte.alpslib diff --git a/src/main/java/com/alpsbte/plotsystem/PlotSystem.java b/src/main/java/com/alpsbte/plotsystem/PlotSystem.java index dfb341a7..08b212be 100644 --- a/src/main/java/com/alpsbte/plotsystem/PlotSystem.java +++ b/src/main/java/com/alpsbte/plotsystem/PlotSystem.java @@ -42,6 +42,7 @@ import com.alpsbte.plotsystem.core.system.tutorial.TutorialEventListener; import com.alpsbte.plotsystem.core.system.tutorial.utils.TutorialNPCTurnTracker; import com.alpsbte.plotsystem.core.system.tutorial.utils.TutorialUtils; +import com.alpsbte.plotsystem.utils.DiscordUtil; import com.alpsbte.plotsystem.utils.PacketListener; import com.alpsbte.plotsystem.utils.Utils; import com.alpsbte.plotsystem.utils.io.ConfigPaths; @@ -61,6 +62,7 @@ import org.bukkit.plugin.java.JavaPlugin; import org.ipvp.canvas.MenuFunctionListener; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.io.IOException; import java.io.InputStream; @@ -206,6 +208,12 @@ public void onEnable() { Bukkit.getScheduler().runTaskTimerAsynchronously(FancyNpcsPlugin.get().getPlugin(), new TutorialNPCTurnTracker(), 0, 1L); } + // Register discord Integration + org.bukkit.plugin.Plugin discordPlugin = PlotSystem.DependencyManager.getDiscordPlotSystemPlugin(); + if(discordPlugin != null) { + DiscordUtil.init(discordPlugin); + } + pluginEnabled = true; Bukkit.getConsoleSender().sendMessage(empty()); Bukkit.getConsoleSender().sendMessage(text("Enabled Plot-System plugin.", DARK_GREEN)); @@ -333,6 +341,10 @@ public static boolean isWorldGuardExtraFlagsEnabled() { return plugin.getServer().getPluginManager().isPluginEnabled("WorldGuardExtraFlags"); } + public static @Nullable org.bukkit.plugin.Plugin getDiscordPlotSystemPlugin() { + return plugin.getServer().getPluginManager().getPlugin("DiscordPlotSystem"); + } + /** * @param worldName Name of the world * @return Config path for the world diff --git a/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Abandon.java b/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Abandon.java index 1cb48d46..7f8743c0 100644 --- a/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Abandon.java +++ b/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Abandon.java @@ -33,6 +33,7 @@ import com.alpsbte.plotsystem.core.system.plot.AbstractPlot; import com.alpsbte.plotsystem.core.system.plot.Plot; import com.alpsbte.plotsystem.core.system.plot.utils.PlotUtils; +import com.alpsbte.plotsystem.utils.DiscordUtil; import com.alpsbte.plotsystem.utils.Utils; import com.alpsbte.plotsystem.utils.enums.Status; import com.alpsbte.plotsystem.utils.io.LangPaths; @@ -91,7 +92,7 @@ public void onCommand(CommandSender sender, String[] args) { } Bukkit.getScheduler().runTask(PlotSystem.getPlugin(), () -> { - if (PlotUtils.Actions.abandonPlot(plot)) { + if (PlotUtils.Actions.abandonPlot(plot, DiscordUtil.AbandonType.MANUALLY)) { sender.sendMessage(Utils.ChatUtils.getInfoFormat(langUtil.get(sender, LangPaths.Message.Info.ABANDONED_PLOT, plot.getID() + ""))); player.playSound(player.getLocation(), Utils.SoundUtils.ABANDON_PLOT_SOUND, 1, 1); } diff --git a/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_UndoSubmit.java b/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_UndoSubmit.java index b4a6bebc..e5d51d75 100644 --- a/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_UndoSubmit.java +++ b/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_UndoSubmit.java @@ -33,6 +33,7 @@ import com.alpsbte.plotsystem.core.system.plot.AbstractPlot; import com.alpsbte.plotsystem.core.system.plot.Plot; import com.alpsbte.plotsystem.core.system.plot.utils.PlotUtils; +import com.alpsbte.plotsystem.utils.DiscordUtil; import com.alpsbte.plotsystem.utils.Utils; import com.alpsbte.plotsystem.utils.enums.Status; import com.alpsbte.plotsystem.utils.io.LangPaths; @@ -94,6 +95,7 @@ public void onCommand(CommandSender sender, String[] args) { Bukkit.getScheduler().runTask(PlotSystem.getPlugin(), () -> { PlotUtils.Actions.undoSubmit(plot); + DiscordUtil.getOpt(plot.getID()).ifPresent(DiscordUtil.PlotEventAction::onPlotUndoSubmit); sender.sendMessage(Utils.ChatUtils.getInfoFormat(langUtil.get(sender, LangPaths.Message.Info.UNDID_SUBMISSION, plot.getID() + ""))); player.playSound(player.getLocation(), Utils.SoundUtils.FINISH_PLOT_SOUND, 1, 1); diff --git a/src/main/java/com/alpsbte/plotsystem/core/menus/review/ReviewPlotTogglesMenu.java b/src/main/java/com/alpsbte/plotsystem/core/menus/review/ReviewPlotTogglesMenu.java index 3dc3b8b7..27cd3692 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/menus/review/ReviewPlotTogglesMenu.java +++ b/src/main/java/com/alpsbte/plotsystem/core/menus/review/ReviewPlotTogglesMenu.java @@ -35,6 +35,7 @@ import com.alpsbte.plotsystem.core.system.review.PlotReview; import com.alpsbte.plotsystem.core.system.review.ReviewRating; import com.alpsbte.plotsystem.core.system.review.ToggleCriteria; +import com.alpsbte.plotsystem.utils.DiscordUtil; import com.alpsbte.plotsystem.utils.Utils; import com.alpsbte.plotsystem.utils.chat.ChatInput; import com.alpsbte.plotsystem.utils.chat.PlayerFeedbackChatInput; @@ -154,9 +155,11 @@ private void submitReview() { if (!isRejected) { reviewerConfirmationMessage = Utils.ChatUtils.getInfoFormat(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Message.Info.PLOT_MARKED_REVIEWED, Integer.toString(plot.getID()), getParticipantsString())); if(!acceptPlot(review.getScore(), review.getSplitScore())) return; + DiscordUtil.getOpt(plot.getID()).ifPresent(DiscordUtil.PlotEventAction::onPlotApprove); } else { reviewerConfirmationMessage = Utils.ChatUtils.getInfoFormat(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Message.Info.PLOT_REJECTED, Integer.toString(plot.getID()), getParticipantsString())); PlotUtils.Actions.undoSubmit(plot); + DiscordUtil.getOpt(plot.getID()).ifPresent(DiscordUtil.PlotEventAction::onPlotReject); } Bukkit.getScheduler().runTask(PlotSystem.getPlugin(), () -> { diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/plot/generator/AbstractPlotGenerator.java b/src/main/java/com/alpsbte/plotsystem/core/system/plot/generator/AbstractPlotGenerator.java index 9900a3e9..1a5a5b76 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/plot/generator/AbstractPlotGenerator.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/plot/generator/AbstractPlotGenerator.java @@ -33,6 +33,7 @@ import com.alpsbte.plotsystem.core.system.plot.world.CityPlotWorld; import com.alpsbte.plotsystem.core.system.plot.world.OnePlotWorld; import com.alpsbte.plotsystem.core.system.plot.world.PlotWorld; +import com.alpsbte.plotsystem.utils.DiscordUtil; import com.alpsbte.plotsystem.utils.Utils; import com.alpsbte.plotsystem.utils.io.ConfigPaths; import com.alpsbte.plotsystem.utils.io.ConfigUtil; @@ -135,7 +136,7 @@ private AbstractPlotGenerator(@NotNull AbstractPlot plot, @NotNull Builder build this.onComplete(exception != null, false); if (exception != null) { - PlotUtils.Actions.abandonPlot(plot); + PlotUtils.Actions.abandonPlot(plot, DiscordUtil.AbandonType.SYSTEM); onException(exception); } } diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/plot/generator/DefaultPlotGenerator.java b/src/main/java/com/alpsbte/plotsystem/core/system/plot/generator/DefaultPlotGenerator.java index 6ada921c..5304016c 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/plot/generator/DefaultPlotGenerator.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/plot/generator/DefaultPlotGenerator.java @@ -33,6 +33,7 @@ import com.alpsbte.plotsystem.core.system.plot.utils.PlotType; import com.alpsbte.plotsystem.core.system.plot.utils.PlotUtils; import com.alpsbte.plotsystem.core.system.plot.world.PlotWorld; +import com.alpsbte.plotsystem.utils.DiscordUtil; import com.alpsbte.plotsystem.utils.Utils; import com.alpsbte.plotsystem.utils.enums.PlotDifficulty; import com.alpsbte.plotsystem.utils.enums.Status; @@ -140,5 +141,8 @@ protected void onComplete(boolean failed, boolean unloadWorld) { PlotUtils.Cache.clearCache(getBuilder().getUUID()); plot.getWorld().teleportPlayer(getBuilder().getPlayer()); LangUtil.getInstance().broadcast(LangPaths.Message.Info.CREATED_NEW_PLOT, getBuilder().getName()); + + // Create the plot to discord forum + DiscordUtil.getOpt(plot.getID()).ifPresent(event -> event.onPlotCreate(this.plot)); } } diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/plot/utils/PlotUtils.java b/src/main/java/com/alpsbte/plotsystem/core/system/plot/utils/PlotUtils.java index 68b80689..1dc746d6 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/plot/utils/PlotUtils.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/plot/utils/PlotUtils.java @@ -37,6 +37,7 @@ import com.alpsbte.plotsystem.core.system.plot.world.PlotWorld; import com.alpsbte.plotsystem.core.system.review.PlotReview; import com.alpsbte.plotsystem.core.system.review.ReviewNotification; +import com.alpsbte.plotsystem.utils.DiscordUtil; import com.alpsbte.plotsystem.utils.ShortLink; import com.alpsbte.plotsystem.utils.Utils; import com.alpsbte.plotsystem.utils.enums.Status; @@ -85,6 +86,8 @@ import java.nio.file.Paths; import java.text.DecimalFormat; import java.time.LocalDate; +import java.time.LocalTime; +import java.time.temporal.ChronoUnit; import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; @@ -291,13 +294,30 @@ public static void checkPlotsForLastActivity() { long inactivityIntervalDays = config.getLong(ConfigPaths.INACTIVITY_INTERVAL); long rejectedInactivityIntervalDays = (config.getLong(ConfigPaths.REJECTED_INACTIVITY_INTERVAL) != -1) ? config.getLong(ConfigPaths.REJECTED_INACTIVITY_INTERVAL) : inactivityIntervalDays; if (inactivityIntervalDays == -2 && rejectedInactivityIntervalDays == -2) return; + + // Determine if the current time is within the notification window. + // Run within a ±75-minute window around 16:00 local time. + // TODO: Maybe a config option? the #startUnfinishedPlotReminderTimer is too frequent to be a discord ping + long minutesDiff = Math.abs(ChronoUnit.MINUTES.between(LocalTime.now(), LocalTime.of(16, 0))); + boolean inNotificationWindow = minutesDiff <= 75; + for (Plot plot : plots) { LocalDate lastActivity = plot.getLastActivity(); + + if(lastActivity == null) continue; long interval = plot.isRejected() ? rejectedInactivityIntervalDays : inactivityIntervalDays; - if (interval == -2 || lastActivity == null || lastActivity.plusDays(interval).isAfter(LocalDate.now())) continue; + LocalDate abandonDate = lastActivity.plusDays(interval); + + // Check if today is within 5 days before the plot's abandon date + if(inNotificationWindow && LocalDate.now().isAfter(abandonDate.minusDays(5))) { + // Notify the plot's owner on discord + DiscordUtil.getOpt(plot.getID()).ifPresent(event -> event.onPlotInactivity(abandonDate)); + } + + if (interval == -2 || abandonDate.isAfter(LocalDate.now())) continue; Bukkit.getScheduler().runTask(PlotSystem.getPlugin(), () -> { - if (Actions.abandonPlot(plot)) { + if (Actions.abandonPlot(plot, DiscordUtil.AbandonType.INACTIVE)) { PlotSystem.getPlugin().getComponentLogger().info(text("Abandoned plot #" + plot.getID() + " due to inactivity!")); } else { PlotSystem.getPlugin().getComponentLogger().warn(text("An error occurred while abandoning plot #" + plot.getID() + " due to inactivity!")); @@ -341,6 +361,8 @@ public static void submitPlot(@NotNull Plot plot) { plot.getPermissions().removeBuilderPerms(builder.getUUID()); } } + + DiscordUtil.getOpt(plot.getID()).ifPresent(DiscordUtil.PlotEventAction::onPlotSubmit); } public static void undoSubmit(@NotNull Plot plot) { @@ -354,7 +376,7 @@ public static void undoSubmit(@NotNull Plot plot) { } } - public static boolean abandonPlot(@NotNull AbstractPlot plot) { + public static boolean abandonPlot(@NotNull AbstractPlot plot, @NotNull DiscordUtil.AbandonType type) { try { if (plot.getWorld() instanceof OnePlotWorld) { if (plot.getWorld().isWorldGenerated()) { @@ -388,6 +410,8 @@ public static boolean abandonPlot(@NotNull AbstractPlot plot) { if (plot.getWorld().isWorldLoaded()) plot.getWorld().unloadWorld(false); } } + // Send to discord + DiscordUtil.getOpt(plot.getID()).ifPresent(event -> event.onPlotAbandon(type)); } catch (IOException | WorldEditException ex) { PlotSystem.getPlugin().getComponentLogger().error(text("Failed to abandon plot with the ID " + plot.getID() + "!"), ex); return false; @@ -418,7 +442,7 @@ public static boolean abandonPlot(@NotNull AbstractPlot plot) { } public static boolean deletePlot(Plot plot) { - if (abandonPlot(plot)) { + if (abandonPlot(plot, DiscordUtil.AbandonType.COMMANDS)) { CompletableFuture.runAsync(() -> DataProvider.PLOT.deletePlot(plot.getID())); return true; } diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/review/PlotReview.java b/src/main/java/com/alpsbte/plotsystem/core/system/review/PlotReview.java index f40b3764..b5ca2bed 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/review/PlotReview.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/review/PlotReview.java @@ -27,6 +27,7 @@ import com.alpsbte.plotsystem.core.database.DataProvider; import com.alpsbte.plotsystem.core.system.Builder; import com.alpsbte.plotsystem.core.system.plot.Plot; +import com.alpsbte.plotsystem.utils.DiscordUtil; import com.alpsbte.plotsystem.utils.enums.Status; import org.jetbrains.annotations.Nullable; @@ -88,6 +89,7 @@ public UUID getReviewerUUID() { public boolean updateFeedback(String feedback) { if (DataProvider.REVIEW.updateFeedback(reviewId, feedback)) { this.feedback = feedback; + DiscordUtil.getOpt(this.plot.getID()).ifPresent(event -> event.onPlotFeedback(feedback)); return true; } return false; @@ -111,6 +113,7 @@ public boolean undoReview() { plot.setPasted(false); DataProvider.PLOT.setCompletedSchematic(plot.getID(), null); + DiscordUtil.getOpt(this.plot.getID()).ifPresent(DiscordUtil.PlotEventAction::onPlotUndoReview); return DataProvider.REVIEW.removeReview(reviewId); } } diff --git a/src/main/java/com/alpsbte/plotsystem/utils/DiscordUtil.java b/src/main/java/com/alpsbte/plotsystem/utils/DiscordUtil.java new file mode 100644 index 00000000..acb390c9 --- /dev/null +++ b/src/main/java/com/alpsbte/plotsystem/utils/DiscordUtil.java @@ -0,0 +1,215 @@ +/* + * The MIT License (MIT) + * + * Copyright © 2021-2025, Alps BTE + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package com.alpsbte.plotsystem.utils; + +import asia.buildtheearth.asean.discord.plotsystem.api.DiscordPlotSystemAPI; +import asia.buildtheearth.asean.discord.plotsystem.api.PlotCreateData; +import asia.buildtheearth.asean.discord.plotsystem.api.PlotCreateProvider; +import asia.buildtheearth.asean.discord.plotsystem.api.events.*; +import com.alpsbte.plotsystem.PlotSystem; +import com.alpsbte.plotsystem.core.database.DataProvider; +import com.alpsbte.plotsystem.core.system.CityProject; +import com.alpsbte.plotsystem.core.system.plot.AbstractPlot; +import com.alpsbte.plotsystem.core.system.plot.Plot; +import com.alpsbte.plotsystem.utils.conversion.CoordinateConversion; +import com.alpsbte.plotsystem.utils.conversion.projection.OutOfProjectionBoundsException; +import com.sk89q.worldedit.math.BlockVector3; +import org.bukkit.plugin.Plugin; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.IOException; +import java.time.LocalDate; +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; + +import static net.kyori.adventure.text.Component.text; +import static net.kyori.adventure.text.format.NamedTextColor.GREEN; + +/** + * Provides optional integration with the {@link DiscordPlotSystemAPI} plugin. + * + *

This singleton utility wraps interaction with the {@link asia.buildtheearth.asean.discord.plotsystem.api.DiscordPlotSystemAPI} + * and should only be initialized if the Discord plugin is available and enabled.

+ * + *

Submitting a plot:

+ *
{@snippet : + * AbstractPlot plot = DataProvider.PLOT.getPlotById(1); + * DiscordUtil.getOpt(plot.getID()).ifPresent(DiscordUtil.PlotEventAction::onPlotSubmit); + * }
+ * + *

Always check for availability using {@link #getOpt(int)} before calling integration methods, + * to avoid runtime errors if the plugin is not installed.

+ * + * @see #init(Plugin) + * @see #getOpt(int) + */ +public class DiscordUtil { + + private static @Nullable DiscordUtil instance; + + private final @NotNull DiscordPlotSystemAPI api; + + private DiscordUtil(@NotNull DiscordPlotSystemAPI api) { + this.api = api; + } + + public static Optional getOpt(int plotID) { + return Optional.ofNullable(instance).map(instance -> new PlotEventAction(plotID, instance)); + } + + public static void init(@Nullable org.bukkit.plugin.Plugin plugin) { + if(plugin instanceof DiscordPlotSystemAPI discordPlugin) { + DiscordUtil.instance = new DiscordUtil(discordPlugin); + DiscordPlotSystemAPI.registerProvider(new DiscordUtil.DiscordDataProvider()); + PlotSystem.getPlugin().getComponentLogger().info(text("Registered data provider to DiscordPlotSystem", GREEN)); + } + } + + public void callEvent(E event) { + this.api.callEvent(event); + } + + /** + * Wrapper for Discord API abandon types. + * + * @see asia.buildtheearth.asean.discord.plotsystem.api.events.AbandonType + */ + public enum AbandonType { + /** @see asia.buildtheearth.asean.discord.plotsystem.api.events.AbandonType#INACTIVE */ + INACTIVE, + /** @see asia.buildtheearth.asean.discord.plotsystem.api.events.AbandonType#MANUALLY */ + MANUALLY, + /** @see asia.buildtheearth.asean.discord.plotsystem.api.events.AbandonType#COMMANDS */ + COMMANDS, + /** @see asia.buildtheearth.asean.discord.plotsystem.api.events.AbandonType#SYSTEM */ + SYSTEM + } + + public static final class PlotEventAction { + + private final int plotID; + private final @NotNull DiscordUtil api; + + private PlotEventAction(int plotID, @NotNull DiscordUtil api) { + this.plotID = plotID; + this.api = api; + } + + public void onPlotCreate(@NotNull AbstractPlot plot) { + CompletableFuture.supplyAsync(() -> DiscordPlotSystemAPI.getDataProvider().getData(plot)) + .thenAccept(createData -> this.api.callEvent(new PlotCreateEvent(this.plotID, createData))); + } + + public void onPlotSubmit() { + this.api.callEvent(new PlotSubmitEvent(this.plotID)); + } + + public void onPlotAbandon(@NotNull AbandonType type) { + this.api.callEvent(new PlotAbandonedEvent(this.plotID, + asia.buildtheearth.asean.discord.plotsystem.api.events.AbandonType.valueOf(type.name())) + ); + } + + public void onPlotReject() { + this.api.callEvent(new PlotRejectedEvent(this.plotID)); + } + + public void onPlotFeedback(String feedback) { + this.api.callEvent(new PlotFeedbackEvent(this.plotID, feedback)); + } + + public void onPlotApprove() { + this.api.callEvent(new PlotApprovedEvent(this.plotID)); + } + + public void onPlotUndoReview() { + this.api.callEvent(new PlotUndoReviewEvent(this.plotID)); + } + + public void onPlotUndoSubmit() { + this.api.callEvent(new PlotUndoSubmitEvent(this.plotID)); + } + + public void onPlotInactivity(LocalDate abandonDate) { + this.api.callEvent(new InactivityNoticeEvent(this.plotID, abandonDate)); + } + } + + /** + * Data Provider for {@link DiscordPlotSystemAPI} + * registered during the plugin onEnabled. + * + * @see DiscordPlotSystemAPI#registerProvider(PlotCreateProvider) + */ + private static final class DiscordDataProvider implements PlotCreateProvider { + + public @Nullable PlotCreateData getData(AbstractPlot plot) { + if(plot == null) return null; + + CityProject cityProject = ((Plot) plot).getCityProject(); + + if(!cityProject.isVisible()) return null; + + // GeoCoordinate + double[] geoCoordinates = null; + try { + BlockVector3 mcCoordinates = plot.getCoordinates(); + + geoCoordinates = CoordinateConversion.convertToGeo(mcCoordinates.x(), mcCoordinates.z()); + } catch (IOException | OutOfProjectionBoundsException ignored) { } + + int plotID = plot.getID(); + + UUID ownerUUID = plot.getPlotOwner().getUUID(); + + String cityProjectID = cityProject.getID(); + + String countryCode = cityProject.getCountry().getCode(); + + try { + PlotCreateData.PlotStatus status = PlotCreateData.prepareStatus(plot.getStatus().name()); + return new PlotCreateData(plotID, ownerUUID.toString(), status, cityProjectID, countryCode, geoCoordinates); + } + catch (IllegalArgumentException ignored) { + return null; + } + } + + @Override + public PlotCreateData getData(Object rawData) { + if(rawData == null) return null; + if(rawData instanceof AbstractPlot plot) + return this.getData(plot); + else return null; + } + + @Override + public PlotCreateData getData(int plotID) { + return this.getData(DataProvider.PLOT.getPlotById(plotID)); + } + } +} diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 5a5f48fd..e6ff7fb8 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -4,7 +4,7 @@ api-version: "1.21" name: Plot-System author: R3tuxn & Cinnazeyy softdepend: [ LangLibs, FancyNpcs, VoidGen, FastAsyncWorldEdit, Multiverse-Core, WorldEdit, - DecentHolograms, WorldGuard, WorldGuardExtraFlags, HeadDatabase, ProtocolLib, ParticleNativeAPI ] + DecentHolograms, WorldGuard, WorldGuardExtraFlags, HeadDatabase, ProtocolLib, ParticleNativeAPI, DiscordPlotSystem ] commands: cancelchat: From 5458bd7ba63c730d27bd157ff4adc19f3b86daa0 Mon Sep 17 00:00:00 2001 From: Tintinkung Date: Sun, 18 Jan 2026 18:55:11 +0700 Subject: [PATCH 2/6] fix: outdated #abandonPlot and #getID --- .../plotsystem/commands/plot/CMD_Plot_UndoSubmit.java | 2 +- .../plotsystem/core/menus/review/ReviewPlotTogglesMenu.java | 4 ++-- .../core/system/plot/generator/AbstractPlotGenerator.java | 3 ++- .../core/system/plot/generator/DefaultPlotGenerator.java | 2 +- .../plotsystem/core/system/plot/utils/PlotUtils.java | 6 +++--- src/main/java/com/alpsbte/plotsystem/utils/DiscordUtil.java | 4 ++-- 6 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_UndoSubmit.java b/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_UndoSubmit.java index 711f1234..2041045c 100644 --- a/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_UndoSubmit.java +++ b/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_UndoSubmit.java @@ -71,7 +71,7 @@ public void onCommand(CommandSender sender, String[] args) { Bukkit.getScheduler().runTask(PlotSystem.getPlugin(), () -> { PlotUtils.Actions.undoSubmit(plot); - DiscordUtil.getOpt(plot.getID()).ifPresent(DiscordUtil.PlotEventAction::onPlotUndoSubmit); + DiscordUtil.getOpt(plot.getId()).ifPresent(DiscordUtil.PlotEventAction::onPlotUndoSubmit); sender.sendMessage(Utils.ChatUtils.getInfoFormat(langUtil.get(sender, LangPaths.Message.Info.UNDID_SUBMISSION, plot.getId() + ""))); player.playSound(player.getLocation(), Utils.SoundUtils.FINISH_PLOT_SOUND, 1, 1); diff --git a/src/main/java/com/alpsbte/plotsystem/core/menus/review/ReviewPlotTogglesMenu.java b/src/main/java/com/alpsbte/plotsystem/core/menus/review/ReviewPlotTogglesMenu.java index 99ab7836..498b19a4 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/menus/review/ReviewPlotTogglesMenu.java +++ b/src/main/java/com/alpsbte/plotsystem/core/menus/review/ReviewPlotTogglesMenu.java @@ -130,11 +130,11 @@ private void submitReview() { if (!isRejected) { reviewerConfirmationMessage = Utils.ChatUtils.getInfoFormat(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Message.Info.PLOT_MARKED_REVIEWED, Integer.toString(plot.getId()), getParticipantsString())); if(!acceptPlot(review.getScore(), review.getSplitScore())) return; - DiscordUtil.getOpt(plot.getID()).ifPresent(DiscordUtil.PlotEventAction::onPlotApprove); + DiscordUtil.getOpt(plot.getId()).ifPresent(DiscordUtil.PlotEventAction::onPlotApprove); } else { reviewerConfirmationMessage = Utils.ChatUtils.getInfoFormat(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Message.Info.PLOT_REJECTED, Integer.toString(plot.getId()), getParticipantsString())); PlotUtils.Actions.undoSubmit(plot); - DiscordUtil.getOpt(plot.getID()).ifPresent(DiscordUtil.PlotEventAction::onPlotReject); + DiscordUtil.getOpt(plot.getId()).ifPresent(DiscordUtil.PlotEventAction::onPlotReject); } Bukkit.getScheduler().runTask(PlotSystem.getPlugin(), () -> { diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/plot/generator/AbstractPlotGenerator.java b/src/main/java/com/alpsbte/plotsystem/core/system/plot/generator/AbstractPlotGenerator.java index 5b4ec0cd..2e1d2569 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/plot/generator/AbstractPlotGenerator.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/plot/generator/AbstractPlotGenerator.java @@ -10,6 +10,7 @@ import com.alpsbte.plotsystem.core.system.plot.world.OnePlotWorld; import com.alpsbte.plotsystem.core.system.plot.world.PlotWorld; import com.alpsbte.plotsystem.utils.DependencyManager; +import com.alpsbte.plotsystem.utils.DiscordUtil; import com.alpsbte.plotsystem.utils.Utils; import com.alpsbte.plotsystem.utils.io.ConfigPaths; import com.alpsbte.plotsystem.utils.io.ConfigUtil; @@ -112,7 +113,7 @@ private AbstractPlotGenerator(@NotNull AbstractPlot plot, @NotNull Builder build this.onComplete(exception != null, false); if (exception != null) { - PlotUtils.Actions.abandonPlot(plot); + PlotUtils.Actions.abandonPlot(plot, DiscordUtil.AbandonType.SYSTEM); onException(exception); } } diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/plot/generator/DefaultPlotGenerator.java b/src/main/java/com/alpsbte/plotsystem/core/system/plot/generator/DefaultPlotGenerator.java index fd302f6b..698caa48 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/plot/generator/DefaultPlotGenerator.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/plot/generator/DefaultPlotGenerator.java @@ -120,6 +120,6 @@ protected void onComplete(boolean failed, boolean unloadWorld) { LangUtil.getInstance().broadcast(LangPaths.Message.Info.CREATED_NEW_PLOT, getBuilder().getName()); // Create the plot to discord forum - DiscordUtil.getOpt(plot.getID()).ifPresent(event -> event.onPlotCreate(this.plot)); + DiscordUtil.getOpt(plot.getId()).ifPresent(event -> event.onPlotCreate(this.plot)); } } diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/plot/utils/PlotUtils.java b/src/main/java/com/alpsbte/plotsystem/core/system/plot/utils/PlotUtils.java index 871a78f2..5e524ae4 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/plot/utils/PlotUtils.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/plot/utils/PlotUtils.java @@ -351,13 +351,13 @@ public static void checkPlotsForLastActivity() { // Check if today is within 5 days before the plot's abandon date if(inNotificationWindow && LocalDate.now().isAfter(abandonDate.minusDays(5))) { // Notify the plot's owner on discord - DiscordUtil.getOpt(plot.getID()).ifPresent(event -> event.onPlotInactivity(abandonDate)); + DiscordUtil.getOpt(plot.getId()).ifPresent(event -> event.onPlotInactivity(abandonDate)); } if (interval == -2 || abandonDate.isAfter(LocalDate.now())) continue; Bukkit.getScheduler().runTask(PlotSystem.getPlugin(), () -> { - if (Actions.abandonPlot(plot)) { + if (Actions.abandonPlot(plot, DiscordUtil.AbandonType.INACTIVE)) { PlotSystem.getPlugin().getComponentLogger().info(text("Abandoned plot #" + plot.getId() + " due to inactivity!")); } else { PlotSystem.getPlugin().getComponentLogger().warn(text("An error occurred while abandoning plot #" + plot.getId() + " due to inactivity!")); @@ -405,7 +405,7 @@ public static void submitPlot(@NotNull Plot plot) { } } - DiscordUtil.getOpt(plot.getID()).ifPresent(DiscordUtil.PlotEventAction::onPlotSubmit); + DiscordUtil.getOpt(plot.getId()).ifPresent(DiscordUtil.PlotEventAction::onPlotSubmit); } public static void undoSubmit(@NotNull Plot plot) { diff --git a/src/main/java/com/alpsbte/plotsystem/utils/DiscordUtil.java b/src/main/java/com/alpsbte/plotsystem/utils/DiscordUtil.java index acb390c9..ba82e6be 100644 --- a/src/main/java/com/alpsbte/plotsystem/utils/DiscordUtil.java +++ b/src/main/java/com/alpsbte/plotsystem/utils/DiscordUtil.java @@ -182,11 +182,11 @@ private static final class DiscordDataProvider implements PlotCreateProvider { geoCoordinates = CoordinateConversion.convertToGeo(mcCoordinates.x(), mcCoordinates.z()); } catch (IOException | OutOfProjectionBoundsException ignored) { } - int plotID = plot.getID(); + int plotID = plot.getId(); UUID ownerUUID = plot.getPlotOwner().getUUID(); - String cityProjectID = cityProject.getID(); + String cityProjectID = cityProject.getId(); String countryCode = cityProject.getCountry().getCode(); From 3f1bd28b91c175a0b27ad3634a16b5d6365c5000 Mon Sep 17 00:00:00 2001 From: Tintinkung Date: Sun, 18 Jan 2026 19:18:39 +0700 Subject: [PATCH 3/6] update: discord-plotsystem-api 1.2.3 (pom.xml & gradle) --- build.gradle.kts | 1 + gradle/libs.versions.toml | 4 +++- pom.xml | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 6013616a..b0fc3a92 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -57,6 +57,7 @@ dependencies { compileOnly(libs.de.oliver.fancynpcs) compileOnly(libs.li.cinnazeyy.langlibs.api) compileOnly(libs.commons.io.commons.io) + compileOnly(libs.asia.buildtheearth.asean.discord.discord.plotsystem.api) } val versionDetails: groovy.lang.Closure by extra diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 0af5093b..01de7e52 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -18,6 +18,7 @@ io-papermc-paper-paper-api = "1.21.8-R0.1-SNAPSHOT" li-cinnazeyy-langlibs-api = "1.5.1" org-mariadb-jdbc-mariadb-java-client = "2.7.4" com-intellectualsites-bom-bom-newest = "1.55" # Ref: https://github.com/IntellectualSites/bom +asia-buildtheearth-asean-discord-discord-plotsystem-api = "1.2.3" # Ref: https://github.com/ASEAN-Build-The-Earth/discordsrv-plotsystem [libraries] com-alpsbte-alpslib-alpslib-hologram = { module = "com.alpsbte.alpslib:alpslib-hologram", version.ref = "com-alpsbte-alpslib-alpslib-hologram" } @@ -35,4 +36,5 @@ de-oliver-fancynpcs = { module = "de.oliver:FancyNpcs", version.ref = "de-oliver io-papermc-paper-paper-api = { module = "io.papermc.paper:paper-api", version.ref = "io-papermc-paper-paper-api" } li-cinnazeyy-langlibs-api = { module = "li.cinnazeyy:LangLibs-API", version.ref = "li-cinnazeyy-langlibs-api" } org-mariadb-jdbc-mariadb-java-client = { module = "org.mariadb.jdbc:mariadb-java-client", version.ref = "org-mariadb-jdbc-mariadb-java-client" } -com-intellectualsites-bom-bom-newest = { module = "com.intellectualsites.bom:bom-newest", version.ref = "com-intellectualsites-bom-bom-newest" } \ No newline at end of file +com-intellectualsites-bom-bom-newest = { module = "com.intellectualsites.bom:bom-newest", version.ref = "com-intellectualsites-bom-bom-newest" } +asia-buildtheearth-asean-discord-discord-plotsystem-api = { module = "asia.buildtheearth.asean.discord:discord-plotsystem-api", version.ref = "asia-buildtheearth-asean-discord-discord-plotsystem-api" } \ No newline at end of file diff --git a/pom.xml b/pom.xml index 5e8fa4cb..026584f4 100644 --- a/pom.xml +++ b/pom.xml @@ -109,7 +109,7 @@ asia.buildtheearth.asean.discord discord-plotsystem-api - 1.2.0 + 1.2.3 provided From 38f9f75621c804d8d0ae1e87ffc50f55744e2779 Mon Sep 17 00:00:00 2001 From: Tintinkung Date: Fri, 20 Jun 2025 00:28:59 +0700 Subject: [PATCH 4/6] fix: incorrect inactivity fixed-timer * Using minutesDiff <= 75 may run 3 times a day * Edited minute-window to 60 which the actual windows will be minutesDiff < (60 / 2) (cherry picked from commit 31c6900a0dd155c5bb52019e96ccf6362abd1e9e) --- .../alpsbte/plotsystem/core/system/plot/utils/PlotUtils.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/plot/utils/PlotUtils.java b/src/main/java/com/alpsbte/plotsystem/core/system/plot/utils/PlotUtils.java index 5e524ae4..0f5fc3aa 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/plot/utils/PlotUtils.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/plot/utils/PlotUtils.java @@ -336,10 +336,11 @@ public static void checkPlotsForLastActivity() { if (inactivityIntervalDays == -2 && rejectedInactivityIntervalDays == -2) return; // Determine if the current time is within the notification window. - // Run within a ±75-minute window around 16:00 local time. + // Run within a ±60-minute window around 16:00 local time. // TODO: Maybe a config option? the #startUnfinishedPlotReminderTimer is too frequent to be a discord ping + int minuteWindow = 60; long minutesDiff = Math.abs(ChronoUnit.MINUTES.between(LocalTime.now(), LocalTime.of(16, 0))); - boolean inNotificationWindow = minutesDiff <= 75; + boolean inNotificationWindow = minutesDiff < (minuteWindow / 2); for (Plot plot : plots) { LocalDate lastActivity = plot.getLastActivity(); From 68b85c6cad2d951aa89c9bbd430bab03e3aa2953 Mon Sep 17 00:00:00 2001 From: Tintinkung Date: Fri, 27 Jun 2025 23:31:35 +0700 Subject: [PATCH 5/6] feat: configurable inactivity notification * make inactivity notification for discord configurable in config.yml * make notification window calculation clearer (cherry picked from commit 0fda61367aaf9bbf524dc2408371e8383c1c7cfd) --- .../core/system/plot/utils/PlotUtils.java | 18 ++++++++++-------- .../plotsystem/utils/io/ConfigPaths.java | 2 ++ src/main/resources/config.yml | 7 +++++++ 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/plot/utils/PlotUtils.java b/src/main/java/com/alpsbte/plotsystem/core/system/plot/utils/PlotUtils.java index 0f5fc3aa..a3652c22 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/plot/utils/PlotUtils.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/plot/utils/PlotUtils.java @@ -331,16 +331,18 @@ public static void checkPlotsForLastActivity() { Bukkit.getScheduler().runTaskTimerAsynchronously(PlotSystem.getPlugin(), () -> { List plots = DataProvider.PLOT.getPlots(Status.unfinished); FileConfiguration config = PlotSystem.getPlugin().getConfig(); - long inactivityIntervalDays = config.getLong(ConfigPaths.INACTIVITY_INTERVAL); + long inactivityIntervalDays = config.getLong(ConfigPaths.INACTIVITY_INTERVAL, -2); long rejectedInactivityIntervalDays = (config.getLong(ConfigPaths.REJECTED_INACTIVITY_INTERVAL) != -1) ? config.getLong(ConfigPaths.REJECTED_INACTIVITY_INTERVAL) : inactivityIntervalDays; + int inactivityNotificationDays = config.getInt(ConfigPaths.INACTIVITY_NOTIFICATION_DAYS, 0); + int inactivityNotificationTime = config.getInt(ConfigPaths.INACTIVITY_NOTIFICATION_TIME, 16); if (inactivityIntervalDays == -2 && rejectedInactivityIntervalDays == -2) return; // Determine if the current time is within the notification window. - // Run within a ±60-minute window around 16:00 local time. - // TODO: Maybe a config option? the #startUnfinishedPlotReminderTimer is too frequent to be a discord ping - int minuteWindow = 60; - long minutesDiff = Math.abs(ChronoUnit.MINUTES.between(LocalTime.now(), LocalTime.of(16, 0))); - boolean inNotificationWindow = minutesDiff < (minuteWindow / 2); + // Run within a ±minute window around a set local time. + LocalTime now = LocalTime.now(); + LocalTime start = LocalTime.of(inactivityNotificationTime, 0).minusMinutes(30); + LocalTime end = LocalTime.of(inactivityNotificationTime, 0).plusMinutes(30); + boolean inNotificationWindow = inactivityNotificationDays > 0 && !now.isBefore(start) && !now.isAfter(end);; for (Plot plot : plots) { LocalDate lastActivity = plot.getLastActivity(); @@ -349,8 +351,8 @@ public static void checkPlotsForLastActivity() { long interval = plot.isRejected() ? rejectedInactivityIntervalDays : inactivityIntervalDays; LocalDate abandonDate = lastActivity.plusDays(interval); - // Check if today is within 5 days before the plot's abandon date - if(inNotificationWindow && LocalDate.now().isAfter(abandonDate.minusDays(5))) { + // Check if today is within X days before the plot's abandon date + if(inNotificationWindow && LocalDate.now().isAfter(abandonDate.minusDays(inactivityNotificationDays))) { // Notify the plot's owner on discord DiscordUtil.getOpt(plot.getId()).ifPresent(event -> event.onPlotInactivity(abandonDate)); } diff --git a/src/main/java/com/alpsbte/plotsystem/utils/io/ConfigPaths.java b/src/main/java/com/alpsbte/plotsystem/utils/io/ConfigPaths.java index 0f263ca1..0ea2c3f7 100644 --- a/src/main/java/com/alpsbte/plotsystem/utils/io/ConfigPaths.java +++ b/src/main/java/com/alpsbte/plotsystem/utils/io/ConfigPaths.java @@ -9,6 +9,8 @@ public abstract class ConfigPaths { public static final String ENABLE_SCORE_REQUIREMENT = "enable-score-requirement"; public static final String DEV_MODE = "dev-mode"; public static final String INACTIVITY_INTERVAL = "inactivity-interval"; + public static final String INACTIVITY_NOTIFICATION_TIME = "inactivity-notification-time"; + public static final String INACTIVITY_NOTIFICATION_DAYS = "inactivity-notification-days"; public static final String REJECTED_INACTIVITY_INTERVAL = "rejected-inactivity-interval"; public static final String ENABLE_GROUP_SUPPORT = "enable-group-support"; public static final String UNFINISHED_REMINDER_INTERVAL = "unfinished-reminder-interval"; diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 1ef96243..f3345ae2 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -21,6 +21,13 @@ enable-score-requirement: true # How many days of inactivity it will take before a claimed plot is automatically abandoned, -2 disables it inactivity-interval: 14 +# How long left (Days) until the plot gets abandon due to inactivity and the system will start pinging owner on discord +# Be careful, if set >= inactivity-interval will ping the owner every day after plot is created +inactivity-notification-days: 5 + +# What local-time in a day to ping the owner discord for their inactive plot (24 Hour) +inactivity-notification-time: 16 + # How many days of inactivity it will take before a rejected plots are automatically abandoned # Use -1 to use the normal inactivity-interval, -2 disables it rejected-inactivity-interval: -1 From ccfac04e331cacff6698ae14957e676488257902 Mon Sep 17 00:00:00 2001 From: Tintinkung Date: Sun, 18 Jan 2026 19:26:24 +0700 Subject: [PATCH 6/6] move: discord plugin #get to DependencyManager --- src/main/java/com/alpsbte/plotsystem/PlotSystem.java | 7 +++---- .../com/alpsbte/plotsystem/utils/DependencyManager.java | 5 +++++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/alpsbte/plotsystem/PlotSystem.java b/src/main/java/com/alpsbte/plotsystem/PlotSystem.java index c19a31aa..4174e785 100644 --- a/src/main/java/com/alpsbte/plotsystem/PlotSystem.java +++ b/src/main/java/com/alpsbte/plotsystem/PlotSystem.java @@ -19,6 +19,7 @@ import com.alpsbte.plotsystem.core.system.tutorial.TutorialEventListener; import com.alpsbte.plotsystem.core.system.tutorial.utils.TutorialNPCTurnTracker; import com.alpsbte.plotsystem.core.system.tutorial.utils.TutorialUtils; +import com.alpsbte.plotsystem.utils.DependencyManager; import com.alpsbte.plotsystem.utils.DiscordUtil; import com.alpsbte.plotsystem.utils.Utils; import com.alpsbte.plotsystem.utils.io.ConfigPaths; @@ -129,10 +130,8 @@ public void onEnable() { } // Register discord Integration - org.bukkit.plugin.Plugin discordPlugin = plugin.getServer().getPluginManager().getPlugin("DiscordPlotSystem"); - if(discordPlugin != null) { - DiscordUtil.init(discordPlugin); - } + org.bukkit.plugin.Plugin discordPlugin = DependencyManager.getDiscordIntegration(); + if(discordPlugin != null) DiscordUtil.init(discordPlugin); pluginEnabled = true; getComponentLogger().info(text("Enabled Plot-System plugin.", DARK_GREEN)); diff --git a/src/main/java/com/alpsbte/plotsystem/utils/DependencyManager.java b/src/main/java/com/alpsbte/plotsystem/utils/DependencyManager.java index e348266e..4ce0007e 100644 --- a/src/main/java/com/alpsbte/plotsystem/utils/DependencyManager.java +++ b/src/main/java/com/alpsbte/plotsystem/utils/DependencyManager.java @@ -4,6 +4,7 @@ import com.sk89q.worldguard.bukkit.WorldGuardPlugin; import org.bukkit.Bukkit; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.mvplugins.multiverse.core.MultiverseCoreApi; import java.util.Objects; @@ -26,6 +27,10 @@ public static boolean isWorldGuardExtraFlagsEnabled() { return PlotSystem.getPlugin().getServer().getPluginManager().isPluginEnabled("WorldGuardExtraFlags"); } + public static @Nullable org.bukkit.plugin.Plugin getDiscordIntegration() { + return PlotSystem.getPlugin().getServer().getPluginManager().getPlugin("DiscordPlotSystem"); + } + /** * @param worldName Name of the world * @return Config path for the world