Skip to content

Commit fac2dfe

Browse files
authored
Merge pull request #11 from amyavi/cleanups
2 parents 10ef0d6 + 94c09b6 commit fac2dfe

8 files changed

Lines changed: 282 additions & 75 deletions

File tree

.github/workflows/main.yml

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
11
name: Maven CI
2-
3-
on:
4-
push:
5-
branches: [ master ]
6-
pull_request:
7-
branches: [ master ]
2+
on: [push, pull_request]
83

94
jobs:
105
build:
@@ -31,3 +26,4 @@ jobs:
3126
with:
3227
name: CommandSpy
3328
path: target/CommandSpy.jar
29+
compression-level: 0

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,5 @@ target/
66
.classpath
77
.project
88
*.iml
9+
.theia/
10+
run/

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ The plugin is created for the Kaboom server.
66

77
## Commands
88

9-
| Command | Alias | Permission | Description |
10-
| ------- | ----- | ---------- | ----------- |
11-
|/commandspy | /c, /cs, /cspy | commandspy.command | Allows you to spy on players' commands|
9+
| Command | Alias | Permission | Description |
10+
|-------------|----------------|--------------------|----------------------------------------|
11+
| /commandspy | /c, /cs, /cspy | commandspy.command | Allows you to spy on players' commands |
1212

1313
## Compiling
1414

pom.xml

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
<dependency>
1616
<groupId>io.papermc.paper</groupId>
1717
<artifactId>paper-api</artifactId>
18-
<version>1.18.2-R0.1-SNAPSHOT</version>
18+
<version>1.20.4-R0.1-SNAPSHOT</version>
1919
<scope>provided</scope>
2020
</dependency>
2121
</dependencies>
@@ -30,10 +30,22 @@
3030
<build>
3131
<finalName>${project.artifactId}</finalName>
3232
<plugins>
33+
<plugin>
34+
<groupId>org.apache.maven.plugins</groupId>
35+
<artifactId>maven-jar-plugin</artifactId>
36+
<version>3.4.2</version>
37+
<configuration>
38+
<archive>
39+
<manifestEntries>
40+
<paperweight-mappings-namespace>mojang</paperweight-mappings-namespace>
41+
</manifestEntries>
42+
</archive>
43+
</configuration>
44+
</plugin>
3345
<plugin>
3446
<groupId>org.apache.maven.plugins</groupId>
3547
<artifactId>maven-checkstyle-plugin</artifactId>
36-
<version>3.1.2</version>
48+
<version>3.6.0</version>
3749
<executions>
3850
<execution>
3951
<id>checkstyle</id>
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
package pw.kaboom.commandspy;
2+
3+
import com.google.common.io.Files;
4+
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
5+
import net.kyori.adventure.text.Component;
6+
import org.bukkit.Bukkit;
7+
import org.bukkit.entity.Player;
8+
import org.bukkit.plugin.java.JavaPlugin;
9+
import org.jetbrains.annotations.NotNull;
10+
import org.slf4j.Logger;
11+
12+
import java.io.*;
13+
import java.nio.ByteBuffer;
14+
import java.util.Collection;
15+
import java.util.UUID;
16+
import java.util.concurrent.atomic.AtomicBoolean;
17+
import java.util.concurrent.locks.StampedLock;
18+
import java.util.stream.Collectors;
19+
20+
public final class CommandSpyState {
21+
private static final Logger LOGGER = JavaPlugin.getPlugin(Main.class).getSLF4JLogger();
22+
23+
private final ObjectOpenHashSet<UUID> users = new ObjectOpenHashSet<>();
24+
private final StampedLock usersLock = new StampedLock();
25+
private final AtomicBoolean dirty = new AtomicBoolean();
26+
private final File file;
27+
28+
public CommandSpyState(final @NotNull File file) {
29+
this.file = file;
30+
31+
try {
32+
this.load();
33+
} catch (final FileNotFoundException exception) {
34+
try {
35+
this.save(); // Create file if it doesn't exist
36+
} catch (IOException ignored) {
37+
}
38+
} catch (final IOException exception) {
39+
LOGGER.error("Failed to load state file:", exception);
40+
}
41+
}
42+
43+
private void load() throws IOException {
44+
final InputStream reader = new BufferedInputStream(new FileInputStream(this.file));
45+
46+
int read;
47+
final ByteBuffer buffer = ByteBuffer.wrap(new byte[16]);
48+
49+
// Loop until we read less than 16 bytes
50+
while ((read = reader.readNBytes(buffer.array(), 0, 16)) == 16) {
51+
this.users.add(new UUID(buffer.getLong(0), buffer.getLong(8)));
52+
}
53+
54+
reader.close();
55+
if (read != 0) {
56+
throw new IOException("Found " + read + " bytes extra whilst reading file");
57+
}
58+
}
59+
60+
private void save() throws IOException {
61+
Files.createParentDirs(this.file);
62+
final OutputStream writer = new BufferedOutputStream(new FileOutputStream(this.file));
63+
final ByteBuffer buffer = ByteBuffer.wrap(new byte[16]);
64+
65+
final long stamp = this.usersLock.readLock();
66+
for (final UUID uuid : this.users) {
67+
buffer.putLong(0, uuid.getMostSignificantBits());
68+
buffer.putLong(8, uuid.getLeastSignificantBits());
69+
writer.write(buffer.array());
70+
}
71+
this.usersLock.unlockRead(stamp);
72+
73+
writer.flush();
74+
writer.close();
75+
}
76+
77+
public void trySave() {
78+
// If the state is not dirty, then we don't need to do anything.
79+
if (!this.dirty.compareAndExchange(true, false)) {
80+
return;
81+
}
82+
83+
try {
84+
this.save();
85+
} catch (final IOException exception) {
86+
LOGGER.error("Failed to save state file:", exception);
87+
}
88+
}
89+
90+
public boolean getCommandSpyState(final @NotNull UUID playerUUID) {
91+
final long stamp = this.usersLock.readLock();
92+
final boolean result = this.users.contains(playerUUID);
93+
this.usersLock.unlockRead(stamp);
94+
95+
return result;
96+
}
97+
98+
public void setCommandSpyState(final @NotNull UUID playerUUID, final boolean state) {
99+
final long stamp = this.usersLock.writeLock();
100+
101+
final boolean dirty;
102+
if (state) {
103+
dirty = this.users.add(playerUUID);
104+
} else {
105+
dirty = this.users.remove(playerUUID);
106+
}
107+
108+
this.usersLock.unlockWrite(stamp);
109+
if (dirty) {
110+
this.dirty.set(true);
111+
}
112+
}
113+
114+
public void broadcastSpyMessage(final @NotNull Component message) {
115+
// Raw access here, so we can get more performance by not locking/unlocking over and over
116+
final long stamp = this.usersLock.readLock();
117+
final Collection<Player> players = Bukkit.getOnlinePlayers()
118+
.stream()
119+
.filter(p -> this.users.contains(p.getUniqueId()))
120+
.collect(Collectors.toUnmodifiableSet());
121+
this.usersLock.unlockRead(stamp);
122+
123+
for (final Player recipient : players) {
124+
recipient.sendMessage(message);
125+
}
126+
}
127+
}

0 commit comments

Comments
 (0)