From cd80f3500670529df6b450f61cce6cb01763c484 Mon Sep 17 00:00:00 2001 From: wolf Date: Wed, 2 Jul 2025 12:44:51 -0400 Subject: [PATCH] Added RTP script, spawn command, and broadcast command. --- .../trouper/clonedupecore/data/io/Config.java | 1 + .../{GamemodeEvent.java => JoinEvent.java} | 2 +- .../clonedupecore/server/gui/RtpGui.java | 79 +++++++++ .../server/scripts/BroadcastCommand.java | 43 +++++ .../server/scripts/RtpCommand.java | 29 ++++ .../server/scripts/SpawnCommand.java | 155 ++++++++++++++++++ .../server/trims/TrimManager.java | 1 + .../server/trolls/LiarTroll.java | 2 +- src/main/resources/plugin.yml | 40 ++++- 9 files changed, 349 insertions(+), 3 deletions(-) rename src/main/java/me/trouper/clonedupecore/server/events/{GamemodeEvent.java => JoinEvent.java} (91%) create mode 100644 src/main/java/me/trouper/clonedupecore/server/gui/RtpGui.java create mode 100644 src/main/java/me/trouper/clonedupecore/server/scripts/BroadcastCommand.java create mode 100644 src/main/java/me/trouper/clonedupecore/server/scripts/RtpCommand.java create mode 100644 src/main/java/me/trouper/clonedupecore/server/scripts/SpawnCommand.java diff --git a/src/main/java/me/trouper/clonedupecore/data/io/Config.java b/src/main/java/me/trouper/clonedupecore/data/io/Config.java index 70d91df..1f9baf4 100755 --- a/src/main/java/me/trouper/clonedupecore/data/io/Config.java +++ b/src/main/java/me/trouper/clonedupecore/data/io/Config.java @@ -63,4 +63,5 @@ public class Config implements JsonSerializable { } public SerialLocation freezeLocation = new SerialLocation("unset",0,64,0,0,0); + public SerialLocation spawnLocation = new SerialLocation("unset",0,64,0,0,0); } \ No newline at end of file diff --git a/src/main/java/me/trouper/clonedupecore/server/events/GamemodeEvent.java b/src/main/java/me/trouper/clonedupecore/server/events/JoinEvent.java similarity index 91% rename from src/main/java/me/trouper/clonedupecore/server/events/GamemodeEvent.java rename to src/main/java/me/trouper/clonedupecore/server/events/JoinEvent.java index 381e10b..8ef5ed0 100644 --- a/src/main/java/me/trouper/clonedupecore/server/events/GamemodeEvent.java +++ b/src/main/java/me/trouper/clonedupecore/server/events/JoinEvent.java @@ -6,7 +6,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.player.PlayerJoinEvent; -public class GamemodeEvent implements QuickListener { +public class JoinEvent implements QuickListener { @EventHandler private void onJoin(PlayerJoinEvent e) { diff --git a/src/main/java/me/trouper/clonedupecore/server/gui/RtpGui.java b/src/main/java/me/trouper/clonedupecore/server/gui/RtpGui.java new file mode 100644 index 0000000..fe2a371 --- /dev/null +++ b/src/main/java/me/trouper/clonedupecore/server/gui/RtpGui.java @@ -0,0 +1,79 @@ +package me.trouper.clonedupecore.server.gui; + +import me.trouper.alias.server.systems.gui.QuickGui; +import me.trouper.alias.utils.ItemBuilder; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.command.ConsoleCommandSender; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import java.util.List; + +public class RtpGui { + public ItemStack EMPTY = ItemBuilder.of(Material.LIGHT_GRAY_STAINED_GLASS_PANE) + .displayName("") + .build(); + + public QuickGui.GuiBuilder create() { + QuickGui.GuiBuilder builder = QuickGui.create(); + builder.titleMini("Random Teleport"); + builder.rows(3); + + builder.item(11, ItemBuilder.headOfTexture("http://textures.minecraft.net/texture/879e54cbe87867d14b2fbdf3f1870894352048dfecd962846dea893b2154c85") + .displayName("ᴏᴠᴇʀᴡᴏʀʟᴅ") + .loreMiniMessage(List.of( + "Teleporter", + "", + "Travel into the Overworld Dimension", + "To get new resources and explore!", + "", + "BORDER 25k x 25k", + "Click To Teleport!" + )) + .build(), + consoleCommand("betterrtp:rtp player %player% world") + ); + + builder.item(13, ItemBuilder.headOfTexture("http://textures.minecraft.net/texture/e8ee8f341eabf65515718163ec3b43ed01e1cde27b3b26c4d92c607299e4d91") + .displayName("ɴᴇᴛʜᴇʀ") + .loreMiniMessage(List.of( + "Teleporter", + "", + "Travel into the Nether Dimension", + "To get new resources and explore!", + "", + "BORDER 25k x 25k", + "Click To Teleport!" + )) + .build(), + consoleCommand("betterrtp:rtp player %player% world_nether") + ); + + builder.item(15, ItemBuilder.headOfTexture("http://textures.minecraft.net/texture/b4346c5e44039a505e5b16dba5ec84b3a379709fb32b8427d29366a5ea036fb") + .displayName("ᴇɴᴅ") + .loreMiniMessage(List.of( + "Teleporter", + "Closed For End Fight", + "Travel into the End Dimension", + "To get new resources and explore!", + "", + "BORDER ∞", + "Click To Teleport!" + )) + .build(), + consoleCommand("betterrtp:rtp player %player% world_the_end") + ); + + builder.fillEmpty(EMPTY); + + return builder; + } + + + private QuickGui.GuiAction consoleCommand(String command) { + return (gui, event) -> { + Bukkit.dispatchCommand(Bukkit.getConsoleSender(),command); + }; + } +} diff --git a/src/main/java/me/trouper/clonedupecore/server/scripts/BroadcastCommand.java b/src/main/java/me/trouper/clonedupecore/server/scripts/BroadcastCommand.java new file mode 100644 index 0000000..d2077f1 --- /dev/null +++ b/src/main/java/me/trouper/clonedupecore/server/scripts/BroadcastCommand.java @@ -0,0 +1,43 @@ +package me.trouper.clonedupecore.server.scripts; + +import me.trouper.alias.server.commands.Args; +import me.trouper.alias.server.commands.CommandRegistry; +import me.trouper.alias.server.commands.Permission; +import me.trouper.alias.server.commands.QuickCommand; +import me.trouper.alias.server.commands.completions.CompletionBuilder; +import me.trouper.alias.server.systems.Text; +import net.kyori.adventure.audience.Audience; +import net.kyori.adventure.text.Component; +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; + +@CommandRegistry( + value = "broadcast", + permission = @Permission("clonedupe.broadcast") +) +public class BroadcastCommand implements QuickCommand { + + @Override + public void handleCommand(CommandSender sender, Command command, String label, Args args) { + Text.Pallet pallet = Text.Pallet.INFO; + String message = args.getAll(1).toString(); + try { + pallet = args.get(0).toEnum(Text.Pallet.class); + } catch (Exception ex) { + message = args.get(0) + " " + message; + } + Component text = Text.color(message); + Audience players = Audience.audience(Bukkit.getOnlinePlayers()); + Text.message(pallet,players,text); + } + + @Override + public void handleCompletion(CommandSender sender, Command command, String label, Args args, CompletionBuilder b) { + b.then( + b.argEnum(Text.Pallet.class) + ).then( + b.arg("") + ); + } +} diff --git a/src/main/java/me/trouper/clonedupecore/server/scripts/RtpCommand.java b/src/main/java/me/trouper/clonedupecore/server/scripts/RtpCommand.java new file mode 100644 index 0000000..e32caba --- /dev/null +++ b/src/main/java/me/trouper/clonedupecore/server/scripts/RtpCommand.java @@ -0,0 +1,29 @@ +package me.trouper.clonedupecore.server.scripts; + +import me.trouper.alias.server.commands.Args; +import me.trouper.alias.server.commands.CommandRegistry; +import me.trouper.alias.server.commands.Permission; +import me.trouper.alias.server.commands.QuickCommand; +import me.trouper.alias.server.commands.completions.CompletionBuilder; +import me.trouper.clonedupecore.server.gui.RtpGui; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +@CommandRegistry( + value = "rtp", + permission = @Permission("clonedupe.hide"), + blocksAllowed = false, + consoleAllowed = false +) +public class RtpCommand implements QuickCommand { + @Override + public void handleCommand(CommandSender sender, Command command, String label, Args args) { + new RtpGui().create().build().open((Player) sender); + } + + @Override + public void handleCompletion(CommandSender sender, Command command, String label, Args args, CompletionBuilder b) { + + } +} diff --git a/src/main/java/me/trouper/clonedupecore/server/scripts/SpawnCommand.java b/src/main/java/me/trouper/clonedupecore/server/scripts/SpawnCommand.java new file mode 100644 index 0000000..b7e5ed5 --- /dev/null +++ b/src/main/java/me/trouper/clonedupecore/server/scripts/SpawnCommand.java @@ -0,0 +1,155 @@ +package me.trouper.clonedupecore.server.scripts; + +import me.trouper.alias.server.commands.Args; +import me.trouper.alias.server.commands.CommandRegistry; +import me.trouper.alias.server.commands.Permission; +import me.trouper.alias.server.commands.QuickCommandListener; +import me.trouper.alias.server.commands.completions.CompletionBuilder; +import me.trouper.alias.server.systems.Text; +import me.trouper.clonedupecore.data.Data; +import me.trouper.clonedupecore.data.SerialLocation; +import net.kyori.adventure.text.Component; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerMoveEvent; +import org.bukkit.event.player.PlayerRespawnEvent; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicInteger; + +@CommandRegistry( + value = "spawn", + permission = @Permission("clonedupe.spawn") +) +public class SpawnCommand implements QuickCommandListener, Data { + + private final Map warmups = new HashMap<>(); + + @Override + public void handleCommand(CommandSender sender, Command command, String label, Args args) { + if (args.getSize() > 0 || "setspawn".equals(label)) { + if (("setspawn".equals(label) || "set".equals(args.get(0).toString())) && sender.hasPermission("clonedupe.spawn.set") && sender instanceof Player setter) { + Location l = setter.getLocation(); + getConfig().spawnLocation = SerialLocation.translate(l); + getConfig().save(); + info(sender, Component.text("Set the spawn location to {0}."), Text.format(Text.Pallet.LOCATION,"({0},{1},{2})",l.getBlockX(),l.getBlockY(),l.getBlockZ())); + return; + } + Player target = Bukkit.getPlayerExact(args.get(0).toString()); + if (!sender.hasPermission("clonedupe.spawn.others")) return; + if (target != null) { + teleportToSpawn(target,false); + infoAny(sender,"Teleported {0} to spawn.",target.getName()); + } else { + errorAny(sender,"{0} is not an online player!",args.get(0).toString()); + } + return; + } + if ("unset".equals(getConfig().spawnLocation.world())) { + errorAny(sender,"Spawn is not set yet!"); + return; + } + if (sender instanceof Player player) { + startSpawnWarmup(player); + return; + } + errorAny(sender,"Only players may teleport to spawn!"); + } + + @Override + public void handleCompletion(CommandSender sender, Command command, String label, Args args, CompletionBuilder b) { + if (sender.hasPermission("clonedupe.spawn.set")) b.then(b.arg("set")); + if (sender.hasPermission("clonedupe.spawn.others")) b.then(b.argOnlinePlayers()); + } + + private void startSpawnWarmup(Player player) { + if (player.hasPermission("clonedupe.spawn.bypass")) { + teleportToSpawn(player, false); + return; + } + + warmups.put(player.getUniqueId(), System.currentTimeMillis()); + int WARMUP_TICKS = 100; + successAny(player, "Teleporting to spawn in {0} seconds. Don't move or take damage!", WARMUP_TICKS / 20); + AtomicInteger secondsLeft = new AtomicInteger((int) WARMUP_TICKS / 20); + + Bukkit.getScheduler().runTaskTimer(main.getPlugin(),(task)->{ + if (!warmups.containsKey(player.getUniqueId()) || secondsLeft.get() < 0 || !player.isOnline()) { + task.cancel(); + return; + } + + if (secondsLeft.get() % 5 == 0 || secondsLeft.get() <= 3) { + if (secondsLeft.get() > 0) { + player.sendActionBar(Text.format(Text.Pallet.INFO,"Teleporting in {0}!",secondsLeft.get())); + } else { + warmups.remove(player.getUniqueId()); + teleportToSpawn(player, true); + task.cancel(); + } + } + + secondsLeft.decrementAndGet(); + },20L,20L); + } + + private void teleportToSpawn(Player player, boolean duringWarmup) { + Location spawnLoc = getConfig().spawnLocation.translate(); + if (spawnLoc.getWorld() == null) { + errorAny(player, "Spawn world is not loaded."); + return; + } + player.teleport(spawnLoc); + successAny(player, "Teleported to spawn."); + if (duringWarmup) { + warmups.remove(player.getUniqueId()); + } + } + + @EventHandler + public void onPlayerMove(PlayerMoveEvent e) { + Player player = e.getPlayer(); + if (!warmups.containsKey(player.getUniqueId())) return; + Location from = e.getFrom(); + Location to = e.getTo(); + + if (from.distanceSquared(to) >= 0.001) { + warmups.remove(player.getUniqueId()); + errorAny(player, "Teleport cancelled due to movement!"); + } + } + + @EventHandler + public void onEntityDamage(EntityDamageEvent e) { + if (!(e.getEntity() instanceof Player player)) return; + if (!warmups.containsKey(player.getUniqueId())) return; + + warmups.remove(player.getUniqueId()); + errorAny(player, "Teleport cancelled because you took damage!"); + } + + @EventHandler + public void onRespawn(PlayerRespawnEvent e) { + if ("unset".equals(getConfig().spawnLocation.world())) return; + Player p = e.getPlayer(); + if (p.getRespawnLocation() != null) return; + e.setRespawnLocation(getConfig().spawnLocation.translate()); + } + + @EventHandler + public void onJoin(PlayerJoinEvent e) { + if ("unset".equals(getConfig().spawnLocation.world())) return; + Player p = e.getPlayer(); + Location loc = getConfig().spawnLocation.translate(); + if (p.getLocation().distanceSquared(loc) > 100*100) return; + p.teleport(loc); + } +} diff --git a/src/main/java/me/trouper/clonedupecore/server/trims/TrimManager.java b/src/main/java/me/trouper/clonedupecore/server/trims/TrimManager.java index 5f3f9a8..dbceab2 100644 --- a/src/main/java/me/trouper/clonedupecore/server/trims/TrimManager.java +++ b/src/main/java/me/trouper/clonedupecore/server/trims/TrimManager.java @@ -52,6 +52,7 @@ public class TrimManager implements QuickListener, Data { if (activeAnimation == null) { return; } else if (lastAnimationMap.containsKey(playerId) && !lastAnimationMap.get(playerId).equals(activeAnimation)) { + lastAnimationMap.get(playerId).onRemove(player); lastAnimationMap.put(playerId,activeAnimation); } else if (!lastAnimationMap.containsKey(playerId)) { lastAnimationMap.put(playerId,activeAnimation); diff --git a/src/main/java/me/trouper/clonedupecore/server/trolls/LiarTroll.java b/src/main/java/me/trouper/clonedupecore/server/trolls/LiarTroll.java index 7e686b2..f7b77d3 100644 --- a/src/main/java/me/trouper/clonedupecore/server/trolls/LiarTroll.java +++ b/src/main/java/me/trouper/clonedupecore/server/trolls/LiarTroll.java @@ -51,7 +51,7 @@ public class LiarTroll implements TrollFeature { activeLiars.put(target.getUniqueId(),target.getEquipment().getLeggings()); AtomicBoolean inverse = new AtomicBoolean(false); - AtomicInteger timeRemaining = new AtomicInteger(30 * 20); + AtomicInteger timeRemaining = new AtomicInteger(15 * 20); Bukkit.getScheduler().runTaskTimer(main.getPlugin(), (task)->{ if (!activeLiars.containsKey(target.getUniqueId())) { diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 25e065e..9a6dd71 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -28,15 +28,17 @@ commands: - admin - cdc offend: - usage: "/offend " + usage: "/offend " permission: clonedupe.offend aliases: - punish trimeffect: usage: /trimeffect + description: Toggle trim effect visibility statedit: usage: /statedit permission: clonedupe.statedit + description: Edit minecraft's tracked statistics freeze: usage: /freeze permission: clonedupe.freeze @@ -50,7 +52,43 @@ commands: wand: usage: /wand permission: clonedupe.getwand + description: Get any of the registered AbstractWands + rtp: + usage: /rtp + description: A gui for BetterRTP + aliases: + - randomtp + - betterrtp + - wild + - wildtp + - tpr + broadcast: + usage: /broadcast [pallet] + description: Broadcast a message with the text system + permission: clonedupe.broadcast + aliases: + - bc + spawn: + usage: /spawn [set|player] + description: Teleport to the spawn location. + aliases: + - setspawn permissions: + clonedupe.spawn.bypass: + default: op + description: Allows bypassing of the spawn warmup. + clonedupe.spawn.others: + default: op + description: allows teleportation of other players to spawn. + clonedupe.spawn.set: + default: op + description: Set the configurable spawn location. + clonedupe.spawn: + default: true + description: Allows teleportation to spawn. + clonedupe.broadcast: + default: op + description: Gives access to the broadcast command. clonedupe.getwand: default: op description: Get any AbstractWand registered.