diff --git a/docs/commands.md b/docs/commands.md index 7685173..b7c886a 100644 --- a/docs/commands.md +++ b/docs/commands.md @@ -1,17 +1,18 @@ # SModeration commands -| Command | Description | Permission | -|----------------------------------------|------------------------------------------------------------------------------|---------------------| -| /smod | Opens the SMod menu. | smod.menu | -| /mute \ \ \ | Mutes a player so that they can't type in chat for the specified duration. | smod.mute | -| /ban \ \ \ | Bans a player so that they can't join the server for the specified duration. | smod.ban | -| /kick \ \ | Kicks a player from the server. | smod.kick | -| /modlogs | Lists a player's active punishments in chat. | smod.logs | -| /unmute | Clears a player's mute status. | smod.unmute | -| /unban | Clears a player's ban status. | smod.unban | -| /invsee \ inventory | Views another player's inventory. | smod.invsee | -| /invsee \ equipment | Views another player's equipment (armor and offhand). | smod.invsee | -| /enderchestsee | Views another player's ender chest. | smod.enderchestsee | -| /vanish | Toggles vanish mode so that other players can't see you're online. | smod.vanish | -| /vanish toggle \ | Toggles vanish mode for another player. | smod.vanish | -| /vanish list | Lists all vanished players. | smod.vanish.see | +| Command | Description | Permission | +|----------------------------------------|------------------------------------------------------------------------------|--------------------| +| /smod | Opens the SMod menu. | smod.menu | +| /mute \ \ \ | Mutes a player so that they can't type in chat for the specified duration. | smod.mute | +| /ban \ \ \ | Bans a player so that they can't join the server for the specified duration. | smod.ban | +| /kick \ \ | Kicks a player from the server. | smod.kick | +| /modlogs | Lists a player's active punishments in chat. | smod.logs | +| /unmute | Clears a player's mute status. | smod.unmute | +| /unban | Clears a player's ban status. | smod.unban | +| /invsee \ inventory | Views another player's inventory. | smod.invsee | +| /invsee \ equipment | Views another player's equipment (armor and offhand). | smod.invsee | +| /enderchestsee | Views another player's ender chest. | smod.enderchestsee | +| /vanish | Toggles vanish mode so that other players can't see you're online. | smod.vanish | +| /vanish toggle \ | Toggles vanish mode for another player. | smod.vanish | +| /vanish list | Lists all vanished players. | smod.vanish.see | +| /socialspy | Enables SocialSpy mode where you can see other player's private messages. | smod.socialspy | \ No newline at end of file diff --git a/docs/permissions.md b/docs/permissions.md index 0572df5..3c05088 100644 --- a/docs/permissions.md +++ b/docs/permissions.md @@ -19,5 +19,6 @@ | smod.enderchestsee.modify | Allows the player to view and modify other players ender chests. | | smod.vanish | Allows the player to enter and leave vanish mode. | | smod.vanish.see | Allows the player to see vanished players | +| smod.socialspy | Allows the player to enable SocialSpy | All of these permissions are granted by default if the player is a server operator. diff --git a/src/main/java/de/shiewk/smoderation/SModeration.java b/src/main/java/de/shiewk/smoderation/SModeration.java index 6bbdb7a..b2c7c07 100644 --- a/src/main/java/de/shiewk/smoderation/SModeration.java +++ b/src/main/java/de/shiewk/smoderation/SModeration.java @@ -1,6 +1,7 @@ package de.shiewk.smoderation; import de.shiewk.smoderation.command.*; +import de.shiewk.smoderation.config.SModerationConfig; import de.shiewk.smoderation.input.ChatInputListener; import de.shiewk.smoderation.listener.*; import de.shiewk.smoderation.storage.PunishmentContainer; @@ -26,6 +27,7 @@ public final class SModeration extends JavaPlugin { public static final PunishmentContainer container = new PunishmentContainer(); public static ComponentLogger LOGGER = null; public static SModeration PLUGIN = null; + public static SModerationConfig CONFIG = null; public static File SAVE_FILE = null; public static final TextColor PRIMARY_COLOR = TextColor.color(212, 0, 255); @@ -38,6 +40,7 @@ public final class SModeration extends JavaPlugin { public void onLoad() { LOGGER = getComponentLogger(); PLUGIN = this; + CONFIG = new SModerationConfig(this.getConfig(), this); SAVE_FILE = new File(this.getDataFolder().getAbsolutePath() + "/container.gz"); } @@ -49,6 +52,7 @@ public final class SModeration extends JavaPlugin { getPluginManager().registerEvents(new EnderchestSeeListener(), this); getPluginManager().registerEvents(new VanishListener(), this); getPluginManager().registerEvents(new ChatInputListener(), this); + getPluginManager().registerEvents(new SocialSpyListener(), this); registerCommand("mute", new MuteCommand()); registerCommand("ban", new BanCommand()); @@ -60,6 +64,7 @@ public final class SModeration extends JavaPlugin { registerCommand("invsee", new InvseeCommand()); registerCommand("enderchestsee", new EnderchestSeeCommand()); registerCommand("vanish", new VanishCommand()); + registerCommand("socialspy", new SocialSpyCommand()); container.load(SAVE_FILE); } diff --git a/src/main/java/de/shiewk/smoderation/command/SocialSpyCommand.java b/src/main/java/de/shiewk/smoderation/command/SocialSpyCommand.java new file mode 100644 index 0000000..bd1a677 --- /dev/null +++ b/src/main/java/de/shiewk/smoderation/command/SocialSpyCommand.java @@ -0,0 +1,32 @@ +package de.shiewk.smoderation.command; + +import de.shiewk.smoderation.listener.SocialSpyListener; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabExecutor; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +import static de.shiewk.smoderation.SModeration.CHAT_PREFIX; +import static net.kyori.adventure.text.Component.text; + +public class SocialSpyCommand implements TabExecutor { + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + final boolean enabled = SocialSpyListener.toggle(sender); + sender.sendMessage(CHAT_PREFIX.append(text("SocialSpy ").append( + enabled ? + text("enabled").color(NamedTextColor.GREEN) : + text("disabled").color(NamedTextColor.RED) + ).append(text(".")))); + return true; + } + + @Override + public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + return List.of(); + } +} diff --git a/src/main/java/de/shiewk/smoderation/config/SModerationConfig.java b/src/main/java/de/shiewk/smoderation/config/SModerationConfig.java new file mode 100644 index 0000000..3de402b --- /dev/null +++ b/src/main/java/de/shiewk/smoderation/config/SModerationConfig.java @@ -0,0 +1,30 @@ +package de.shiewk.smoderation.config; + +import de.shiewk.smoderation.SModeration; +import org.bukkit.configuration.file.FileConfiguration; + +import java.util.List; + +public class SModerationConfig { + + private final FileConfiguration config; + private final SModeration plugin; + + public SModerationConfig(FileConfiguration config, SModeration plugin) { + this.config = config; + this.plugin = plugin; + } + + public List getSocialSpyCommands(List default_){ + final String path = "socialspy-commands"; + if (!config.contains(path)){ + config.set(path, default_); + plugin.saveConfig(); + } + return config.getStringList(path); + } + + public FileConfiguration getConfig() { + return config; + } +} diff --git a/src/main/java/de/shiewk/smoderation/listener/SocialSpyListener.java b/src/main/java/de/shiewk/smoderation/listener/SocialSpyListener.java new file mode 100644 index 0000000..ad8329e --- /dev/null +++ b/src/main/java/de/shiewk/smoderation/listener/SocialSpyListener.java @@ -0,0 +1,94 @@ +package de.shiewk.smoderation.listener; + +import de.shiewk.smoderation.SModeration; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import org.bukkit.NamespacedKey; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerCommandPreprocessEvent; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.persistence.PersistentDataContainer; +import org.bukkit.persistence.PersistentDataType; + +import java.util.List; + +import static de.shiewk.smoderation.SModeration.PRIMARY_COLOR; +import static de.shiewk.smoderation.SModeration.SECONDARY_COLOR; +import static net.kyori.adventure.text.Component.text; + +public class SocialSpyListener implements Listener { + + private static final List defaultCommands = List.of( + "w", + "tell", + "msg", + "teammsg", + "tm", + "minecraft:w", + "minecraft:tell", + "minecraft:msg", + "minecraft:teammsg", + "minecraft:tm" + ); + + private static final NamespacedKey SAVE_KEY = new NamespacedKey("smoderation", "socialspy"); + private static final ObjectArrayList targets = new ObjectArrayList<>(); + + public static boolean toggle(CommandSender sender) { + boolean enabledNow = isEnabled(sender); + if (enabledNow){ + targets.remove(sender); + if (sender instanceof Player player){ + player.getPersistentDataContainer().set(SAVE_KEY, PersistentDataType.BOOLEAN, false); + } + return false; + } else { + targets.add(sender); + if (sender instanceof Player player){ + player.getPersistentDataContainer().set(SAVE_KEY, PersistentDataType.BOOLEAN, true); + } + return true; + } + } + + @EventHandler public void onPlayerJoin(PlayerJoinEvent event){ + final PersistentDataContainer pdc = event.getPlayer().getPersistentDataContainer(); + if (Boolean.TRUE.equals(pdc.get(SAVE_KEY, PersistentDataType.BOOLEAN))){ + targets.add(event.getPlayer()); + } + } + + @EventHandler public void onPlayerQuit(PlayerQuitEvent event){ + targets.remove(event.getPlayer()); + } + + public static boolean isEnabled(CommandSender sender){ + return targets.contains(sender); + } + + @EventHandler(ignoreCancelled = true, priority = EventPriority.NORMAL) + public void onPlayerSendCommand(PlayerCommandPreprocessEvent event){ + List ssCommands = SModeration.CONFIG.getSocialSpyCommands(defaultCommands); + final String message = event.getMessage(); + if (ssCommands.stream().anyMatch(str -> + message.startsWith("/"+str+" ") + || message.startsWith(str+" ") + )){ + SocialSpyListener.command(event.getPlayer(), message); + } + } + + public static void command(Player player, String command){ + for (CommandSender target : targets) { + target.sendMessage(text("[SocialSpy] ") + .append(player.displayName().colorIfAbsent(SECONDARY_COLOR)) + .append(text(": " + command).color(SECONDARY_COLOR)) + .color(PRIMARY_COLOR)); + } + } + +} diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index becbadc..65651c6 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -75,8 +75,20 @@ commands: usage: "§cUsage: /vanish list or /vanish toggle " aliases: - smvanish + - smodvanish + - v + - smv permission: smod.vanish description: Toggles vanish mode which prevents other players from seeing you're online + socialspy: + usage: "§cUsage: /socialspy" + description: Enables socialspy mode (you can see private messages of other players) + permission: smod.socialspy + aliases: + - smodsocialspy + - smsocialspy + - smss + - ss permissions: smod.mute: default: op @@ -137,4 +149,7 @@ permissions: description: Allows the player to use /vanish smod.vanish.see: default: op - description: Allows the player to see vanished players \ No newline at end of file + description: Allows the player to see vanished players + smod.socialspy: + default: op + description: Allows the player to enable SocialSpy \ No newline at end of file