Skip to content

Commit 6fc2230

Browse files
committed
Merge branch 'main' into 3-add-togglemsg-command
2 parents deade7a + 884a63a commit 6fc2230

23 files changed

+436
-25
lines changed

.github/workflows/maven.yml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time
2+
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-maven
3+
4+
# This workflow uses actions that are not certified by GitHub.
5+
# They are provided by a third-party and are governed by
6+
# separate terms of service, privacy policy, and support
7+
# documentation.
8+
9+
name: Java CI with Maven
10+
11+
on:
12+
push:
13+
branches: [ "main" ]
14+
pull_request:
15+
branches: [ "main" ]
16+
17+
jobs:
18+
build:
19+
20+
runs-on: ubuntu-latest
21+
22+
steps:
23+
- uses: actions/checkout@v3
24+
- name: Set up JDK 17
25+
uses: actions/setup-java@v3
26+
with:
27+
java-version: '17'
28+
distribution: 'temurin'
29+
cache: maven
30+
- name: Build with Maven
31+
run: mvn -B package --file pom.xml
32+
33+
# Optional: Uploads the full dependency graph to GitHub to improve the quality of Dependabot alerts this repository can receive
34+
- name: Update dependency graph
35+
uses: advanced-security/maven-dependency-submission-action@571e99aab1055c2e71a1e2309b9691de18d6b7d6

src/main/java/pro/cloudnode/smp/cloudnodemsg/CloudnodeMSG.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
package pro.cloudnode.smp.cloudnodemsg;
22

3+
import org.bukkit.entity.Player;
4+
import org.bukkit.metadata.MetadataValue;
35
import org.bukkit.plugin.java.JavaPlugin;
46
import org.jetbrains.annotations.NotNull;
7+
import pro.cloudnode.smp.cloudnodemsg.command.IgnoreCommand;
58
import pro.cloudnode.smp.cloudnodemsg.command.MainCommand;
69
import pro.cloudnode.smp.cloudnodemsg.command.MessageCommand;
710
import pro.cloudnode.smp.cloudnodemsg.command.ReplyCommand;
11+
import pro.cloudnode.smp.cloudnodemsg.command.UnIgnoreCommand;
812
import pro.cloudnode.smp.cloudnodemsg.command.ToggleMessageCommand;
913

1014
import java.util.Objects;
@@ -26,7 +30,8 @@ public void onEnable() {
2630

2731
Objects.requireNonNull(getCommand("cloudnodemsg")).setExecutor(new MainCommand());
2832
Objects.requireNonNull(getCommand("message")).setExecutor(new MessageCommand());
29-
Objects.requireNonNull(getCommand("reply")).setExecutor(new ReplyCommand());
33+
Objects.requireNonNull(getCommand("reply")).setExecutor(new ReplyCommand());Objects.requireNonNull(getCommand("ignore")).setExecutor(new IgnoreCommand());
34+
Objects.requireNonNull(getCommand("unignore")).setExecutor(new UnIgnoreCommand());
3035
Objects.requireNonNull(getCommand("togglemsg")).setExecutor(new ToggleMessageCommand());
3136
}
3237

@@ -35,6 +40,12 @@ public void onDisable() {
3540
// Plugin shutdown logic
3641
}
3742

43+
public static boolean isVanished(final @NotNull Player player) {
44+
for (final @NotNull MetadataValue meta : player.getMetadata("vanished"))
45+
if (meta.asBoolean()) return true;
46+
return false;
47+
}
48+
3849
private final @NotNull PluginConfig config = new PluginConfig(getConfig());
3950

