diff --git a/Datura/src/main/java/me/totalfreedom/datura/cmd/AdminChatCommand.java b/Datura/src/main/java/me/totalfreedom/datura/cmd/AdminChatCommand.java index 966d2bd..6920d2f 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/cmd/AdminChatCommand.java +++ b/Datura/src/main/java/me/totalfreedom/datura/cmd/AdminChatCommand.java @@ -1,12 +1,19 @@ package me.totalfreedom.datura.cmd; +import me.totalfreedom.base.Patchwork; import me.totalfreedom.command.Commander; import me.totalfreedom.command.annotation.Base; +import me.totalfreedom.command.annotation.Info; +import me.totalfreedom.command.annotation.Permissive; +import me.totalfreedom.command.annotation.Subcommand; +import net.kyori.adventure.text.Component; import org.bukkit.command.CommandSender; -import org.bukkit.event.HandlerList; +import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; import org.jetbrains.annotations.NotNull; +@Info(name = "") +@Permissive(perm = "") public class AdminChatCommand extends Commander { @@ -25,7 +32,33 @@ public class AdminChatCommand extends Commander } @Base - public void onAdminChat(final CommandSender sender) { - + public void onAdminChat(final CommandSender sender) + { + if (!(sender instanceof Player)) return; + + final Player player = (Player) sender; + + Patchwork.getInstance() + .getAdminChatDisplay() + .toggleChat(player); + + final boolean toggled = Patchwork.getInstance() + .getAdminChatDisplay() + .isToggled(player); + + String message = "Toggled adminchat "; + + message += toggled ? "on" : "off"; + + player.sendPlainMessage(message + "."); + } + + // String here will automatically have all additional args appended to it :) + @Subcommand(permission = "patchwork.adminchat", args = {String.class}) + public void sendMessage(final CommandSender sender, final String message) + { + Patchwork.getInstance() + .getAdminChatDisplay() + .adminChatMessage(sender, Component.text(message)); } } diff --git a/Datura/src/main/java/me/totalfreedom/datura/cmd/CageCommand.java b/Datura/src/main/java/me/totalfreedom/datura/cmd/CageCommand.java index 91c12fc..375b38a 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/cmd/CageCommand.java +++ b/Datura/src/main/java/me/totalfreedom/datura/cmd/CageCommand.java @@ -21,6 +21,7 @@ package me.totalfreedom.datura.cmd; +import me.totalfreedom.base.Shortcuts; import me.totalfreedom.command.Commander; import me.totalfreedom.command.annotation.Completion; import me.totalfreedom.command.annotation.Info; @@ -68,13 +69,15 @@ public class CageCommand extends Commander { if (string.equalsIgnoreCase("on")) { - ((Datura) getPlugin()).getCager() - .cagePlayer(player.getUniqueId(), material); + Shortcuts.provideModule(Datura.class) + .getCager() + .cagePlayer(player.getUniqueId(), material); sender.sendPlainMessage("Caged " + player.getName() + "."); } else if (string.equalsIgnoreCase("off")) { - ((Datura) getPlugin()).getCager() - .uncagePlayer(player.getUniqueId()); + Shortcuts.provideModule(Datura.class) + .getCager() + .uncagePlayer(player.getUniqueId()); sender.sendPlainMessage("Liberated " + player.getName() + "."); } } diff --git a/Datura/src/main/java/me/totalfreedom/datura/cmd/HaltCommand.java b/Datura/src/main/java/me/totalfreedom/datura/cmd/HaltCommand.java index 0edca7c..a4bfd32 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/cmd/HaltCommand.java +++ b/Datura/src/main/java/me/totalfreedom/datura/cmd/HaltCommand.java @@ -2,6 +2,7 @@ package me.totalfreedom.datura.cmd; import me.totalfreedom.base.Shortcuts; import me.totalfreedom.command.Commander; +import me.totalfreedom.command.annotation.Completion; import me.totalfreedom.command.annotation.Info; import me.totalfreedom.command.annotation.Permissive; import me.totalfreedom.command.annotation.Subcommand; @@ -18,8 +19,7 @@ import org.jetbrains.annotations.NotNull; @Permissive(perm = "datura.halt") public class HaltCommand extends Commander { - private final Datura plugin = Shortcuts.provideModule(Datura.class) - .getModule(); + private final Datura plugin = Shortcuts.provideModule(Datura.class); /** * Initializes this command object. The provided {@link JavaPlugin} should be the plugin which contains the @@ -36,6 +36,8 @@ public class HaltCommand extends Commander } + @Completion(index = 0, args = {"%player%", "all"}) + @Completion(index = 1, args = {"on", "off"}) @Subcommand(permission = "datura.halt", args = {Player.class, String.class}) public void haltPlayer(final CommandSender sender, final Player target, final String toggle) { @@ -56,6 +58,7 @@ public class HaltCommand extends Commander } } + // No completion needed here since it's already registered. @Subcommand(permission = "datura.halt.all", args = {String.class, String.class}) public void haltAll(final CommandSender sender, final String all, final String toggle) { @@ -65,11 +68,8 @@ public class HaltCommand extends Commander { Bukkit.getServer() .getOnlinePlayers() - .forEach(player -> - { - plugin.getHalter() - .halt(player.getUniqueId()); - }); + .forEach(player -> plugin.getHalter() + .halt(player.getUniqueId())); final Component message = sender.name() .append(Component.text(": Freezing all players")) diff --git a/Datura/src/main/java/me/totalfreedom/datura/cmd/SmiteCommand.java b/Datura/src/main/java/me/totalfreedom/datura/cmd/SmiteCommand.java new file mode 100644 index 0000000..531f59f --- /dev/null +++ b/Datura/src/main/java/me/totalfreedom/datura/cmd/SmiteCommand.java @@ -0,0 +1,51 @@ +package me.totalfreedom.datura.cmd; + +import me.totalfreedom.command.Commander; +import me.totalfreedom.command.annotation.Completion; +import me.totalfreedom.command.annotation.Info; +import me.totalfreedom.command.annotation.Permissive; +import me.totalfreedom.command.annotation.Subcommand; +import org.bukkit.Location; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.plugin.java.JavaPlugin; +import org.jetbrains.annotations.NotNull; + +@Info(name = "smite", description = "Smite a player.", usage = "/smite ", aliases = {"sm"}) +@Permissive(perm = "datura.smite") +public class SmiteCommand extends Commander +{ + /** + * Initializes this command object. The provided {@link JavaPlugin} should be the plugin which contains the + * command. + *

+ * This constructor will automatically register all subcommands and completions for this command. It will also + * automatically infer all required information from the provided {@link Info} and {@link Permissive} annotations. + * + * @param plugin The plugin which contains this command. + */ + protected SmiteCommand(@NotNull final JavaPlugin plugin) + { + super(plugin); + } + + @Subcommand(permission = "datura.smite", args = {Player.class}) + @Completion(index = 0, args = {"%player%"}) + public void smite(final CommandSender sender, final Player player) + { + final double size = 5D; + for (int i = 0; i < size * size * size; i++) + { + final double x = i % size; + final double y = (i / size) % size; + final double z = (i / size / size) % size; + + final Location location = player.getLocation() + .clone() + .add(x - size / 2, y - size / 2, z - size / 2); + + player.getWorld() + .strikeLightning(location); + } + } +} diff --git a/Datura/src/main/java/me/totalfreedom/datura/punishment/Halter.java b/Datura/src/main/java/me/totalfreedom/datura/punishment/Halter.java index af61b9b..5ffff30 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/punishment/Halter.java +++ b/Datura/src/main/java/me/totalfreedom/datura/punishment/Halter.java @@ -27,7 +27,8 @@ public class Halter implements Listener this.haltedPlayers.remove(uuid); } - public void clear() { + public void clear() + { this.haltedPlayers.clear(); } diff --git a/Datura/src/main/java/me/totalfreedom/datura/user/SimpleUserData.java b/Datura/src/main/java/me/totalfreedom/datura/user/SimpleUserData.java index 4a391c6..c8d95e7 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/user/SimpleUserData.java +++ b/Datura/src/main/java/me/totalfreedom/datura/user/SimpleUserData.java @@ -230,16 +230,16 @@ public class SimpleUserData implements UserData return hasCustomACFormat; } + @Override + public AdminChatFormat getCustomACFormat() + { + return AdminChatFormat.deserialize(customACFormat); + } + @Override public void setCustomACFormat(final String format) { this.hasCustomACFormat = format.equals(AdminChatFormat.DEFAULT.serialize()); this.customACFormat = format; } - - @Override - public AdminChatFormat getCustomACFormat() - { - return AdminChatFormat.deserialize(customACFormat); - } } diff --git a/Patchwork/src/main/java/me/totalfreedom/base/Patchwork.java b/Patchwork/src/main/java/me/totalfreedom/base/Patchwork.java index 2ee663b..e12ed34 100644 --- a/Patchwork/src/main/java/me/totalfreedom/base/Patchwork.java +++ b/Patchwork/src/main/java/me/totalfreedom/base/Patchwork.java @@ -1,5 +1,6 @@ package me.totalfreedom.base; +import me.totalfreedom.display.adminchat.AdminChatDisplay; import me.totalfreedom.event.EventBus; import me.totalfreedom.service.FreedomExecutor; import me.totalfreedom.service.SubscriptionProvider; @@ -23,6 +24,10 @@ public class Patchwork extends JavaPlugin * The {@link FreedomExecutor} for this plugin. */ private final FreedomExecutor executor = new FreedomExecutor(); + /** + * The {@link AdminChatDisplay} for this plugin. + */ + private final AdminChatDisplay acdisplay = new AdminChatDisplay(); /** * Provides this plugin instance through a safe static method. This is effectively the same thing as using @@ -89,4 +94,15 @@ public class Patchwork extends JavaPlugin { return eventBus; } + + /** + * Gets the {@link AdminChatDisplay} for this plugin. The AdminChatDisplay is used to display messages sent in + * adminchat. + * + * @return the {@link AdminChatDisplay} + */ + public AdminChatDisplay getAdminChatDisplay() + { + return acdisplay; + } } diff --git a/Patchwork/src/main/java/me/totalfreedom/base/Shortcuts.java b/Patchwork/src/main/java/me/totalfreedom/base/Shortcuts.java index d3d7bf7..0cb80e0 100644 --- a/Patchwork/src/main/java/me/totalfreedom/base/Shortcuts.java +++ b/Patchwork/src/main/java/me/totalfreedom/base/Shortcuts.java @@ -1,15 +1,31 @@ package me.totalfreedom.base; -import me.totalfreedom.provider.ModuleProvider; +import me.totalfreedom.api.Context; +import me.totalfreedom.user.User; +import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; public final class Shortcuts { - private Shortcuts() { + private Shortcuts() + { throw new AssertionError(); } - public static ModuleProvider provideModule(final Class pluginClass) { - return Patchwork.getInstance().getRegistrations().getModuleRegistry().getProvider(pluginClass); + public static T provideModule(final Class pluginClass) + { + return Patchwork.getInstance() + .getRegistrations() + .getModuleRegistry() + .getProvider(pluginClass) + .getModule(); + } + + public static User getUser(final Player player) + { + return Patchwork.getInstance() + .getRegistrations() + .getUserRegistry() + .getUser(player); } } diff --git a/Patchwork/src/main/java/me/totalfreedom/command/BukkitDelegate.java b/Patchwork/src/main/java/me/totalfreedom/command/BukkitDelegate.java index c122527..6da4d29 100644 --- a/Patchwork/src/main/java/me/totalfreedom/command/BukkitDelegate.java +++ b/Patchwork/src/main/java/me/totalfreedom/command/BukkitDelegate.java @@ -69,7 +69,7 @@ public final class BukkitDelegate extends Command implements PluginIdentifiableC @NotNull final String commandLabel, @NotNull final String[] args) { - if (sender instanceof ConsoleCommandSender && noConsole) + if (!(sender instanceof Player) && noConsole) { sender.sendMessage(Component.text("This command can only be run by players.")); return true; @@ -101,8 +101,13 @@ public final class BukkitDelegate extends Command implements PluginIdentifiableC { try { - command.getBaseMethod() - .invoke(command, sender); + if (noConsole) { + command.getBaseMethod() + .invoke(command, (Player)sender); + } else { + command.getBaseMethod() + .invoke(command, sender); + } } catch (Exception ex) { FreedomLogger.getLogger("Patchwork") @@ -154,9 +159,15 @@ public final class BukkitDelegate extends Command implements PluginIdentifiableC } try { - command.getSubcommands() - .get(node) - .invoke(command, sender, objects); + if (noConsole) { + command.getSubcommands() + .get(node) + .invoke(command, (Player)sender, objects); + } else { + command.getSubcommands() + .get(node) + .invoke(command, sender, objects); + } } catch (Exception ex) { FreedomLogger.getLogger("Patchwork") diff --git a/Patchwork/src/main/java/me/totalfreedom/display/adminchat/AdminChatDisplay.java b/Patchwork/src/main/java/me/totalfreedom/display/adminchat/AdminChatDisplay.java index 06ec6d9..1c27cff 100644 --- a/Patchwork/src/main/java/me/totalfreedom/display/adminchat/AdminChatDisplay.java +++ b/Patchwork/src/main/java/me/totalfreedom/display/adminchat/AdminChatDisplay.java @@ -3,9 +3,11 @@ package me.totalfreedom.display.adminchat; import io.papermc.paper.event.player.AsyncChatEvent; import me.totalfreedom.base.Patchwork; import me.totalfreedom.base.Shortcuts; -import me.totalfreedom.data.UserRegistry; +import me.totalfreedom.security.Groups; import me.totalfreedom.user.UserData; +import net.kyori.adventure.text.Component; import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; @@ -19,10 +21,12 @@ import java.util.UUID; public class AdminChatDisplay { + protected static final String ACPERM = "patchwork.adminchat"; private final Map adminChatFormat = new HashMap<>(); private final Set toggledChat = new HashSet<>(); - public AdminChatDisplay() { + public AdminChatDisplay() + { new ACListener(this); } @@ -61,6 +65,39 @@ public class AdminChatDisplay return adminChatFormat; } + public boolean isToggled(final Player player) + { + return toggledChat.contains(player.getUniqueId()); + } + + public void toggleChat(final Player player) + { + if (toggledChat.contains(player.getUniqueId())) + { + toggledChat.remove(player.getUniqueId()); + } else + { + toggledChat.add(player.getUniqueId()); + } + } + + public void adminChatMessage(final CommandSender sender, final Component message) + { + Bukkit.getOnlinePlayers() + .forEach(player -> + { + if (player.hasPermission(ACPERM)) + { + final Component formatted = Component.empty(); + formatted.append(getFormat(player).format(sender.getName(), Groups.fromSender(sender))) + .append(Component.space()) + .append(message); + + player.sendMessage(formatted); + } + }); + } + public static final class ACListener implements Listener { private final AdminChatDisplay display; @@ -69,26 +106,34 @@ public class AdminChatDisplay { this.display = display; Bukkit.getPluginManager() - .registerEvents(this, Shortcuts.provideModule(Patchwork.class) - .getModule()); + .registerEvents(this, Shortcuts.provideModule(Patchwork.class)); } @EventHandler - public void playerChat(final AsyncChatEvent event) { - if (display.getPlayers().contains(event.getPlayer().getUniqueId())) { + public void playerChat(final AsyncChatEvent event) + { + if (display.isToggled(event.getPlayer())) + { event.setCancelled(true); - + display.adminChatMessage(event.getPlayer(), event.message()); } } @EventHandler - public void playerJoin(final PlayerJoinEvent event) { + public void playerJoin(final PlayerJoinEvent event) + { final Player player = event.getPlayer(); - if (player.hasPermission("patchwork.adminchat")) { - final UserData data = Patchwork.getInstance().getRegistrations().getUserRegistry().fromPlayer(player); - if (data.hasCustomACFormat()) { + if (player.hasPermission(ACPERM)) + { + final UserData data = Patchwork.getInstance() + .getRegistrations() + .getUserRegistry() + .fromPlayer(player); + if (data.hasCustomACFormat()) + { display.addPlayer(player, data.getCustomACFormat()); - } else { + } else + { display.addPlayer(player, AdminChatFormat.DEFAULT); } } diff --git a/Patchwork/src/main/java/me/totalfreedom/display/adminchat/AdminChatFormat.java b/Patchwork/src/main/java/me/totalfreedom/display/adminchat/AdminChatFormat.java index b8dd757..5580c9e 100644 --- a/Patchwork/src/main/java/me/totalfreedom/display/adminchat/AdminChatFormat.java +++ b/Patchwork/src/main/java/me/totalfreedom/display/adminchat/AdminChatFormat.java @@ -25,15 +25,25 @@ public final class AdminChatFormat this.rank = Component.text(builder.openBracket(), builder.bracketColor()) .append(Component.text("%rank%", builder.rankColor())) .append(Component.text(builder.closeBracket(), builder.bracketColor())); - this.chatSplitter = Component.text(builder.chatSplitter(), NamedTextColor.WHITE); - this.fullFormat = prefix.append(Component.space()) + // Nice formatting :( + if (builder.chatSplitter() + .equals(":")) + { + this.chatSplitter = Component.text(":", NamedTextColor.WHITE); + } else + { + this.chatSplitter = Component.space() + .append(Component.text(builder.chatSplitter(), NamedTextColor.WHITE)); + } + + // Formatting because []: is cleaner than [] :, but anything else such as [] >> or [] -> looks better with the space between. + this.fullFormat = prefix.appendSpace() .append(userName) - .append(Component.space()) + .appendSpace() .append(rank) - .append(Component.space()) .append(chatSplitter) - .append(Component.space()); + .appendSpace(); } public static AdminChatFormat deserialize(final String serialized) diff --git a/Patchwork/src/main/java/me/totalfreedom/security/Groups.java b/Patchwork/src/main/java/me/totalfreedom/security/Groups.java index 2f92fa3..105a54a 100644 --- a/Patchwork/src/main/java/me/totalfreedom/security/Groups.java +++ b/Patchwork/src/main/java/me/totalfreedom/security/Groups.java @@ -1,20 +1,30 @@ package me.totalfreedom.security; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + public enum Groups { - NON_OP("patchwork.group.non-op"), - OP("patchwork.group.op"), - SUPER_ADMIN("patchwork.group.super"), - SENIOR_ADMIN("patchwork.group.senior"), - DEVELOPER("patchwork.group.dev"), - EXECUTIVE("patchwork.group.exec"), - OWNER("patchwork.group.owner"); + NON_OP("patchwork.group.non-op", "Non-OP"), + OP("patchwork.group.op", "OP"), + SUPER_ADMIN("patchwork.group.super", "Super Admin"), + SENIOR_ADMIN("patchwork.group.senior", "Senior Admin"), + DEVELOPER("patchwork.group.dev", "Developer"), + EXECUTIVE("patchwork.group.exec", "Executive"), + OWNER("patchwork.group.owner", "Owner"); private final String permission; + private final String name; - Groups(final String permission) + Groups(final String permission, final String name) { this.permission = permission; + this.name = name; + } + + public String getName() + { + return this.name; } public String getPermission() @@ -27,4 +37,19 @@ public enum Groups { return this.permission; } + + public static String fromPlayer(final Player player) { + for (final Groups group : values()) { + if (player.hasPermission(group.getPermission())) { + return group.getName(); + } + } + return Groups.NON_OP.getName(); + } + + public static String fromSender(final CommandSender sender) { + if (!(sender instanceof Player)) return "CONSOLE"; + + return fromPlayer((Player) sender); + } }