Introduce support for web chat integration.

- Replaced synchronous permission checks with asynchronous LuckPerms user loading.
- Added `getOrLoadUser` utility to simplify user-related operations.
- Introduced web-originated chat command processing via new `PunishmentCommandBuilder` and `PunishFromWebHandler`.
- Updated `MuteServer`, `ToggleGlobalChat`, and `ToggleableForCustomChannel` to use async permission checks.
- Added test suite for `PunishmentCommandBuilder`.
- Expanded chat handling to process party messages from web events.
This commit is contained in:
2026-08-09 19:39:55 +02:00
parent 0d2ac3763f
commit 9e647f83a8
26 changed files with 900 additions and 169 deletions
@@ -1,6 +1,7 @@
package com.alttd.chat;
import com.alttd.chat.chat_web.ChatMessageSender;
import com.alttd.chat.chat_web.handlers.WebChannelChatHandler;
import com.alttd.chat.chat_web.handlers.WebChatHandler;
import com.alttd.chat.commands.*;
import com.alttd.chat.config.Config;
@@ -72,9 +73,13 @@ public class ChatPlugin extends JavaPlugin {
if (!(channel instanceof CustomChannel customChannel)) {
continue;
}
ChatChannel chatChannel = new ChatChannel(customChannel, chatAPI.getLuckPerms());
this.getServer()
.getCommandMap()
.register(channel.getChannelName().toLowerCase(), new ChatChannel(customChannel));
.register(channel.getChannelName().toLowerCase(), chatChannel);
if (customChannel.getWebPath() != null) {
sseSubscribeClient.register(customChannel.getWebPath(), new WebChannelChatHandler(chatChannel));
}
}
String messageChannel = Config.MESSAGECHANNEL;
@@ -25,9 +25,7 @@ import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
import net.luckperms.api.LuckPerms;
import net.luckperms.api.context.ImmutableContextSet;
import net.luckperms.api.model.user.User;
import net.luckperms.api.query.QueryOptions;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.Sound;
@@ -76,7 +74,7 @@ public class ChatMessageSender {
ALogger.error("OfflinePlayer is null");
return;
}
if (ChatPlugin.getInstance().serverMuted() && !hasPermission(user, "chat.bypass-server-muted")) {
if (ChatPlugin.getInstance().serverMuted() && !Utility.hasPermission(user, "chat.bypass-server-muted")) {
sendBlockNotifIfOnline(offlinePlayer, message);
return;
}
@@ -105,7 +103,7 @@ public class ChatMessageSender {
Stream<Player> stream = Bukkit.getOnlinePlayers().stream()
.map(audience -> (Player) audience);
if (!hasPermission(user, "chat.ignorebypass")) {
if (!Utility.hasPermission(user, "chat.ignorebypass")) {
stream = stream.filter(receiver -> {
boolean isPlayerIgnored = ChatUserManager
.getChatUser(receiver.getUniqueId())
@@ -205,7 +203,7 @@ public class ChatMessageSender {
if (!ChatUserManager.getChatUser(onlinePlayer.getUniqueId())
.getIgnoredPlayers()
.contains(offlinePlayer.getUniqueId())
|| hasPermission(user, "chat.ignorebypass")) {
|| Utility.hasPermission(user, "chat.ignorebypass")) {
playersToPing.add(onlinePlayer);
}
} else if (nickPattern.matcher(modifiableString.string()).find()) {
@@ -217,7 +215,7 @@ public class ChatMessageSender {
if (!ChatUserManager.getChatUser(onlinePlayer.getUniqueId())
.getIgnoredPlayers()
.contains(offlinePlayer.getUniqueId())
|| hasPermission(user, "chat.ignorebypass")) {
|| Utility.hasPermission(user, "chat.ignorebypass")) {
playersToPing.add(onlinePlayer);
}
}
@@ -272,11 +270,4 @@ public class ChatMessageSender {
GalaxyUtility.sendBlockedNotification("Chat Muted", player, message, "");
}
private boolean hasPermission(User user, String permission) {
return user.getCachedData()
.getPermissionData(QueryOptions.contextual(ImmutableContextSet.of("server", luckPerms.getServerName())))
.checkPermission(permission)
.asBoolean();
}
}
@@ -0,0 +1,22 @@
package com.alttd.chat.chat_web.handlers;
import com.alttd.chat.commands.ChatChannel;
import com.alttd.chat.web.WebHandler;
import com.alttd.chat.web.handler_class.ChatFromWeb;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public class WebChannelChatHandler implements WebHandler<ChatFromWeb> {
private final ChatChannel chatChannel;
@Override
public Class<ChatFromWeb> type() {
return ChatFromWeb.class;
}
@Override
public void handle(ChatFromWeb chatFromWeb) {
this.chatChannel.execute(chatFromWeb);
}
}
@@ -2,10 +2,17 @@ package com.alttd.chat.commands;
import com.alttd.chat.config.Config;
import com.alttd.chat.objects.channels.CustomChannel;
import com.alttd.chat.util.ALogger;
import com.alttd.chat.util.ToggleableForCustomChannel;
import com.alttd.chat.util.Utility;
import com.alttd.chat.web.handler_class.ChatFromWeb;
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
import net.luckperms.api.LuckPerms;
import net.luckperms.api.model.user.User;
import org.apache.commons.lang3.StringUtils;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.CommandSender;
import org.bukkit.command.defaults.BukkitCommand;
import org.bukkit.entity.Player;
@@ -13,16 +20,19 @@ import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class ChatChannel extends BukkitCommand {
CustomChannel channel;
String command;
ToggleableForCustomChannel toggleableForCustomChannel;
private final LuckPerms luckPerms;
private static final List<ChatChannel> activeCommands = new ArrayList<>();
public ChatChannel(CustomChannel channel) {
public ChatChannel(CustomChannel channel, LuckPerms luckPerms) {
super(channel.getChannelName().toLowerCase());
this.luckPerms = luckPerms;
this.channel = channel;
this.command = channel.getChannelName().toLowerCase();
this.description = "Chat channel named " + channel.getChannelName() + ".";
@@ -40,9 +50,12 @@ public class ChatChannel extends BukkitCommand {
if (args.length == 0 && player.hasPermission(channel.getPermission())) {
player.sendRichMessage(Config.CUSTOM_CHANNEL_TOGGLED, TagResolver.resolver(
Placeholder.unparsed("channel", channel.getChannelName()),
Placeholder.component("status", toggleableForCustomChannel.toggle(player.getUniqueId())
? Config.TOGGLED_ON : Config.TOGGLED_OFF)));
Placeholder.unparsed("channel", channel.getChannelName()),
Placeholder.component("status", toggleableForCustomChannel.toggle(player.getUniqueId())
? Config.TOGGLED_ON : Config.TOGGLED_OFF
)
)
);
return false;
}
@@ -52,4 +65,28 @@ public class ChatChannel extends BukkitCommand {
return false;
}
public void execute(ChatFromWeb chatFromWeb) {
UUID uuid = chatFromWeb.getSender();
OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(uuid);
if (luckPerms.getUserManager().isLoaded(uuid)) {
User user = luckPerms.getUserManager().getUser(uuid);
if (user == null) {
ALogger.error("Failed to load loaded user: " + uuid);
return;
}
if (!Utility.hasPermission(user, channel.getPermission())) {
ALogger.warn("Web user %s does not have permission to use this channel".formatted(uuid.toString()));
return;
}
toggleableForCustomChannel.sendMessage(user, offlinePlayer, chatFromWeb.getMessage());
} else {
luckPerms.getUserManager().loadUser(uuid).whenComplete((user, throwable) -> {
if (throwable != null) {
ALogger.error("Failed to load user: " + uuid, throwable);
}
toggleableForCustomChannel.sendMessage(user, offlinePlayer, chatFromWeb.getMessage());
});
}
}
}
@@ -9,11 +9,8 @@ import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
import org.jetbrains.annotations.NotNull;
import java.util.UUID;
public class MuteServer implements CommandExecutor {
@Override
@@ -21,27 +18,27 @@ public class MuteServer implements CommandExecutor {
if (!(sender instanceof Player player)) { // must be a player
return true;
}
new BukkitRunnable() {
@Override
public void run() {
UUID uuid = player.getUniqueId();
if (!Utility.hasPermission(uuid, Config.SERVERMUTEPERMISSION)) {
sender.sendRichMessage("<red>You don't have permission to use this command.</red>");
return;
}
ChatPlugin.getInstance().toggleServerMuted();
ComponentLike component;
if (ChatPlugin.getInstance().serverMuted()) {
component = Utility.parseMiniMessage(Utility.getDisplayName(player.getUniqueId(), player.getName()) + " <red>muted</red><white> chat.");
} else {
component = Utility.parseMiniMessage(Utility.getDisplayName(player.getUniqueId(), player.getName()) + " <green>un-muted</green><white> chat.");
}
Bukkit.getOnlinePlayers().forEach(player -> player.sendMessage(component));
Utility.getOrLoadUser(player.getUniqueId()).thenAcceptAsync(user -> {
if (!Utility.hasPermission(user, Config.SERVERMUTEPERMISSION)) {
sender.sendRichMessage("<red>You don't have permission to use this command.</red>");
return;
}
}.runTaskAsynchronously(ChatPlugin.getInstance());
ChatPlugin.getInstance().toggleServerMuted();
ComponentLike component;
if (ChatPlugin.getInstance().serverMuted()) {
component = Utility.parseMiniMessage(Utility.getDisplayName(player.getUniqueId(),
player.getName()
) + " <red>muted</red><white> chat.");
} else {
component = Utility.parseMiniMessage(Utility.getDisplayName(player.getUniqueId(),
player.getName()
) + " <green>un-muted</green><white> chat.");
}
Bukkit.getOnlinePlayers().forEach(onlinePlayer -> onlinePlayer.sendMessage(component));
});
return false;
}
@@ -5,7 +5,9 @@ import com.alttd.chat.config.Config;
import com.alttd.chat.objects.Toggleable;
import com.alttd.chat.util.ALogger;
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
import net.luckperms.api.model.user.User;
import org.apache.commons.lang3.StringUtils;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
@@ -70,4 +72,9 @@ public class PartyChat extends Toggleable implements CommandExecutor {
}
}.runTaskAsynchronously(ChatPlugin.getInstance());
}
@Override
public void sendMessage(User user, OfflinePlayer offlinePlayer, String message) {
//TODO [Stijn] [2026-08-09]: Implement
}
}
@@ -1,6 +1,5 @@
package com.alttd.chat.commands;
import com.alttd.chat.ChatPlugin;
import com.alttd.chat.config.Config;
import com.alttd.chat.managers.ChatUserManager;
import com.alttd.chat.util.Utility;
@@ -8,7 +7,6 @@ import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
import org.jetbrains.annotations.NotNull;
import java.util.UUID;
@@ -17,18 +15,17 @@ public class ToggleGlobalChat implements CommandExecutor {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) {
if (!(sender instanceof Player)) {
if (!(sender instanceof Player player)) {
return true;
}
new BukkitRunnable() {
@Override
public void run() {
UUID uuid = ((Player) sender).getUniqueId();
ChatUserManager.getChatUser(uuid);
Utility.flipPermission(uuid, Config.GCPERMISSION);
sender.sendRichMessage("You have turned globalchat " + (!Utility.hasPermission(uuid, Config.GCPERMISSION) ? "<green>on." : "<red>off.")); // TODO load from config and minimessage
}
}.runTaskAsynchronously(ChatPlugin.getInstance());
UUID uuid = player.getUniqueId();
Utility.getOrLoadUser(uuid).thenAcceptAsync(user -> {
ChatUserManager.getChatUser(uuid);
Utility.flipPermission(uuid, Config.GCPERMISSION);
sender.sendRichMessage("You have turned globalchat " + (!Utility.hasPermission(user,
Config.GCPERMISSION
) ? "<green>on." : "<red>off.")); // TODO load from config and minimessage
});
return false;
}
@@ -16,6 +16,7 @@ import com.alttd.chat.util.ServerName;
import com.alttd.chat.util.Utility;
import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams;
import lombok.extern.slf4j.Slf4j;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.ComponentLike;
import net.kyori.adventure.text.TextReplacementConfig;
@@ -24,20 +25,24 @@ import net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
import net.luckperms.api.model.user.User;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.jspecify.annotations.Nullable;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;
@Slf4j
public class ChatHandler {
private final ChatPlugin plugin;
@@ -52,11 +57,16 @@ public class ChatHandler {
}
public void continuePrivateMessage(Player player, String target, String message) {
Utility.getOrLoadUser(player.getUniqueId())
.thenAccept(user -> continuePrivateMessage(user, player, target, message));
}
public void continuePrivateMessage(User user, Player player, String target, String message) {
// ChatUser user = ChatUserManager.getChatUser(player.getUniqueId());
// user.setReplyTarget(target);
TagResolver placeholders = TagResolver.resolver(
Placeholder.component("message", parseMessageContent(player, message)),
Placeholder.component("message", parseMessageContent(user, player, message)),
Placeholder.component("sendername", player.name()),
Placeholder.parsed("receivername", target)
);
@@ -87,10 +97,15 @@ public class ChatHandler {
}
public void privateMessage(Player player, String target, String message) {
Utility.getOrLoadUser(player.getUniqueId())
.thenAccept(user -> privateMessage(user, player, target, message));
}
public void privateMessage(User user, Player player, String target, String message) {
// ChatUser user = ChatUserManager.getChatUser(player.getUniqueId());
// user.setReplyTarget(target);
Component messageComponent = parseMessageContent(player, message);
Component messageComponent = parseMessageContent(user, player, message);
TagResolver placeholders = TagResolver.resolver(
Placeholder.component("message", messageComponent),
Placeholder.component("sendername", player.name()),
@@ -124,17 +139,22 @@ public class ChatHandler {
}
public void globalChat(Player player, String message) {
ChatUser user = ChatUserManager.getChatUser(player.getUniqueId());
if (!Utility.hasPermission(player.getUniqueId(), Config.GCPERMISSION)) {
Utility.getOrLoadUser(player.getUniqueId())
.thenAccept(user -> globalChat(user, player, message));
}
public void globalChat(User user, Player player, String message) {
ChatUser chatUser = ChatUserManager.getChatUser(player.getUniqueId());
if (!Utility.hasPermission(user, Config.GCPERMISSION)) {
player.sendMessage(GCNOTENABLED);// GC IS OFF INFORM THEM ABOUT THIS and cancel
return;
}
if (isMuted(player, message, "[GC Muted] ")) {
if (isMuted(user, player, message, "[GC Muted] ")) {
return;
}
long timeLeft = TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis() - user.getGcCooldown());
long timeLeft = TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis() - chatUser.getGcCooldown());
if (timeLeft <= Config.GCCOOLDOWN && !player.hasPermission("chat.globalchat.cooldownbypass")) { // player is on cooldown and should wait x seconds
player.sendRichMessage(Config.GCONCOOLDOWN,
Placeholder.parsed("cooldown", Config.GCCOOLDOWN - timeLeft + "")
@@ -142,12 +162,12 @@ public class ChatHandler {
return;
}
ComponentLike senderName = user.getDisplayName();
ComponentLike prefix = user.getPrefix();
ComponentLike senderName = chatUser.getDisplayName();
ComponentLike prefix = chatUser.getPrefix();
TagResolver placeholders = TagResolver.resolver(
Placeholder.component("sender", senderName),
Placeholder.component("prefix", prefix),
Placeholder.component("message", parseMessageContent(player, message)),
Placeholder.component("message", parseMessageContent(user, player, message)),
Placeholder.parsed("server", ServerName.getServerName())
);
@@ -175,40 +195,47 @@ public class ChatHandler {
false
);
user.setGcCooldown(System.currentTimeMillis());
chatUser.setGcCooldown(System.currentTimeMillis());
sendPluginMessage(player, "globalchat", component);
}
public void chatChannel(Player player, CustomChannel channel, String message) {
if (!player.hasPermission(channel.getPermission())) {
player.sendRichMessage("<red>You don't have permission to use this channel.</red>");
public void chatChannel(User user, OfflinePlayer offlinePlayer, CustomChannel channel, String message) {
if (!Utility.hasPermission(user, channel.getPermission())) {
if (offlinePlayer.isOnline()) {
Player onlinePlayer = offlinePlayer.getPlayer();
if (onlinePlayer == null) {
log.error("Player is online but getPlayer() returned null");
return;
}
onlinePlayer.sendRichMessage("<red>You don't have permission to use this channel.</red>");
}
return;
}
if (isMuted(player, message, "[" + channel.getChannelName() + " Muted] ")) {
if (isMuted(user, offlinePlayer, message, "[" + channel.getChannelName() + " Muted] ")) {
ALogger.info("Refusing to send message by muted user");
return;
}
ChatUser user = ChatUserManager.getChatUser(player.getUniqueId());
ComponentLike senderName = user.getDisplayName();
ChatUser chatUser = ChatUserManager.getChatUser(offlinePlayer.getUniqueId());
ComponentLike senderName = chatUser.getDisplayName();
TagResolver placeholders = TagResolver.resolver(
Placeholder.component("sender", senderName),
Placeholder.component("message", parseMessageContent(player, message)),
Placeholder.component("message", parseMessageContent(user, offlinePlayer, message)),
Placeholder.parsed("server", ServerName.getServerName()),
Placeholder.parsed("channel", channel.getChannelName())
);
Component component = Utility.parseMiniMessage(channel.getFormat(), placeholders).asComponent();
ModifiableString modifiableString = new ModifiableString(component);
if (!RegexManager.filterText(player.getName(),
player.getUniqueId(),
if (!RegexManager.filterText(offlinePlayer.getName(),
offlinePlayer.getUniqueId(),
modifiableString,
channel.getChannelName()
)) {
GalaxyUtility.sendBlockedNotification(channel.getChannelName() + " Language",
player,
offlinePlayer,
Utility.parseMiniMessage(Utility.parseColors(modifiableString.string())),
""
);
@@ -219,9 +246,9 @@ public class ChatHandler {
component = modifiableString.component();
if (channel.isProxy()) {
sendChatChannelMessage(player, channel.getChannelName(), "chatchannel", component, message);
sendChatChannelMessage(offlinePlayer, channel.getChannelName(), "chatchannel", component, message);
} else {
sendChatChannelMessage(channel, player.getUniqueId(), component, message);
sendChatChannelMessage(channel, offlinePlayer.getUniqueId(), component, message);
}
}
@@ -366,27 +393,36 @@ public class ChatHandler {
player.sendPluginMessage(plugin, Config.MESSAGECHANNEL, out.toByteArray());
}
public void sendChatChannelMessage(Player player, String chatChannelName, String channel, Component component, String ignored) {
public void sendChatChannelMessage(OfflinePlayer player, String chatChannelName, String channel, Component component, String ignored) {
ByteArrayDataOutput out = ByteStreams.newDataOutput();
out.writeUTF(channel);
out.writeUTF(chatChannelName);
out.writeUTF(player.getUniqueId().toString());
out.writeUTF(GsonComponentSerializer.gson().serialize(component));
player.sendPluginMessage(plugin, Config.MESSAGECHANNEL, out.toByteArray());
Collection<? extends Player> onlinePlayers = Bukkit.getOnlinePlayers();
if (player.isOnline() && player.getPlayer() != null) {
player.getPlayer().sendPluginMessage(plugin, Config.MESSAGECHANNEL, out.toByteArray());
} else {
//TODO [Stijn] [2026-08-09]: Validate that this works
onlinePlayers.stream().findFirst().ifPresent(p ->
p.sendPluginMessage(plugin, Config.MESSAGECHANNEL, out.toByteArray()));
}
}
// Start - move these to util
private boolean isMuted(Player player, String message, String prefix) {
ChatUser user = ChatUserManager.getChatUser(player.getUniqueId());
if (user == null) {
private boolean isMuted(User user, OfflinePlayer offlinePlayer, String message, String prefix) {
ChatUser chatUser = ChatUserManager.getChatUser(offlinePlayer.getUniqueId());
if (chatUser == null) {
return false;
}
if (user.isMuted() || (ChatPlugin.getInstance().serverMuted() && !player.hasPermission(
"chat.bypass-server-muted"))) {
if (chatUser.isMuted() || (ChatPlugin.getInstance()
.serverMuted() && !Utility.hasPermission(user,
"chat.bypass-server-muted"
))) {
// if (Database.get().isPlayerMuted(player.getUniqueId(), null) || (ChatPlugin.getInstance().serverMuted() && !player.hasPermission("chat.bypass-server-muted"))) {
GalaxyUtility.sendBlockedNotification(prefix,
player,
offlinePlayer,
Utility.parseMiniMessage(Utility.stripTokens(message)),
""
);
@@ -437,11 +473,11 @@ public class ChatHandler {
}
// end - move these to util
private Component parseMessageContent(Player player, String rawMessage) {
private Component parseMessageContent(User user, OfflinePlayer offlinePlayer, String rawMessage) {
TagResolver.Builder tagResolver = TagResolver.builder();
Utility.formattingPerms.forEach((perm, pair) -> {
if (player.hasPermission(perm)) {
if (Utility.hasPermission(user, perm)) {
tagResolver.resolver(pair.getX());
}
});
@@ -456,13 +492,16 @@ public class ChatHandler {
.replacement(chatFilter.getReplacement()).build());
}
component = component
.replaceText(
TextReplacementConfig.builder()
.once()
.matchLiteral("[i]")
.replacement(ChatHandler.itemComponent(player.getInventory().getItemInMainHand()))
.build());
if (offlinePlayer.isOnline() && offlinePlayer.getPlayer() != null) {
component = component
.replaceText(
TextReplacementConfig.builder()
.once()
.matchLiteral("[i]")
.replacement(ChatHandler.itemComponent(offlinePlayer.getPlayer().getInventory()
.getItemInMainHand()))
.build());
}
return component;
@@ -3,6 +3,8 @@ package com.alttd.chat.util;
import com.alttd.chat.ChatPlugin;
import com.alttd.chat.objects.Toggleable;
import com.alttd.chat.objects.channels.CustomChannel;
import net.luckperms.api.model.user.User;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
@@ -38,11 +40,27 @@ public class ToggleableForCustomChannel extends Toggleable {
@Override
public void sendMessage(Player player, String message) {
Utility.getOrLoadUser(player.getUniqueId()).thenAcceptAsync(user -> {
ALogger.info(String.format("%s sent %s message: %s",
player.getName(),
customChannel.getChannelName(),
message
));
ChatPlugin.getInstance().getChatHandler().chatChannel(user, player, customChannel, message);
});
}
@Override
public void sendMessage(User user, OfflinePlayer offlinePlayer, String message) {
new BukkitRunnable() {
@Override
public void run() {
ALogger.info(String.format("%s sent %s message: %s", player.getName(), customChannel.getChannelName(), message));
ChatPlugin.getInstance().getChatHandler().chatChannel(player, customChannel, message);
ALogger.info(String.format("%s sent %s message: %s",
offlinePlayer.getName(),
customChannel.getChannelName(),
message
));
ChatPlugin.getInstance().getChatHandler().chatChannel(user, offlinePlayer, customChannel, message);
}
}.runTaskAsynchronously(ChatPlugin.getInstance());
}