From 020275f3785c46e0a3d29b1f9e318d08d73fc94e Mon Sep 17 00:00:00 2001
From: amyavi <144570677+amyavi@users.noreply.github.com>
Date: Sun, 23 Jun 2024 12:41:24 -0300
Subject: [PATCH 01/14] style: match file structure with Extras
---
.gitignore | 2 ++
README.md | 6 +++---
suppressions.xml | 4 +++-
3 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/.gitignore b/.gitignore
index f845591..d3ee570 100755
--- a/.gitignore
+++ b/.gitignore
@@ -6,3 +6,5 @@ target/
.classpath
.project
*.iml
+.theia/
+run/
\ No newline at end of file
diff --git a/README.md b/README.md
index 57d3662..bb7b021 100644
--- a/README.md
+++ b/README.md
@@ -6,9 +6,9 @@ The plugin is created for the Kaboom server.
## Commands
-| Command | Alias | Permission | Description |
-| ------- | ----- | ---------- | ----------- |
-|/commandspy | /c, /cs, /cspy | commandspy.command | Allows you to spy on players' commands|
+| Command | Alias | Permission | Description |
+|-------------|----------------|--------------------|----------------------------------------|
+| /commandspy | /c, /cs, /cspy | commandspy.command | Allows you to spy on players' commands |
## Compiling
diff --git a/suppressions.xml b/suppressions.xml
index 8990963..30ced2c 100644
--- a/suppressions.xml
+++ b/suppressions.xml
@@ -5,4 +5,6 @@
-
+
+
+
\ No newline at end of file
From d5c402cfc7cc9242f647b99416be938956964383 Mon Sep 17 00:00:00 2001
From: amyavi <144570677+amyavi@users.noreply.github.com>
Date: Sun, 23 Jun 2024 12:51:26 -0300
Subject: [PATCH 02/14] chore: bump used actions, checkstyle & paper
---
.github/workflows/main.yml | 9 +++++----
pom.xml | 4 ++--
src/main/resources/plugin.yml | 5 ++---
3 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index d5644a3..3af4259 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -11,14 +11,14 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
- - uses: actions/setup-java@v3
+ - uses: actions/checkout@v4
+ - uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: 17
- name: Cache maven packages to speed up build
- uses: actions/cache@v3
+ uses: actions/cache@v4
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
@@ -27,7 +27,8 @@ jobs:
- name: Build with Maven
run: mvn -B package --file pom.xml
- - uses: actions/upload-artifact@v3
+ - uses: actions/upload-artifact@v4
with:
name: CommandSpy
path: target/CommandSpy.jar
+ compression-level: 0
diff --git a/pom.xml b/pom.xml
index 8c686a8..15ddd18 100644
--- a/pom.xml
+++ b/pom.xml
@@ -15,7 +15,7 @@
io.papermc.paper
paper-api
- 1.18.2-R0.1-SNAPSHOT
+ 1.19.4-R0.1-SNAPSHOT
provided
@@ -33,7 +33,7 @@
org.apache.maven.plugins
maven-checkstyle-plugin
- 3.1.2
+ 3.4.0
checkstyle
diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml
index f95cb20..af086de 100644
--- a/src/main/resources/plugin.yml
+++ b/src/main/resources/plugin.yml
@@ -1,13 +1,12 @@
name: CommandSpy
main: pw.kaboom.commandspy.Main
description: Plugin that allows you to spy on players' commands.
-api-version: 1.13
+api-version: '1.19'
version: master
folia-supported: true
commands:
commandspy:
- aliases: [c,cs,cspy]
+ aliases: [ c, cs, cspy ]
description: Allows you to spy on players' commands
- usage: /commandspy
permission: commandspy.command
From 130f06fe5ac02c71cb14730b2fc14f3cf1c314c4 Mon Sep 17 00:00:00 2001
From: amyavi <144570677+amyavi@users.noreply.github.com>
Date: Sun, 23 Jun 2024 12:54:02 -0300
Subject: [PATCH 03/14] fix: use MONITOR priority for the command event
This hides commands from players that are being controlled with
iControlU.
---
src/main/java/pw/kaboom/commandspy/Main.java | 9 ++-------
1 file changed, 2 insertions(+), 7 deletions(-)
diff --git a/src/main/java/pw/kaboom/commandspy/Main.java b/src/main/java/pw/kaboom/commandspy/Main.java
index 7aab4d7..8e7e48c 100644
--- a/src/main/java/pw/kaboom/commandspy/Main.java
+++ b/src/main/java/pw/kaboom/commandspy/Main.java
@@ -1,6 +1,5 @@
package pw.kaboom.commandspy;
-import java.util.Set;
import java.util.UUID;
import org.bukkit.Bukkit;
@@ -11,10 +10,10 @@ import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.SignChangeEvent;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
-import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
@@ -71,12 +70,8 @@ public final class Main extends JavaPlugin implements CommandExecutor, Listener
return true;
}
- @EventHandler
+ @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
void onPlayerCommandPreprocess(final PlayerCommandPreprocessEvent event) {
- if (event.isCancelled()) {
- return;
- }
-
final Player player = event.getPlayer();
final NamedTextColor color = getTextColor(player);
final Component message = Component.text(player.getName(), color)
From 1ca2ffc91aea7c593f32d771ba754cfb0fbbfc43 Mon Sep 17 00:00:00 2001
From: amyavi <144570677+amyavi@users.noreply.github.com>
Date: Sun, 23 Jun 2024 13:07:12 -0300
Subject: [PATCH 04/14] perf: opt-out of paper plugin remapping
Since we don't use NMS, this is harmless. Saves about 100ms of startup
time on first boot on my machine
---
pom.xml | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/pom.xml b/pom.xml
index 15ddd18..6dfe236 100644
--- a/pom.xml
+++ b/pom.xml
@@ -30,6 +30,18 @@
${project.artifactId}
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 3.4.2
+
+
+
+ mojang
+
+
+
+
org.apache.maven.plugins
maven-checkstyle-plugin
From 3de6d8d6c96d69ee03c54c25e7f5d0dca8b56340 Mon Sep 17 00:00:00 2001
From: amyavi <144570677+amyavi@users.noreply.github.com>
Date: Sun, 23 Jun 2024 13:18:37 -0300
Subject: [PATCH 05/14] style: misc style fixes
Finalizes everything, adds @NotNull to onCommand parameters, and uses
pattern matching for the onCommand instanceof Player check.
---
src/main/java/pw/kaboom/commandspy/Main.java | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/src/main/java/pw/kaboom/commandspy/Main.java b/src/main/java/pw/kaboom/commandspy/Main.java
index 8e7e48c..10692b4 100644
--- a/src/main/java/pw/kaboom/commandspy/Main.java
+++ b/src/main/java/pw/kaboom/commandspy/Main.java
@@ -6,7 +6,6 @@ import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
-import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@@ -17,6 +16,7 @@ import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.plugin.java.JavaPlugin;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
+import org.jetbrains.annotations.NotNull;
public final class Main extends JavaPlugin implements CommandExecutor, Listener {
private FileConfiguration config;
@@ -44,19 +44,18 @@ public final class Main extends JavaPlugin implements CommandExecutor, Listener
if (config.contains(player.getUniqueId().toString())) {
return NamedTextColor.YELLOW;
}
+
return NamedTextColor.AQUA;
}
@Override
- public boolean onCommand(final CommandSender sender, final Command cmd, final String label,
- final String[] args) {
- if (sender instanceof ConsoleCommandSender) {
+ public boolean onCommand(final @NotNull CommandSender sender, final @NotNull Command cmd,
+ final @NotNull String label, final String[] args) {
+ if (!(sender instanceof final Player player)) {
sender.sendMessage(Component.text("Command has to be run by a player"));
return true;
}
- final Player player = (Player) sender;
-
if (args.length >= 1 && "on".equalsIgnoreCase(args[0])) {
enableCommandSpy(player);
return true;
@@ -78,31 +77,32 @@ public final class Main extends JavaPlugin implements CommandExecutor, Listener
.append(Component.text(": "))
.append(Component.text(event.getMessage()));
- for (String uuidString : config.getKeys(false)) {
+ for (final String uuidString : config.getKeys(false)) {
final UUID uuid = UUID.fromString(uuidString);
final Player recipient = Bukkit.getPlayer(uuid);
if (recipient == null) {
continue;
}
+
recipient.sendMessage(message);
}
}
- @EventHandler
+ @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
void onSignChange(final SignChangeEvent event) {
final Player player = event.getPlayer();
final NamedTextColor color = getTextColor(player);
Component message = Component.text(player.getName(), color)
.append(Component.text(" created a sign with contents:"));
- for (Component line : event.lines()) {
+ for (final Component line : event.lines()) {
message = message
.append(Component.text("\n "))
.append(line);
}
- for (String uuidString : config.getKeys(false)) {
+ for (final String uuidString : config.getKeys(false)) {
final UUID uuid = UUID.fromString(uuidString);
final Player recipient = Bukkit.getPlayer(uuid);
From 7635411849bcb686516e413a9c995ad49636b32a Mon Sep 17 00:00:00 2001
From: amyavi <144570677+amyavi@users.noreply.github.com>
Date: Sun, 23 Jun 2024 16:22:21 -0300
Subject: [PATCH 06/14] perf: rewrite config logic; use binary format
This was done so spamming CommandSpy commands wouldn't lag the server as
much, and having a bunch of players turn on CommandSpy wouldn't fill up
the server storage.
---
.../pw/kaboom/commandspy/CommandSpyState.java | 126 ++++++++++++++++++
src/main/java/pw/kaboom/commandspy/Main.java | 48 +++----
2 files changed, 145 insertions(+), 29 deletions(-)
create mode 100644 src/main/java/pw/kaboom/commandspy/CommandSpyState.java
diff --git a/src/main/java/pw/kaboom/commandspy/CommandSpyState.java b/src/main/java/pw/kaboom/commandspy/CommandSpyState.java
new file mode 100644
index 0000000..97e8542
--- /dev/null
+++ b/src/main/java/pw/kaboom/commandspy/CommandSpyState.java
@@ -0,0 +1,126 @@
+package pw.kaboom.commandspy;
+
+import com.google.common.io.Files;
+import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
+import net.kyori.adventure.text.Component;
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Player;
+import org.bukkit.plugin.java.JavaPlugin;
+import org.jetbrains.annotations.NotNull;
+import org.slf4j.Logger;
+
+import java.io.*;
+import java.nio.ByteBuffer;
+import java.util.Collection;
+import java.util.UUID;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.locks.StampedLock;
+import java.util.stream.Collectors;
+
+public final class CommandSpyState {
+ private static final Logger LOGGER = JavaPlugin.getPlugin(Main.class).getSLF4JLogger();
+
+ private final ObjectOpenHashSet users = new ObjectOpenHashSet<>();
+ private final StampedLock usersLock = new StampedLock();
+ private final AtomicBoolean dirty = new AtomicBoolean();
+ private final File file;
+
+ public CommandSpyState(final @NotNull File file) {
+ this.file = file;
+
+ try {
+ this.load();
+ } catch (final FileNotFoundException exception) {
+ try {
+ this.save(); // Create file if it doesn't exist
+ } catch (IOException ignored) {}
+ } catch (final IOException exception) {
+ LOGGER.error("Failed to load state file:", exception);
+ }
+ }
+
+ private void load() throws IOException {
+ final InputStream reader = new BufferedInputStream(new FileInputStream(this.file));
+
+ int read;
+ final ByteBuffer buffer = ByteBuffer.wrap(new byte[16]);
+
+ // Loop until we read less than 16 bytes
+ while ((read = reader.readNBytes(buffer.array(), 0, 16)) == 16) {
+ this.users.add(new UUID(buffer.getLong(0), buffer.getLong(8)));
+ }
+
+ reader.close();
+ if (read != 0) {
+ throw new IOException("Found " + read + " bytes extra whilst reading file");
+ }
+ }
+
+ private void save() throws IOException {
+ Files.createParentDirs(this.file);
+ final OutputStream writer = new BufferedOutputStream(new FileOutputStream(this.file));
+ final ByteBuffer buffer = ByteBuffer.wrap(new byte[16]);
+
+ final long stamp = this.usersLock.readLock();
+ for (final UUID uuid: this.users) {
+ buffer.putLong(0, uuid.getMostSignificantBits());
+ buffer.putLong(8, uuid.getLeastSignificantBits());
+ writer.write(buffer.array());
+ }
+ this.usersLock.unlockRead(stamp);
+
+ writer.flush();
+ writer.close();
+ }
+
+ public void trySave() {
+ // If the state is not dirty, then we don't need to do anything.
+ if (!this.dirty.compareAndExchange(true, false)) {
+ return;
+ }
+
+ try {
+ this.save();
+ } catch (final IOException exception) {
+ LOGGER.error("Failed to save state file:", exception);
+ }
+ }
+
+ public boolean getCommandSpyState(final @NotNull UUID playerUUID) {
+ final long stamp = this.usersLock.readLock();
+ final boolean result = this.users.contains(playerUUID);
+ this.usersLock.unlockRead(stamp);
+
+ return result;
+ }
+
+ public void setCommandSpyState(final @NotNull UUID playerUUID, final boolean state) {
+ final long stamp = this.usersLock.writeLock();
+
+ final boolean dirty;
+ if (state) {
+ dirty = this.users.add(playerUUID);
+ } else {
+ dirty = this.users.remove(playerUUID);
+ }
+
+ this.usersLock.unlockWrite(stamp);
+ if (dirty) {
+ this.dirty.set(true);
+ }
+ }
+
+ public void broadcastSpyMessage(final @NotNull Component message) {
+ // Raw access here, so we can get more performance by not locking/unlocking over and over
+ final long stamp = this.usersLock.readLock();
+ final Collection players = Bukkit.getOnlinePlayers()
+ .stream()
+ .filter(p -> this.users.contains(p.getUniqueId()))
+ .collect(Collectors.toUnmodifiableSet());
+ this.usersLock.unlockRead(stamp);
+
+ for (final Player recipient : players) {
+ recipient.sendMessage(message);
+ }
+ }
+}
diff --git a/src/main/java/pw/kaboom/commandspy/Main.java b/src/main/java/pw/kaboom/commandspy/Main.java
index 10692b4..9679dc5 100644
--- a/src/main/java/pw/kaboom/commandspy/Main.java
+++ b/src/main/java/pw/kaboom/commandspy/Main.java
@@ -1,12 +1,11 @@
package pw.kaboom.commandspy;
-import java.util.UUID;
+import java.io.File;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
-import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
@@ -19,29 +18,36 @@ import net.kyori.adventure.text.format.NamedTextColor;
import org.jetbrains.annotations.NotNull;
public final class Main extends JavaPlugin implements CommandExecutor, Listener {
- private FileConfiguration config;
+ private CommandSpyState config;
@Override
public void onEnable() {
- config = getConfig();
+ this.config = new CommandSpyState(new File(this.getDataFolder(), "state.bin"));
+
this.getCommand("commandspy").setExecutor(this);
this.getServer().getPluginManager().registerEvents(this, this);
+
+ // Save the config every 30 seconds
+ Bukkit.getScheduler().runTaskTimerAsynchronously(this, this.config::trySave, 600L, 600L);
+ }
+
+ @Override
+ public void onDisable() {
+ this.config.trySave();
}
private void enableCommandSpy(final Player player) {
- config.set(player.getUniqueId().toString(), true);
- saveConfig();
+ this.config.setCommandSpyState(player.getUniqueId(), true);
player.sendMessage(Component.text("Successfully enabled CommandSpy"));
}
private void disableCommandSpy(final Player player) {
- config.set(player.getUniqueId().toString(), null);
- saveConfig();
+ this.config.setCommandSpyState(player.getUniqueId(), false);
player.sendMessage(Component.text("Successfully disabled CommandSpy"));
}
private NamedTextColor getTextColor(final Player player) {
- if (config.contains(player.getUniqueId().toString())) {
+ if (this.config.getCommandSpyState(player.getUniqueId())) {
return NamedTextColor.YELLOW;
}
@@ -61,7 +67,7 @@ public final class Main extends JavaPlugin implements CommandExecutor, Listener
return true;
}
if ((args.length >= 1 && "off".equalsIgnoreCase(args[0]))
- || config.contains(player.getUniqueId().toString())) {
+ || this.config.getCommandSpyState(player.getUniqueId())) {
disableCommandSpy(player);
return true;
}
@@ -73,20 +79,12 @@ public final class Main extends JavaPlugin implements CommandExecutor, Listener
void onPlayerCommandPreprocess(final PlayerCommandPreprocessEvent event) {
final Player player = event.getPlayer();
final NamedTextColor color = getTextColor(player);
+
final Component message = Component.text(player.getName(), color)
.append(Component.text(": "))
.append(Component.text(event.getMessage()));
- for (final String uuidString : config.getKeys(false)) {
- final UUID uuid = UUID.fromString(uuidString);
- final Player recipient = Bukkit.getPlayer(uuid);
-
- if (recipient == null) {
- continue;
- }
-
- recipient.sendMessage(message);
- }
+ this.config.broadcastSpyMessage(message);
}
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
@@ -102,14 +100,6 @@ public final class Main extends JavaPlugin implements CommandExecutor, Listener
.append(line);
}
- for (final String uuidString : config.getKeys(false)) {
- final UUID uuid = UUID.fromString(uuidString);
- final Player recipient = Bukkit.getPlayer(uuid);
-
- if (recipient == null) {
- continue;
- }
- recipient.sendMessage(message);
- }
+ this.config.broadcastSpyMessage(message);
}
}
From c6351f3f5447f61a71f2e14fce16e60770e688a1 Mon Sep 17 00:00:00 2001
From: amyavi <144570677+amyavi@users.noreply.github.com>
Date: Sun, 23 Jun 2024 18:42:10 -0300
Subject: [PATCH 07/14] feat: allow players to disable/enable cspy for others
---
src/main/java/pw/kaboom/commandspy/Main.java | 124 +++++++++++++++----
src/main/resources/plugin.yml | 1 +
2 files changed, 101 insertions(+), 24 deletions(-)
diff --git a/src/main/java/pw/kaboom/commandspy/Main.java b/src/main/java/pw/kaboom/commandspy/Main.java
index 9679dc5..62da442 100644
--- a/src/main/java/pw/kaboom/commandspy/Main.java
+++ b/src/main/java/pw/kaboom/commandspy/Main.java
@@ -1,6 +1,7 @@
package pw.kaboom.commandspy;
import java.io.File;
+import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
@@ -27,7 +28,7 @@ public final class Main extends JavaPlugin implements CommandExecutor, Listener
this.getCommand("commandspy").setExecutor(this);
this.getServer().getPluginManager().registerEvents(this, this);
- // Save the config every 30 seconds
+ // Save the state every 30 seconds
Bukkit.getScheduler().runTaskTimerAsynchronously(this, this.config::trySave, 600L, 600L);
}
@@ -36,14 +37,26 @@ public final class Main extends JavaPlugin implements CommandExecutor, Listener
this.config.trySave();
}
- private void enableCommandSpy(final Player player) {
- this.config.setCommandSpyState(player.getUniqueId(), true);
- player.sendMessage(Component.text("Successfully enabled CommandSpy"));
- }
+ private void updateCommandSpyState(final @NotNull Player target,
+ final @NotNull CommandSender source, final boolean state) {
+ this.config.setCommandSpyState(target.getUniqueId(), state);
- private void disableCommandSpy(final Player player) {
- this.config.setCommandSpyState(player.getUniqueId(), false);
- player.sendMessage(Component.text("Successfully disabled CommandSpy"));
+ final Component stateString = Component.text(state ? "enabled" : "disabled");
+
+ target.sendMessage(Component.empty()
+ .append(Component.text("Successfully "))
+ .append(stateString)
+ .append(Component.text(" CommandSpy.")));
+
+ if (source != target) {
+ source.sendMessage(Component.empty()
+ .append(Component.text("Successfully "))
+ .append(stateString)
+ .append(Component.text(" CommandSpy for "))
+ .append(target.name())
+ .append(Component.text("."))
+ );
+ }
}
private NamedTextColor getTextColor(final Player player) {
@@ -57,21 +70,54 @@ public final class Main extends JavaPlugin implements CommandExecutor, Listener
@Override
public boolean onCommand(final @NotNull CommandSender sender, final @NotNull Command cmd,
final @NotNull String label, final String[] args) {
- if (!(sender instanceof final Player player)) {
- sender.sendMessage(Component.text("Command has to be run by a player"));
- return true;
+
+ Player target = null;
+ Boolean state = null;
+
+ switch (args.length) {
+ case 0 -> {}
+ case 1, 2 -> {
+ // Get the last argument as a state. Fail if we have 2 arguments.
+ state = getState(args[args.length - 1]);
+ if (state != null && args.length == 1) {
+ break;
+ } else if (state == null && args.length == 2) {
+ return false;
+ }
+
+ // Get the first argument as a player. Fail if it can't be found.
+ target = getPlayer(args[0]);
+ if (target != null) {
+ break;
+ }
+
+ sender.sendMessage(Component.empty()
+ .append(Component.text("Player \""))
+ .append(Component.text(args[0]))
+ .append(Component.text("\" not found"))
+ );
+ return true;
+ }
+ default -> {
+ return false;
+ }
}
- if (args.length >= 1 && "on".equalsIgnoreCase(args[0])) {
- enableCommandSpy(player);
- return true;
+ if (target == null) {
+ if (!(sender instanceof final Player player)) {
+ sender.sendMessage(Component.text("Command has to be run by a player"));
+ return true;
+ }
+
+ target = player;
}
- if ((args.length >= 1 && "off".equalsIgnoreCase(args[0]))
- || this.config.getCommandSpyState(player.getUniqueId())) {
- disableCommandSpy(player);
- return true;
+
+ if (state == null) {
+ state = !this.config.getCommandSpyState(target.getUniqueId());
}
- enableCommandSpy(player);
+
+ this.updateCommandSpyState(target, sender, state);
+
return true;
}
@@ -81,8 +127,8 @@ public final class Main extends JavaPlugin implements CommandExecutor, Listener
final NamedTextColor color = getTextColor(player);
final Component message = Component.text(player.getName(), color)
- .append(Component.text(": "))
- .append(Component.text(event.getMessage()));
+ .append(Component.text(": "))
+ .append(Component.text(event.getMessage()));
this.config.broadcastSpyMessage(message);
}
@@ -92,14 +138,44 @@ public final class Main extends JavaPlugin implements CommandExecutor, Listener
final Player player = event.getPlayer();
final NamedTextColor color = getTextColor(player);
Component message = Component.text(player.getName(), color)
- .append(Component.text(" created a sign with contents:"));
+ .append(Component.text(" created a sign with contents:"));
for (final Component line : event.lines()) {
message = message
- .append(Component.text("\n "))
- .append(line);
+ .append(Component.text("\n "))
+ .append(line);
}
this.config.broadcastSpyMessage(message);
}
+
+ private static Player getPlayer(final String arg) {
+ final Player player = Bukkit.getPlayer(arg);
+ if (player != null) {
+ return player;
+ }
+
+ final UUID uuid;
+ try {
+ uuid = UUID.fromString(arg);
+ } catch (final IllegalArgumentException ignored) {
+ return null;
+ }
+
+ return Bukkit.getPlayer(uuid);
+ }
+
+ private static Boolean getState(final String arg) {
+ switch (arg) {
+ case "on", "enable" -> {
+ return true;
+ }
+ case "off", "disable" -> {
+ return false;
+ }
+ default -> {
+ return null;
+ }
+ }
+ }
}
diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml
index af086de..6a93917 100644
--- a/src/main/resources/plugin.yml
+++ b/src/main/resources/plugin.yml
@@ -10,3 +10,4 @@ commands:
aliases: [ c, cs, cspy ]
description: Allows you to spy on players' commands
permission: commandspy.command
+ usage: 'Usage: / [player] [on|enable|off|disable]'
From 74db21dea145ec7b2011b1b4f01cc91ecd1832d4 Mon Sep 17 00:00:00 2001
From: amyavi <144570677+amyavi@users.noreply.github.com>
Date: Sun, 23 Jun 2024 22:18:51 -0300
Subject: [PATCH 08/14] fix: use correct usage; color usage in red
---
src/main/java/pw/kaboom/commandspy/Main.java | 10 ++++++++--
src/main/resources/plugin.yml | 2 +-
2 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/src/main/java/pw/kaboom/commandspy/Main.java b/src/main/java/pw/kaboom/commandspy/Main.java
index 62da442..01f7536 100644
--- a/src/main/java/pw/kaboom/commandspy/Main.java
+++ b/src/main/java/pw/kaboom/commandspy/Main.java
@@ -82,7 +82,10 @@ public final class Main extends JavaPlugin implements CommandExecutor, Listener
if (state != null && args.length == 1) {
break;
} else if (state == null && args.length == 2) {
- return false;
+ sender.sendMessage(Component.text("Usage: ", NamedTextColor.RED)
+ .append(Component.text(cmd.getUsage().replace("", label)))
+ );
+ return true;
}
// Get the first argument as a player. Fail if it can't be found.
@@ -99,7 +102,10 @@ public final class Main extends JavaPlugin implements CommandExecutor, Listener
return true;
}
default -> {
- return false;
+ sender.sendMessage(Component.text("Usage: ", NamedTextColor.RED)
+ .append(Component.text(cmd.getUsage().replace("", label)))
+ );
+ return true;
}
}
diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml
index 6a93917..7a39943 100644
--- a/src/main/resources/plugin.yml
+++ b/src/main/resources/plugin.yml
@@ -10,4 +10,4 @@ commands:
aliases: [ c, cs, cspy ]
description: Allows you to spy on players' commands
permission: commandspy.command
- usage: 'Usage: / [player] [on|enable|off|disable]'
+ usage: '/ [player] [on|enable|off|disable]'
From dbf9796791c1e21e92f1e2626ac1fa96215fe4d8 Mon Sep 17 00:00:00 2001
From: amyavi <144570677+amyavi@users.noreply.github.com>
Date: Mon, 24 Jun 2024 11:48:00 -0300
Subject: [PATCH 09/14] feat: run build action on every branch
---
.github/workflows/main.yml | 7 +------
1 file changed, 1 insertion(+), 6 deletions(-)
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 3af4259..45948ae 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -1,10 +1,5 @@
name: Maven CI
-
-on:
- push:
- branches: [ master ]
- pull_request:
- branches: [ master ]
+on: [push, pull_request]
jobs:
build:
From 876ec6ae447b80d37f7f52c28f535c261a4678a3 Mon Sep 17 00:00:00 2001
From: amyavi <144570677+amyavi@users.noreply.github.com>
Date: Mon, 24 Jun 2024 16:45:57 -0300
Subject: [PATCH 10/14] chore: bump paper to 1.20.4; fix warnings
We should probably keep kaboom plugins' API version synced with the main
server
---
pom.xml | 2 +-
src/main/java/pw/kaboom/commandspy/Main.java | 1 +
src/main/resources/plugin.yml | 2 +-
3 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/pom.xml b/pom.xml
index 6dfe236..494839c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -15,7 +15,7 @@
io.papermc.paper
paper-api
- 1.19.4-R0.1-SNAPSHOT
+ 1.20.4-R0.1-SNAPSHOT
provided
diff --git a/src/main/java/pw/kaboom/commandspy/Main.java b/src/main/java/pw/kaboom/commandspy/Main.java
index 01f7536..111587f 100644
--- a/src/main/java/pw/kaboom/commandspy/Main.java
+++ b/src/main/java/pw/kaboom/commandspy/Main.java
@@ -25,6 +25,7 @@ public final class Main extends JavaPlugin implements CommandExecutor, Listener
public void onEnable() {
this.config = new CommandSpyState(new File(this.getDataFolder(), "state.bin"));
+ //noinspection DataFlowIssue
this.getCommand("commandspy").setExecutor(this);
this.getServer().getPluginManager().registerEvents(this, this);
diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml
index 7a39943..9ba5483 100644
--- a/src/main/resources/plugin.yml
+++ b/src/main/resources/plugin.yml
@@ -1,7 +1,7 @@
name: CommandSpy
main: pw.kaboom.commandspy.Main
description: Plugin that allows you to spy on players' commands.
-api-version: '1.19'
+api-version: '1.20'
version: master
folia-supported: true
From 91787dec900e3e89d58cdf60d0d18a2280a3a105 Mon Sep 17 00:00:00 2001
From: amyavi <144570677+amyavi@users.noreply.github.com>
Date: Tue, 25 Jun 2024 22:31:31 -0300
Subject: [PATCH 11/14] fix: consistency, maven warning
---
pom.xml | 3 +--
.../pw/kaboom/commandspy/CommandSpyState.java | 7 ++++---
src/main/java/pw/kaboom/commandspy/Main.java | 16 ++++++++--------
3 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/pom.xml b/pom.xml
index 494839c..090e76e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,8 +5,7 @@
master
- 17
- 17
+ 17
true
UTF-8
diff --git a/src/main/java/pw/kaboom/commandspy/CommandSpyState.java b/src/main/java/pw/kaboom/commandspy/CommandSpyState.java
index 97e8542..676ba89 100644
--- a/src/main/java/pw/kaboom/commandspy/CommandSpyState.java
+++ b/src/main/java/pw/kaboom/commandspy/CommandSpyState.java
@@ -33,7 +33,8 @@ public final class CommandSpyState {
} catch (final FileNotFoundException exception) {
try {
this.save(); // Create file if it doesn't exist
- } catch (IOException ignored) {}
+ } catch (IOException ignored) {
+ }
} catch (final IOException exception) {
LOGGER.error("Failed to load state file:", exception);
}
@@ -47,7 +48,7 @@ public final class CommandSpyState {
// Loop until we read less than 16 bytes
while ((read = reader.readNBytes(buffer.array(), 0, 16)) == 16) {
- this.users.add(new UUID(buffer.getLong(0), buffer.getLong(8)));
+ this.users.add(new UUID(buffer.getLong(0), buffer.getLong(8)));
}
reader.close();
@@ -62,7 +63,7 @@ public final class CommandSpyState {
final ByteBuffer buffer = ByteBuffer.wrap(new byte[16]);
final long stamp = this.usersLock.readLock();
- for (final UUID uuid: this.users) {
+ for (final UUID uuid : this.users) {
buffer.putLong(0, uuid.getMostSignificantBits());
buffer.putLong(8, uuid.getLeastSignificantBits());
writer.write(buffer.array());
diff --git a/src/main/java/pw/kaboom/commandspy/Main.java b/src/main/java/pw/kaboom/commandspy/Main.java
index 111587f..a5d4f40 100644
--- a/src/main/java/pw/kaboom/commandspy/Main.java
+++ b/src/main/java/pw/kaboom/commandspy/Main.java
@@ -1,8 +1,7 @@
package pw.kaboom.commandspy;
-import java.io.File;
-import java.util.UUID;
-
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
@@ -14,10 +13,11 @@ import org.bukkit.event.Listener;
import org.bukkit.event.block.SignChangeEvent;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.plugin.java.JavaPlugin;
-import net.kyori.adventure.text.Component;
-import net.kyori.adventure.text.format.NamedTextColor;
import org.jetbrains.annotations.NotNull;
+import java.io.File;
+import java.util.UUID;
+
public final class Main extends JavaPlugin implements CommandExecutor, Listener {
private CommandSpyState config;
@@ -47,7 +47,7 @@ public final class Main extends JavaPlugin implements CommandExecutor, Listener
target.sendMessage(Component.empty()
.append(Component.text("Successfully "))
.append(stateString)
- .append(Component.text(" CommandSpy.")));
+ .append(Component.text(" CommandSpy")));
if (source != target) {
source.sendMessage(Component.empty()
@@ -55,7 +55,6 @@ public final class Main extends JavaPlugin implements CommandExecutor, Listener
.append(stateString)
.append(Component.text(" CommandSpy for "))
.append(target.name())
- .append(Component.text("."))
);
}
}
@@ -76,7 +75,8 @@ public final class Main extends JavaPlugin implements CommandExecutor, Listener
Boolean state = null;
switch (args.length) {
- case 0 -> {}
+ case 0 -> {
+ }
case 1, 2 -> {
// Get the last argument as a state. Fail if we have 2 arguments.
state = getState(args[args.length - 1]);
From d4ca1c84ad5dc65003d9532128dbd633ff4ae210 Mon Sep 17 00:00:00 2001
From: amyavi <144570677+amyavi@users.noreply.github.com>
Date: Tue, 25 Jun 2024 22:34:09 -0300
Subject: [PATCH 12/14] fix: maven skill issue
---
pom.xml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/pom.xml b/pom.xml
index 090e76e..7e7e78e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,6 +5,8 @@
master
+ 17
+ 17
17
true
UTF-8
From 2a5a9da5672afb060bbdee6f4d9db6d633fde98c Mon Sep 17 00:00:00 2001
From: amy <144570677+amyavi@users.noreply.github.com>
Date: Fri, 27 Sep 2024 21:08:11 -0300
Subject: [PATCH 13/14] chore: bump checkstyle version
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index 7e7e78e..66bc096 100644
--- a/pom.xml
+++ b/pom.xml
@@ -46,7 +46,7 @@
org.apache.maven.plugins
maven-checkstyle-plugin
- 3.4.0
+ 3.5.0
checkstyle
From 94c09b61f83ae4ac42578c7ff97d1dc7a980412d Mon Sep 17 00:00:00 2001
From: amyavi <144570677+amyavi@users.noreply.github.com>
Date: Sat, 21 Dec 2024 15:41:34 -0300
Subject: [PATCH 14/14] chore: bump checkstyle version
---
pom.xml | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/pom.xml b/pom.xml
index 66bc096..61c531f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -7,7 +7,6 @@
17
17
- 17
true
UTF-8
@@ -46,7 +45,7 @@
org.apache.maven.plugins
maven-checkstyle-plugin
- 3.5.0
+ 3.6.0
checkstyle