diff --git a/src/main/java/fun/ogre/ogredupealias/OgreDupeAlias.java b/src/main/java/fun/ogre/ogredupealias/OgreDupeAlias.java index ed9792c..7f757bf 100644 --- a/src/main/java/fun/ogre/ogredupealias/OgreDupeAlias.java +++ b/src/main/java/fun/ogre/ogredupealias/OgreDupeAlias.java @@ -8,11 +8,14 @@ import fun.ogre.ogredupealias.plugin.custom.items.CustomItems; import fun.ogre.ogredupealias.plugin.funitems.AdminUtility; import fun.ogre.ogredupealias.plugin.funitems.Pickler; import fun.ogre.ogredupealias.plugin.funitems.PotatoCannon; +import fun.ogre.ogredupealias.utils.ServerUtils; import org.bukkit.Bukkit; import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.scheduler.BukkitScheduler; +import java.util.ConcurrentModificationException; +import java.util.Map; import java.util.logging.Logger; public final class OgreDupeAlias extends JavaPlugin { @@ -30,6 +33,7 @@ public final class OgreDupeAlias extends JavaPlugin { this.initConfig(); CustomItems.init(); CraftingKeys.initRecipes(); + this.initTimer(); } @Override @@ -83,6 +87,8 @@ public final class OgreDupeAlias extends JavaPlugin { getCommand("showdonation").setTabCompleter(new ShowDonationCommand()); getCommand("ranks").setExecutor(new RanksCommand()); getCommand("ranks").setTabCompleter(new RanksCommand()); + getCommand("timer").setExecutor(new TimerCommand()); + getCommand("timer").setTabCompleter(new TimerCommand()); } public void initConfig() { @@ -90,6 +96,22 @@ public final class OgreDupeAlias extends JavaPlugin { this.saveDefaultConfig(); } + public void initTimer() { + Bukkit.getScheduler().scheduleSyncRepeatingTask(this, () -> { + try { + if (TimerCommand.timers.isEmpty()) { + return; + } + for (Map.Entry entry : TimerCommand.timers.entrySet()) { + TimerCommand.TimerEntry timer = entry.getValue(); + String msg = "%s: %s".formatted(timer.name(), timer.getTimeLeft()); + ServerUtils.forEachPlayerRun(player -> player.getScoreboardTags().contains(timer.tag()), player -> ServerUtils.sendActionBar(player, msg)); + } + } + catch (ConcurrentModificationException ignore) {} + }, 0, 20); + } + public static String prefix() { return Config.Plugin.prefix(); } diff --git a/src/main/java/fun/ogre/ogredupealias/commands/LocationParser.java b/src/main/java/fun/ogre/ogredupealias/commands/LocationParser.java new file mode 100644 index 0000000..7fd7cf1 --- /dev/null +++ b/src/main/java/fun/ogre/ogredupealias/commands/LocationParser.java @@ -0,0 +1,108 @@ +package fun.ogre.ogredupealias.commands; + +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.block.Block; + +public class LocationParser { + + private final double x, y, z; + + public LocationParser(String input) { + String[] secs = input.replaceAll("[^0-9 ]", "").trim().split(" "); + double x = 0.0; + double y = 0.0; + double z = 0.0; + + for (int i = 0; i < secs.length; i++) { + if (secs[i].isEmpty()) { + continue; + } + + switch (i) { + case 0 -> x = Double.parseDouble(secs[i]); + case 1 -> y = Double.parseDouble(secs[i]); + case 2 -> z = Double.parseDouble(secs[i]); + } + if (i >= 3) { + break; + } + } + + this.x = x; + this.y = y; + this.z = z; + } + + public LocationParser(String input, Location relativeTo) { + String[] secs = input.replaceAll("[^0-9 ~]", "").trim().split(" "); + double x = 0.0; + double y = 0.0; + double z = 0.0; + + for (int i = 0; i < secs.length; i++) { + switch (i) { + case 0 -> { + String parsing = secs[i].replaceAll("[^0-9]", ""); + if (!parsing.isEmpty()) { + x = Double.parseDouble(parsing); + } + x = secs[i].contains("~") ? relativeTo.getX() + x : x; + } + case 1 -> { + String parsing = secs[i].replaceAll("[^0-9]", ""); + if (!parsing.isEmpty()) { + y = Double.parseDouble(parsing); + } + y = secs[i].contains("~") ? relativeTo.getY() + y : y; + } + case 2 -> { + String parsing = secs[i].replaceAll("[^0-9]", ""); + if (!parsing.isEmpty()) { + z = Double.parseDouble(parsing); + } + z = secs[i].contains("~") ? relativeTo.getZ() + z : z; + } + } + if (i >= 3) { + break; + } + } + + this.x = x; + this.y = y; + this.z = z; + } + + public LocationParser(String x, String y, String z) { + this(x + " " + y + " " + z); + } + + public LocationParser(String x, String y, String z, Location relativeTo) { + this(x + " " + y + " " + z, relativeTo); + } + + public Location getLocation(World world) { + return new Location(world, x, y, z); + } + + public Block getBlock(World world) { + return getLocation(world).getBlock(); + } + + public Location getBlockLocation(World world) { + return getBlock(world).getLocation(); + } + + public double getX() { + return x; + } + + public double getY() { + return y; + } + + public double getZ() { + return z; + } +} diff --git a/src/main/java/fun/ogre/ogredupealias/commands/commands/TimerCommand.java b/src/main/java/fun/ogre/ogredupealias/commands/commands/TimerCommand.java new file mode 100644 index 0000000..871f1bf --- /dev/null +++ b/src/main/java/fun/ogre/ogredupealias/commands/commands/TimerCommand.java @@ -0,0 +1,150 @@ +package fun.ogre.ogredupealias.commands.commands; + +import fun.ogre.ogredupealias.OgreDupeAlias; +import fun.ogre.ogredupealias.commands.CmdExHandler; +import fun.ogre.ogredupealias.commands.LocationParser; +import fun.ogre.ogredupealias.utils.ArrayUtils; +import fun.ogre.ogredupealias.utils.Text; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.command.BlockCommandSender; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabExecutor; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class TimerCommand implements TabExecutor { + + public static final Map timers = new HashMap<>(); + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + try { + switch (args[0]) { + case "set" -> { + String timer = args[1]; + + if (timers.containsKey(timer)) { + sender.sendMessage(Text.ofAll("&cTimer is already running!")); + return true; + } + + String tag = args[2]; + long ticks = Long.parseLong(args[3]) * 20L; + LocationParser parser; + World world; + + if (sender instanceof BlockCommandSender source) { + parser = new LocationParser(args[4], args[5], args[6], source.getBlock().getLocation()); + world = source.getBlock().getWorld(); + } + else if (sender instanceof Player source) { + parser = new LocationParser(args[4], args[5], args[6], source.getLocation()); + world = source.getWorld(); + } + else { + throw new IllegalArgumentException("Sender should be a command block or player!"); + } + + Material type = Material.valueOf(args[7].toUpperCase()); + timers.put(timer, new TimerEntry(timer, tag, System.currentTimeMillis() + ticks * 50L, () -> { + parser.getBlock(world).setType(type); + timers.remove(timer); + })); + Bukkit.getScheduler().runTaskLater(OgreDupeAlias.instance, () -> { + if (timers.containsKey(timer)) { + timers.get(timer).endAction().run(); + } + }, ticks); + + sender.sendMessage(Text.ofAll("&bRegistered timer &7" + timers.get(timer))); + } + case "stop" -> { + String timer = args[1]; + if (timers.containsKey(timer)) { + sender.sendMessage(Text.ofAll("&cRemoved timer &7" + timers.get(timer))); + timers.remove(timer); + } + else { + sender.sendMessage(Text.ofAll("&cTimer not found.")); + } + } + } + } + catch (Exception ex) { + CmdExHandler handler = new CmdExHandler(ex, command); + sender.sendMessage(handler.getHelp()); + } + return true; + } + + @Override + public List onTabComplete(CommandSender sender, Command command, String label, String[] args) { + List l = new ArrayList<>(); + + switch (args.length) { + case 1 -> l.addAll(List.of("stop", "set")); + case 2 -> { + l.addAll(timers.keySet()); + switch (args[0]) { + case "set" -> { + if (timers.isEmpty()) { + l.add("timer1"); + } + } + } + } + case 3 -> { + switch (args[0]) { + case "set" -> l.add(args[1]); + } + } + case 4 -> { + switch (args[0]) { + case "set" -> l.addAll(List.of("5", "10", "20")); + } + } + case 5 -> { + switch (args[0]) { + case "set" -> l.addAll(List.of("~", "~ ~", "~ ~ ~")); + } + } + case 6 -> { + switch (args[0]) { + case "set" -> l.addAll(List.of("~", "~ ~")); + } + } + case 7 -> { + switch (args[0]) { + case "set" -> l.addAll(List.of("~")); + } + } + case 8 -> { + switch (args[0]) { + case "set" -> l.addAll(ArrayUtils.Constants.MATERIAL_NAMES); + } + } + } + + l.removeIf(s -> !s.toLowerCase().contains(args[args.length - 1].toLowerCase())); + return l; + } + + public record TimerEntry(String name, String tag, long end, Runnable endAction) { + public String getTimeLeft() { + long diff = end - System.currentTimeMillis(); + return (int)(diff / 1000.0) + " secs"; + } + + @Override + public String toString() { + return "{name=%s, tag=%s, end=%s}".formatted(name, tag, end); + } + } +} diff --git a/src/main/java/fun/ogre/ogredupealias/events/LiteBansEvents.java b/src/main/java/fun/ogre/ogredupealias/events/LiteBansEvents.java index bcc621b..fc062de 100644 --- a/src/main/java/fun/ogre/ogredupealias/events/LiteBansEvents.java +++ b/src/main/java/fun/ogre/ogredupealias/events/LiteBansEvents.java @@ -1,14 +1,12 @@ package fun.ogre.ogredupealias.events; + import fun.ogre.ogredupealias.OgreDupeAlias; import fun.ogre.ogredupealias.data.Config; import fun.ogre.ogredupealias.data.Emojis; -import fun.ogre.ogredupealias.utils.Webhook; +import fun.ogre.ogredupealias.utils.Webhook; import litebans.api.Entry; import litebans.api.Events; import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; import java.awt.*; import java.io.IOException; diff --git a/src/main/java/fun/ogre/ogredupealias/events/TurfWarsEventListener.java b/src/main/java/fun/ogre/ogredupealias/events/TurfWarsEventListener.java index f72489f..63a5233 100644 --- a/src/main/java/fun/ogre/ogredupealias/events/TurfWarsEventListener.java +++ b/src/main/java/fun/ogre/ogredupealias/events/TurfWarsEventListener.java @@ -15,7 +15,6 @@ import org.bukkit.event.entity.EntityShootBowEvent; import org.bukkit.event.entity.ProjectileHitEvent; import org.bukkit.event.player.PlayerMoveEvent; import org.bukkit.event.player.PlayerRespawnEvent; -import org.bukkit.inventory.ItemStack; import org.bukkit.util.Vector; import java.util.ArrayList; diff --git a/src/main/java/fun/ogre/ogredupealias/plugin/custom/items/CustomItems.java b/src/main/java/fun/ogre/ogredupealias/plugin/custom/items/CustomItems.java index 8e4b084..7a375de 100644 --- a/src/main/java/fun/ogre/ogredupealias/plugin/custom/items/CustomItems.java +++ b/src/main/java/fun/ogre/ogredupealias/plugin/custom/items/CustomItems.java @@ -1,9 +1,5 @@ package fun.ogre.ogredupealias.plugin.custom.items; -import fun.ogre.ogredupealias.plugin.custom.items.customitems.LazerGunItem; -import fun.ogre.ogredupealias.plugin.custom.items.customitems.LazerItem; -import fun.ogre.ogredupealias.plugin.custom.items.customitems.RailgunItem; -import fun.ogre.ogredupealias.plugin.custom.items.customitems.TazerItem; import fun.ogre.ogredupealias.utils.ItemUtils; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; diff --git a/src/main/java/fun/ogre/ogredupealias/plugin/funitems/VoidCharm.java b/src/main/java/fun/ogre/ogredupealias/plugin/funitems/VoidCharm.java index 14ba032..c687e61 100644 --- a/src/main/java/fun/ogre/ogredupealias/plugin/funitems/VoidCharm.java +++ b/src/main/java/fun/ogre/ogredupealias/plugin/funitems/VoidCharm.java @@ -3,10 +3,12 @@ package fun.ogre.ogredupealias.plugin.funitems; import fun.ogre.ogredupealias.OgreDupeAlias; import fun.ogre.ogredupealias.data.builder.ItemBuilder; import fun.ogre.ogredupealias.plugin.ItemPresets; -import fun.ogre.ogredupealias.utils.*; +import fun.ogre.ogredupealias.utils.ItemUtils; +import fun.ogre.ogredupealias.utils.RaycastUtils; +import fun.ogre.ogredupealias.utils.SoundPlayer; +import fun.ogre.ogredupealias.utils.Text; import fun.ogre.ogredupealias.utils.raytracers.CustomDisplayRaytracer; import org.bukkit.*; -import org.bukkit.block.Block; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.Entity; import org.bukkit.entity.LivingEntity; @@ -20,7 +22,6 @@ import org.bukkit.util.Vector; import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; public class VoidCharm { public static void handleVoidCharm(PlayerInteractEvent e) { diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 3007a9a..df03d0a 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -56,6 +56,9 @@ permissions: - oda.chat.bypass.spam - oda.chat.bypass.repeat - oda.chat.bypass.unicode + oda.commands.timer: + description: Timer to place blocks + default: op oda.chat.bypass.swear: description: Bypass anti-swear default: op @@ -156,4 +159,8 @@ commands: permission: oda.store aliases: - store - - buy \ No newline at end of file + - buy + timer: + description: Block placement timer + usage: /timer [set|stop] <~x> <~y> <~z> + permission: oda.commands.timer \ No newline at end of file