From 2b6480c880286e84f049a2c30cd77e08ac01ac28 Mon Sep 17 00:00:00 2001 From: akastijn Date: Mon, 15 Jun 2026 22:45:06 +0200 Subject: [PATCH] Add warmup period for `/hg stuck` with movement and damage cancellation --- TODO.md | 1 + .../hunger_games/commands/BaseCommand.java | 2 +- .../commands/subcommands/Stuck.java | 83 ++++++++++++++++++- .../com/alttd/hunger_games/config/Config.java | 2 + .../alttd/hunger_games/config/Messages.java | 8 ++ 5 files changed, 91 insertions(+), 5 deletions(-) diff --git a/TODO.md b/TODO.md index f6073bc..6a7915a 100644 --- a/TODO.md +++ b/TODO.md @@ -144,6 +144,7 @@ Track each registered player in one of these states: - [x] Launch fireworks at the destination on use - [x] Configure firework count/type - [x] Optional cooldown to prevent spam +- [x] Warmup period (configurable) that cancels on movement or damage ### `/hg stats [player]` - [ ] Show overall stats for the specified player (or self if no argument) diff --git a/src/main/java/com/alttd/hunger_games/commands/BaseCommand.java b/src/main/java/com/alttd/hunger_games/commands/BaseCommand.java index af61cc6..4bfaf5a 100644 --- a/src/main/java/com/alttd/hunger_games/commands/BaseCommand.java +++ b/src/main/java/com/alttd/hunger_games/commands/BaseCommand.java @@ -38,7 +38,7 @@ public class BaseCommand implements CommandExecutor, TabExecutor { new RoundState(roundService), new Register(playerService), new StartRound(round, roundService), - new Stuck() + new Stuck(main) )); } diff --git a/src/main/java/com/alttd/hunger_games/commands/subcommands/Stuck.java b/src/main/java/com/alttd/hunger_games/commands/subcommands/Stuck.java index f80112e..9800304 100644 --- a/src/main/java/com/alttd/hunger_games/commands/subcommands/Stuck.java +++ b/src/main/java/com/alttd/hunger_games/commands/subcommands/Stuck.java @@ -1,5 +1,5 @@ package com.alttd.hunger_games.commands.subcommands; - +import com.alttd.hunger_games.Main; import com.alttd.hunger_games.commands.SubCommand; import com.alttd.hunger_games.config.Config; import com.alttd.hunger_games.config.Messages; @@ -14,15 +14,29 @@ import org.bukkit.command.CommandSender; import org.bukkit.entity.EntityType; import org.bukkit.entity.Firework; import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.event.player.PlayerMoveEvent; import org.bukkit.inventory.meta.FireworkMeta; +import org.bukkit.scheduler.BukkitTask; import java.time.Duration; import java.time.Instant; import java.util.*; -public class Stuck extends SubCommand { +public class Stuck extends SubCommand implements Listener { + private final Main main; private final Map cooldowns = new HashMap<>(); + private final Map warmups = new HashMap<>(); + + public Stuck(Main main) { + this.main = main; + main.getServer().getPluginManager().registerEvents(this, main); + } + + private record Warmup(Location location, BukkitTask task) { } @Override public boolean onCommand(CommandSender commandSender, String[] args) { @@ -31,6 +45,11 @@ public class Stuck extends SubCommand { return true; } + if (warmups.containsKey(player.getUniqueId())) { + player.sendRichMessage(Messages.STUCK.ALREADY_WARMING_UP); + return true; + } + if (player.getLocation().getY() < Config.DESTINATION.STUCK_MIN_HEIGHT) { player.sendRichMessage(Messages.STUCK.TOO_LOW, Placeholder.parsed("height", String.valueOf(Config.DESTINATION.STUCK_MIN_HEIGHT)) @@ -52,12 +71,68 @@ public class Stuck extends SubCommand { return true; } - player.teleport(safeLocation.get().add(0.5, 1, 0.5)); + startWarmup(player, safeLocation.get()); + return true; + } + + private void startWarmup(Player player, Location safeLocation) { + Duration warmupTime = Config.DESTINATION.STUCK_WARMUP; + if (warmupTime.isZero() || warmupTime.isNegative()) { + teleport(player, safeLocation); + return; + } + + player.sendRichMessage(Messages.STUCK.WARMUP_STARTED, + Placeholder.parsed("time", warmupTime.toSeconds() + "s") + ); + + BukkitTask task = main.getServer().getScheduler().runTaskLater(main, () -> { + warmups.remove(player.getUniqueId()); + teleport(player, safeLocation); + }, warmupTime.toSeconds() * 20L); + + warmups.put(player.getUniqueId(), new Warmup(player.getLocation(), task)); + } + + private void teleport(Player player, Location safeLocation) { + player.teleport(safeLocation.add(0.5, 1, 0.5)); spawnFireworks(player.getLocation()); player.sendRichMessage(Messages.STUCK.TELEPORTED); cooldowns.put(player.getUniqueId(), Instant.now()); + } - return true; + @EventHandler + public void onPlayerMove(PlayerMoveEvent event) { + UUID uuid = event.getPlayer().getUniqueId(); + Warmup warmup = warmups.get(uuid); + if (warmup == null) { + return; + } + + Location from = warmup.location(); + Location to = event.getTo(); + + if (from.getWorld() != to.getWorld() || from.distanceSquared(to) > 0.25) { + warmup.task().cancel(); + warmups.remove(uuid); + event.getPlayer().sendRichMessage(Messages.STUCK.WARMUP_CANCELLED_MOVEMENT); + } + } + + @EventHandler + public void onPlayerDamage(EntityDamageEvent event) { + if (!(event.getEntity() instanceof Player player)) { + return; + } + + Warmup warmup = warmups.get(player.getUniqueId()); + if (warmup == null) { + return; + } + + warmup.task().cancel(); + warmups.remove(player.getUniqueId()); + player.sendRichMessage(Messages.STUCK.WARMUP_CANCELLED_DAMAGE); } private boolean isOnCooldown(Player player) { diff --git a/src/main/java/com/alttd/hunger_games/config/Config.java b/src/main/java/com/alttd/hunger_games/config/Config.java index f9d3a54..a582b8d 100644 --- a/src/main/java/com/alttd/hunger_games/config/Config.java +++ b/src/main/java/com/alttd/hunger_games/config/Config.java @@ -113,6 +113,7 @@ public class Config extends AbstractConfig { public static int STUCK_MIN_HEIGHT = 64; public static int STUCK_FIREWORK_COUNT = 3; public static Duration STUCK_COOLDOWN = Duration.ofMinutes(2); + public static Duration STUCK_WARMUP = Duration.ofSeconds(5); @SuppressWarnings("unused") private static void load() { @@ -130,6 +131,7 @@ public class Config extends AbstractConfig { STUCK_MIN_HEIGHT = config.getInt(prefix, "stuck-min-height", STUCK_MIN_HEIGHT); STUCK_FIREWORK_COUNT = config.getInt(prefix, "stuck-firework-count", STUCK_FIREWORK_COUNT); STUCK_COOLDOWN = Duration.ofSeconds(config.getInt(prefix, "stuck-cooldown-seconds", (int) STUCK_COOLDOWN.toSeconds())); + STUCK_WARMUP = Duration.ofSeconds(config.getInt(prefix, "stuck-warmup-seconds", (int) STUCK_WARMUP.toSeconds())); } } } diff --git a/src/main/java/com/alttd/hunger_games/config/Messages.java b/src/main/java/com/alttd/hunger_games/config/Messages.java index 1b9ad64..4750c31 100644 --- a/src/main/java/com/alttd/hunger_games/config/Messages.java +++ b/src/main/java/com/alttd/hunger_games/config/Messages.java @@ -128,6 +128,10 @@ public class Messages extends AbstractConfig { public static String TOO_LOW = "You are too low to use this command (minimum height: ). If you are truly stuck here dm a staff member for help"; public static String NO_SAFE_LOCATION = "Unable to find a safe grass block nearby"; public static String ON_COOLDOWN = "You must wait "; + public static String WARMUP_STARTED = "Teleporting in "; + public static String WARMUP_CANCELLED_MOVEMENT = "Teleportation cancelled due to movement."; + public static String WARMUP_CANCELLED_DAMAGE = "Teleportation cancelled due to taking damage."; + public static String ALREADY_WARMING_UP = "You are already warming up!"; @SuppressWarnings("unused") private static void load() { @@ -135,6 +139,10 @@ public class Messages extends AbstractConfig { TOO_LOW = config.getString(prefix, "too-low", TOO_LOW); NO_SAFE_LOCATION = config.getString(prefix, "no-safe-location", NO_SAFE_LOCATION); ON_COOLDOWN = config.getString(prefix, "on-cooldown", ON_COOLDOWN); + WARMUP_STARTED = config.getString(prefix, "warmup-started", WARMUP_STARTED); + WARMUP_CANCELLED_MOVEMENT = config.getString(prefix, "warmup-cancelled-movement", WARMUP_CANCELLED_MOVEMENT); + WARMUP_CANCELLED_DAMAGE = config.getString(prefix, "warmup-cancelled-damage", WARMUP_CANCELLED_DAMAGE); + ALREADY_WARMING_UP = config.getString(prefix, "already-warming-up", ALREADY_WARMING_UP); } } }