4051
public @NotNull PluginConfig config() {

src/main/java/pro/cloudnode/smp/cloudnodemsg/Permission.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,21 @@ public final class Permission {
1313
*/
1414
public final static @NotNull String RELOAD = "cloudnodemsg.reload";
1515

16+
/**
17+
* Allows sending messages to vanished players
18+
*/
19+
public final static @NotNull String SEND_VANISHED = "cloudnodemsg.send.vanished";
20+
21+
/**
22+
* Allows ignoring and unignoring players
23+
*/
24+
public final static @NotNull String IGNORE = "cloudnodemsg.ignore";
25+
26+
/**
27+
* Player's messages are immune to ignoring
28+
*/
29+
public final static @NotNull String IGNORE_IMMUNE = "cloudnodemsg.ignore.bypass";
30+
1631
/**
1732
* Allows using the /togglemsg command
1833
*/

src/main/java/pro/cloudnode/smp/cloudnodemsg/PluginConfig.java

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,32 @@ public PluginConfig(final @NotNull FileConfiguration config) {
5757
);
5858
}
5959

60+
/**
61+
* Player has successfully been ignored
62+
* <p>Placeholders:</p>
63+
* <ul><li>{@code <player>} - the username of the player</li></ul>
64+
*
65+
* @param player The username of the player
66+
*/
67+
public @NotNull Component ignored(final @NotNull String player) {
68+
return MiniMessage.miniMessage().deserialize(Objects.requireNonNull(config.getString("ignored")),
69+
Placeholder.unparsed("player", player)
70+
);
71+
}
72+
73+
/**
74+
* Player has successfully been unignored
75+
* <p>Placeholders:</p>
76+
* <ul><li>{@code <player>} - the username of the player</li></ul>
77+
*
78+
* @param player The username of the player
79+
*/
80+
public @NotNull Component unignored(final @NotNull String player) {
81+
return MiniMessage.miniMessage().deserialize(Objects.requireNonNull(config.getString("unignored")),
82+
Placeholder.unparsed("player", player)
83+
);
84+
}
85+
6086
/**
6187
* Command usage format
6288
* <p>Placeholders:</p>
@@ -170,5 +196,51 @@ public PluginConfig(final @NotNull FileConfiguration config) {
170196
Placeholder.unparsed("player", player)
171197
);
172198
}
199+
200+
/**
201+
* Only players can use this command
202+
*/
203+
public @NotNull Component notPlayer() {
204+
return MiniMessage.miniMessage().deserialize(Objects.requireNonNull(config.getString("errors.not-player")));
205+
}
206+
207+
/**
208+
* That player is not ignored
209+
* <p>Placeholders:</p>
210+
* <ul><li>{@code <player>} - the player's username</li></ul>
211+
*
212+
* @param player The player's username
213+
*/
214+
public @NotNull Component notIgnored(final @NotNull String player) {
215+
return MiniMessage.miniMessage().deserialize(Objects.requireNonNull(config.getString("errors.not-ignored")),
216+
Placeholder.unparsed("player", player)
217+
);
218+
}
219+
220+
/**
221+
* Player cannot be ignored
222+
* <p>Placeholders:</p>
223+
* <ul><li>{@code <player>} - the player's username</li></ul>
224+
*
225+
* @param player The player's username
226+
*/
227+
public @NotNull Component cannotIgnore(final @NotNull String player) {
228+
return MiniMessage.miniMessage().deserialize(Objects.requireNonNull(config.getString("errors.cannot-ignore")),
229+
Placeholder.unparsed("player", player)
230+
);
231+
}
232+
233+
/**
234+
* Target player has never joined the server
235+
* <p>Placeholders:</p>
236+
* <ul><li>{@code <player>} - the player's username</li></ul>
237+
*
238+
* @param player The player's username
239+
*/
240+
public @NotNull Component neverJoined(final @NotNull String player) {
241+
return MiniMessage.miniMessage().deserialize(Objects.requireNonNull(config.getString("errors.never-joined")),
242+
Placeholder.unparsed("player", player)
243+
);
244+
}
173245
}
174246

src/main/java/pro/cloudnode/smp/cloudnodemsg/command/Command.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,24 @@
33
import net.kyori.adventure.audience.Audience;
44
import net.kyori.adventure.text.Component;
55
import org.bukkit.command.CommandExecutor;
6+
import org.bukkit.command.CommandSender;
67
import org.bukkit.command.TabCompleter;
78
import org.jetbrains.annotations.NotNull;
9+
import pro.cloudnode.smp.cloudnodemsg.CloudnodeMSG;
810

