diff --git a/paper/src/main/java/net/minelink/ctplus/Settings.java b/paper/src/main/java/net/minelink/ctplus/Settings.java index be118f1..f9e0587 100644 --- a/paper/src/main/java/net/minelink/ctplus/Settings.java +++ b/paper/src/main/java/net/minelink/ctplus/Settings.java @@ -1,5 +1,11 @@ package net.minelink.ctplus; +import static java.util.concurrent.TimeUnit.DAYS; +import static java.util.concurrent.TimeUnit.HOURS; +import static java.util.concurrent.TimeUnit.MINUTES; +import static java.util.concurrent.TimeUnit.SECONDS; + + import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; @@ -15,14 +21,11 @@ import java.util.Locale; import java.util.Map; import java.util.concurrent.TimeUnit; - import org.apache.commons.lang.StringUtils; import org.bukkit.ChatColor; import org.bukkit.configuration.Configuration; import org.bukkit.configuration.file.YamlConfiguration; -import static java.util.concurrent.TimeUnit.*; - public final class Settings { private final CombatTagPlus plugin; @@ -312,6 +315,14 @@ public boolean disableCrafting() { return plugin.getConfig().getBoolean("disable-crafting"); } + public boolean cooldownBlockPlacingInCombat() { + return plugin.getConfig().getBoolean("cooldown-block-placing-in-combat", false); + } + + public long getBlockPlacingCooldownTimeInCombat() { + return plugin.getConfig().getLong("cooldown-block-placing-time", 60L); + } + public String getDisableCraftingMessage() { String message = plugin.getConfig().getString("disable-crafting-message", ""); return ChatColor.translateAlternateColorCodes('&', message); diff --git a/paper/src/main/java/net/minelink/ctplus/listener/PlayerListener.java b/paper/src/main/java/net/minelink/ctplus/listener/PlayerListener.java index 66f47ca..7020592 100644 --- a/paper/src/main/java/net/minelink/ctplus/listener/PlayerListener.java +++ b/paper/src/main/java/net/minelink/ctplus/listener/PlayerListener.java @@ -1,17 +1,21 @@ package net.minelink.ctplus.listener; +import java.text.DecimalFormat; +import java.util.HashMap; +import java.util.Map; import java.util.UUID; import javax.annotation.Nullable; - +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; import net.minelink.ctplus.CombatTagPlus; import net.minelink.ctplus.Tag; import net.minelink.ctplus.event.CombatLogEvent; import net.minelink.ctplus.event.PlayerCombatTagEvent; import net.minelink.ctplus.task.SafeLogoutTask; import net.minelink.ctplus.task.TagUpdateTask; - import org.apache.commons.lang.WordUtils; import org.bukkit.Bukkit; +import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -31,13 +35,16 @@ import org.bukkit.event.player.PlayerToggleFlightEvent; import org.bukkit.inventory.InventoryView; import org.bukkit.inventory.ItemStack; +import org.bukkit.plugin.java.JavaPlugin; public final class PlayerListener implements Listener { - private final CombatTagPlus plugin; + private CombatTagPlus plugin; + private TickCoolDownHandler handler; public PlayerListener(CombatTagPlus plugin) { this.plugin = plugin; + this.handler = new TickCoolDownHandler(plugin, plugin.getSettings().getBlockPlacingCooldownTimeInCombat()); } @EventHandler(priority = EventPriority.LOWEST) @@ -407,4 +414,81 @@ public void denySafeZoneEntry(PlayerTeleportEvent event) { } } + @EventHandler(ignoreCancelled = true) + public void blockPlacementCooldown(BlockPlaceEvent event){ + if (!plugin.getSettings().cooldownBlockPlacingInCombat()) { + return; + } + Player player = event.getPlayer(); + if (!plugin.getTagManager().isTagged(player.getUniqueId())) { + return; + } + + if (handler.onCoolDown(player.getUniqueId())) { + event.setCancelled(true); + player.sendMessage(Component.text("You may place blocks again in " + formatCoolDown(player.getUniqueId()) + " seconds", + NamedTextColor.RED)); + return; + } + handler.putOnCoolDown(player.getUniqueId()); + } + + private String formatCoolDown(UUID uuid) { + long cd = handler.getRemainingCoolDown(uuid); + if (cd <= 0) { + return ChatColor.GREEN + "READY"; + } + //convert from ticks to ms + return new DecimalFormat("#.0").format(cd / 20.0) + " sec"; + } +} + +class TickCoolDownHandler { + + private Map cds; + + private long cooldown; + + private long tickCounter; + + public TickCoolDownHandler(JavaPlugin executingPlugin, long cooldown) { + this.cooldown = cooldown; + cds = new HashMap<>(); + Bukkit.getScheduler().scheduleSyncRepeatingTask(executingPlugin, () -> { + tickCounter++; // increment every tick + }, 1L, 1L); + } + + public void putOnCoolDown(E e) { + cds.put(e, tickCounter); + } + + public boolean onCoolDown(E e) { + Long lastUsed = cds.get(e); + if (lastUsed == null || (tickCounter - lastUsed) > cooldown) { + return false; + } + return true; + } + + public long getRemainingCoolDown(E e) { + Long lastUsed = cds.get(e); + if (lastUsed == null) { + return 0L; + } + long leftOver = tickCounter - lastUsed; + if (leftOver < cooldown) { + return cooldown - leftOver; + } + return 0L; + } + + public long getTotalCoolDown() { + return cooldown; + } + + public void removeCooldown(E e) { + cds.remove(e); + } + } diff --git a/paper/src/main/resources/config.yml b/paper/src/main/resources/config.yml index b39e3d4..d07db34 100644 --- a/paper/src/main/resources/config.yml +++ b/paper/src/main/resources/config.yml @@ -96,6 +96,12 @@ untag-on-plugin-teleport: false # This message is displayed when a player attempts to teleport within pvp if teleportation is disabled in pvp. disable-teleportation-message: '&bTeleportation &cis disabled in combat.' +#Should block placement have a cooldown while a player is tagged? +cooldown-block-placing-in-combat: false + +#Cooldown time between block placements while tagged. This value is in ticks. 20 ticks = 1 second +cooldown-block-placing-time: 100 + # Prevents tagged players from crafting during combat. disable-crafting: false