Skip to content

Commit 448fcfe

Browse files
committed
Add support for local and global chats in Discord
This change makes use of added separate events for local and global chats, making it possible to change formatting of messages sent from different chat types, as well as disable them altogether (for example, if you don't want to see local chat messages in Discord). By default Essentials Discord will continue to use Bukkit chat events without any kind of separation, you must explicitly opt in to have new behaviour by changing use-essential-events to true.
1 parent a0fc04c commit 448fcfe

File tree

10 files changed

+245
-26
lines changed

10 files changed

+245
-26
lines changed

EssentialsDiscord/src/main/java/net/essentialsx/api/v2/events/discord/DiscordChatMessageEvent.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package net.essentialsx.api.v2.events.discord;
22

3+
import net.essentialsx.api.v2.ChatType;
34
import org.bukkit.entity.Player;
45
import org.bukkit.event.Cancellable;
56
import org.bukkit.event.Event;
@@ -14,20 +15,22 @@ public class DiscordChatMessageEvent extends Event implements Cancellable {
1415
private static final HandlerList handlers = new HandlerList();
1516

1617
private final Player player;
18+
private final ChatType chatType;
1719
private String message;
1820
private boolean cancelled = false;
1921

2022
/**
2123
* @param player The player which caused this event.
2224
* @param message The message of this event.
2325
*/
24-
public DiscordChatMessageEvent(Player player, String message) {
26+
public DiscordChatMessageEvent(Player player, String message, ChatType chatType) {
2527
this.player = player;
2628
this.message = message;
29+
this.chatType = chatType;
2730
}
2831

2932
/**
30-
* The player which which caused this chat message.
33+
* The player which caused this chat message.
3134
* @return the player who caused the event.
3235
*/
3336
public Player getPlayer() {
@@ -50,6 +53,14 @@ public void setMessage(String message) {
5053
this.message = message;
5154
}
5255

56+
/**
57+
* Type of chat of the original message.
58+
* @return type of chat of the original message.
59+
*/
60+
public ChatType getChatType() {
61+
return chatType;
62+
}
63+
5364
@Override
5465
public boolean isCancelled() {
5566
return cancelled;

EssentialsDiscord/src/main/java/net/essentialsx/api/v2/services/discord/DiscordService.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package net.essentialsx.api.v2.services.discord;
22

3+
import net.essentialsx.api.v2.ChatType;
34
import net.essentialsx.api.v2.events.discord.DiscordChatMessageEvent;
45
import org.bukkit.entity.Player;
56
import org.bukkit.plugin.Plugin;
@@ -17,7 +18,7 @@ public interface DiscordService {
1718
void sendMessage(final MessageType type, final String message, final boolean allowGroupMentions);
1819

1920
/**
20-
* Sends a chat messages to the {@link MessageType.DefaultTypes#CHAT default chat channel} with the same format
21+
* Sends a chat message to the {@link MessageType.DefaultTypes#CHAT default chat channel} with the same format
2122
* used for regular chat messages specified in the EssentialsX Discord configuration.
2223
* <p>
2324
* Note: Messages sent with this method will not fire a {@link DiscordChatMessageEvent}.
@@ -26,6 +27,16 @@ public interface DiscordService {
2627
*/
2728
void sendChatMessage(final Player player, final String chatMessage);
2829

30+
/**
31+
* Sends a chat message to the appropriate chat channel depending on the chat type with the format specified
32+
* for that type in the EssentialsX Discord configuration.
33+
* <p>
34+
* Note: Messages sent with this method will not fire a {@link DiscordChatMessageEvent}.
35+
* @param player The player who send the message.
36+
* @param chatMessage The chat message the player has sent.
37+
*/
38+
void sendChatMessage(final ChatType chatType, final Player player, final String chatMessage);
39+
2940
/**
3041
* Checks if a {@link MessageType} by the given key is already registered.
3142
* @param key The {@link MessageType} key to check.

EssentialsDiscord/src/main/java/net/essentialsx/api/v2/services/discord/MessageType.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,10 @@ public static final class DefaultTypes {
6464
public final static MessageType SERVER_STOP = new MessageType("server-stop", false);
6565
public final static MessageType KICK = new MessageType("kick", false);
6666
public final static MessageType MUTE = new MessageType("mute", false);
67-
private final static MessageType[] VALUES = new MessageType[]{JOIN, LEAVE, CHAT, DEATH, AFK, ADVANCEMENT, ACTION, SERVER_START, SERVER_STOP, KICK, MUTE};
67+
public final static MessageType LOCAL = new MessageType("local", true);
68+
public final static MessageType QUESTION = new MessageType("question", true);
69+
public final static MessageType SHOUT = new MessageType("shout", true);
70+
private final static MessageType[] VALUES = new MessageType[]{JOIN, LEAVE, CHAT, DEATH, AFK, ADVANCEMENT, ACTION, SERVER_START, SERVER_STOP, KICK, MUTE, LOCAL, QUESTION, SHOUT};
6871

6972
/**
7073
* Gets an array of all the default {@link MessageType MessageTypes}.

EssentialsDiscord/src/main/java/net/essentialsx/discord/DiscordSettings.java

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import com.earth2me.essentials.utils.FormatUtil;
77
import net.dv8tion.jda.api.OnlineStatus;
88
import net.dv8tion.jda.api.entities.Activity;
9+
import net.essentialsx.api.v2.ChatType;
910
import org.apache.logging.log4j.Level;
1011
import org.bukkit.entity.Player;
1112

@@ -107,6 +108,10 @@ public boolean isAlwaysReceivePrimary() {
107108
return config.getBoolean("always-receive-primary", false);
108109
}
109110

111+
public boolean isUseEssentialsEvents() {
112+
return config.getBoolean("use-essentials-events", false);
113+
}
114+
110115
public int getChatDiscordMaxLength() {
111116
return config.getInt("chat.discord-max-length", 2000);
112117
}
@@ -212,17 +217,47 @@ public MessageFormat getDiscordToMcFormat() {
212217
}
213218

214219
public MessageFormat getMcToDiscordFormat(Player player) {
215-
final String format = getFormatString("mc-to-discord");
220+
return getMcToDiscordFormat(player, ChatType.UNKNOWN);
221+
}
222+
223+
public MessageFormat getMcToDiscordFormat(Player player, ChatType chatType) {
224+
final String format = getFormatString(getMcToDiscordFormatKey(chatType));
216225
final String filled;
217226
if (plugin.isPAPI() && format != null) {
218227
filled = me.clip.placeholderapi.PlaceholderAPI.setPlaceholders(player, format);
219228
} else {
220229
filled = format;
221230
}
222-
return generateMessageFormat(filled, "{displayname}: {message}", false,
231+
return generateMessageFormat(filled, getMcToDiscordDefaultFormat(chatType), false,
223232
"username", "displayname", "message", "world", "prefix", "suffix");
224233
}
225234

235+
private String getMcToDiscordFormatKey(ChatType chatType) {
236+
switch (chatType) {
237+
case LOCAL:
238+
return "mc-to-discord-local";
239+
case QUESTION:
240+
return "mc-to-discord-question";
241+
case SHOUT:
242+
return "mc-to-discord-shout";
243+
default:
244+
return "mc-to-discord";
245+
}
246+
}
247+
248+
private String getMcToDiscordDefaultFormat(ChatType chatType) {
249+
switch (chatType) {
250+
case LOCAL:
251+
return "**[Local]** {displayname}: {message}";
252+
case QUESTION:
253+
return "**[Question]** {displayname}: {message}";
254+
case SHOUT:
255+
return "**[Shout]** {displayname}: {message}";
256+
default:
257+
return "{displayname}: {message}";
258+
}
259+
}
260+
226261
public MessageFormat getTempMuteFormat() {
227262
return tempMuteFormat;
228263
}

EssentialsDiscord/src/main/java/net/essentialsx/discord/EssentialsDiscord.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ public class EssentialsDiscord extends JavaPlugin implements IEssentialsModule {
2424
private JDADiscordService jda;
2525
private DiscordSettings settings;
2626
private boolean isPAPI = false;
27+
private boolean isEssentialsChat = false;
2728

2829
@Override
2930
public void onEnable() {
@@ -45,6 +46,8 @@ public void onEnable() {
4546

4647
isPAPI = getServer().getPluginManager().getPlugin("PlaceholderAPI") != null;
4748

49+
isEssentialsChat = getServer().getPluginManager().getPlugin("EssentialsChat") != null;
50+
4851
settings = new DiscordSettings(this);
4952
ess.addReloadListener(settings);
5053

@@ -69,6 +72,7 @@ public void onEnable() {
6972

7073
public void onReload() {
7174
if (jda != null && !jda.isInvalidStartup()) {
75+
jda.updateListener();
7276
jda.updatePresence();
7377
jda.updatePrimaryChannel();
7478
jda.updateConsoleRelay();
@@ -92,6 +96,10 @@ public boolean isPAPI() {
9296
return isPAPI;
9397
}
9498

99+
public boolean isEssentialsChat() {
100+
return isEssentialsChat;
101+
}
102+
95103
@Override
96104
public void onDisable() {
97105
if (jda != null && !jda.isInvalidStartup()) {

EssentialsDiscord/src/main/java/net/essentialsx/discord/JDADiscordService.java

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import net.ess3.nms.refl.providers.AchievementListenerProvider;
2323
import net.ess3.nms.refl.providers.AdvancementListenerProvider;
2424
import net.ess3.provider.providers.PaperAdvancementListenerProvider;
25+
import net.essentialsx.api.v2.ChatType;
2526
import net.essentialsx.api.v2.events.discord.DiscordMessageEvent;
2627
import net.essentialsx.api.v2.services.discord.DiscordService;
2728
import net.essentialsx.api.v2.services.discord.InteractionController;
@@ -35,12 +36,15 @@
3536
import net.essentialsx.discord.listeners.BukkitListener;
3637
import net.essentialsx.discord.listeners.DiscordCommandDispatcher;
3738
import net.essentialsx.discord.listeners.DiscordListener;
39+
import net.essentialsx.discord.listeners.EssentialsChatListener;
40+
import net.essentialsx.discord.listeners.BukkitChatListener;
3841
import net.essentialsx.discord.util.ConsoleInjector;
3942
import net.essentialsx.discord.util.DiscordUtil;
4043
import net.essentialsx.discord.util.MessageUtil;
4144
import org.bukkit.Bukkit;
4245
import org.bukkit.entity.Player;
4346
import org.bukkit.event.HandlerList;
47+
import org.bukkit.event.Listener;
4448
import org.bukkit.plugin.Plugin;
4549
import org.bukkit.plugin.ServicePriority;
4650
import org.jetbrains.annotations.NotNull;
@@ -75,6 +79,7 @@ public class JDADiscordService implements DiscordService, IEssentialsModule {
7579
private ConsoleInjector injector;
7680
private DiscordCommandDispatcher commandDispatcher;
7781
private InteractionControllerImpl interactionController;
82+
private Listener chatListener;
7883
private boolean invalidStartup = false;
7984

8085
public JDADiscordService(EssentialsDiscord plugin) {
@@ -206,6 +211,8 @@ public void startup() throws LoginException, InterruptedException {
206211

207212
Bukkit.getPluginManager().registerEvents(new BukkitListener(this), plugin);
208213

214+
updateListener();
215+
209216
try {
210217
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_12_0_R01)) {
211218
try {
@@ -259,9 +266,14 @@ public void sendMessage(MessageType type, String message, boolean allowGroupMent
259266

260267
@Override
261268
public void sendChatMessage(final Player player, final String chatMessage) {
269+
sendChatMessage(ChatType.UNKNOWN, player, chatMessage);
270+
}
271+
272+
@Override
273+
public void sendChatMessage(ChatType chatType, Player player, String chatMessage) {
262274
final User user = getPlugin().getEss().getUser(player);
263275

264-
final String formattedMessage = MessageUtil.formatMessage(getSettings().getMcToDiscordFormat(player),
276+
final String formattedMessage = MessageUtil.formatMessage(getSettings().getMcToDiscordFormat(player, chatType),
265277
MessageUtil.sanitizeDiscordMarkdown(player.getName()),
266278
MessageUtil.sanitizeDiscordMarkdown(player.getDisplayName()),
267279
user.isAuthorized("essentials.discord.markdown") ? chatMessage : MessageUtil.sanitizeDiscordMarkdown(chatMessage),
@@ -272,7 +284,20 @@ public void sendChatMessage(final Player player, final String chatMessage) {
272284
final String avatarUrl = DiscordUtil.getAvatarUrl(this, player);
273285
final String name = getSettings().isShowName() ? player.getName() : (getSettings().isShowDisplayName() ? player.getDisplayName() : null);
274286

275-
DiscordUtil.dispatchDiscordMessage(this, MessageType.DefaultTypes.CHAT, formattedMessage, user.isAuthorized("essentials.discord.ping"), avatarUrl, name, player.getUniqueId());
287+
DiscordUtil.dispatchDiscordMessage(this, chatTypeToMessageType(chatType), formattedMessage, user.isAuthorized("essentials.discord.ping"), avatarUrl, name, player.getUniqueId());
288+
}
289+
290+
private MessageType chatTypeToMessageType(ChatType chatType) {
291+
switch (chatType) {
292+
case SHOUT:
293+
return MessageType.DefaultTypes.SHOUT;
294+
case QUESTION:
295+
return MessageType.DefaultTypes.QUESTION;
296+
case LOCAL:
297+
return MessageType.DefaultTypes.LOCAL;
298+
default:
299+
return MessageType.DefaultTypes.CHAT;
300+
}
276301
}
277302

278303
@Override
@@ -303,6 +328,30 @@ public String parseMessageEmotes(String message) {
303328
return message;
304329
}
305330

331+
public void updateListener() {
332+
if (getSettings().isUseEssentialsEvents() && plugin.isEssentialsChat()) {
333+
if (!(chatListener instanceof EssentialsChatListener)) {
334+
if (chatListener != null) {
335+
HandlerList.unregisterAll(chatListener);
336+
}
337+
338+
chatListener = new EssentialsChatListener(this);
339+
340+
Bukkit.getPluginManager().registerEvents(chatListener, plugin);
341+
}
342+
} else {
343+
if (!(chatListener instanceof BukkitChatListener)) {
344+
if (chatListener != null) {
345+
HandlerList.unregisterAll(chatListener);
346+
}
347+
348+
chatListener = new BukkitChatListener(this);
349+
350+
Bukkit.getPluginManager().registerEvents(chatListener, plugin);
351+
}
352+
}
353+
}
354+
306355
public void updatePresence() {
307356
jda.getPresence().setPresence(plugin.getSettings().getStatus(), plugin.getSettings().getStatusActivity());
308357
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package net.essentialsx.discord.listeners;
2+
3+
import net.essentialsx.api.v2.ChatType;
4+
import net.essentialsx.api.v2.events.discord.DiscordChatMessageEvent;
5+
import net.essentialsx.discord.JDADiscordService;
6+
import org.bukkit.Bukkit;
7+
import org.bukkit.entity.Player;
8+
import org.bukkit.event.EventHandler;
9+
import org.bukkit.event.EventPriority;
10+
import org.bukkit.event.Listener;
11+
import org.bukkit.event.player.AsyncPlayerChatEvent;
12+
13+
public class BukkitChatListener implements Listener {
14+
private final JDADiscordService jda;
15+
16+
public BukkitChatListener(JDADiscordService jda) {
17+
this.jda = jda;
18+
}
19+
20+
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
21+
public void onChat(AsyncPlayerChatEvent event) {
22+
final Player player = event.getPlayer();
23+
Bukkit.getScheduler().runTask(jda.getPlugin(), () -> {
24+
final DiscordChatMessageEvent chatEvent = new DiscordChatMessageEvent(event.getPlayer(), event.getMessage(), ChatType.UNKNOWN);
25+
chatEvent.setCancelled(!jda.getSettings().isShowAllChat() && !event.getRecipients().containsAll(Bukkit.getOnlinePlayers()));
26+
Bukkit.getPluginManager().callEvent(chatEvent);
27+
if (chatEvent.isCancelled()) {
28+
return;
29+
}
30+
31+
jda.sendChatMessage(player, chatEvent.getMessage());
32+
});
33+
}
34+
}

EssentialsDiscord/src/main/java/net/essentialsx/discord/listeners/BukkitListener.java

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,18 @@
1010
import net.ess3.provider.AbstractAchievementEvent;
1111
import net.essentialsx.api.v2.events.AsyncUserDataLoadEvent;
1212
import net.essentialsx.api.v2.events.UserActionEvent;
13-
import net.essentialsx.api.v2.events.discord.DiscordChatMessageEvent;
1413
import net.essentialsx.api.v2.events.discord.DiscordMessageEvent;
1514
import net.essentialsx.api.v2.services.discord.MessageType;
1615
import net.essentialsx.discord.JDADiscordService;
1716
import net.essentialsx.discord.util.DiscordUtil;
1817
import net.essentialsx.discord.util.MessageUtil;
19-
import org.bukkit.Bukkit;
2018
import org.bukkit.ChatColor;
2119
import org.bukkit.GameRule;
2220
import org.bukkit.entity.Player;
2321
import org.bukkit.event.EventHandler;
2422
import org.bukkit.event.EventPriority;
2523
import org.bukkit.event.Listener;
2624
import org.bukkit.event.entity.PlayerDeathEvent;
27-
import org.bukkit.event.player.AsyncPlayerChatEvent;
2825
import org.bukkit.event.player.PlayerKickEvent;
2926
import org.bukkit.event.player.PlayerQuitEvent;
3027

@@ -80,21 +77,6 @@ public void onMute(MuteStatusChangeEvent event) {
8077
}
8178
}
8279

83-
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
84-
public void onChat(AsyncPlayerChatEvent event) {
85-
final Player player = event.getPlayer();
86-
Bukkit.getScheduler().runTask(jda.getPlugin(), () -> {
87-
final DiscordChatMessageEvent chatEvent = new DiscordChatMessageEvent(event.getPlayer(), event.getMessage());
88-
chatEvent.setCancelled(!jda.getSettings().isShowAllChat() && !event.getRecipients().containsAll(Bukkit.getOnlinePlayers()));
89-
Bukkit.getPluginManager().callEvent(chatEvent);
90-
if (chatEvent.isCancelled()) {
91-
return;
92-
}
93-
94-
jda.sendChatMessage(player, chatEvent.getMessage());
95-
});
96-
}
97-
9880
@EventHandler(priority = EventPriority.MONITOR)
9981
public void onJoin(AsyncUserDataLoadEvent event) {
10082
// Delay join to let nickname load

0 commit comments

Comments
 (0)