911
public abstract class Command implements TabCompleter, CommandExecutor {
10-
public boolean sendMessage(final @NotNull Audience recipient, final @NotNull Component message) {
12+
public static boolean sendMessage(final @NotNull Audience recipient, final @NotNull Component message) {
1113
recipient.sendMessage(message);
1214
return true;
1315
}
16+
17+
public abstract boolean run(final @NotNull CommandSender sender, final @NotNull String label, final @NotNull String[] args);
18+
19+
@Override
20+
public final boolean onCommand(final @NotNull CommandSender sender, final @NotNull org.bukkit.command.Command command, final @NotNull String label, @NotNull String @NotNull [] args) {
21+
CloudnodeMSG.getInstance().getServer().getScheduler().runTaskAsynchronously(CloudnodeMSG.getInstance(), () -> {
22+
final boolean ignored = run(sender, label, args);
23+
});
24+
return true;
25+
}
1426
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package pro.cloudnode.smp.cloudnodemsg.command;
2+
3+
import org.bukkit.OfflinePlayer;
4+
import org.bukkit.command.CommandSender;
5+
import org.bukkit.entity.Player;
6+
import org.jetbrains.annotations.NotNull;
7+
import org.jetbrains.annotations.Nullable;
8+
import pro.cloudnode.smp.cloudnodemsg.CloudnodeMSG;
9+
import pro.cloudnode.smp.cloudnodemsg.Permission;
10+
import pro.cloudnode.smp.cloudnodemsg.error.CannotIgnoreError;
11+
import pro.cloudnode.smp.cloudnodemsg.error.NeverJoinedError;
12+
import pro.cloudnode.smp.cloudnodemsg.error.NoPermissionError;
13+
import pro.cloudnode.smp.cloudnodemsg.error.NotPlayerError;
14+
import pro.cloudnode.smp.cloudnodemsg.message.Message;
15+
16+
import java.util.ArrayList;
17+
import java.util.List;
18+
import java.util.Objects;
19+
import java.util.Optional;
20+
21+
public final class IgnoreCommand extends Command {
22+
public static final @NotNull String usage = "<player>";
23+
24+
@Override
25+
public boolean run(final @NotNull CommandSender sender, final @NotNull String label, @NotNull String @NotNull [] args) {
26+
if (!sender.hasPermission(Permission.IGNORE)) return new NoPermissionError().send(sender);
27+
if (!(sender instanceof final @NotNull Player player)) return new NotPlayerError().send(sender);
28+
if (args.length == 0) return sendMessage(player, CloudnodeMSG.getInstance().config().usage(label, usage));
29+
final @NotNull OfflinePlayer target = CloudnodeMSG.getInstance().getServer().getOfflinePlayer(args[0]);
30+
if (Message.isIgnored(player, target)) return unignore(player, target);
31+
return ignore(player, target);
32+
}
33+
34+
public static boolean ignore(final @NotNull Player player, final @NotNull OfflinePlayer target) {
35+
if (target.isOnline() && Objects.requireNonNull(target.getPlayer()).hasPermission(Permission.IGNORE_IMMUNE)) return new CannotIgnoreError(Optional.ofNullable(target.getName()).orElse("Unknown Player")).send(player);
36+
if (!target.hasPlayedBefore()) return new NeverJoinedError(Optional.ofNullable(target.getName()).orElse("Unknown Player")).send(player);
37+
Message.ignore(player, target);
38+
return sendMessage(player, CloudnodeMSG.getInstance().config().ignored(Optional.ofNullable(target.getName()).orElse("Unknown Player")));
39+
}
40+
41+
public static boolean unignore(final @NotNull Player player, final @NotNull OfflinePlayer target) {
42+
Message.unignore(player, target);
43+
return sendMessage(player, CloudnodeMSG.getInstance().config().unignored(Optional.ofNullable(target.getName()).orElse("Unknown Player")));
44+
}
45+
46+
@Override
47+
public @Nullable List<@NotNull String> onTabComplete(final @NotNull CommandSender sender, final @NotNull org.bukkit.command.Command command, final @NotNull String label, final @NotNull String @NotNull [] args) {
48+
if (args.length == 1 && sender.hasPermission(Permission.IGNORE) && sender instanceof Player) return null;
49+
return new ArrayList<>();
50+
}
51+
}

src/main/java/pro/cloudnode/smp/cloudnodemsg/command/MainCommand.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
public final class MainCommand extends Command {
1616

1717
@Override
18-
public boolean onCommand(final @NotNull CommandSender sender, final @NotNull org.bukkit.command.Command command, final @NotNull String label, @NotNull String @NotNull [] args) {
18+
public boolean run(final @NotNull CommandSender sender, final @NotNull String label, @NotNull String @NotNull [] args) {
1919
if (args.length == 1) switch (args[0]) {
2020
case "reload", "rl" -> {
2121
return reload(sender);

src/main/java/pro/cloudnode/smp/cloudnodemsg/command/MessageCommand.java

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import org.bukkit.command.CommandSender;
44
import org.bukkit.entity.Player;
55
import org.jetbrains.annotations.NotNull;
6+
import org.jetbrains.annotations.Nullable;
67
import pro.cloudnode.smp.cloudnodemsg.CloudnodeMSG;
78
import pro.cloudnode.smp.cloudnodemsg.Permission;
89
import pro.cloudnode.smp.cloudnodemsg.error.InvalidPlayerError;
@@ -20,15 +21,15 @@ public final class MessageCommand extends Command {
2021
public static final @NotNull String usage = "<player> <message>";
2122

2223
@Override
23-
public boolean onCommand(final @NotNull CommandSender sender, final @NotNull org.bukkit.command.Command command, final @NotNull String label, @NotNull String @NotNull [] args) {
24+
public boolean run(final @NotNull CommandSender sender, final @NotNull String label, @NotNull String @NotNull [] args) {
2425
if (!sender.hasPermission(Permission.USE)) return new NoPermissionError().send(sender);
2526
if (args.length == 0) return sendMessage(sender, CloudnodeMSG.getInstance().config().usage(label, usage));
2627
if (args.length == 1) return sendMessage(sender, CloudnodeMSG.getInstance().config()
2728
.usage(label, usage.replace("<player>", args[0])));
2829

2930
final @NotNull Optional<@NotNull Player> recipient = Optional.ofNullable(CloudnodeMSG.getInstance().getServer()
3031
.getPlayer(args[0]));
31-
if (recipient.isEmpty()) return new PlayerNotFoundError(args[0]).send(sender);
32+
if (recipient.isEmpty() || (CloudnodeMSG.isVanished(recipient.get()) && !sender.hasPermission(Permission.SEND_VANISHED))) return new PlayerNotFoundError(args[0]).send(sender);
3233
if (sender instanceof final @NotNull Player player && recipient.get().getUniqueId().equals(player.getUniqueId()))
3334
return new MessageYourselfError().send(sender);
3435

@@ -42,13 +43,10 @@ public boolean onCommand(final @NotNull CommandSender sender, final @NotNull org
4243
}
4344

4445
@Override
45-
public @NotNull List<@NotNull String> onTabComplete(final @NotNull CommandSender sender, final @NotNull org.bukkit.command.Command command, final @NotNull String label, final @NotNull String @NotNull [] args) {
46+
public @Nullable List<@NotNull String> onTabComplete(final @NotNull CommandSender sender, final @NotNull org.bukkit.command.Command command, final @NotNull String label, final @NotNull String @NotNull [] args) {
4647
if (!sender.hasPermission(Permission.USE)) return new ArrayList<>();
47-
final @NotNull List<@NotNull String> completions = new ArrayList<>();
48-
if (args.length == 1) completions.addAll(CloudnodeMSG.getInstance().getServer().getOnlinePlayers().stream()
49-
.map(Player::getName)
50-
.filter(n -> n.toLowerCase().startsWith(args[0].toLowerCase()))
51-
.toList());
52-
return completions;
48+
// `null` works for list of players
49+
if (args.length == 1) return null;
50+
return new ArrayList<>();
5351
}
5452
}

src/main/java/pro/cloudnode/smp/cloudnodemsg/command/ReplyCommand.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,27 @@
1313

1414
import java.util.ArrayList;
1515
import java.util.List;
16+
import java.util.Objects;
1617
import java.util.Optional;
1718

1819
public final class ReplyCommand extends Command {
1920
public static final @NotNull String usage = "<message>";
2021

2122
@Override
22-
public boolean onCommand(final @NotNull CommandSender sender, final @NotNull org.bukkit.command.Command command, final @NotNull String label, @NotNull String @NotNull [] args) {
23+
public boolean run(final @NotNull CommandSender sender, final @NotNull String label, @NotNull String @NotNull [] args) {
2324
if (!sender.hasPermission(Permission.USE)) return new NoPermissionError().send(sender);
2425
if (args.length == 0) return sendMessage(sender, CloudnodeMSG.getInstance().config().usage(label, usage));
2526

2627
final @NotNull Optional<@NotNull OfflinePlayer> recipient = Message.getReplyTo(Message.offlinePlayer(sender));
2728
if (recipient.isEmpty()) return new NobodyReplyError().send(sender);
28-
if (!recipient.get().getUniqueId().equals(Message.console.getUniqueId()) && !recipient.get().isOnline()) return new ReplyOfflineError(Optional.ofNullable(recipient.get().getName()).orElse("Unknown Player")).send(sender);
29+
if (
30+
!recipient.get().getUniqueId().equals(Message.console.getUniqueId())
31+
&& (
32+
!recipient.get().isOnline()
33+
|| (CloudnodeMSG.isVanished(Objects.requireNonNull(recipient.get().getPlayer())) && !sender.hasPermission(Permission.SEND_VANISHED))
34+
)
35+
)
36+
return new ReplyOfflineError(Optional.ofNullable(recipient.get().getName()).orElse("Unknown Player")).send(sender);
2937

3038
try {
3139
new Message(Message.offlinePlayer(sender), recipient.get(), String.join(" ", args)).send();
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package pro.cloudnode.smp.cloudnodemsg.command;
2+
3+
import org.bukkit.OfflinePlayer;
4+
import org.bukkit.Server;
5+
import org.bukkit.command.CommandSender;
6+
import org.bukkit.entity.Player;
7+
import org.jetbrains.annotations.NotNull;
8+
import org.jetbrains.annotations.Nullable;
9+
import pro.cloudnode.smp.cloudnodemsg.CloudnodeMSG;
10+
import pro.cloudnode.smp.cloudnodemsg.Permission;
11+
import pro.cloudnode.smp.cloudnodemsg.error.NoPermissionError;
12+
import pro.cloudnode.smp.cloudnodemsg.error.NotIgnoredError;
13+
import pro.cloudnode.smp.cloudnodemsg.error.NotPlayerError;
14+
import pro.cloudnode.smp.cloudnodemsg.message.Message;
15+
16+
import java.util.ArrayList;
17+
import java.util.HashSet;
18+
import java.util.List;
19+
import java.util.Objects;
20+
import java.util.UUID;
21+
22+
public final class UnIgnoreCommand extends Command {
23+
public static final @NotNull String usage = "<player>";
24+
25+
@Override
26+
public boolean run(final @NotNull CommandSender sender, final @NotNull String label, @NotNull String @NotNull [] args) {
27+
if (!sender.hasPermission(Permission.IGNORE)) return new NoPermissionError().send(sender);
28+
if (!(sender instanceof final @NotNull Player player)) return new NotPlayerError().send(sender);
29+
if (args.length == 0) return sendMessage(sender, CloudnodeMSG.getInstance().config().usage(label, usage));
30+
final @NotNull OfflinePlayer target = CloudnodeMSG.getInstance().getServer().getOfflinePlayer(args[0]);
31+
if (Message.isIgnored(player, target)) return IgnoreCommand.unignore(player, target);
32+
return new NotIgnoredError(args[0]).send(sender);
33+
}
34+
35+
@Override
36+
public @Nullable List<@NotNull String> onTabComplete(final @NotNull CommandSender sender, final @NotNull org.bukkit.command.Command command, final @NotNull String label, final @NotNull String @NotNull [] args) {
37+
if (args.length == 1 && sender.hasPermission(Permission.IGNORE) && sender instanceof final @NotNull Player player) {
38+
final @NotNull HashSet<@NotNull UUID> ignored = Message.getIgnored(player);
39+
final @NotNull Server server = CloudnodeMSG.getInstance().getServer();
40+
return new ArrayList<>(ignored.stream().map(u -> server.getOfflinePlayer(u).getName())
41+
.filter(Objects::nonNull).filter(n -> n.toLowerCase().startsWith(args[0].toLowerCase())).toList());
42+
}
43+
return new ArrayList<>();
44+
}
45+
}

0 commit comments

Comments
 (0)