Skip to content

Commit 09dbc09

Browse files
authored
Add /reply (#8)
2 parents ebec077 + 123b3a2 commit 09dbc09

File tree

8 files changed

+131
-0
lines changed

8 files changed

+131
-0
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import org.jetbrains.annotations.NotNull;
55
import pro.cloudnode.smp.cloudnodemsg.command.MainCommand;
66
import pro.cloudnode.smp.cloudnodemsg.command.MessageCommand;
7+
import pro.cloudnode.smp.cloudnodemsg.command.ReplyCommand;
78

89
import java.util.Objects;
910

@@ -24,6 +25,7 @@ public void onEnable() {
2425

2526
Objects.requireNonNull(getCommand("cloudnodemsg")).setExecutor(new MainCommand());
2627
Objects.requireNonNull(getCommand("message")).setExecutor(new MessageCommand());
28+
Objects.requireNonNull(getCommand("reply")).setExecutor(new ReplyCommand());
2729
}
2830

2931
@Override

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,5 +119,22 @@ public PluginConfig(final @NotNull FileConfiguration config) {
119119
public @NotNull Component messageYourself() {
120120
return MiniMessage.miniMessage().deserialize(Objects.requireNonNull(config.getString("errors.message-yourself")));
121121
}
122+
123+
public @NotNull Component nobodyReply() {
124+
return MiniMessage.miniMessage().deserialize(Objects.requireNonNull(config.getString("errors.nobody-reply")));
125+
}
126+
127+
/**
128+
* The player that messaged you is no longer online
129+
* <p>Placeholders:</p>
130+
* <ul><li>{@code <player>} - the player's username</li></ul>
131+
*
132+
* @param player The player's username
133+
*/
134+
public @NotNull Component replyOffline(final @NotNull String player) {
135+
return MiniMessage.miniMessage().deserialize(Objects.requireNonNull(config.getString("errors.reply-offline")),
136+
Placeholder.unparsed("player", player)
137+
);
138+
}
122139
}
123140

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package pro.cloudnode.smp.cloudnodemsg.command;
2+
3+
import org.bukkit.OfflinePlayer;
4+
import org.bukkit.command.CommandSender;
5+
import org.jetbrains.annotations.NotNull;
6+
import pro.cloudnode.smp.cloudnodemsg.CloudnodeMSG;
7+
import pro.cloudnode.smp.cloudnodemsg.Permission;
8+
import pro.cloudnode.smp.cloudnodemsg.error.InvalidPlayerError;
9+
import pro.cloudnode.smp.cloudnodemsg.error.NoPermissionError;
10+
import pro.cloudnode.smp.cloudnodemsg.error.NobodyReplyError;
11+
import pro.cloudnode.smp.cloudnodemsg.error.ReplyOfflineError;
12+
import pro.cloudnode.smp.cloudnodemsg.message.Message;
13+
14+
import java.util.ArrayList;
15+
import java.util.List;
16+
import java.util.Optional;
17+
18+
public final class ReplyCommand extends Command {
19+
public static final @NotNull String usage = "<message>";
20+
21+
@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+
if (!sender.hasPermission(Permission.USE)) return new NoPermissionError().send(sender);
24+
if (args.length == 0) return sendMessage(sender, CloudnodeMSG.getInstance().config().usage(label, usage));
25+
26+
final @NotNull Optional<@NotNull OfflinePlayer> recipient = Message.getReplyTo(Message.offlinePlayer(sender));
27+
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+
30+
try {
31+
new Message(Message.offlinePlayer(sender), recipient.get(), String.join(" ", args)).send();
32+
return true;
33+
}
34+
catch (final @NotNull InvalidPlayerError e) {
35+
return e.log().send(sender);
36+
}
37+
}
38+
39+
@Override
40+
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) {
41+
return new ArrayList<>();
42+
}
43+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package pro.cloudnode.smp.cloudnodemsg.error;
2+
3+
import pro.cloudnode.smp.cloudnodemsg.CloudnodeMSG;
4+
5+
/**
6+
* Player has no username (somehow)
7+
*/
8+
public final class NobodyReplyError extends Error {
9+
public NobodyReplyError() {
10+
super(CloudnodeMSG.getInstance().config().nobodyReply());
11+
}
12+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package pro.cloudnode.smp.cloudnodemsg.error;
2+
3+
import org.jetbrains.annotations.NotNull;
4+
import pro.cloudnode.smp.cloudnodemsg.CloudnodeMSG;
5+
6+
/**
7+
* Player has no username (somehow)
8+
*/
9+
public final class ReplyOfflineError extends Error {
10+
public ReplyOfflineError(final @NotNull String player) {
11+
super(CloudnodeMSG.getInstance().config().replyOffline(player));
12+
}
13+
}

src/main/java/pro/cloudnode/smp/cloudnodemsg/message/Message.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
package pro.cloudnode.smp.cloudnodemsg.message;
22

33
import net.kyori.adventure.text.Component;
4+
import org.bukkit.NamespacedKey;
45
import org.bukkit.OfflinePlayer;
56
import org.bukkit.command.CommandSender;
67
import org.bukkit.entity.Player;
8+
import org.bukkit.persistence.PersistentDataType;
79
import org.jetbrains.annotations.NotNull;
10+
import org.jetbrains.annotations.Nullable;
811
import pro.cloudnode.smp.cloudnodemsg.CloudnodeMSG;
912
import pro.cloudnode.smp.cloudnodemsg.error.InvalidPlayerError;
1013

@@ -31,6 +34,9 @@ public void send() throws InvalidPlayerError {
3134
sendMessage(sender, CloudnodeMSG.getInstance().config().outgoing(senderUsername, recipientUsername, message));
3235
sendMessage(recipient, CloudnodeMSG.getInstance().config()
3336
.incoming(senderUsername, recipientUsername, message));
37+
38+
setReplyTo(sender, recipient);
39+
setReplyTo(recipient, sender);
3440
}
3541

3642
public final static @NotNull OfflinePlayer console = CloudnodeMSG.getInstance().getServer()
@@ -45,4 +51,31 @@ public static void sendMessage(final @NotNull OfflinePlayer recipient, final @No
4551
CloudnodeMSG.getInstance().getServer().getConsoleSender().sendMessage(message);
4652
else if (recipient.isOnline()) Objects.requireNonNull(recipient.getPlayer()).sendMessage(message);
4753
}
54+
55+
private static @Nullable UUID consoleReply;
56+
57+
public static final @NotNull NamespacedKey REPLY_TO = new NamespacedKey(CloudnodeMSG.getInstance(), "reply");
58+
59+
public static void setReplyTo(final @NotNull OfflinePlayer sender, final @NotNull OfflinePlayer recipient) {
60+
if (sender.getUniqueId().equals(console.getUniqueId())) consoleReply = recipient.getUniqueId();
61+
else if (sender.isOnline())
62+
Objects.requireNonNull(sender.getPlayer()).getPersistentDataContainer()
63+
.set(REPLY_TO, PersistentDataType.STRING, recipient.getUniqueId().toString());
64+
}
65+
66+
public static @NotNull Optional<@NotNull OfflinePlayer> getReplyTo(final @NotNull OfflinePlayer player) {
67+
if (player.getUniqueId().equals(console.getUniqueId())) return Optional.ofNullable(consoleReply)
68+
.map(uuid -> CloudnodeMSG.getInstance().getServer().getOfflinePlayer(uuid));
69+
if (player.isOnline())
70+
return Optional.ofNullable(Objects.requireNonNull(player.getPlayer()).getPersistentDataContainer()
71+
.get(REPLY_TO, PersistentDataType.STRING))
72+
.map(uuid -> CloudnodeMSG.getInstance().getServer().getOfflinePlayer(UUID.fromString(uuid)));
73+
return Optional.empty();
74+
}
75+
76+
public static void removeReplyTo(final @NotNull OfflinePlayer player) {
77+
if (player.getUniqueId().equals(console.getUniqueId())) consoleReply = null;
78+
else if (player.isOnline())
79+
Objects.requireNonNull(player.getPlayer()).getPersistentDataContainer().remove(REPLY_TO);
80+
}
4881
}

src/main/resources/config.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,10 @@ errors:
3535
player-not-found: "<red>(!) Player <gray><player></gray> not found.</red>"
3636

3737
message-yourself: "<red>(!) You can't send a message to yourself.</red>"
38+
39+
nobody-reply: "<red>(!) You have no one to reply to.</red>"
40+
41+
# The player that messaged you is no longer online
42+
# Placeholders:
43+
# <player> - the player's username
44+
reply-offline: "<red>(!) Player <gray><player></gray> is no longer online.</red>"

src/main/resources/plugin.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ commands:
88
description: Send a private message
99
usage: /<command> <player> <message>
1010
aliases: [ "msg", "tell", "t", "whisper", "dm", "m", "pm" ]
11+
reply:
12+
description: Reply to a private message
13+
usage: /<command> <message>
14+
aliases: [ "r", "re" ]
1115
cloudnodemsg:
1216
description: CloudnodeMSG
1317
usage: /<command>

0 commit comments

Comments
 (0)