diff --git a/api/src/main/java/dev/plex/api/PlexApi.java b/api/src/main/java/dev/plex/api/PlexApi.java index 377e552..7013e3d 100644 --- a/api/src/main/java/dev/plex/api/PlexApi.java +++ b/api/src/main/java/dev/plex/api/PlexApi.java @@ -9,6 +9,7 @@ import dev.plex.api.message.MessageApi; import dev.plex.api.module.ModulesApi; import dev.plex.api.player.PlayersApi; import dev.plex.api.punishment.PunishmentsApi; +import dev.plex.api.rollback.RollbackApi; import dev.plex.api.scheduler.SchedulerApi; import dev.plex.api.storage.StorageApi; @@ -49,6 +50,8 @@ public interface PlexApi PunishmentsApi punishments(); + RollbackApi rollback(); + SchedulerApi scheduler(); StorageApi storage(); diff --git a/api/src/main/java/dev/plex/api/rollback/RollbackApi.java b/api/src/main/java/dev/plex/api/rollback/RollbackApi.java new file mode 100644 index 0000000..4f8ece3 --- /dev/null +++ b/api/src/main/java/dev/plex/api/rollback/RollbackApi.java @@ -0,0 +1,15 @@ +package dev.plex.api.rollback; + +import org.bukkit.command.CommandSender; + +public interface RollbackApi +{ + boolean isAvailable(); + + boolean rollback(CommandSender sender, String playerName, int seconds); + + default boolean rollbackLastDay(CommandSender sender, String playerName) + { + return rollback(sender, playerName, 86400); + } +} diff --git a/api/src/main/java/dev/plex/api/scheduler/SchedulerApi.java b/api/src/main/java/dev/plex/api/scheduler/SchedulerApi.java index c23ea96..c20d007 100644 --- a/api/src/main/java/dev/plex/api/scheduler/SchedulerApi.java +++ b/api/src/main/java/dev/plex/api/scheduler/SchedulerApi.java @@ -1,8 +1,142 @@ package dev.plex.api.scheduler; +import io.papermc.paper.threadedregions.scheduler.ScheduledTask; + +import java.util.concurrent.Executor; +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; + +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.entity.Entity; +import org.jetbrains.annotations.Nullable; + public interface SchedulerApi { - Object runSync(Runnable task); - Object runLater(Runnable task, long delayTicks); - Object runTimer(Runnable task, long delayTicks, long periodTicks); + Executor asyncExecutor(); + + void executeGlobal(Runnable task); + + ScheduledTask runGlobal(Consumer task); + + default ScheduledTask runGlobal(Runnable task) + { + return runGlobal(scheduledTask -> task.run()); + } + + ScheduledTask runGlobalLater(Consumer task, long delayTicks); + + default ScheduledTask runGlobalLater(Runnable task, long delayTicks) + { + return runGlobalLater(scheduledTask -> task.run(), delayTicks); + } + + ScheduledTask runGlobalTimer(Consumer task, long delayTicks, long periodTicks); + + default ScheduledTask runGlobalTimer(Runnable task, long delayTicks, long periodTicks) + { + return runGlobalTimer(scheduledTask -> task.run(), delayTicks, periodTicks); + } + + ScheduledTask runAsync(Consumer task); + + default ScheduledTask runAsync(Runnable task) + { + return runAsync(scheduledTask -> task.run()); + } + + ScheduledTask runAsyncLater(Consumer task, long delay, TimeUnit unit); + + default ScheduledTask runAsyncLater(Runnable task, long delay, TimeUnit unit) + { + return runAsyncLater(scheduledTask -> task.run(), delay, unit); + } + + ScheduledTask runAsyncTimer(Consumer task, long delay, long period, TimeUnit unit); + + default ScheduledTask runAsyncTimer(Runnable task, long delay, long period, TimeUnit unit) + { + return runAsyncTimer(scheduledTask -> task.run(), delay, period, unit); + } + + void executeRegion(Location location, Runnable task); + + void executeRegion(World world, int chunkX, int chunkZ, Runnable task); + + ScheduledTask runRegion(Location location, Consumer task); + + default ScheduledTask runRegion(Location location, Runnable task) + { + return runRegion(location, scheduledTask -> task.run()); + } + + ScheduledTask runRegion(World world, int chunkX, int chunkZ, Consumer task); + + default ScheduledTask runRegion(World world, int chunkX, int chunkZ, Runnable task) + { + return runRegion(world, chunkX, chunkZ, scheduledTask -> task.run()); + } + + ScheduledTask runRegionLater(Location location, Consumer task, long delayTicks); + + default ScheduledTask runRegionLater(Location location, Runnable task, long delayTicks) + { + return runRegionLater(location, scheduledTask -> task.run(), delayTicks); + } + + ScheduledTask runRegionLater(World world, int chunkX, int chunkZ, Consumer task, long delayTicks); + + default ScheduledTask runRegionLater(World world, int chunkX, int chunkZ, Runnable task, long delayTicks) + { + return runRegionLater(world, chunkX, chunkZ, scheduledTask -> task.run(), delayTicks); + } + + ScheduledTask runRegionTimer(Location location, Consumer task, long delayTicks, long periodTicks); + + default ScheduledTask runRegionTimer(Location location, Runnable task, long delayTicks, long periodTicks) + { + return runRegionTimer(location, scheduledTask -> task.run(), delayTicks, periodTicks); + } + + ScheduledTask runRegionTimer(World world, int chunkX, int chunkZ, Consumer task, long delayTicks, long periodTicks); + + default ScheduledTask runRegionTimer(World world, int chunkX, int chunkZ, Runnable task, long delayTicks, long periodTicks) + { + return runRegionTimer(world, chunkX, chunkZ, scheduledTask -> task.run(), delayTicks, periodTicks); + } + + boolean executeEntity(Entity entity, Runnable task, @Nullable Runnable retired, long delayTicks); + + default boolean executeEntity(Entity entity, Runnable task, long delayTicks) + { + return executeEntity(entity, task, null, delayTicks); + } + + @Nullable + ScheduledTask runEntity(Entity entity, Consumer task, @Nullable Runnable retired); + + default @Nullable ScheduledTask runEntity(Entity entity, Runnable task) + { + return runEntity(entity, scheduledTask -> task.run(), null); + } + + @Nullable + ScheduledTask runEntityLater(Entity entity, Consumer task, @Nullable Runnable retired, long delayTicks); + + default @Nullable ScheduledTask runEntityLater(Entity entity, Runnable task, long delayTicks) + { + return runEntityLater(entity, scheduledTask -> task.run(), null, delayTicks); + } + + @Nullable + ScheduledTask runEntityTimer(Entity entity, Consumer task, @Nullable Runnable retired, long delayTicks, long periodTicks); + + default @Nullable ScheduledTask runEntityTimer(Entity entity, Runnable task, long delayTicks, long periodTicks) + { + return runEntityTimer(entity, scheduledTask -> task.run(), null, delayTicks, periodTicks); + } + + void cancelGlobalTasks(); + + void cancelAsyncTasks(); } diff --git a/proxy/src/main/java/dev/plex/api/impl/DefaultPlexApi.java b/proxy/src/main/java/dev/plex/api/impl/DefaultPlexApi.java index b4671c8..18e9e25 100644 --- a/proxy/src/main/java/dev/plex/api/impl/DefaultPlexApi.java +++ b/proxy/src/main/java/dev/plex/api/impl/DefaultPlexApi.java @@ -12,6 +12,7 @@ import dev.plex.api.message.MessageApi; import dev.plex.api.module.ModulesApi; import dev.plex.api.player.PlayersApi; import dev.plex.api.punishment.PunishmentsApi; +import dev.plex.api.rollback.RollbackApi; import dev.plex.api.scheduler.SchedulerApi; import dev.plex.api.storage.StorageApi; @@ -38,6 +39,7 @@ public final class DefaultPlexApi implements PlexApi @Override public MessageApi messages() { throw unsupported(); } @Override public PlayersApi players() { throw unsupported(); } @Override public PunishmentsApi punishments() { throw unsupported(); } + @Override public RollbackApi rollback() { throw unsupported(); } @Override public SchedulerApi scheduler() { throw unsupported(); } @Override public StorageApi storage() { throw unsupported(); } diff --git a/server/src/main/java/dev/plex/Plex.java b/server/src/main/java/dev/plex/Plex.java index 1020501..812ea5d 100644 --- a/server/src/main/java/dev/plex/Plex.java +++ b/server/src/main/java/dev/plex/Plex.java @@ -11,6 +11,7 @@ import dev.plex.handlers.CommandHandler; import dev.plex.handlers.ListenerHandler; import dev.plex.hook.CoreProtectHook; import dev.plex.hook.PrismHook; +import dev.plex.hook.RollbackManager; import dev.plex.module.ModuleManager; import dev.plex.player.PlayerService; import dev.plex.player.PlexPlayer; @@ -18,7 +19,6 @@ import dev.plex.punishment.PunishmentManager; import dev.plex.services.ServiceManager; import dev.plex.storage.RedisConnection; import dev.plex.storage.SQLConnection; -import dev.plex.storage.StorageExecutor; import dev.plex.storage.StorageType; import dev.plex.storage.player.SQLPlayerData; import dev.plex.storage.punishment.SQLNotes; @@ -79,6 +79,7 @@ public class Plex extends JavaPlugin private CoreProtectHook coreProtectHook; private PrismHook prismHook; + private RollbackManager rollbackManager; public static Plex get() { @@ -227,6 +228,8 @@ public class Plex extends JavaPlugin PlexLog.debug("Not hooking into SuperVanish / PremiumVanish"); } + rollbackManager = new RollbackManager(this); + updateChecker = new UpdateChecker(this); PlexLog.log("Update checking enabled"); @@ -246,9 +249,9 @@ public class Plex extends JavaPlugin PlexLog.log("Redis is disabled in the configuration file, not connecting."); } - punishmentRepository = new SQLPunishment(sqlConnection.getConnectionSource()); + punishmentRepository = new SQLPunishment(sqlConnection.getConnectionSource(), api.scheduler().asyncExecutor()); playerRepository = new SQLPlayerData(sqlConnection.getConnectionSource(), punishmentRepository); - noteRepository = new SQLNotes(sqlConnection.getConnectionSource()); + noteRepository = new SQLNotes(sqlConnection.getConnectionSource(), api.scheduler().asyncExecutor()); playerService = new PlayerService(playerCache, playerRepository); new ListenerHandler(this); @@ -292,13 +295,17 @@ public class Plex extends JavaPlugin this.getServer().getMessenger().unregisterOutgoingPluginChannel(this); + if (serviceManager != null) + { + serviceManager.endServices(); + } + moduleManager.disableModules(); if (sqlConnection != null) { sqlConnection.close(); } - StorageExecutor.shutdown(); } private void generateWorlds() diff --git a/server/src/main/java/dev/plex/api/impl/DefaultPlexApi.java b/server/src/main/java/dev/plex/api/impl/DefaultPlexApi.java index 33e3555..667721c 100644 --- a/server/src/main/java/dev/plex/api/impl/DefaultPlexApi.java +++ b/server/src/main/java/dev/plex/api/impl/DefaultPlexApi.java @@ -12,6 +12,7 @@ import dev.plex.api.message.MessageApi; import dev.plex.api.module.ModulesApi; import dev.plex.api.player.PlayersApi; import dev.plex.api.punishment.PunishmentsApi; +import dev.plex.api.rollback.RollbackApi; import dev.plex.api.scheduler.SchedulerApi; import dev.plex.api.storage.StorageApi; @@ -27,6 +28,7 @@ public final class DefaultPlexApi implements PlexApi private final MessageApi messages; private final PlayersApi players; private final PunishmentsApi punishments; + private final RollbackApi rollback; private final SchedulerApi scheduler; private final StorageApi storage; @@ -42,6 +44,7 @@ public final class DefaultPlexApi implements PlexApi this.messages = new DefaultMessageApi(); this.players = new DefaultPlayersApi(plugin); this.punishments = new DefaultPunishmentsApi(plugin); + this.rollback = new DefaultRollbackApi(plugin); this.scheduler = new DefaultSchedulerApi(plugin); this.storage = new DefaultStorageApi(plugin); } @@ -56,6 +59,7 @@ public final class DefaultPlexApi implements PlexApi @Override public MessageApi messages() { return messages; } @Override public PlayersApi players() { return players; } @Override public PunishmentsApi punishments() { return punishments; } + @Override public RollbackApi rollback() { return rollback; } @Override public SchedulerApi scheduler() { return scheduler; } @Override public StorageApi storage() { return storage; } } diff --git a/server/src/main/java/dev/plex/api/impl/DefaultRollbackApi.java b/server/src/main/java/dev/plex/api/impl/DefaultRollbackApi.java new file mode 100644 index 0000000..e3f0ebf --- /dev/null +++ b/server/src/main/java/dev/plex/api/impl/DefaultRollbackApi.java @@ -0,0 +1,30 @@ +package dev.plex.api.impl; + +import dev.plex.Plex; +import dev.plex.api.rollback.RollbackApi; +import dev.plex.hook.RollbackManager; +import org.bukkit.command.CommandSender; + +final class DefaultRollbackApi implements RollbackApi +{ + private final Plex plugin; + + DefaultRollbackApi(Plex plugin) + { + this.plugin = plugin; + } + + @Override + public boolean isAvailable() + { + RollbackManager rollbackManager = plugin.getRollbackManager(); + return rollbackManager != null && rollbackManager.isAvailable(); + } + + @Override + public boolean rollback(CommandSender sender, String playerName, int seconds) + { + RollbackManager rollbackManager = plugin.getRollbackManager(); + return rollbackManager != null && rollbackManager.rollback(sender, playerName, seconds); + } +} diff --git a/server/src/main/java/dev/plex/api/impl/DefaultSchedulerApi.java b/server/src/main/java/dev/plex/api/impl/DefaultSchedulerApi.java index fe7d53f..89627a0 100644 --- a/server/src/main/java/dev/plex/api/impl/DefaultSchedulerApi.java +++ b/server/src/main/java/dev/plex/api/impl/DefaultSchedulerApi.java @@ -2,14 +2,158 @@ package dev.plex.api.impl; import dev.plex.Plex; import dev.plex.api.scheduler.SchedulerApi; +import io.papermc.paper.threadedregions.scheduler.ScheduledTask; + +import java.util.concurrent.Executor; +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.entity.Entity; +import org.jetbrains.annotations.Nullable; final class DefaultSchedulerApi implements SchedulerApi { private final Plex plugin; + private final Executor asyncExecutor; - DefaultSchedulerApi(Plex plugin) { this.plugin = plugin; } + DefaultSchedulerApi(Plex plugin) + { + this.plugin = plugin; + this.asyncExecutor = task -> Bukkit.getAsyncScheduler().runNow(plugin, scheduledTask -> task.run()); + } - @Override public Object runSync(Runnable task) { return plugin.getServer().getScheduler().runTask(plugin, task); } - @Override public Object runLater(Runnable task, long delayTicks) { return plugin.getServer().getScheduler().runTaskLater(plugin, task, delayTicks); } - @Override public Object runTimer(Runnable task, long delayTicks, long periodTicks) { return plugin.getServer().getScheduler().runTaskTimer(plugin, task, delayTicks, periodTicks); } + @Override + public Executor asyncExecutor() + { + return asyncExecutor; + } + + @Override + public void executeGlobal(Runnable task) + { + Bukkit.getGlobalRegionScheduler().execute(plugin, task); + } + + @Override + public ScheduledTask runGlobal(Consumer task) + { + return Bukkit.getGlobalRegionScheduler().run(plugin, task); + } + + @Override + public ScheduledTask runGlobalLater(Consumer task, long delayTicks) + { + return Bukkit.getGlobalRegionScheduler().runDelayed(plugin, task, delayTicks); + } + + @Override + public ScheduledTask runGlobalTimer(Consumer task, long delayTicks, long periodTicks) + { + return Bukkit.getGlobalRegionScheduler().runAtFixedRate(plugin, task, delayTicks, periodTicks); + } + + @Override + public ScheduledTask runAsync(Consumer task) + { + return Bukkit.getAsyncScheduler().runNow(plugin, task); + } + + @Override + public ScheduledTask runAsyncLater(Consumer task, long delay, TimeUnit unit) + { + return Bukkit.getAsyncScheduler().runDelayed(plugin, task, delay, unit); + } + + @Override + public ScheduledTask runAsyncTimer(Consumer task, long delay, long period, TimeUnit unit) + { + return Bukkit.getAsyncScheduler().runAtFixedRate(plugin, task, delay, period, unit); + } + + @Override + public void executeRegion(Location location, Runnable task) + { + Bukkit.getRegionScheduler().execute(plugin, location, task); + } + + @Override + public void executeRegion(World world, int chunkX, int chunkZ, Runnable task) + { + Bukkit.getRegionScheduler().execute(plugin, world, chunkX, chunkZ, task); + } + + @Override + public ScheduledTask runRegion(Location location, Consumer task) + { + return Bukkit.getRegionScheduler().run(plugin, location, task); + } + + @Override + public ScheduledTask runRegion(World world, int chunkX, int chunkZ, Consumer task) + { + return Bukkit.getRegionScheduler().run(plugin, world, chunkX, chunkZ, task); + } + + @Override + public ScheduledTask runRegionLater(Location location, Consumer task, long delayTicks) + { + return Bukkit.getRegionScheduler().runDelayed(plugin, location, task, delayTicks); + } + + @Override + public ScheduledTask runRegionLater(World world, int chunkX, int chunkZ, Consumer task, long delayTicks) + { + return Bukkit.getRegionScheduler().runDelayed(plugin, world, chunkX, chunkZ, task, delayTicks); + } + + @Override + public ScheduledTask runRegionTimer(Location location, Consumer task, long delayTicks, long periodTicks) + { + return Bukkit.getRegionScheduler().runAtFixedRate(plugin, location, task, delayTicks, periodTicks); + } + + @Override + public ScheduledTask runRegionTimer(World world, int chunkX, int chunkZ, Consumer task, long delayTicks, long periodTicks) + { + return Bukkit.getRegionScheduler().runAtFixedRate(plugin, world, chunkX, chunkZ, task, delayTicks, periodTicks); + } + + @Override + public boolean executeEntity(Entity entity, Runnable task, @Nullable Runnable retired, long delayTicks) + { + return entity.getScheduler().execute(plugin, task, retired, delayTicks); + } + + @Override + public @Nullable ScheduledTask runEntity(Entity entity, Consumer task, @Nullable Runnable retired) + { + return entity.getScheduler().run(plugin, task, retired); + } + + @Override + public @Nullable ScheduledTask runEntityLater(Entity entity, Consumer task, @Nullable Runnable retired, long delayTicks) + { + return entity.getScheduler().runDelayed(plugin, task, retired, delayTicks); + } + + @Override + public @Nullable ScheduledTask runEntityTimer(Entity entity, Consumer task, @Nullable Runnable retired, long delayTicks, long periodTicks) + { + return entity.getScheduler().runAtFixedRate(plugin, task, retired, delayTicks, periodTicks); + } + + @Override + public void cancelGlobalTasks() + { + Bukkit.getGlobalRegionScheduler().cancelTasks(plugin); + } + + @Override + public void cancelAsyncTasks() + { + Bukkit.getAsyncScheduler().cancelTasks(plugin); + } } diff --git a/server/src/main/java/dev/plex/command/impl/BanCMD.java b/server/src/main/java/dev/plex/command/impl/BanCMD.java index 0af1099..264af03 100644 --- a/server/src/main/java/dev/plex/command/impl/BanCMD.java +++ b/server/src/main/java/dev/plex/command/impl/BanCMD.java @@ -14,10 +14,8 @@ import dev.plex.util.PlexLog; import dev.plex.util.PlexUtils; import dev.plex.util.TimeUtils; -import java.time.Instant; import java.time.ZoneId; import java.time.ZonedDateTime; -import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -28,9 +26,6 @@ import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.prism_mc.prism.api.activities.ActivityQuery; -import org.prism_mc.prism.paper.api.PrismPaperApi; -import org.prism_mc.prism.paper.api.activities.PaperActivityQuery; @CommandParameters(name = "ban", usage = "/ [reason] [-rb]", aliases = "offlineban,gtfo", description = "Bans a player, offline or online") @CommandPermissions(permission = "plex.ban", source = RequiredCommandSource.ANY) @@ -56,84 +51,52 @@ public class BanCMD extends ServerCommand plugin.getPunishmentManager().isAsyncBanned(plexPlayer.getUuid()).whenComplete((aBoolean, throwable) -> { - if (aBoolean) - { - send(sender, messageComponent("playerBanned")); - return; - } - String reason; - Punishment punishment = new Punishment(plexPlayer.getUuid(), getUUID(sender)); - punishment.setType(PunishmentType.BAN); - boolean rollBack = false; - if (args.length > 1) - { - reason = StringUtils.join(args, " ", 1, args.length); - String newReason = StringUtils.normalizeSpace(reason.replace("-rb", "")); - punishment.setReason(newReason.trim().isEmpty() ? messageString("noReasonProvided") : newReason); - rollBack = reason.startsWith("-rb") || reason.endsWith("-rb"); - } - else - { - punishment.setReason(messageString("noReasonProvided")); - } - punishment.setPunishedUsername(plexPlayer.getName()); - ZonedDateTime date = ZonedDateTime.now(ZoneId.of(TimeUtils.TIMEZONE)); - punishment.setEndDate(date.plusDays(1)); - punishment.setCustomTime(false); - punishment.setActive(true); - punishment.setIp(player != null ? player.getAddress().getAddress().getHostAddress().trim() : plexPlayer.getIps().getLast()); - plugin.getPunishmentManager().punish(plexPlayer, punishment); - PlexUtils.broadcast(messageComponent("banningPlayer", sender.getName(), plexPlayer.getName())); - Bukkit.getGlobalRegionScheduler().execute(plugin, () -> + plugin.getApi().scheduler().runGlobal(() -> { + if (throwable != null) + { + PlexLog.error("Unable to check ban state for {0}: {1}", plexPlayer.getName(), throwable.getMessage()); + return; + } + if (aBoolean) + { + send(sender, messageComponent("playerBanned")); + return; + } + String reason; + Punishment punishment = new Punishment(plexPlayer.getUuid(), getUUID(sender)); + punishment.setType(PunishmentType.BAN); + boolean rollBack = false; + if (args.length > 1) + { + reason = StringUtils.join(args, " ", 1, args.length); + String newReason = StringUtils.normalizeSpace(reason.replace("-rb", "")); + punishment.setReason(newReason.trim().isEmpty() ? messageString("noReasonProvided") : newReason); + rollBack = reason.startsWith("-rb") || reason.endsWith("-rb"); + } + else + { + punishment.setReason(messageString("noReasonProvided")); + } + punishment.setPunishedUsername(plexPlayer.getName()); + ZonedDateTime date = ZonedDateTime.now(ZoneId.of(TimeUtils.TIMEZONE)); + punishment.setEndDate(date.plusDays(1)); + punishment.setCustomTime(false); + punishment.setActive(true); + punishment.setIp(plexPlayer.getIps().getLast()); + plugin.getPunishmentManager().punish(plexPlayer, punishment); + PlexUtils.broadcast(messageComponent("banningPlayer", sender.getName(), plexPlayer.getName())); if (player != null) { - BungeeUtil.kickPlayer(plugin, player, Punishment.generateBanMessage(punishment, plugin.config.getString("banning.ban_url"), plugin.getPlayerService())); + plugin.getApi().scheduler().runEntity(player, () -> BungeeUtil.kickPlayer(plugin, player, Punishment.generateBanMessage(punishment, plugin.config.getString("banning.ban_url"), plugin.getPlayerService()))); + } + PlexLog.debug("(From /ban command) PunishedPlayer UUID: " + plexPlayer.getUuid()); + + if (rollBack) + { + plugin.getApi().rollback().rollbackLastDay(sender, plexPlayer.getName()); } }); - PlexLog.debug("(From /ban command) PunishedPlayer UUID: " + plexPlayer.getUuid()); - - if (rollBack) - { - if (plugin.getPrismHook() != null && plugin.getPrismHook().hasPrism()) - { - PrismPaperApi prism = plugin.getPrismHook().getPrism(); - ActivityQuery query = PaperActivityQuery.builder() - .actionTypeKeys(Arrays.asList("block-place", "block-break", "block-burn", "entity-spawn", "entity-kill", "entity-explode")) - .causePlayerName(plexPlayer.getName()) - .before(Instant.now().getEpochSecond()) - .after(Instant.now().getEpochSecond() - 86400) - .rollback() - .build(); - prism.rollback(sender, query).whenCompleteAsync((result, error) -> - { - if (error != null) - { - send(sender, messageComponent("prismRollbackError", error.getMessage())); - PlexLog.error("Unable to rollback: {0}", error); - return; - } - - int count = result.applied(); - if (count == 0) - { - send(sender, messageComponent("prismNoResult", count)); - PlexLog.debug("No activities are available to rollback"); - return; - } - - send(sender, messageComponent("prismRollbackMessage", count)); - PlexLog.debug("Rolled back {0} activities", count); - }); - } - else if (plugin.getCoreProtectHook() != null && plugin.getCoreProtectHook().hasCoreProtect()) - { - Bukkit.getAsyncScheduler().runNow(plugin, scheduledTask -> - { - plugin.getCoreProtectHook().coreProtectAPI().performRollback(86400, Collections.singletonList(plexPlayer.getName()), null, null, null, null, 0, null); - }); - } - } }); return null; diff --git a/server/src/main/java/dev/plex/command/impl/TempbanCMD.java b/server/src/main/java/dev/plex/command/impl/TempbanCMD.java index b8baadf..07d0c48 100644 --- a/server/src/main/java/dev/plex/command/impl/TempbanCMD.java +++ b/server/src/main/java/dev/plex/command/impl/TempbanCMD.java @@ -11,11 +11,9 @@ import dev.plex.player.PlexPlayer; import dev.plex.punishment.Punishment; import dev.plex.punishment.PunishmentType; import dev.plex.util.BungeeUtil; -import dev.plex.util.PlexLog; import dev.plex.util.PlexUtils; import dev.plex.util.TimeUtils; -import java.util.Collections; import java.util.List; import net.kyori.adventure.text.Component; @@ -70,49 +68,16 @@ public class TempbanCMD extends ServerCommand punishment.setEndDate(TimeUtils.createDate(args[1])); punishment.setCustomTime(false); punishment.setActive(true); - if (player != null) - { - punishment.setIp(player.getAddress().getAddress().getHostAddress().trim()); - } + punishment.setIp(target.getIps().getLast()); plugin.getPunishmentManager().punish(target, punishment); PlexUtils.broadcast(messageComponent("banningPlayer", sender.getName(), target.getName())); if (player != null) { - BungeeUtil.kickPlayer(plugin, player, Punishment.generateBanMessage(punishment, plugin.config.getString("banning.ban_url"), plugin.getPlayerService())); + plugin.getApi().scheduler().runEntity(player, () -> BungeeUtil.kickPlayer(plugin, player, Punishment.generateBanMessage(punishment, plugin.config.getString("banning.ban_url"), plugin.getPlayerService()))); } if (rollBack) { - /*if (plugin.getPrismHook().hasPrism()) { - PrismParameters parameters = plugin.getPrismHook().prismApi().createParameters(); - parameters.addActionType("block-place"); - parameters.addActionType("block-break"); - parameters.addActionType("block-burn"); - parameters.addActionType("entity-spawn"); - parameters.addActionType("entity-kill"); - parameters.addActionType("entity-explode"); - parameters.addPlayerName(plexPlayer.getName()); - parameters.setBeforeTime(Instant.now().toEpochMilli()); - parameters.setProcessType(PrismProcessType.ROLLBACK); - final Future result = plugin.getPrismHook().prismApi().performLookup(parameters, sender); - Bukkit.getAsyncScheduler().runNow(plugin, scheduledTask -> { - try - { - final Result done = result.get(); - } catch (InterruptedException | ExecutionException e) - { - throw new RuntimeException(e); - } - }); - } - else */ - if (plugin.getCoreProtectHook() != null && plugin.getCoreProtectHook().hasCoreProtect()) - { - PlexLog.debug("Testing coreprotect"); - Bukkit.getAsyncScheduler().runNow(plugin, scheduledTask -> - { - plugin.getCoreProtectHook().coreProtectAPI().performRollback(86400, Collections.singletonList(target.getName()), null, null, null, null, 0, null); - }); - } + plugin.getApi().rollback().rollbackLastDay(sender, target.getName()); } return null; } diff --git a/server/src/main/java/dev/plex/hook/RollbackManager.java b/server/src/main/java/dev/plex/hook/RollbackManager.java new file mode 100644 index 0000000..b51f2ca --- /dev/null +++ b/server/src/main/java/dev/plex/hook/RollbackManager.java @@ -0,0 +1,103 @@ +package dev.plex.hook; + +import dev.plex.Plex; +import dev.plex.api.rollback.RollbackApi; +import dev.plex.util.PlexLog; +import dev.plex.util.PlexUtils; + +import java.time.Instant; +import java.util.Collections; +import java.util.List; + +import net.kyori.adventure.text.Component; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.prism_mc.prism.api.activities.ActivityQuery; +import org.prism_mc.prism.paper.api.activities.PaperActivityQuery; + +public class RollbackManager implements RollbackApi +{ + private static final List ROLLBACK_ACTIONS = List.of("block-place", "block-break", "block-burn", "entity-spawn", "entity-kill", "entity-explode"); + + private final Plex plugin; + + public RollbackManager(Plex plugin) + { + this.plugin = plugin; + } + + @Override + public boolean isAvailable() + { + return (plugin.getPrismHook() != null && plugin.getPrismHook().hasPrism()) + || (plugin.getCoreProtectHook() != null && plugin.getCoreProtectHook().hasCoreProtect()); + } + + @Override + public boolean rollback(CommandSender sender, String playerName, int seconds) + { + if (plugin.getPrismHook() != null && plugin.getPrismHook().hasPrism()) + { + plugin.getApi().scheduler().runGlobal(() -> rollbackWithPrism(sender, playerName, seconds)); + return true; + } + + if (plugin.getCoreProtectHook() != null && plugin.getCoreProtectHook().hasCoreProtect()) + { + rollbackWithCoreProtect(playerName, seconds); + return true; + } + + return false; + } + + private void rollbackWithPrism(CommandSender sender, String playerName, int seconds) + { + long now = Instant.now().getEpochSecond(); + ActivityQuery query = PaperActivityQuery.builder() + .actionTypeKeys(ROLLBACK_ACTIONS) + .causePlayerName(playerName) + .before(now) + .after(now - seconds) + .rollback() + .build(); + + plugin.getPrismHook().getPrism().rollback(sender, query).whenComplete((result, error) -> + plugin.getApi().scheduler().runGlobal(() -> + { + if (error != null) + { + sendMessage(sender, PlexUtils.messageComponent("prismRollbackError", error.getMessage())); + PlexLog.error("Unable to rollback: {0}", error); + return; + } + + int count = result.applied(); + if (count == 0) + { + sendMessage(sender, PlexUtils.messageComponent("prismNoResult", count)); + PlexLog.debug("No activities are available to rollback"); + return; + } + + sendMessage(sender, PlexUtils.messageComponent("prismRollbackMessage", count)); + PlexLog.debug("Rolled back {0} activities", count); + })); + } + + private void rollbackWithCoreProtect(String playerName, int seconds) + { + plugin.getApi().scheduler().runAsync(() -> + plugin.getCoreProtectHook().coreProtectAPI().performRollback(seconds, Collections.singletonList(playerName), null, null, null, null, 0, null)); + } + + private void sendMessage(CommandSender sender, Component message) + { + if (sender instanceof Player player) + { + plugin.getApi().scheduler().runEntity(player, () -> sender.sendMessage(message)); + return; + } + sender.sendMessage(message); + } +} diff --git a/server/src/main/java/dev/plex/listener/impl/ChatListener.java b/server/src/main/java/dev/plex/listener/impl/ChatListener.java index 2df0d08..4ad556a 100644 --- a/server/src/main/java/dev/plex/listener/impl/ChatListener.java +++ b/server/src/main/java/dev/plex/listener/impl/ChatListener.java @@ -36,12 +36,12 @@ public class ChatListener extends ServerListenerBase matchResult.group() ))).build(); public static BiConsumer PRE_RENDERER = ChatListener::defaultChatProcessing; - private final PlexChatRenderer renderer = new PlexChatRenderer(); @EventHandler(priority = EventPriority.LOWEST) public void onChat(AsyncChatEvent event) { PlexPlayer plexPlayer = plugin.getPlayerCache().getPlexPlayerMap().get(event.getPlayer().getUniqueId()); + PlexChatRenderer renderer = new PlexChatRenderer(); renderer.format = SafeMiniMessage.mmDeserialize(plugin.config.getString("chat.format")); if (plexPlayer.isStaffChat()) { diff --git a/server/src/main/java/dev/plex/listener/impl/PlayerListener.java b/server/src/main/java/dev/plex/listener/impl/PlayerListener.java index 505646c..be51093 100644 --- a/server/src/main/java/dev/plex/listener/impl/PlayerListener.java +++ b/server/src/main/java/dev/plex/listener/impl/PlayerListener.java @@ -9,7 +9,6 @@ import dev.plex.util.PlexUtils; import java.util.List; -import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; @@ -90,7 +89,7 @@ public class PlayerListener extends ServerListenerBase PlexPlayer player = plugin.getPlayerService().getPlayer(event.getPlayer().getUniqueId()); if (player.isLockedUp()) { - Bukkit.getGlobalRegionScheduler().runDelayed(plugin, (scheduledTask) -> event.getPlayer().openInventory(event.getInventory()), 1L); + event.getPlayer().getScheduler().runDelayed(plugin, scheduledTask -> event.getPlayer().openInventory(event.getInventory()), null, 1L); } } diff --git a/server/src/main/java/dev/plex/punishment/PunishmentManager.java b/server/src/main/java/dev/plex/punishment/PunishmentManager.java index c06ace4..c32b657 100644 --- a/server/src/main/java/dev/plex/punishment/PunishmentManager.java +++ b/server/src/main/java/dev/plex/punishment/PunishmentManager.java @@ -5,7 +5,6 @@ import com.google.common.reflect.TypeToken; import com.google.gson.Gson; import dev.plex.Plex; import dev.plex.player.PlexPlayer; -import dev.plex.storage.StorageExecutor; import dev.plex.util.PlexLog; import dev.plex.util.PlexUtils; import dev.plex.util.TimeUtils; @@ -25,7 +24,6 @@ import lombok.Data; import lombok.Getter; import org.apache.commons.io.FileUtils; import org.bukkit.Bukkit; -import org.bukkit.scheduler.BukkitRunnable; import org.jetbrains.annotations.Nullable; public class PunishmentManager @@ -135,7 +133,7 @@ public class PunishmentManager } return plugin.getPunishmentRepository().getPunishments(uuid).stream().anyMatch(punishment -> (punishment.getType() == PunishmentType.BAN || punishment.getType() == PunishmentType.TEMPBAN) && punishment.isActive()); - }, StorageExecutor.io()); + }, plugin.getApi().scheduler().asyncExecutor()); } public boolean isBanned(UUID uuid) @@ -194,25 +192,20 @@ public class PunishmentManager ZonedDateTime now = ZonedDateTime.now(ZoneId.of(TimeUtils.TIMEZONE)); ZonedDateTime then = punishment.getEndDate(); long seconds = ChronoUnit.SECONDS.between(now, then); - new BukkitRunnable() + plugin.getApi().scheduler().runGlobalLater(scheduledTask -> { - @Override - public void run() + PlexPlayer afterPlayer = plugin.getPlayerService().getPlayer(player.getUuid()); + if (!afterPlayer.isFrozen()) { - PlexPlayer afterPlayer = plugin.getPlayerService().getPlayer(player.getUuid()); - if (!afterPlayer.isFrozen()) - { - this.cancel(); - return; - } - afterPlayer.setFrozen(false); - punishment.setActive(false); - plugin.getPunishmentRepository().updatePunishment(punishment.getType(), false, punishment.getPunished()); - - plugin.getPlayerService().update(afterPlayer); - Bukkit.broadcast(PlexUtils.messageComponent("unfrozePlayer", "Plex", Bukkit.getOfflinePlayer(afterPlayer.getUuid()).getName())); + return; } - }.runTaskLater(plugin, 20 * seconds); + afterPlayer.setFrozen(false); + punishment.setActive(false); + plugin.getPunishmentRepository().updatePunishment(punishment.getType(), false, punishment.getPunished()); + + plugin.getPlayerService().update(afterPlayer); + Bukkit.broadcast(PlexUtils.messageComponent("unfrozePlayer", "Plex", Bukkit.getOfflinePlayer(afterPlayer.getUuid()).getName())); + }, Math.max(1L, 20L * seconds)); } else if (punishment.getType() == PunishmentType.MUTE) { @@ -220,24 +213,19 @@ public class PunishmentManager ZonedDateTime now = ZonedDateTime.now(ZoneId.of(TimeUtils.TIMEZONE)); ZonedDateTime then = punishment.getEndDate(); long seconds = ChronoUnit.SECONDS.between(now, then); - new BukkitRunnable() + plugin.getApi().scheduler().runGlobalLater(scheduledTask -> { - @Override - public void run() + PlexPlayer afterPlayer = plugin.getPlayerService().getPlayer(player.getUuid()); + if (!afterPlayer.isMuted()) { - PlexPlayer afterPlayer = plugin.getPlayerService().getPlayer(player.getUuid()); - if (!afterPlayer.isMuted()) - { - this.cancel(); - return; - } - afterPlayer.setMuted(false); - punishment.setActive(false); - plugin.getPunishmentRepository().updatePunishment(punishment.getType(), false, punishment.getPunished()); - - Bukkit.broadcast(PlexUtils.messageComponent("unmutedPlayer", "Plex", Bukkit.getOfflinePlayer(afterPlayer.getUuid()).getName())); + return; } - }.runTaskLater(plugin, 20 * seconds); + afterPlayer.setMuted(false); + punishment.setActive(false); + plugin.getPunishmentRepository().updatePunishment(punishment.getType(), false, punishment.getPunished()); + + Bukkit.broadcast(PlexUtils.messageComponent("unmutedPlayer", "Plex", Bukkit.getOfflinePlayer(afterPlayer.getUuid()).getName())); + }, Math.max(1L, 20L * seconds)); } } diff --git a/server/src/main/java/dev/plex/services/ServiceManager.java b/server/src/main/java/dev/plex/services/ServiceManager.java index e2af842..3a16f21 100644 --- a/server/src/main/java/dev/plex/services/ServiceManager.java +++ b/server/src/main/java/dev/plex/services/ServiceManager.java @@ -7,8 +7,11 @@ import dev.plex.services.impl.BanService; import dev.plex.services.impl.GameRuleService; import dev.plex.services.impl.TimingService; import dev.plex.services.impl.UpdateCheckerService; +import io.papermc.paper.threadedregions.scheduler.ScheduledTask; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.concurrent.TimeUnit; import org.bukkit.Bukkit; @@ -17,6 +20,7 @@ public class ServiceManager { private final Plex plugin; private final List services = Lists.newArrayList(); + private final Map scheduledTasks = new HashMap<>(); public ServiceManager(Plex plugin) { @@ -45,25 +49,36 @@ public class ServiceManager public void startService(AbstractService service) { + ScheduledTask existingTask = scheduledTasks.remove(service); + if (existingTask != null) + { + existingTask.cancel(); + } + + ScheduledTask task = null; if (!service.isRepeating()) { int time = service.repeatInSeconds(); if (time == 0) { - Bukkit.getGlobalRegionScheduler().run(plugin, service::run); + task = Bukkit.getGlobalRegionScheduler().run(plugin, service::run); } else { - Bukkit.getAsyncScheduler().runDelayed(plugin, service::run, time, TimeUnit.SECONDS); + task = Bukkit.getAsyncScheduler().runDelayed(plugin, service::run, time, TimeUnit.SECONDS); } } else if (service.isRepeating() && service.isAsynchronous()) { - Bukkit.getAsyncScheduler().runAtFixedRate(plugin, service::run, 1, service.repeatInSeconds(), TimeUnit.SECONDS); + task = Bukkit.getAsyncScheduler().runAtFixedRate(plugin, service::run, 1, service.repeatInSeconds(), TimeUnit.SECONDS); } else if (service.isRepeating() && !service.isAsynchronous()) { - Bukkit.getGlobalRegionScheduler().runAtFixedRate(plugin, service::run, 1, 20L * service.repeatInSeconds()); + task = Bukkit.getGlobalRegionScheduler().runAtFixedRate(plugin, service::run, 1, 20L * service.repeatInSeconds()); + } + if (task != null) + { + scheduledTasks.put(service, task); } if (!services.contains(service)) { @@ -74,8 +89,11 @@ public class ServiceManager public void endService(AbstractService service, boolean remove) { - Bukkit.getGlobalRegionScheduler().cancelTasks(plugin); - Bukkit.getAsyncScheduler().cancelTasks(plugin); + ScheduledTask task = scheduledTasks.remove(service); + if (task != null) + { + task.cancel(); + } service.onEnd(); if (remove) { diff --git a/server/src/main/java/dev/plex/services/impl/AutoWipeService.java b/server/src/main/java/dev/plex/services/impl/AutoWipeService.java index df1057a..0f0c9e8 100644 --- a/server/src/main/java/dev/plex/services/impl/AutoWipeService.java +++ b/server/src/main/java/dev/plex/services/impl/AutoWipeService.java @@ -30,33 +30,16 @@ public class AutoWipeService extends AbstractService { if (entities.stream().anyMatch(entityName -> entityName.equalsIgnoreCase(entity.getType().name()))) { - Bukkit.getRegionScheduler().run(plugin, entity.getLocation(), this::entityRun); + entity.getScheduler().run(plugin, scheduledTask -> entity.remove(), null); } } } } } - private void entityRun(ScheduledTask task) - { - List entities = plugin.config.getStringList("autowipe.entities"); - - for (World world : Bukkit.getWorlds()) - { - for (Entity entity : world.getEntities()) - { - if (entities.stream().anyMatch(entityName -> entityName.equalsIgnoreCase(entity.getType().name()))) - { - entity.remove(); - task.cancel(); - } - } - } - } - @Override public int repeatInSeconds() { return Math.max(1, plugin.config.getInt("autowipe.interval")); } -} \ No newline at end of file +} diff --git a/server/src/main/java/dev/plex/storage/RedisConnection.java b/server/src/main/java/dev/plex/storage/RedisConnection.java index bd6df63..45c8fa9 100644 --- a/server/src/main/java/dev/plex/storage/RedisConnection.java +++ b/server/src/main/java/dev/plex/storage/RedisConnection.java @@ -55,7 +55,7 @@ public class RedisConnection public void runAsync(Consumer jedisConsumer) { - StorageExecutor.io().execute(() -> execute(jedisConsumer)); + plugin.getApi().scheduler().runAsync(() -> execute(jedisConsumer)); } public final boolean isEnabled() diff --git a/server/src/main/java/dev/plex/storage/StorageExecutor.java b/server/src/main/java/dev/plex/storage/StorageExecutor.java deleted file mode 100644 index 7aaab5f..0000000 --- a/server/src/main/java/dev/plex/storage/StorageExecutor.java +++ /dev/null @@ -1,36 +0,0 @@ -package dev.plex.storage; - -import java.util.concurrent.Executor; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.atomic.AtomicInteger; - -public final class StorageExecutor -{ - private static final AtomicInteger THREAD_ID = new AtomicInteger(); - private static final ExecutorService IO = Executors.newFixedThreadPool(Math.max(2, Runtime.getRuntime().availableProcessors() / 2), new ThreadFactory() - { - @Override - public Thread newThread(Runnable runnable) - { - Thread thread = new Thread(runnable, "Plex Storage IO-" + THREAD_ID.incrementAndGet()); - thread.setDaemon(true); - return thread; - } - }); - - private StorageExecutor() - { - } - - public static Executor io() - { - return IO; - } - - public static void shutdown() - { - IO.shutdownNow(); - } -} diff --git a/server/src/main/java/dev/plex/storage/punishment/SQLNotes.java b/server/src/main/java/dev/plex/storage/punishment/SQLNotes.java index 1bc89e2..331bff5 100644 --- a/server/src/main/java/dev/plex/storage/punishment/SQLNotes.java +++ b/server/src/main/java/dev/plex/storage/punishment/SQLNotes.java @@ -6,7 +6,6 @@ import com.j256.ormlite.dao.DaoManager; import com.j256.ormlite.support.ConnectionSource; import com.j256.ormlite.stmt.DeleteBuilder; import dev.plex.punishment.extra.Note; -import dev.plex.storage.StorageExecutor; import dev.plex.storage.database.entity.NoteEntity; import dev.plex.storage.repository.NoteRepository; import dev.plex.util.TimeUtils; @@ -19,16 +18,19 @@ import java.util.Comparator; import java.util.List; import java.util.UUID; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; public class SQLNotes implements NoteRepository { private final Dao notes; + private final Executor executor; - public SQLNotes(ConnectionSource connectionSource) + public SQLNotes(ConnectionSource connectionSource, Executor executor) { try { this.notes = DaoManager.createDao(connectionSource, NoteEntity.class); + this.executor = executor; } catch (SQLException e) { @@ -52,7 +54,7 @@ public class SQLNotes implements NoteRepository e.printStackTrace(); return Lists.newArrayList(); } - }, StorageExecutor.io()); + }, executor); } public CompletableFuture deleteNote(int id, UUID uuid) @@ -69,7 +71,7 @@ public class SQLNotes implements NoteRepository { e.printStackTrace(); } - }, StorageExecutor.io()); + }, executor); } public CompletableFuture addNote(Note note) @@ -91,7 +93,7 @@ public class SQLNotes implements NoteRepository { e.printStackTrace(); } - }, StorageExecutor.io()); + }, executor); } private Note toNote(NoteEntity entity) diff --git a/server/src/main/java/dev/plex/storage/punishment/SQLPunishment.java b/server/src/main/java/dev/plex/storage/punishment/SQLPunishment.java index b74a9b9..aa2e01c 100644 --- a/server/src/main/java/dev/plex/storage/punishment/SQLPunishment.java +++ b/server/src/main/java/dev/plex/storage/punishment/SQLPunishment.java @@ -7,7 +7,6 @@ import com.j256.ormlite.support.ConnectionSource; import com.j256.ormlite.stmt.UpdateBuilder; import dev.plex.punishment.Punishment; import dev.plex.punishment.PunishmentType; -import dev.plex.storage.StorageExecutor; import dev.plex.storage.database.entity.PunishmentEntity; import dev.plex.storage.repository.PunishmentRepository; import dev.plex.util.PlexLog; @@ -20,16 +19,19 @@ import java.time.ZonedDateTime; import java.util.List; import java.util.UUID; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; public class SQLPunishment implements PunishmentRepository { private final Dao punishments; + private final Executor executor; - public SQLPunishment(ConnectionSource connectionSource) + public SQLPunishment(ConnectionSource connectionSource, Executor executor) { try { this.punishments = DaoManager.createDao(connectionSource, PunishmentEntity.class); + this.executor = executor; } catch (SQLException e) { @@ -50,7 +52,7 @@ public class SQLPunishment implements PunishmentRepository e.printStackTrace(); return Lists.newArrayList(); } - }, StorageExecutor.io()); + }, executor); } public List getPunishments(UUID uuid) @@ -92,7 +94,7 @@ public class SQLPunishment implements PunishmentRepository { e.printStackTrace(); } - }, StorageExecutor.io()); + }, executor); } public void syncRemoveBan(UUID uuid) @@ -103,12 +105,12 @@ public class SQLPunishment implements PunishmentRepository public CompletableFuture updatePunishment(PunishmentType type, boolean active, UUID punished) { - return CompletableFuture.runAsync(() -> setActive(punished, type, active), StorageExecutor.io()); + return CompletableFuture.runAsync(() -> setActive(punished, type, active), executor); } public CompletableFuture removeBan(UUID uuid) { - return CompletableFuture.runAsync(() -> syncRemoveBan(uuid), StorageExecutor.io()); + return CompletableFuture.runAsync(() -> syncRemoveBan(uuid), executor); } private void setActive(UUID punished, PunishmentType type, boolean active) diff --git a/server/src/main/java/dev/plex/util/UpdateChecker.java b/server/src/main/java/dev/plex/util/UpdateChecker.java index 1cf79c7..75e6993 100644 --- a/server/src/main/java/dev/plex/util/UpdateChecker.java +++ b/server/src/main/java/dev/plex/util/UpdateChecker.java @@ -12,7 +12,6 @@ import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URI; import java.nio.charset.StandardCharsets; -import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicReference; import lombok.NonNull; @@ -21,6 +20,7 @@ import net.kyori.adventure.text.format.NamedTextColor; import org.apache.commons.io.FileUtils; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; import org.json.JSONException; public class UpdateChecker @@ -121,7 +121,7 @@ public class UpdateChecker { if (verbosity == 2) { - sender.sendMessage(Component.text("There was an error checking for updates.").color(NamedTextColor.RED)); + sendMessage(sender, Component.text("There was an error checking for updates.").color(NamedTextColor.RED)); } return false; } @@ -129,7 +129,7 @@ public class UpdateChecker { if (verbosity == 2) { - sender.sendMessage(Component.text("Plex is up to date!").color(NamedTextColor.GREEN)); + sendMessage(sender, Component.text("Plex is up to date!").color(NamedTextColor.GREEN)); } return false; } @@ -137,7 +137,7 @@ public class UpdateChecker { if (verbosity == 2) { - sender.sendMessage(Component.text("Unknown version, unable to check for updates.").color(NamedTextColor.RED)); + sendMessage(sender, Component.text("Unknown version, unable to check for updates.").color(NamedTextColor.RED)); } return false; } @@ -145,9 +145,9 @@ public class UpdateChecker { if (verbosity >= 1) { - sender.sendMessage(Component.text("Plex is not up to date!", NamedTextColor.RED)); - sender.sendMessage(Component.text("Download a new version at: " + DOWNLOAD_PAGE + "Plex").color(NamedTextColor.RED)); - sender.sendMessage(Component.text("Or run: /plex update").color(NamedTextColor.RED)); + sendMessage(sender, Component.text("Plex is not up to date!", NamedTextColor.RED)); + sendMessage(sender, Component.text("Download a new version at: " + DOWNLOAD_PAGE + "Plex").color(NamedTextColor.RED)); + sendMessage(sender, Component.text("Or run: /plex update").color(NamedTextColor.RED)); } return true; } @@ -174,7 +174,7 @@ public class UpdateChecker JsonObject object = new Gson().fromJson(reader, JsonObject.class); JsonObject artifact = object.getAsJsonArray("artifacts").asList().getFirst().getAsJsonObject(); String jarFile = artifact.get("fileName").getAsString(); - sender.sendMessage(PlexUtils.mmDeserialize("Downloading latest JAR file: " + jarFile)); + sendMessage(sender, PlexUtils.mmDeserialize("Downloading latest JAR file: " + jarFile)); File copyTo; if (!module) { @@ -184,7 +184,7 @@ public class UpdateChecker { copyTo = new File(plugin.getModulesFolder().getPath(), jarFile); } - CompletableFuture.runAsync(() -> + plugin.getApi().scheduler().runAsync(() -> { try { @@ -192,7 +192,7 @@ public class UpdateChecker URI.create(url + "/lastSuccessfulBuild/artifact/build/libs/" + jarFile).toURL(), copyTo ); - sender.sendMessage(PlexUtils.mmDeserialize("New JAR file downloaded successfully.")); + sendMessage(sender, PlexUtils.mmDeserialize("New JAR file downloaded successfully.")); } catch (IOException e) { @@ -207,11 +207,11 @@ public class UpdateChecker } else if (statusCode == HttpURLConnection.HTTP_NOT_FOUND) { - sender.sendMessage(PlexUtils.mmDeserialize("Could not update " + name + " as it can't be found on Jenkins.")); + sendMessage(sender, PlexUtils.mmDeserialize("Could not update " + name + " as it can't be found on Jenkins.")); } else { - sender.sendMessage(PlexUtils.mmDeserialize("Something went wrong while trying to update " + name + ". Please check the log for more information.")); + sendMessage(sender, PlexUtils.mmDeserialize("Something went wrong while trying to update " + name + ". Please check the log for more information.")); PlexLog.error("Unable to update module {0} due to unexpected status code returned from Jenkins - Status Code: {1}", name, statusCode); } } @@ -221,9 +221,19 @@ public class UpdateChecker } catch (JSONException e) { - sender.sendMessage(PlexUtils.mmDeserialize("Something went wrong while trying to gather information from Jenkins for " + name + ". Please check the log for more information")); + sendMessage(sender, PlexUtils.mmDeserialize("Something went wrong while trying to gather information from Jenkins for " + name + ". Please check the log for more information")); PlexLog.error("Unable to parse JSON information received from Jenkins - see below for more information..."); e.printStackTrace(); } } + + private void sendMessage(CommandSender sender, Component message) + { + if (sender instanceof Player player) + { + plugin.getApi().scheduler().runEntity(player, () -> sender.sendMessage(message)); + return; + } + plugin.getApi().scheduler().runGlobal(() -> sender.sendMessage(message)); + } }