From 7cc9395cbc4c6a4abcb7b346b092821fbf5a730f Mon Sep 17 00:00:00 2001 From: unurled Date: Thu, 29 Feb 2024 15:29:56 +0100 Subject: [PATCH] add reset command + exists method for data source --- .../sr/commands/CommandManager.java | 5 + .../player/ResetAdventureCommand.java | 145 ++++++++++++++++++ .../sr/components/player/PlayerManager.java | 4 +- .../sacredrealms/sr/data/DataHandler.java | 7 + .../unurled/sacredrealms/sr/data/Redis.java | 10 ++ src/main/resources/plugin.yml | 3 + 6 files changed, 172 insertions(+), 2 deletions(-) create mode 100644 src/main/java/me/unurled/sacredrealms/sr/commands/player/ResetAdventureCommand.java diff --git a/src/main/java/me/unurled/sacredrealms/sr/commands/CommandManager.java b/src/main/java/me/unurled/sacredrealms/sr/commands/CommandManager.java index b30061f..ef9ee08 100644 --- a/src/main/java/me/unurled/sacredrealms/sr/commands/CommandManager.java +++ b/src/main/java/me/unurled/sacredrealms/sr/commands/CommandManager.java @@ -2,6 +2,7 @@ package me.unurled.sacredrealms.sr.commands; import me.unurled.sacredrealms.sr.SR; import me.unurled.sacredrealms.sr.commands.admin.AttributeCommand; +import me.unurled.sacredrealms.sr.commands.player.ResetAdventureCommand; import me.unurled.sacredrealms.sr.managers.Manager; public class CommandManager extends Manager { @@ -11,5 +12,9 @@ public class CommandManager extends Manager { public void load() { super.load(); SR.getInstance().getCommand("attributes").setExecutor(new AttributeCommand()); + SR.getInstance().getCommand("attributes").setTabCompleter(new AttributeCommand()); + + SR.getInstance().getCommand("resetadventure").setExecutor(new ResetAdventureCommand()); + SR.getInstance().getCommand("resetadventure").setTabCompleter(new ResetAdventureCommand()); } } diff --git a/src/main/java/me/unurled/sacredrealms/sr/commands/player/ResetAdventureCommand.java b/src/main/java/me/unurled/sacredrealms/sr/commands/player/ResetAdventureCommand.java new file mode 100644 index 0000000..e99d611 --- /dev/null +++ b/src/main/java/me/unurled/sacredrealms/sr/commands/player/ResetAdventureCommand.java @@ -0,0 +1,145 @@ +package me.unurled.sacredrealms.sr.commands.player; + +import static me.unurled.sacredrealms.sr.utils.Component.comp; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Objects; +import me.unurled.sacredrealms.sr.SR; +import me.unurled.sacredrealms.sr.components.player.PlayerManager; +import me.unurled.sacredrealms.sr.data.DataManager; +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabExecutor; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class ResetAdventureCommand implements TabExecutor { + + private static final Long COOLDOWN = 120L; + + private final HashMap cooldowns = new HashMap<>(); + + /** + * Executes the given command, returning its success.
+ * If false is returned, then the "usage" plugin.yml entry for this command (if defined) will be + * sent to the player. + * + * @param sender Source of the command + * @param command Command which was executed + * @param label Alias of the command which was used + * @param args Passed command arguments + * @return true if a valid command, otherwise false + */ + @Override + public boolean onCommand( + @NotNull CommandSender sender, + @NotNull Command command, + @NotNull String label, + @NotNull String[] args) { + if (sender.hasPermission("sr.resetadventure")) { + if (args.length > 2) { + sender.sendMessage(comp("Usage: /resetadventure ")); + return true; + } + if (sender instanceof Player p) { + if (args.length == 0) { + boolean status = resetAdventure(p); + if (status) { + p.sendMessage(comp("Your adventure has been reset.")); + } else { + p.sendMessage(comp("Failed to reset your adventure.")); + } + return true; + } + } + OfflinePlayer player = SR.getInstance().getServer().getOfflinePlayer(args[0]); + + boolean status = resetAdventure(player); + if (status) { + sender.sendMessage(comp("Successfully reset " + player.getName() + "'s adventure.")); + } else { + sender.sendMessage(comp("Failed to reset " + player.getName() + "'s adventure.")); + } + return true; + } + if (args.length > 0) { + sender.sendMessage(comp("Usage: /resetadventure")); + return true; + } + if (sender instanceof Player player) { + if (cooldowns.containsKey(player)) { + long lastUsed = cooldowns.get(player); + long secondsLeft = ((lastUsed / 1000) + COOLDOWN) - (System.currentTimeMillis() / 1000); + if (secondsLeft > 0) { + player.sendMessage( + comp( + "You must wait " + + secondsLeft + + " seconds before using this command again.")); + return true; + } + } + boolean status = resetAdventure(player); + if (status) { + player.sendMessage(comp("Your adventure has been reset.")); + } else { + player.sendMessage(comp("Failed to reset your adventure.")); + } + cooldowns.put(player, System.currentTimeMillis()); + } + return true; + } + + private boolean resetAdventure(OfflinePlayer player) { + DataManager dataManager = (DataManager) DataManager.getInstance(DataManager.class); + if (dataManager != null) { + if (dataManager.getDataHandler().exists(PlayerManager.PLAYER_KEY + player.getUniqueId())) { + dataManager.getDataHandler().remove(PlayerManager.PLAYER_KEY + player.getUniqueId()); + return true; + } else { + return false; + } + } + return false; + } + + /** + * Requests a list of possible completions for a command argument. + * + * @param sender Source of the command. For players tab-completing a command inside of a command + * block, this will be the player, not the command block. + * @param command Command which was executed + * @param label Alias of the command which was used + * @param args The arguments passed to the command, including final partial argument to be + * completed + * @return A List of possible completions for the final argument, or null to default to the + * command executor + */ + @Override + public @Nullable List onTabComplete( + @NotNull CommandSender sender, + @NotNull Command command, + @NotNull String label, + @NotNull String[] args) { + if (sender.hasPermission("sr.resetadventure")) { + if (args.length == 1) { + return null; + } + if (args[0].isBlank()) { + return Arrays.stream(Bukkit.getOfflinePlayers()) + .map(OfflinePlayer::getName) + .toList().stream().limit(10).toList(); + } + return Arrays.stream(Bukkit.getOfflinePlayers()) + .map(OfflinePlayer::getName).filter(Objects::nonNull) + .filter(name -> name.toLowerCase().startsWith(args[0].toLowerCase())) + .toList().stream().limit(10).toList(); + } + return null; + } +} diff --git a/src/main/java/me/unurled/sacredrealms/sr/components/player/PlayerManager.java b/src/main/java/me/unurled/sacredrealms/sr/components/player/PlayerManager.java index 420c84d..7bdf286 100644 --- a/src/main/java/me/unurled/sacredrealms/sr/components/player/PlayerManager.java +++ b/src/main/java/me/unurled/sacredrealms/sr/components/player/PlayerManager.java @@ -23,6 +23,7 @@ import org.jetbrains.annotations.Nullable; public class PlayerManager extends Manager { + public static final String PLAYER_KEY = "sr.players."; private final HashMap players; public PlayerManager() { @@ -64,7 +65,6 @@ public class PlayerManager extends Manager { @EventHandler public void onPlayerJoin(PlayerJoinEvent e) { - // load data from db // TODO: test this after redis cache DataManager dm = (DataManager) DataManager.getInstance(DataManager.class); if (dm == null) { error("DataManager is null, Can't load player " + e.getPlayer().getName() + "'s data" + "."); @@ -77,7 +77,7 @@ public class PlayerManager extends Manager { .registerTypeAdapter(PotionEffect.class, new PotionEffectDeserializer()) .excludeFieldsWithoutExposeAnnotation() .create(); - String json = dh.get("sr.players." + e.getPlayer().getUniqueId()); + String json = dh.get(PLAYER_KEY + e.getPlayer().getUniqueId()); SRPlayer srPlayer = gson.fromJson(json, SRPlayer.class); addPlayer(srPlayer); diff --git a/src/main/java/me/unurled/sacredrealms/sr/data/DataHandler.java b/src/main/java/me/unurled/sacredrealms/sr/data/DataHandler.java index 66a6275..bb561de 100644 --- a/src/main/java/me/unurled/sacredrealms/sr/data/DataHandler.java +++ b/src/main/java/me/unurled/sacredrealms/sr/data/DataHandler.java @@ -53,4 +53,11 @@ public interface DataHandler { * @param key The key to remove the value from */ void remove(@NotNull String key); + + /** + * Check if a key exists in the data source + * @param key The key to check + * @return If the key exists + */ + boolean exists(@NotNull String key); } diff --git a/src/main/java/me/unurled/sacredrealms/sr/data/Redis.java b/src/main/java/me/unurled/sacredrealms/sr/data/Redis.java index 57e4aa4..e902917 100644 --- a/src/main/java/me/unurled/sacredrealms/sr/data/Redis.java +++ b/src/main/java/me/unurled/sacredrealms/sr/data/Redis.java @@ -94,4 +94,14 @@ public class Redis implements DataHandler { public void remove(@NotNull String key) { client.del(key); } + + /** + * Check if a key exists + * @param key The key to check + * @return If the key exists + */ + @Override + public boolean exists(@NotNull String key) { + return client.exists(key); + } } diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 01de738..28b48b2 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -17,6 +17,9 @@ permissions: sr.attributes: default: op description: When the player has permission for the command /attributes set + sr.resetadventure: + default: op + description: When the player has permission for the command /resetadventure commands: attributes: