diff --git a/src/main/java/org/vindicterra/vindicterralib/VindicterraLib.java b/src/main/java/org/vindicterra/vindicterralib/VindicterraLib.java index dd493e3..f672be7 100644 --- a/src/main/java/org/vindicterra/vindicterralib/VindicterraLib.java +++ b/src/main/java/org/vindicterra/vindicterralib/VindicterraLib.java @@ -1,15 +1,20 @@ package org.vindicterra.vindicterralib; +import lombok.Getter; import org.bukkit.plugin.java.JavaPlugin; import org.vindicterra.vindicterralib.utils.StringUtils; + @SuppressWarnings("unused") public final class VindicterraLib extends JavaPlugin { + @Getter + private static VindicterraLib instance; @Override public void onEnable() { // Plugin startup logic StringUtils.loadConfigs(); + instance = this; getLogger().info("-- VindicterraLib Enabled! --"); } diff --git a/src/main/java/org/vindicterra/vindicterralib/commandcreator/CommandUtils.java b/src/main/java/org/vindicterra/vindicterralib/commandcreator/CommandUtils.java new file mode 100644 index 0000000..4a8ce4c --- /dev/null +++ b/src/main/java/org/vindicterra/vindicterralib/commandcreator/CommandUtils.java @@ -0,0 +1,31 @@ +package org.vindicterra.vindicterralib.commandcreator; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; + +import java.util.ArrayList; +import java.util.List; + +public class CommandUtils { + /** + * Returns the help menu containing all sub commands and their descriptions + * @param command Parent command to show menu for + * @return Component message to show to player + */ + public static Component returnHelpMenu(ParentCommand command) { + List subCommands = new ArrayList<>(); + for (ChildCommand sub : command.getSubCommands()) { + subCommands.add(Component.text(sub.getName() + " - " + sub.getDescription())); + } + Component header = Component.text("-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-", NamedTextColor.GOLD) + .appendNewline() + .append(Component.text(String.format(" --- /%s Subcommands ---", + command.getName()), NamedTextColor.AQUA)) + .appendNewline().appendNewline(); + for (Component component : subCommands) { + header = header.append(component).appendNewline(); + } + return header.append(Component.text( + "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-", NamedTextColor.GOLD)); + } +} diff --git a/src/main/java/org/vindicterra/vindicterralib/cooldown/Cooldown.java b/src/main/java/org/vindicterra/vindicterralib/cooldown/Cooldown.java new file mode 100644 index 0000000..d1294e6 --- /dev/null +++ b/src/main/java/org/vindicterra/vindicterralib/cooldown/Cooldown.java @@ -0,0 +1,77 @@ +package org.vindicterra.vindicterralib.cooldown; + +import lombok.Getter; +import lombok.Setter; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; +import org.vindicterra.vindicterralib.utils.StringUtils; + +@Getter +public class Cooldown extends BukkitRunnable { + @Setter + private long timeLeft; + private final long initialTime; + private final int duration; + private final String reason; + private final boolean showMessage; + private final Player player; + private long timeRan = 0L; + + public Cooldown(Player player, long initialTime, int duration, String reason, boolean showMessage) { + this.player = player; + this.initialTime = initialTime; + this.duration = duration; + this.timeLeft = duration; + this.reason = reason; + this.showMessage = showMessage; + } + + @Override + public void run() { + if (timeRan >= duration) { + sendOffCooldownMessage(); + remove(); + return; + } + timeRan++; + timeLeft = (long) ((((double) initialTime / 1000) + duration) + - ((double) System.currentTimeMillis() / 1000)); + } + + /** + * @param message Message to send to player + */ + public void sendActionBar(Component message) { + if (!showMessage) { + return; + } + player.sendActionBar(message); + } + + /** + * Send off cooldown message to player + */ + public void sendOffCooldownMessage() { + sendActionBar(Component.text( + "You are no longer on cooldown for " + StringUtils.toFriendlyFormat(reason) + "!", + NamedTextColor.GREEN) + ); + } + + /** + * Send on cooldown message to player + */ + public void sendOnCooldownMessage() { + sendActionBar(Component.text( + String.format("You are on cooldown for %s seconds...", timeLeft), + NamedTextColor.RED) + ); + } + + public void remove() { + CooldownManager.cooldowns.remove(this); + this.cancel(); + } +} diff --git a/src/main/java/org/vindicterra/vindicterralib/cooldown/CooldownManager.java b/src/main/java/org/vindicterra/vindicterralib/cooldown/CooldownManager.java new file mode 100644 index 0000000..082d717 --- /dev/null +++ b/src/main/java/org/vindicterra/vindicterralib/cooldown/CooldownManager.java @@ -0,0 +1,80 @@ +package org.vindicterra.vindicterralib.cooldown; + +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.vindicterra.vindicterralib.VindicterraLib; + +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +public class CooldownManager { + public static final List cooldowns = new ArrayList<>(); + /** + * @param player Player to apply cooldown to + * @param event Cancellable event thrown by player + * @param seconds Duration of cooldown + * @param reason Reason for cooldown + * @param showMessage Whether to show cooldown message as actionbar + * @return Status of new or existing cooldown + */ + public static CooldownStatus handleCooldown(Player player, @Nullable Event event, int seconds, String reason, boolean showMessage) { + UUID uuid = player.getUniqueId(); + + if (player.hasPermission("vindicterralib.admin.cooldown-bypass")) { + return CooldownStatus.NEW_COOLDOWN; + } + + Cooldown pCooldown = getCooldown(player, reason); + if (pCooldown != null) { + long timeLeft = pCooldown.getTimeLeft(); + if (timeLeft > 0) { + pCooldown.sendOnCooldownMessage(); + /* + if (event instanceof Cancellable) { + ((Cancellable) event).setCancelled(true); + } + */ + return CooldownStatus.ON_COOLDOWN; + } else { + pCooldown.remove(); + pCooldown.sendOffCooldownMessage(); + return CooldownStatus.OFF_COOLDOWN; + } + } + + Cooldown cd = new Cooldown(player, System.currentTimeMillis(), seconds, reason, showMessage); + cd.runTaskTimer(VindicterraLib.getInstance(), 0, 20); + cooldowns.add(cd); + return CooldownStatus.NEW_COOLDOWN; + } + + /** + * @param player Player to get all cooldowns for + * @return Possibly-empty list of active cooldowns associated with the player + */ + public static List getCooldowns(Player player) { + List playerCooldowns = new ArrayList<>(); + for (Cooldown cd : cooldowns) { + if (cd.getPlayer().getUniqueId() != player.getUniqueId()) continue; + playerCooldowns.add(cd); + } + return playerCooldowns; + } + + /** + * @param player Player to get a cooldown for + * @param reason Reason for cooldown + * @return Possibly-null active cooldown associated with player + */ + public static @Nullable Cooldown getCooldown(Player player, String reason) { + List pCooldowns = getCooldowns(player); + for (Cooldown cd : pCooldowns) { + if (!cd.getReason().equals(reason)) continue; + return cd; + } + return null; + } +} diff --git a/src/main/java/org/vindicterra/vindicterralib/cooldown/CooldownStatus.java b/src/main/java/org/vindicterra/vindicterralib/cooldown/CooldownStatus.java new file mode 100644 index 0000000..158d500 --- /dev/null +++ b/src/main/java/org/vindicterra/vindicterralib/cooldown/CooldownStatus.java @@ -0,0 +1,19 @@ +package org.vindicterra.vindicterralib.cooldown; + +/** + * Status of player cooldown + */ +public enum CooldownStatus { + /** + * Player is off cooldown + */ + OFF_COOLDOWN, + /** + * Player is on cooldown + */ + ON_COOLDOWN, + /** + * A new cooldown has been created for the player + */ + NEW_COOLDOWN +} diff --git a/src/main/java/org/vindicterra/vindicterralib/cooldown/CooldownUtils.java b/src/main/java/org/vindicterra/vindicterralib/cooldown/CooldownUtils.java new file mode 100644 index 0000000..ef70dde --- /dev/null +++ b/src/main/java/org/vindicterra/vindicterralib/cooldown/CooldownUtils.java @@ -0,0 +1,39 @@ +package org.vindicterra.vindicterralib.cooldown; + +import org.bukkit.entity.Player; + +import java.util.List; + +public class CooldownUtils { + /** + * @param player Player to check for cooldown + * @return True if player is on cooldown, otherwise false + * @apiNote This method will return if the player is on cooldown for ANY reason! + * To check for a specific reason, use {@link CooldownUtils#isOnCooldownForReason(Player, String)} + */ + public static boolean isOnCooldown(Player player) { + List cooldowns = CooldownManager.cooldowns; + for (Cooldown cd : cooldowns) { + if (!cd.getPlayer().getUniqueId().equals(player.getUniqueId())) continue; + return true; + } + return false; + } + + /** + * @param player Player to check for cooldown + * @param reason Reason for cooldown + * @return True if player is on cooldown for specified reason, otherwise false + * @apiNote This method will return if the player is on cooldown for a SPECIFIC reason! + * To check for any reason, use {@link CooldownUtils#isOnCooldown(Player)} + */ + public static boolean isOnCooldownForReason(Player player, String reason) { + if (!isOnCooldown(player)) return false; + for (Cooldown cd : CooldownManager.cooldowns) { + if (!cd.getPlayer().getUniqueId().equals(player.getUniqueId())) continue; + if (!cd.getReason().equals(reason)) continue; + return true; + } + return false; + } +} diff --git a/src/main/java/org/vindicterra/vindicterralib/entities/players/ItemUtils.java b/src/main/java/org/vindicterra/vindicterralib/entities/players/ItemUtils.java new file mode 100644 index 0000000..d229981 --- /dev/null +++ b/src/main/java/org/vindicterra/vindicterralib/entities/players/ItemUtils.java @@ -0,0 +1,29 @@ +package org.vindicterra.vindicterralib.entities.players; + +import org.bukkit.GameMode; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +public class ItemUtils { + /** + * Removes the specified amount of Bukkit material from the player's inventory + * @param player Player to remove item from + * @param material Bukkit material of item being removed + * @param amount Amount of item to be removed + * + * @return True if item was successfully removed, otherwise false + */ + public static boolean removeItem(Player player, Material material, int amount, boolean checkGamemode) { + if (checkGamemode && player.getGameMode().equals(GameMode.CREATIVE)) { + return false; + } + int index = player.getInventory().first(material); + if (index == -1) return false; + ItemStack first = player.getInventory().getItem(index); + if (first == null) return false; + first.setAmount(first.getAmount() - amount); + player.getInventory().setItem(index, first); + return true; + } +} diff --git a/src/main/java/org/vindicterra/vindicterralib/utils/MathUtils.java b/src/main/java/org/vindicterra/vindicterralib/utils/MathUtils.java new file mode 100644 index 0000000..b57c840 --- /dev/null +++ b/src/main/java/org/vindicterra/vindicterralib/utils/MathUtils.java @@ -0,0 +1,32 @@ +package org.vindicterra.vindicterralib.utils; + +@SuppressWarnings("unused") +public class MathUtils { + /** + * Clamps a value between a minimum and maximum value + *
+ *
+ * Clamped values will not go below or above the specified min and max values + * @param value Integer value to clamp + * @param min Minimum value allowed + * @param max Maximum value allowed + * @return Clamped value + */ + public static int clamp(int value, int min, int max) { + return Math.max(min, Math.min(max, value)); + } + + /** + * Clamps a value between a minimum and maximum value + *
+ *
+ * Clamped values will not go below or above the specified min and max values + * @param value Double value to clamp + * @param min Minimum value allowed + * @param max Maximum value allowed + * @return Clamped value + */ + public static double clamp(double value, double min, double max) { + return Math.max(min, Math.min(max, value)); + } +} diff --git a/src/main/java/org/vindicterra/vindicterralib/utils/StringUtils.java b/src/main/java/org/vindicterra/vindicterralib/utils/StringUtils.java index 4e8911f..5160409 100644 --- a/src/main/java/org/vindicterra/vindicterralib/utils/StringUtils.java +++ b/src/main/java/org/vindicterra/vindicterralib/utils/StringUtils.java @@ -13,7 +13,6 @@ import java.net.URL; import java.util.ArrayList; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -169,24 +168,31 @@ public static double round(double value, int places) { return decimal.doubleValue(); } - //what is this for? is it really necessary to have it in lib? + // what is this for? is it really necessary to have it in lib? /** - * @param name Item name to format - * @return Formatted item name in the style of "Grass Block" + * Formats the given input into a readable format (Ex. Grass Block) + * + * @param input Input to format + * @return Formatted string */ - public static String format(final String name) { - StringBuilder output = new StringBuilder(); - for (String character : name.split("_")) { - output.append(character.substring(0, 1).toUpperCase()).append(character.substring(1).toLowerCase()).append(" "); + public static String toFriendlyFormat(final String input) { + StringBuilder builder = new StringBuilder(); + for (String s : input.split("_")) { + builder.append(s.substring(0, 1).toUpperCase()) + .append(s.substring(1).toLowerCase()) + .append(" "); } - return output.substring(0, output.length() - 1); + return builder.toString(); } /** - * @param name Name to remove formatting from - * @return Unformatted name in the style of "GRASS_BLOCK" + * Deformats a string into Bukkit material formatting (Ex. GRASS_BLOCK) + * + * @param input Input to deformat + * @return Deformatted String */ - public static String deformat(final String name) { - return ((TextComponent) Component.text(name.toUpperCase().replace(" ", "_")).compact()).content(); + public static String toBukkitFormat(final String input) { + return ((TextComponent) Component.text(input.toUpperCase() + .replace(" ", "_")).compact()).content(); } } diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 545265b..4dd5289 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -4,3 +4,9 @@ main: org.vindicterra.vindicterralib.VindicterraLib api-version: '1.20' load: STARTUP description: Vindicterra Standard Library +permissions: + vindicterralib.admin: + default: op + description: Allows you to access admin commands or features + children: + - vindicterralib.admin.cooldown-bypass