From e54f88fa5e23766d96b07ca46823a69c0fa0b5c6 Mon Sep 17 00:00:00 2001 From: Shiewk Date: Tue, 18 Jun 2024 18:01:13 +0200 Subject: [PATCH 1/3] Add Invsee command and permissions --- .../de/shiewk/smoderation/SModeration.java | 8 +++ .../smoderation/command/InvseeCommand.java | 64 +++++++++++++++++++ .../smoderation/event/InvSeeEvents.java | 29 +++++++++ .../shiewk/smoderation/util/PlayerUtil.java | 10 +++ src/main/resources/plugin.yml | 21 +++++- 5 files changed, 131 insertions(+), 1 deletion(-) create mode 100644 src/main/java/de/shiewk/smoderation/command/InvseeCommand.java create mode 100644 src/main/java/de/shiewk/smoderation/event/InvSeeEvents.java diff --git a/src/main/java/de/shiewk/smoderation/SModeration.java b/src/main/java/de/shiewk/smoderation/SModeration.java index d8075cb..bb386ae 100644 --- a/src/main/java/de/shiewk/smoderation/SModeration.java +++ b/src/main/java/de/shiewk/smoderation/SModeration.java @@ -2,6 +2,7 @@ package de.shiewk.smoderation; import de.shiewk.smoderation.command.*; import de.shiewk.smoderation.event.CustomInventoryEvents; +import de.shiewk.smoderation.event.InvSeeEvents; import de.shiewk.smoderation.listener.PunishmentListener; import de.shiewk.smoderation.storage.PunishmentContainer; import net.kyori.adventure.text.Component; @@ -26,6 +27,7 @@ public final class SModeration extends JavaPlugin { public static final TextColor PRIMARY_COLOR = TextColor.color(212, 0, 255); public static final TextColor SECONDARY_COLOR = TextColor.color(52, 143, 255); public static final TextColor INACTIVE_COLOR = NamedTextColor.GRAY; + public static final TextColor FAIL_COLOR = NamedTextColor.RED; public static final TextComponent CHAT_PREFIX = Component.text("SM \u00BB ").color(PRIMARY_COLOR); @Override @@ -39,6 +41,7 @@ public final class SModeration extends JavaPlugin { public void onEnable() { getPluginManager().registerEvents(new PunishmentListener(), this); getPluginManager().registerEvents(new CustomInventoryEvents(), this); + getPluginManager().registerEvents(new InvSeeEvents(), this); final PluginCommand mute = getCommand("mute"); assert mute != null; @@ -75,6 +78,11 @@ public final class SModeration extends JavaPlugin { unban.setExecutor(new UnbanCommand()); unban.setTabCompleter(new UnbanCommand()); + final PluginCommand invsee = getCommand("invsee"); + assert invsee != null; + invsee.setExecutor(new InvseeCommand()); + invsee.setTabCompleter(new InvseeCommand()); + container.load(SAVE_FILE); } diff --git a/src/main/java/de/shiewk/smoderation/command/InvseeCommand.java b/src/main/java/de/shiewk/smoderation/command/InvseeCommand.java new file mode 100644 index 0000000..97250c1 --- /dev/null +++ b/src/main/java/de/shiewk/smoderation/command/InvseeCommand.java @@ -0,0 +1,64 @@ +package de.shiewk.smoderation.command; + +import de.shiewk.smoderation.util.PlayerUtil; +import net.kyori.adventure.text.Component; +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabCompleter; +import org.bukkit.entity.HumanEntity; +import org.bukkit.entity.Player; +import org.bukkit.util.StringUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; + +import static de.shiewk.smoderation.SModeration.*; + +public class InvseeCommand implements CommandExecutor, TabCompleter { + + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + if (args.length < 1) { + return false; + } + if (sender instanceof HumanEntity human){ + final Player player = PlayerUtil.findOnlinePlayer(args[0]); + if (player != null) { + if (human.getUniqueId().equals(player.getUniqueId())){ + human.sendMessage(Component.text("You can't open your own inventory.").color(FAIL_COLOR)); + } else { + human.sendMessage(CHAT_PREFIX.append( + Component.text("Opening inventory of ").color(PRIMARY_COLOR) + .append(Component.text(player.getName()).color(SECONDARY_COLOR)) + .append(Component.text(".")) + )); + human.openInventory(player.getInventory()); + } + } else { + human.sendMessage(Component.text("This player is not online.").color(FAIL_COLOR)); + } + } else { + sender.sendMessage(Component.text("Only an entity that can open inventories can execute this command!").color(FAIL_COLOR)); + } + return true; + } + + @Override + public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + if (args.length > 1){ + return List.of(); + } + List available = new ArrayList<>(); + for (Player onlinePlayer : Bukkit.getOnlinePlayers()) { + available.add(onlinePlayer.getName()); + } + List completions = new ArrayList<>(); + StringUtil.copyPartialMatches(args.length > 0 ? args[0] : "", available, completions); + return completions; + } +} diff --git a/src/main/java/de/shiewk/smoderation/event/InvSeeEvents.java b/src/main/java/de/shiewk/smoderation/event/InvSeeEvents.java new file mode 100644 index 0000000..0c96c82 --- /dev/null +++ b/src/main/java/de/shiewk/smoderation/event/InvSeeEvents.java @@ -0,0 +1,29 @@ +package de.shiewk.smoderation.event; + +import org.bukkit.entity.HumanEntity; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.PlayerInventory; + +public class InvSeeEvents implements Listener { + + @EventHandler + public void onInventoryClick(InventoryClickEvent event){ + final Inventory clicked = event.getView().getTopInventory(); + if (clicked instanceof PlayerInventory inventory){ + final HumanEntity holder = inventory.getHolder(); + if (!event.getWhoClicked().hasPermission("smod.invsee.modify")){ + event.setCancelled(true); + return; + } + if (holder != null) { + if (holder.hasPermission("smod.invsee.preventmodify")){ + event.setCancelled(true); + } + } + } + } + +} diff --git a/src/main/java/de/shiewk/smoderation/util/PlayerUtil.java b/src/main/java/de/shiewk/smoderation/util/PlayerUtil.java index 590f489..8fdf034 100644 --- a/src/main/java/de/shiewk/smoderation/util/PlayerUtil.java +++ b/src/main/java/de/shiewk/smoderation/util/PlayerUtil.java @@ -5,6 +5,7 @@ import de.shiewk.smoderation.punishments.Punishment; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -45,4 +46,13 @@ public abstract class PlayerUtil { } } + public static @Nullable Player findOnlinePlayer(String name){ + for (Player onlinePlayer : Bukkit.getOnlinePlayers()) { + if (onlinePlayer.getName().equalsIgnoreCase(name)){ + return onlinePlayer; + } + } + return null; + } + } diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 20e0b93..4c85e98 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -54,6 +54,14 @@ commands: - spardon permission: smod.unban description: Unbans a banned player. + invsee: + usage: "§cUsage: /invsee " + aliases: + - sinvsee + - smodinvsee + - invs + permission: smod.invsee + description: Views the inventory of another player. permissions: smod.mute: default: op @@ -80,4 +88,15 @@ permissions: description: Allows the player to unban other players. smod.logs: default: op - description: Allows the player to view mod logs. \ No newline at end of file + description: Allows the player to view mod logs. + smod.invsee: + default: op + description: Allows the player to view other players inventories. + smod.invsee.modify: + default: op + description: Allows the player to view and modify other players inventories. + children: + - smod.invsee + smod.invsee.preventmodify: + default: op + description: When giving this permission to a player, prevents their inventory from being modified. \ No newline at end of file From 7eeb6daa46aa1717b60b308db2bb4e44bd98fc4e Mon Sep 17 00:00:00 2001 From: Shiewk Date: Tue, 18 Jun 2024 18:26:50 +0200 Subject: [PATCH 2/3] Add Enderchest see command and permissions --- .../de/shiewk/smoderation/SModeration.java | 7 ++ .../command/EnderchestSeeCommand.java | 64 +++++++++++++++++++ .../event/EnderchestSeeEvents.java | 26 ++++++++ src/main/resources/plugin.yml | 19 +++++- 4 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 src/main/java/de/shiewk/smoderation/command/EnderchestSeeCommand.java create mode 100644 src/main/java/de/shiewk/smoderation/event/EnderchestSeeEvents.java diff --git a/src/main/java/de/shiewk/smoderation/SModeration.java b/src/main/java/de/shiewk/smoderation/SModeration.java index bb386ae..63f111a 100644 --- a/src/main/java/de/shiewk/smoderation/SModeration.java +++ b/src/main/java/de/shiewk/smoderation/SModeration.java @@ -2,6 +2,7 @@ package de.shiewk.smoderation; import de.shiewk.smoderation.command.*; import de.shiewk.smoderation.event.CustomInventoryEvents; +import de.shiewk.smoderation.event.EnderchestSeeEvents; import de.shiewk.smoderation.event.InvSeeEvents; import de.shiewk.smoderation.listener.PunishmentListener; import de.shiewk.smoderation.storage.PunishmentContainer; @@ -42,6 +43,7 @@ public final class SModeration extends JavaPlugin { getPluginManager().registerEvents(new PunishmentListener(), this); getPluginManager().registerEvents(new CustomInventoryEvents(), this); getPluginManager().registerEvents(new InvSeeEvents(), this); + getPluginManager().registerEvents(new EnderchestSeeEvents(), this); final PluginCommand mute = getCommand("mute"); assert mute != null; @@ -83,6 +85,11 @@ public final class SModeration extends JavaPlugin { invsee.setExecutor(new InvseeCommand()); invsee.setTabCompleter(new InvseeCommand()); + final PluginCommand ecsee = getCommand("enderchestsee"); + assert ecsee != null; + ecsee.setExecutor(new EnderchestSeeCommand()); + ecsee.setTabCompleter(new EnderchestSeeCommand()); + container.load(SAVE_FILE); } diff --git a/src/main/java/de/shiewk/smoderation/command/EnderchestSeeCommand.java b/src/main/java/de/shiewk/smoderation/command/EnderchestSeeCommand.java new file mode 100644 index 0000000..1553896 --- /dev/null +++ b/src/main/java/de/shiewk/smoderation/command/EnderchestSeeCommand.java @@ -0,0 +1,64 @@ +package de.shiewk.smoderation.command; + +import de.shiewk.smoderation.util.PlayerUtil; +import net.kyori.adventure.text.Component; +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabCompleter; +import org.bukkit.entity.HumanEntity; +import org.bukkit.entity.Player; +import org.bukkit.util.StringUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; + +import static de.shiewk.smoderation.SModeration.*; + +public class EnderchestSeeCommand implements CommandExecutor, TabCompleter { + + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + if (args.length < 1) { + return false; + } + if (sender instanceof HumanEntity human){ + final Player player = PlayerUtil.findOnlinePlayer(args[0]); + if (player != null) { + if (human.getUniqueId().equals(player.getUniqueId())){ + human.sendMessage(Component.text("You can't open your own ender chest.").color(FAIL_COLOR)); + } else { + human.sendMessage(CHAT_PREFIX.append( + Component.text("Opening ender chest of ").color(PRIMARY_COLOR) + .append(Component.text(player.getName()).color(SECONDARY_COLOR)) + .append(Component.text(".")) + )); + human.openInventory(player.getEnderChest()); + } + } else { + human.sendMessage(Component.text("This player is not online.").color(FAIL_COLOR)); + } + } else { + sender.sendMessage(Component.text("Only an entity that can open inventories can execute this command!").color(FAIL_COLOR)); + } + return true; + } + + @Override + public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + if (args.length > 1){ + return List.of(); + } + List available = new ArrayList<>(); + for (Player onlinePlayer : Bukkit.getOnlinePlayers()) { + available.add(onlinePlayer.getName()); + } + List completions = new ArrayList<>(); + StringUtil.copyPartialMatches(args.length > 0 ? args[0] : "", available, completions); + return completions; + } +} diff --git a/src/main/java/de/shiewk/smoderation/event/EnderchestSeeEvents.java b/src/main/java/de/shiewk/smoderation/event/EnderchestSeeEvents.java new file mode 100644 index 0000000..7962e0e --- /dev/null +++ b/src/main/java/de/shiewk/smoderation/event/EnderchestSeeEvents.java @@ -0,0 +1,26 @@ +package de.shiewk.smoderation.event; + +import org.bukkit.entity.HumanEntity; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; +import org.bukkit.inventory.PlayerInventory; + +public class EnderchestSeeEvents implements Listener { + + @EventHandler + public void onInventoryClick(InventoryClickEvent event){ + final Inventory clicked = event.getView().getTopInventory(); + if (!(clicked instanceof PlayerInventory)){ + final InventoryHolder holder = clicked.getHolder(); + if (holder instanceof HumanEntity humanHolder){ + if (!event.getWhoClicked().hasPermission("smod.enderchestsee.modify")){ + event.setCancelled(true); + } + } + } + } + +} diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 4c85e98..1dd8336 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -62,6 +62,15 @@ commands: - invs permission: smod.invsee description: Views the inventory of another player. + enderchestsee: + usage: "§cUsage: /enderchestsee " + aliases: + - secsee + - senderchestsee + - ecsee + - ecs + permission: smod.enderchestsee + description: Views the ender chest of another player. permissions: smod.mute: default: op @@ -99,4 +108,12 @@ permissions: - smod.invsee smod.invsee.preventmodify: default: op - description: When giving this permission to a player, prevents their inventory from being modified. \ No newline at end of file + description: When giving this permission to a player, prevents their inventory from being modified. + smod.enderchestsee: + default: op + description: Allows the player to view other players ender chests. + smod.enderchestsee.modify: + default: op + description: Allows the player to view and modify other players ender chests. + children: + - smod.enderchestsee \ No newline at end of file From 9ca54567b2017b655b334e62c56f6da702c4f3b1 Mon Sep 17 00:00:00 2001 From: Shiewk Date: Tue, 18 Jun 2024 18:32:06 +0200 Subject: [PATCH 3/3] Update readme and version to 1.1 --- README.md | 18 ++++++++++++++++++ build.gradle | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b59f625..8b4852b 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ SModeration can be used to mute, ban, and kick players that break the rules while providing a nice interface to your moderators. It keeps track of all punishments to ensure that you get a complete overview of every rule violation on your server. +You can also modify player inventories and ender chests. If you have any feature requests, please [open an issue](https://github.com/Shiewk/SModeration/issues). @@ -10,6 +11,7 @@ If you have any feature requests, please [open an issue](https://github.com/Shie ![SMod Menu Interface](https://github.com/Shiewk/SModeration/assets/152653291/d89da0f5-61de-44cf-b59e-feea08831959) SModeration provides a nice user interface that can be used instead of chat commands. + ![SMod Menu Sort](https://github.com/Shiewk/SModeration/assets/152653291/23e3862d-0915-47bd-9c47-6d8d10f8ab69) It has helpful functions like filtering and sorting options. @@ -46,6 +48,17 @@ Example: **/modlogs playername** shows you a message in chat that tells you whet The /unmute and /unban commands only take one argument, the player name. The specified player will then be unmuted or unbanned. +### /invsee +The /invsee command can be used to view the inventory of another player. + +It takes one argument: the player name. +The player has to be online. +### /enderchestsee +The /enderchestsee command can, similarly to /invsee, be used to view the ender chest of another player. + +It takes one argument: the player name. +The player has to be online. + ## Permissions This plugin uses Bukkit permissions for commands and other actions. - **smod.mute**: Allows the player to mute other players. @@ -56,5 +69,10 @@ This plugin uses Bukkit permissions for commands and other actions. - **smod.unmute**: Allows the player to unmute other players. - **smod.unban**: Allows the player to unban other players. - **smod.logs**: Allows the player to view mod logs. +- **smod.invsee**: Allows the player to view other players inventories. +- **smod.invsee.modify**: Allows the player to view and modify other players inventories. +- **smod.invsee.preventmodify**: When giving this permission to a player, prevents their inventory from being modified. +- **smod.enderchestsee**: Allows the player to view other players ender chests. +- **smod.enderchestsee.modify**: Allows the player to view and modify other players ender chests. All of these permissions are granted by default if the player is a server operator. \ No newline at end of file diff --git a/build.gradle b/build.gradle index b429f88..31ea363 100644 --- a/build.gradle +++ b/build.gradle @@ -3,7 +3,7 @@ plugins { } group = 'de.shiewk' -version = '1.0' +version = '1.1' repositories { mavenCentral()