diff --git a/build.gradle.kts b/build.gradle.kts index 19a9fa07a9..d8242c3071 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -33,6 +33,7 @@ repositories { maven("https://repo.opencollab.dev/maven-releases/") // Cumulus (for Floodgate) maven("https://repo.codemc.io/repository/maven-releases/") // PacketEvents maven("https://repo.codemc.io/repository/maven-snapshots/") + maven("https://repo.extendedclip.com/content/repositories/placeholderapi/") // placeholderapi mavenCentral() // FastUtil, Discord-Webhooks } @@ -48,11 +49,14 @@ dependencies { // Used for local testing: implementation("ac.grim.grimac:GRIMAPI:1.0") implementation("com.github.grimanticheat:grimapi:fc5634e444") + implementation("net.kyori:adventure-text-minimessage:4.17.0") + implementation("net.kyori:adventure-platform-bukkit:4.3.3") + implementation("org.jetbrains:annotations:24.1.0") compileOnly("org.geysermc.floodgate:api:2.0-SNAPSHOT") compileOnly("org.spigotmc:spigot-api:1.18.2-R0.1-SNAPSHOT") compileOnly("com.viaversion:viaversion-api:4.9.4-SNAPSHOT") - // + compileOnly("me.clip:placeholderapi:2.11.6") compileOnly("io.netty:netty-all:4.1.85.Final") } diff --git a/src/main/java/ac/grim/grimac/GrimExternalAPI.java b/src/main/java/ac/grim/grimac/GrimExternalAPI.java index 1d2e7afc30..a6c66b9c2f 100644 --- a/src/main/java/ac/grim/grimac/GrimExternalAPI.java +++ b/src/main/java/ac/grim/grimac/GrimExternalAPI.java @@ -51,8 +51,7 @@ public void setServerName(String name) { @Getter private final Map staticReplacements = new ConcurrentHashMap<>(); - public String replaceVariables(GrimUser user, String content, boolean colors) { - if (colors) content = ChatColor.translateAlternateColorCodes('&', content); + public String replaceVariables(GrimUser user, String content) { for (Map.Entry entry : staticReplacements.entrySet()) { content = content.replace(entry.getKey(), entry.getValue()); } diff --git a/src/main/java/ac/grim/grimac/checks/impl/misc/ClientBrand.java b/src/main/java/ac/grim/grimac/checks/impl/misc/ClientBrand.java index ce51c019d6..0687749cc0 100644 --- a/src/main/java/ac/grim/grimac/checks/impl/misc/ClientBrand.java +++ b/src/main/java/ac/grim/grimac/checks/impl/misc/ClientBrand.java @@ -5,9 +5,11 @@ import ac.grim.grimac.checks.impl.exploit.ExploitA; import ac.grim.grimac.checks.type.PacketCheck; import ac.grim.grimac.player.GrimPlayer; +import ac.grim.grimac.utils.anticheat.MessageUtil; import com.github.retrooper.packetevents.event.PacketReceiveEvent; import com.github.retrooper.packetevents.protocol.packettype.PacketType; import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPluginMessage; +import net.kyori.adventure.text.Component; import org.bukkit.Bukkit; import org.bukkit.entity.Player; @@ -41,11 +43,14 @@ public void handle(String channel, byte[] data) { if (player.checkManager.getPrePredictionCheck(ExploitA.class).checkString(brand)) brand = "sent log4j"; if (!GrimAPI.INSTANCE.getConfigManager().isIgnoredClient(brand)) { String message = GrimAPI.INSTANCE.getConfigManager().getConfig().getStringElse("client-brand-format", "%prefix% &f%player% joined using %brand%"); - message = GrimAPI.INSTANCE.getExternalAPI().replaceVariables(getPlayer(), message, true); + message = MessageUtil.replacePlaceholders(getPlayer(), message); + + Component component = MessageUtil.miniMessage(message); + // sendMessage is async safe while broadcast isn't due to adventure for (Player player : Bukkit.getOnlinePlayers()) { if (player.hasPermission("grim.brand")) { - player.sendMessage(message); + MessageUtil.sendMessage(player, component); } } } diff --git a/src/main/java/ac/grim/grimac/commands/GrimHelp.java b/src/main/java/ac/grim/grimac/commands/GrimHelp.java index 41e4b7de86..c2ae7056bc 100644 --- a/src/main/java/ac/grim/grimac/commands/GrimHelp.java +++ b/src/main/java/ac/grim/grimac/commands/GrimHelp.java @@ -16,8 +16,8 @@ public class GrimHelp extends BaseCommand { @CommandPermission("grim.help") public void onHelp(CommandSender sender) { for (String string : GrimAPI.INSTANCE.getConfigManager().getConfig().getStringList("help")) { - string = MessageUtil.format(string); - sender.sendMessage(string); + string = MessageUtil.replacePlaceholders(sender, string); + MessageUtil.sendMessage(sender, MessageUtil.miniMessage(string)); } } } diff --git a/src/main/java/ac/grim/grimac/commands/GrimLog.java b/src/main/java/ac/grim/grimac/commands/GrimLog.java index 924ef29d2d..24669602f3 100644 --- a/src/main/java/ac/grim/grimac/commands/GrimLog.java +++ b/src/main/java/ac/grim/grimac/commands/GrimLog.java @@ -26,43 +26,50 @@ public void onLog(CommandSender sender, int flagId) { if (builder == null) { String failure = GrimAPI.INSTANCE.getConfigManager().getConfig().getStringElse("upload-log-not-found", "%prefix% &cUnable to find that log"); - sender.sendMessage(MessageUtil.format(failure)); - } else { - String uploading = GrimAPI.INSTANCE.getConfigManager().getConfig().getStringElse("upload-log-start", "%prefix% &fUploading log... please wait"); - String success = GrimAPI.INSTANCE.getConfigManager().getConfig().getStringElse("upload-log", "%prefix% &fUploaded debug to: %url%"); - String failure = GrimAPI.INSTANCE.getConfigManager().getConfig().getStringElse("upload-log-upload-failure", "%prefix% &cSomething went wrong while uploading this log, see console for more information."); + failure = MessageUtil.replacePlaceholders(sender, failure); + MessageUtil.sendMessage(sender, MessageUtil.miniMessage(failure)); + return; + } - sender.sendMessage(MessageUtil.format(uploading)); + String success = GrimAPI.INSTANCE.getConfigManager().getConfig().getStringElse("upload-log", "%prefix% &fUploaded debug to: %url%"); + String failure = GrimAPI.INSTANCE.getConfigManager().getConfig().getStringElse("upload-log-upload-failure", "%prefix% &cSomething went wrong while uploading this log, see console for more information."); - FoliaScheduler.getAsyncScheduler().runNow(GrimAPI.INSTANCE.getPlugin(), (dummy) -> { - try { - URL mUrl = new URL("https://paste.grim.ac/data/post"); - HttpURLConnection urlConn = (HttpURLConnection) mUrl.openConnection(); - urlConn.setDoOutput(true); - urlConn.setRequestMethod("POST"); - urlConn.addRequestProperty("User-Agent", "GrimAC/" + GrimAPI.INSTANCE.getExternalAPI().getGrimVersion()); - urlConn.addRequestProperty("Content-Type", "text/yaml"); // Not really yaml, but looks nicer than plaintext - urlConn.setRequestProperty("Content-Length", Integer.toString(builder.length())); - urlConn.getOutputStream().write(builder.toString().getBytes(StandardCharsets.UTF_8)); + String uploading = GrimAPI.INSTANCE.getConfigManager().getConfig().getStringElse("upload-log-start", "%prefix% &fUploading log... please wait"); + uploading = MessageUtil.replacePlaceholders(sender, uploading); + MessageUtil.sendMessage(sender, MessageUtil.miniMessage(uploading)); - urlConn.getOutputStream().close(); + FoliaScheduler.getAsyncScheduler().runNow(GrimAPI.INSTANCE.getPlugin(), (dummy) -> { + try { + URL mUrl = new URL("https://paste.grim.ac/data/post"); + HttpURLConnection urlConn = (HttpURLConnection) mUrl.openConnection(); + urlConn.setDoOutput(true); + urlConn.setRequestMethod("POST"); + urlConn.addRequestProperty("User-Agent", "GrimAC/" + GrimAPI.INSTANCE.getExternalAPI().getGrimVersion()); + urlConn.addRequestProperty("Content-Type", "text/yaml"); // Not really yaml, but looks nicer than plaintext + urlConn.setRequestProperty("Content-Length", Integer.toString(builder.length())); + urlConn.getOutputStream().write(builder.toString().getBytes(StandardCharsets.UTF_8)); - int response = urlConn.getResponseCode(); + urlConn.getOutputStream().close(); - if (response == HttpURLConnection.HTTP_CREATED) { - String responseURL = urlConn.getHeaderField("Location"); - sender.sendMessage(MessageUtil.format(success.replace("%url%", "https://paste.grim.ac/" + responseURL))); - } else { - sender.sendMessage(MessageUtil.format(failure)); - LogUtil.error("Returned response code " + response + ": " + urlConn.getResponseMessage()); - } + int response = urlConn.getResponseCode(); - urlConn.disconnect(); - } catch (Exception e) { - sender.sendMessage(MessageUtil.format(failure)); - e.printStackTrace(); + if (response == HttpURLConnection.HTTP_CREATED) { + String responseURL = urlConn.getHeaderField("Location"); + String message = success.replace("%url%", "https://paste.grim.ac/" + responseURL); + message = MessageUtil.replacePlaceholders(sender, message); + MessageUtil.sendMessage(sender, MessageUtil.miniMessage(message)); + } else { + String message = MessageUtil.replacePlaceholders(sender, failure); + MessageUtil.sendMessage(sender, MessageUtil.miniMessage(message)); + LogUtil.error("Returned response code " + response + ": " + urlConn.getResponseMessage()); } - }); - } + + urlConn.disconnect(); + } catch (Exception e) { + String message = MessageUtil.replacePlaceholders(sender, failure); + MessageUtil.sendMessage(sender, MessageUtil.miniMessage(message)); + e.printStackTrace(); + } + }); } } diff --git a/src/main/java/ac/grim/grimac/commands/GrimProfile.java b/src/main/java/ac/grim/grimac/commands/GrimProfile.java index d6f5444787..a5ba5d2ae9 100644 --- a/src/main/java/ac/grim/grimac/commands/GrimProfile.java +++ b/src/main/java/ac/grim/grimac/commands/GrimProfile.java @@ -1,12 +1,9 @@ package ac.grim.grimac.commands; import ac.grim.grimac.GrimAPI; -import ac.grim.grimac.checks.impl.aim.processor.AimProcessor; -import ac.grim.grimac.checks.impl.misc.ClientBrand; import ac.grim.grimac.player.GrimPlayer; import ac.grim.grimac.utils.anticheat.MessageUtil; import ac.grim.grimac.utils.anticheat.MultiLibUtil; -import ac.grim.grimac.utils.math.GrimMath; import co.aikar.commands.BaseCommand; import co.aikar.commands.annotation.CommandAlias; import co.aikar.commands.annotation.CommandCompletion; @@ -16,7 +13,6 @@ import com.github.retrooper.packetevents.PacketEvents; import com.github.retrooper.packetevents.manager.server.ServerVersion; import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; @CommandAlias("grim|grimac") public class GrimProfile extends BaseCommand { @@ -24,26 +20,25 @@ public class GrimProfile extends BaseCommand { @CommandPermission("grim.profile") @CommandCompletion("@players") public void onConsoleDebug(CommandSender sender, OnlinePlayer target) { - Player player = null; - if (sender instanceof Player) player = (Player) sender; - // Short circuit due to minimum java requirements for MultiLib if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_18) && MultiLibUtil.isExternalPlayer(target.getPlayer())) { String alertString = GrimAPI.INSTANCE.getConfigManager().getConfig().getStringElse("player-not-this-server", "%prefix% &cThis player isn't on this server!"); - sender.sendMessage(MessageUtil.format(alertString)); + alertString = MessageUtil.replacePlaceholders(sender, alertString); + MessageUtil.sendMessage(sender, MessageUtil.miniMessage(alertString)); return; } GrimPlayer grimPlayer = GrimAPI.INSTANCE.getPlayerDataManager().getPlayer(target.getPlayer()); if (grimPlayer == null) { String message = GrimAPI.INSTANCE.getConfigManager().getConfig().getStringElse("player-not-found", "%prefix% &cPlayer is exempt or offline!"); - sender.sendMessage(MessageUtil.format(message)); + message = MessageUtil.replacePlaceholders(sender, message); + MessageUtil.sendMessage(sender, MessageUtil.miniMessage(message)); return; } for (String message : GrimAPI.INSTANCE.getConfigManager().getConfig().getStringList("profile")) { - message = GrimAPI.INSTANCE.getExternalAPI().replaceVariables(grimPlayer, message, true); - sender.sendMessage(message); + message = MessageUtil.replacePlaceholders(grimPlayer, message); + MessageUtil.sendMessage(sender, MessageUtil.miniMessage(message)); } } } diff --git a/src/main/java/ac/grim/grimac/commands/GrimReload.java b/src/main/java/ac/grim/grimac/commands/GrimReload.java index bd1025f5a6..d74c7fa7d2 100644 --- a/src/main/java/ac/grim/grimac/commands/GrimReload.java +++ b/src/main/java/ac/grim/grimac/commands/GrimReload.java @@ -13,16 +13,15 @@ public class GrimReload extends BaseCommand { @Subcommand("reload") @CommandPermission("grim.reload") public void onReload(CommandSender sender) { - //reload config - sender.sendMessage(MessageUtil.format("%prefix% &7Reloading config...")); + // reload config + String reloading = GrimAPI.INSTANCE.getConfigManager().getConfig().getStringElse("reloading", "%prefix% &7Reloading config..."); + MessageUtil.sendMessage(sender, MessageUtil.miniMessage(MessageUtil.replacePlaceholders(sender, reloading))); GrimAPI.INSTANCE.getExternalAPI().reloadAsync().exceptionally(throwable -> false) .thenAccept(bool -> { - if (bool) { - sender.sendMessage(MessageUtil.format("%prefix% &fConfig has been reloaded.")); - } else { - sender.sendMessage(MessageUtil.format("%prefix% &cFailed to reload config.")); - } + String message = bool + ? GrimAPI.INSTANCE.getConfigManager().getConfig().getStringElse("reloaded", "%prefix% &fConfig has been reloaded.") + : GrimAPI.INSTANCE.getConfigManager().getConfig().getStringElse("reload-failed", "%prefix% &cFailed to reload config."); + MessageUtil.sendMessage(sender, MessageUtil.miniMessage(MessageUtil.replacePlaceholders(sender, message))); }); } - } diff --git a/src/main/java/ac/grim/grimac/commands/GrimSendAlert.java b/src/main/java/ac/grim/grimac/commands/GrimSendAlert.java index 1d7036afc0..1f1f15e383 100644 --- a/src/main/java/ac/grim/grimac/commands/GrimSendAlert.java +++ b/src/main/java/ac/grim/grimac/commands/GrimSendAlert.java @@ -7,6 +7,7 @@ import co.aikar.commands.annotation.CommandAlias; import co.aikar.commands.annotation.CommandPermission; import co.aikar.commands.annotation.Subcommand; +import net.kyori.adventure.text.Component; import org.bukkit.entity.Player; @CommandAlias("grim|grimac") @@ -14,14 +15,15 @@ public class GrimSendAlert extends BaseCommand { @Subcommand("sendalert") @CommandPermission("grim.sendalert") public void sendAlert(String string) { - string = MessageUtil.format(string); + string = MessageUtil.replacePlaceholders((Object) null, string); + Component message = MessageUtil.miniMessage(string); for (Player bukkitPlayer : GrimAPI.INSTANCE.getAlertManager().getEnabledAlerts()) { - bukkitPlayer.sendMessage(string); + MessageUtil.sendMessage(bukkitPlayer, message); } if (GrimAPI.INSTANCE.getConfigManager().getConfig().getBooleanElse("alerts.print-to-console", true)) { - LogUtil.console(string); // Print alert to console + LogUtil.console(message); // Print alert to console } } } diff --git a/src/main/java/ac/grim/grimac/commands/GrimSpectate.java b/src/main/java/ac/grim/grimac/commands/GrimSpectate.java index 2b6617c4e9..78773664ef 100644 --- a/src/main/java/ac/grim/grimac/commands/GrimSpectate.java +++ b/src/main/java/ac/grim/grimac/commands/GrimSpectate.java @@ -9,10 +9,6 @@ import co.aikar.commands.bukkit.contexts.OnlinePlayer; import com.github.retrooper.packetevents.PacketEvents; import com.github.retrooper.packetevents.manager.server.ServerVersion; -import io.github.retrooper.packetevents.adventure.serializer.legacy.LegacyComponentSerializer; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.event.ClickEvent; -import net.kyori.adventure.text.event.HoverEvent; import org.bukkit.GameMode; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -28,32 +24,29 @@ public void onSpectate(CommandSender sender, @Optional OnlinePlayer target) { if (target != null && target.getPlayer().getUniqueId().equals(player.getUniqueId())) { String message = GrimAPI.INSTANCE.getConfigManager().getConfig().getStringElse("cannot-run-on-self", "%prefix% &cYou cannot use this command on yourself!"); - sender.sendMessage(MessageUtil.format(message)); + message = MessageUtil.replacePlaceholders(target, message); + MessageUtil.sendMessage(player, MessageUtil.miniMessage(message)); return; } if (target == null || (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_18) && MultiLibUtil.isExternalPlayer(target.getPlayer()))) { String message = GrimAPI.INSTANCE.getConfigManager().getConfig().getStringElse("player-not-this-server", "%prefix% &cThis player isn't on this server!"); - sender.sendMessage(MessageUtil.format(message)); + message = MessageUtil.replacePlaceholders(target, message); + MessageUtil.sendMessage(player, MessageUtil.miniMessage(message)); return; } + //hide player from tab list if (GrimAPI.INSTANCE.getSpectateManager().enable(player)) { GrimPlayer grimPlayer = GrimAPI.INSTANCE.getPlayerDataManager().getPlayer(player); if (grimPlayer != null) { - String message = GrimAPI.INSTANCE.getConfigManager().getConfig().getStringElse("spectate-return", "\n%prefix% &fClick here to return to previous location\n"); - grimPlayer.user.sendMessage( - LegacyComponentSerializer.legacy('&') - .deserialize(MessageUtil.formatWithNoColor(message)) - .clickEvent(ClickEvent.clickEvent(ClickEvent.Action.RUN_COMMAND, "/grim stopspectating")) - .hoverEvent(HoverEvent.showText(Component.text("/grim stopspectating"))) - ); + String message = GrimAPI.INSTANCE.getConfigManager().getConfig().getStringElse("spectate-return", "\n%prefix% &fClick here to return to previous location\n"); + message = MessageUtil.replacePlaceholders(target, message); + grimPlayer.user.sendMessage(MessageUtil.miniMessage(message)); } } player.setGameMode(GameMode.SPECTATOR); player.teleport(target.getPlayer()); } - - } diff --git a/src/main/java/ac/grim/grimac/commands/GrimStopSpectating.java b/src/main/java/ac/grim/grimac/commands/GrimStopSpectating.java index ffbe0f6d9e..51a3c3c508 100644 --- a/src/main/java/ac/grim/grimac/commands/GrimStopSpectating.java +++ b/src/main/java/ac/grim/grimac/commands/GrimStopSpectating.java @@ -24,8 +24,8 @@ public void onStopSpectate(CommandSender sender, String[] args) { GrimAPI.INSTANCE.getSpectateManager().disable(player, teleportBack); } else { String message = GrimAPI.INSTANCE.getConfigManager().getConfig().getStringElse("cannot-spectate-return", "%prefix% &cYou can only do this after spectating a player."); - sender.sendMessage(MessageUtil.format(message)); + message = MessageUtil.replacePlaceholders(sender, message); + MessageUtil.sendMessage(sender, MessageUtil.miniMessage(message)); } } } - diff --git a/src/main/java/ac/grim/grimac/events/packets/ProxyAlertMessenger.java b/src/main/java/ac/grim/grimac/events/packets/ProxyAlertMessenger.java index caf54d88bc..9d87b922fe 100644 --- a/src/main/java/ac/grim/grimac/events/packets/ProxyAlertMessenger.java +++ b/src/main/java/ac/grim/grimac/events/packets/ProxyAlertMessenger.java @@ -2,6 +2,7 @@ import ac.grim.grimac.GrimAPI; import ac.grim.grimac.utils.anticheat.LogUtil; +import ac.grim.grimac.utils.anticheat.MessageUtil; import com.github.retrooper.packetevents.PacketEvents; import com.github.retrooper.packetevents.event.PacketListenerAbstract; import com.github.retrooper.packetevents.event.PacketReceiveEvent; @@ -59,7 +60,7 @@ public void onPacketReceive(final PacketReceiveEvent event) { } for (Player bukkitPlayer : GrimAPI.INSTANCE.getAlertManager().getEnabledAlerts()) - bukkitPlayer.sendMessage(alert); + MessageUtil.sendMessage(bukkitPlayer, MessageUtil.miniMessage(alert)); } public static void sendPluginMessage(String message) { diff --git a/src/main/java/ac/grim/grimac/manager/AlertManagerImpl.java b/src/main/java/ac/grim/grimac/manager/AlertManagerImpl.java index 873d0af92b..0170288f1f 100644 --- a/src/main/java/ac/grim/grimac/manager/AlertManagerImpl.java +++ b/src/main/java/ac/grim/grimac/manager/AlertManagerImpl.java @@ -25,13 +25,13 @@ public boolean hasAlertsEnabled(Player player) { public void toggleAlerts(Player player) { if (!enabledAlerts.remove(player)) { String alertString = GrimAPI.INSTANCE.getConfigManager().getConfig().getStringElse("alerts-enabled", "%prefix% &fAlerts enabled"); - alertString = MessageUtil.format(alertString); - player.sendMessage(alertString); + alertString = MessageUtil.replacePlaceholders(player, alertString); + MessageUtil.sendMessage(player, MessageUtil.miniMessage(alertString)); enabledAlerts.add(player); } else { String alertString = GrimAPI.INSTANCE.getConfigManager().getConfig().getStringElse("alerts-disabled", "%prefix% &fAlerts disabled"); - alertString = MessageUtil.format(alertString); - player.sendMessage(alertString); + alertString = MessageUtil.replacePlaceholders(player, alertString); + MessageUtil.sendMessage(player, MessageUtil.miniMessage(alertString)); } } @@ -44,13 +44,13 @@ public boolean hasVerboseEnabled(Player player) { public void toggleVerbose(Player player) { if (!enabledVerbose.remove(player)) { String alertString = GrimAPI.INSTANCE.getConfigManager().getConfig().getStringElse("verbose-enabled", "%prefix% &fVerbose enabled"); - alertString = MessageUtil.format(alertString); - player.sendMessage(alertString); + alertString = MessageUtil.replacePlaceholders(player, alertString); + MessageUtil.sendMessage(player, MessageUtil.miniMessage(alertString)); enabledVerbose.add(player); } else { String alertString = GrimAPI.INSTANCE.getConfigManager().getConfig().getStringElse("verbose-disabled", "%prefix% &fVerbose disabled"); - alertString = MessageUtil.format(alertString); - player.sendMessage(alertString); + alertString = MessageUtil.replacePlaceholders(player, alertString); + MessageUtil.sendMessage(player, MessageUtil.miniMessage(alertString)); } } diff --git a/src/main/java/ac/grim/grimac/manager/DiscordManager.java b/src/main/java/ac/grim/grimac/manager/DiscordManager.java index 471ed59cd6..b9d6a172ee 100644 --- a/src/main/java/ac/grim/grimac/manager/DiscordManager.java +++ b/src/main/java/ac/grim/grimac/manager/DiscordManager.java @@ -4,6 +4,7 @@ import ac.grim.grimac.manager.init.Initable; import ac.grim.grimac.player.GrimPlayer; import ac.grim.grimac.utils.anticheat.LogUtil; +import ac.grim.grimac.utils.anticheat.MessageUtil; import club.minnced.discord.webhook.WebhookClient; import club.minnced.discord.webhook.send.WebhookEmbed; import club.minnced.discord.webhook.send.WebhookEmbedBuilder; @@ -76,7 +77,7 @@ public void sendAlert(GrimPlayer player, String verbose, String checkName, Strin String content = staticContent; content = content.replace("%check%", checkName); content = content.replace("%violations%", violations); - content = GrimAPI.INSTANCE.getExternalAPI().replaceVariables(player, content, false); + content = MessageUtil.replacePlaceholders(player, content); content = content.replace("_", "\\_"); WebhookEmbedBuilder embed = new WebhookEmbedBuilder() diff --git a/src/main/java/ac/grim/grimac/manager/PunishmentManager.java b/src/main/java/ac/grim/grimac/manager/PunishmentManager.java index 1d3a105d09..b5ad42f4ab 100644 --- a/src/main/java/ac/grim/grimac/manager/PunishmentManager.java +++ b/src/main/java/ac/grim/grimac/manager/PunishmentManager.java @@ -96,17 +96,16 @@ private String replaceAlertPlaceholders(String original, PunishGroup group, Chec // Streams are slow but this isn't a hot path... it's fine. String vl = group.violations.values().stream().filter((e) -> e == check).count() + ""; - original = MessageUtil.format(original + original = original .replace("[alert]", alertString) .replace("[proxy]", alertString) .replace("%check_name%", check.getCheckName()) .replace("%experimental%", check.isExperimental() ? experimentalSymbol : "") .replace("%vl%", vl) .replace("%verbose%", verbose) - .replace("%description%", check.getDescription()) - ); + .replace("%description%", check.getDescription()); - original = GrimAPI.INSTANCE.getExternalAPI().replaceVariables(player, original, true); + original = MessageUtil.replacePlaceholders(player, original); return original; } @@ -127,10 +126,10 @@ public boolean handleAlert(GrimPlayer player, String verbose, Check check) { if (GrimAPI.INSTANCE.getAlertManager().getEnabledVerbose().size() > 0 && command.command.equals("[alert]")) { sentDebug = true; for (Player bukkitPlayer : GrimAPI.INSTANCE.getAlertManager().getEnabledVerbose()) { - bukkitPlayer.sendMessage(cmd); + MessageUtil.sendMessage(bukkitPlayer, MessageUtil.miniMessage(cmd)); } if (GrimAPI.INSTANCE.getConfigManager().getConfig().getBooleanElse("verbose.print-to-console", false)) { - LogUtil.console(cmd); // Print verbose to console + LogUtil.console(MessageUtil.miniMessage(cmd)); // Print verbose to console } } @@ -154,7 +153,7 @@ public boolean handleAlert(GrimPlayer player, String verbose, Check check) { if (command.command.equals("[alert]")) { sentDebug = true; if (testMode) { // secret test mode - player.user.sendMessage(cmd); + player.user.sendMessage(MessageUtil.miniMessage(cmd)); continue; } cmd = "grim sendalert " + cmd; // Not test mode, we can add the command prefix diff --git a/src/main/java/ac/grim/grimac/utils/anticheat/LogUtil.java b/src/main/java/ac/grim/grimac/utils/anticheat/LogUtil.java index 3a8c09f6ee..1534275f75 100644 --- a/src/main/java/ac/grim/grimac/utils/anticheat/LogUtil.java +++ b/src/main/java/ac/grim/grimac/utils/anticheat/LogUtil.java @@ -2,6 +2,7 @@ import ac.grim.grimac.GrimAPI; import lombok.experimental.UtilityClass; +import net.kyori.adventure.text.Component; import org.bukkit.Bukkit; import org.bukkit.ChatColor; @@ -29,4 +30,7 @@ public void console(final String info) { Bukkit.getConsoleSender().sendMessage(ChatColor.translateAlternateColorCodes('&', info)); } + public void console(final Component info) { + MessageUtil.sendMessage(Bukkit.getConsoleSender(), info); + } } diff --git a/src/main/java/ac/grim/grimac/utils/anticheat/MessageUtil.java b/src/main/java/ac/grim/grimac/utils/anticheat/MessageUtil.java index 10914621ad..c647b61c99 100644 --- a/src/main/java/ac/grim/grimac/utils/anticheat/MessageUtil.java +++ b/src/main/java/ac/grim/grimac/utils/anticheat/MessageUtil.java @@ -1,18 +1,43 @@ package ac.grim.grimac.utils.anticheat; import ac.grim.grimac.GrimAPI; +import ac.grim.grimac.player.GrimPlayer; import com.github.retrooper.packetevents.PacketEvents; import com.github.retrooper.packetevents.manager.server.ServerVersion; import com.github.retrooper.packetevents.util.Vector3f; import com.github.retrooper.packetevents.util.Vector3i; import lombok.experimental.UtilityClass; +import me.clip.placeholderapi.PlaceholderAPI; +import net.kyori.adventure.platform.bukkit.BukkitAudiences; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.minimessage.MiniMessage; import net.md_5.bungee.api.ChatColor; +import org.bukkit.OfflinePlayer; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.regex.Matcher; import java.util.regex.Pattern; @UtilityClass public class MessageUtil { + private final BukkitAudiences adventure = BukkitAudiences.create(GrimAPI.INSTANCE.getPlugin()); + private final boolean hasPlaceholderAPI; + + static { + boolean placeholderAPI; + + try { + Class.forName("me.clip.placeholderapi.PlaceholderAPI"); + placeholderAPI = true; + } catch (ClassNotFoundException ignored) { + placeholderAPI = false; + } + + hasPlaceholderAPI = placeholderAPI; + } + public String toUnlabledString(Vector3i vec) { return vec == null ? "null" : vec.x + ", " + vec.y + ", " + vec.z; } @@ -21,27 +46,70 @@ public String toUnlabledString(Vector3f vec) { return vec == null ? "null" : vec.x + ", " + vec.y + ", " + vec.z; } - public String format(String string) { - string = formatWithNoColor(string); - if(PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_16)) - string = translateHexCodes(string); - return ChatColor.translateAlternateColorCodes('&', string); + public @NotNull String replacePlaceholders(@NotNull GrimPlayer player, @NotNull String string) { + return replacePlaceholders(player.bukkitPlayer, GrimAPI.INSTANCE.getExternalAPI().replaceVariables(player, string)); + } + + public @NotNull String replacePlaceholders(@Nullable Object object, @NotNull String string) { + if (!hasPlaceholderAPI) return string; + + OfflinePlayer player = null; + if (object instanceof OfflinePlayer) { + player = (OfflinePlayer) object; + } + + return PlaceholderAPI.setPlaceholders(player, string); } - public String formatWithNoColor(String string) { - return string.replace("%prefix%", GrimAPI.INSTANCE.getConfigManager().getConfig().getStringElse("prefix", "&bGrim &8»")); + public @NotNull String replacePlaceholders(@Nullable OfflinePlayer player, @NotNull String string) { + return hasPlaceholderAPI ? PlaceholderAPI.setPlaceholders(player, string) : string; } - private String translateHexCodes(String message) { - final String hexPattern = "#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{8})"; - Matcher matcher = Pattern.compile(hexPattern).matcher(message); - StringBuffer sb = new StringBuffer(message.length()); - while (matcher.find()) { - String hex = matcher.group(1); - ChatColor color = ChatColor.of("#" + hex); - matcher.appendReplacement(sb, color.toString()); + public @NotNull Component miniMessage(@NotNull String string) { + string = string.replace("%prefix%", GrimAPI.INSTANCE.getConfigManager().getConfig().getStringElse("prefix", "&bGrim &8»")); + + // hex codes + if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_16)) { + Matcher matcher = Pattern.compile("&#[A-Fa-f0-9]{6}").matcher(string); + StringBuffer sb = new StringBuffer(string.length()); + + while (matcher.find()) { + matcher.appendReplacement(sb, "<#" + matcher.group(1) + ">"); + } + + matcher.appendTail(sb); + string = sb.toString(); } - matcher.appendTail(sb); - return sb.toString(); + + // MiniMessage doesn't like legacy formatting codes + string = ChatColor.translateAlternateColorCodes('&', string) + .replace("§0", "") + .replace("§1", "") + .replace("§2", "") + .replace("§3", "") + .replace("§4", "") + .replace("§5", "") + .replace("§6", "") + .replace("§7", "") + .replace("§8", "") + .replace("§9", "") + .replace("§a", "") + .replace("§b", "") + .replace("§c", "") + .replace("§d", "") + .replace("§e", "") + .replace("§f", "") + .replace("§r", "") + .replace("§k", "") + .replace("§l", "") + .replace("§m", "") + .replace("§n", "") + .replace("§o", ""); + + return MiniMessage.miniMessage().deserialize(string).compact(); + } + + public void sendMessage(CommandSender commandSender, @NotNull Component component) { + adventure.sender(commandSender).sendMessage(component); } } diff --git a/src/main/resources/messages/de.yml b/src/main/resources/messages/de.yml index 61e928214a..97042c79ef 100644 --- a/src/main/resources/messages/de.yml +++ b/src/main/resources/messages/de.yml @@ -7,10 +7,13 @@ alerts-enabled: "%prefix% &fAlerts aktiviert" alerts-disabled: "%prefix% &fAlerts deaktiviert" client-brand-format: "%prefix% &f%player% beigetreten mit %brand%" console-specify-target: "%prefix% &cSie müssen ein Ziel als Konsole angeben!" +reloading: "%prefix% &7Reloading config..." +reloaded: "%prefix% &fConfig has been reloaded." +reload-failed: "%prefix% &cFailed to reload config." player-not-found: "%prefix% &cDer Spieler ist freigestellt oder offline!" player-not-this-server: "%prefix% &cSpieler ist nicht auf diesem Server!" spectate-return: "\n%prefix% &fKlicken Sie hier, um zur vorherigen Position zurückzukehren\n" -cannot-spectate-return: "%prefix% &cSie können dies nur tun, nachdem Sie einen Spieler beobachtet haben" +cannot-spectate-return: "%prefix% &cSie können dies nur tun, nachdem Sie einen Spieler beobachtet haben" cannot-run-on-self: "%prefix% &cSie können diesen Befehl nicht auf sich selbst anwenden!" upload-log: "%prefix% &fDebug wurde hochgeladen nach: %url%" upload-log-start: "%prefix% &fProtokoll hochladen... bitte warten" diff --git a/src/main/resources/messages/en.yml b/src/main/resources/messages/en.yml index dc65841abb..ea016bacdc 100644 --- a/src/main/resources/messages/en.yml +++ b/src/main/resources/messages/en.yml @@ -7,9 +7,12 @@ alerts-enabled: "%prefix% &fAlerts enabled" alerts-disabled: "%prefix% &fAlerts disabled" client-brand-format: "%prefix% &f%player% joined using %brand%" console-specify-target: "%prefix% &cYou must specify a target as the console!" +reloading: "%prefix% &7Reloading config..." +reloaded: "%prefix% &fConfig has been reloaded." +reload-failed: "%prefix% &cFailed to reload config." player-not-found: "%prefix% &cPlayer is exempt or offline!" player-not-this-server: "%prefix% &cPlayer is not on this server!" -spectate-return: "\n%prefix% &fClick here to return to previous location\n" +spectate-return: "\n%prefix% &fClick here to return to previous location\n" cannot-spectate-return: "%prefix% &cYou can only do this after spectating a player" cannot-run-on-self: "%prefix% &cYou cannot use this command on yourself!" upload-log: "%prefix% &fUploaded debug to: %url%" diff --git a/src/main/resources/messages/es.yml b/src/main/resources/messages/es.yml index 8306ee1228..840ecaa881 100644 --- a/src/main/resources/messages/es.yml +++ b/src/main/resources/messages/es.yml @@ -7,9 +7,12 @@ alerts-enabled: "%prefix% &fAlertas habilitadas" alerts-disabled: "%prefix% &fAlertas deshabilitadas" client-brand-format: "%prefix% &f%player% se ha unido usando %brand%" console-specify-target: "%prefix% &c¡Debes especificar a alguien siendo la consola!" +reloading: "%prefix% &7Reloading config..." +reloaded: "%prefix% &fConfig has been reloaded." +reload-failed: "%prefix% &cFailed to reload config." player-not-found: "%prefix% &c¡El jugador esta excluido o fuera de linea!" player-not-this-server: "%prefix% &c¡El jugador no esta en este servidor!" -spectate-return: "\n%prefix% &fClick aquí para volver a la localización previa\n" +spectate-return: "\n%prefix% &fClick aquí para volver a la localización previa\n" cannot-spectate-return: "%prefix% &cSolo puedes hacer esto despues de espectar a un jugador" cannot-run-on-self: "%prefix% &cNo puedes usar este comando en ti mismo!" upload-log: "%prefix% &fSubido el registro de depuración a: %url%" diff --git a/src/main/resources/messages/fr.yml b/src/main/resources/messages/fr.yml index e43ef4bf97..73f2a91e16 100644 --- a/src/main/resources/messages/fr.yml +++ b/src/main/resources/messages/fr.yml @@ -7,9 +7,12 @@ alerts-enabled: "%prefix% &fAlertes activées" alerts-disabled: "%prefix% &fAlertes désactivées" client-brand-format: "%prefix% &f%player% a rejoint en utilisant %brand%" console-specify-target: "%prefix% &cVous devez spécifier une cible en tant que console !" +reloading: "%prefix% &7Reloading config..." +reloaded: "%prefix% &fConfig has been reloaded." +reload-failed: "%prefix% &cFailed to reload config." player-not-found: "%prefix% &cPlayer est ignoré ou hors ligne !" player-not-this-server: "%prefix% &cPlayer n'est pas sur ce serveur !" -spectate-return: "\n%prefix% &fClickez ici pour retourner à votre position d'origine\n" +spectate-return: "\n%prefix% &fClickez ici pour retourner à votre position d'origine\n" cannot-spectate-return: "%prefix% &cVous pouvez faire cela uniquement en étant en spectateur" cannot-run-on-self: "%prefix% &cVous ne pouvez pas utiliser cette commande sur vous-même !" upload-log: "%prefix% &fLe fichier de débogage a été téléversé vers : %url%" diff --git a/src/main/resources/messages/it.yml b/src/main/resources/messages/it.yml index f0b757ba6b..a6bf1f9c49 100644 --- a/src/main/resources/messages/it.yml +++ b/src/main/resources/messages/it.yml @@ -7,9 +7,12 @@ alerts-enabled: "%prefix% &fAlerts abilitati" alerts-disabled: "%prefix% &fAlerts disabilitati" client-brand-format: "%prefix% &f%player% si è connesso usando %brand%" console-specify-target: "%prefix% &cDevi specificare un destinatario come console!" +reloading: "%prefix% &7Reloading config..." +reloaded: "%prefix% &fConfig has been reloaded." +reload-failed: "%prefix% &cFailed to reload config." player-not-found: "%prefix% &cIl giocatore è esente o offline!" player-not-this-server: "%prefix% &cIl giocatore non è in questo server!" -spectate-return: "\n%prefix% &fClicca qui per tornare alla posizione precedente\n" +spectate-return: "\n%prefix% &fClicca qui per tornare alla posizione precedente\n" cannot-spectate-return: "%prefix% &cPuoi farlo solo dopo aver osservato un giocatore" cannot-run-on-self: "%prefix% &cNon puoi usare questo comando su te stesso!" upload-log: "%prefix% &fDebug caricato su: %url%" diff --git a/src/main/resources/messages/nl.yml b/src/main/resources/messages/nl.yml index d2dae39e4f..f11ae4fb00 100644 --- a/src/main/resources/messages/nl.yml +++ b/src/main/resources/messages/nl.yml @@ -7,9 +7,12 @@ alerts-enabled: "%prefix% &fMeldingen ingeschakeld" alerts-disabled: "%prefix% &fMeldingen uitgeschakeld" client-brand-format: "%prefix% &f%player% is lid geworden met %brand%" console-specify-target: "%prefix% &cJe moet een doel opgeven als de console!" +reloading: "%prefix% &7Reloading config..." +reloaded: "%prefix% &fConfig has been reloaded." +reload-failed: "%prefix% &cFailed to reload config." player-not-found: "%prefix% &cSpeler is vrijgesteld of offline!" player-not-this-server: "%prefix% &cSpeler is niet op deze server!" -spectate-return: "\n%prefix% &fKlik hier om terug te keren naar de vorige locatie\n" +spectate-return: "\n%prefix% &fKlik hier om terug te keren naar de vorige locatie\n" cannot-spectate-return: "%prefix% &cJe kunt dit alleen doen nadat je een speler hebt bekeken" cannot-run-on-self: "%prefix% &cJe kunt dit commando niet op jezelf gebruiken!" upload-log: "%prefix% &fDebug geüpload naar: %url%" diff --git a/src/main/resources/messages/pt.yml b/src/main/resources/messages/pt.yml index 7955b1a0bc..20be796430 100644 --- a/src/main/resources/messages/pt.yml +++ b/src/main/resources/messages/pt.yml @@ -6,9 +6,12 @@ alerts-enabled: "%prefix% &fAlertas habilitados." alerts-disabled: "%prefix% &fAlertas desabilitados." client-brand-format: "%prefix% &f%player% entrou usando %brand%." console-specify-target: "%prefix% &cVocê deve especificar o nome do alvo!" +reloading: "%prefix% &7Reloading config..." +reloaded: "%prefix% &fConfig has been reloaded." +reload-failed: "%prefix% &cFailed to reload config." player-not-found: "%prefix% &cJogador não encontrado!" player-not-this-server: "%prefix% &cO jogador não está no servidor!" -spectate-return: "\n%prefix% &fClique aqui para retornar a localização anterior\n" +spectate-return: "\n%prefix% &fClique aqui para retornar a localização anterior\n" cannot-spectate-return: "%prefix% &cVocê só pode fazer isso após espectar um jogador." cannot-run-on-self: "%prefix% &cVocê não pode usar esse comando em sí mesmo!" upload-log: "%prefix% &fRegistro enviado para: %url%" diff --git a/src/main/resources/messages/ru.yml b/src/main/resources/messages/ru.yml index 2695337055..f66b63578e 100644 --- a/src/main/resources/messages/ru.yml +++ b/src/main/resources/messages/ru.yml @@ -7,9 +7,12 @@ alerts-enabled: "%prefix% &fОповещения включены" alerts-disabled: "%prefix% &fОповещения отключены" client-brand-format: "%prefix% &f%player% присоединился, используя %brand%" console-specify-target: "%prefix% &cВы должны указать цель в качестве консоли!" +reloading: "%prefix% &7Reloading config..." +reloaded: "%prefix% &fConfig has been reloaded." +reload-failed: "%prefix% &cFailed to reload config." player-not-found: "%prefix% &cИгрок исключен или находится вне сети!" player-not-this-server: "%prefix% &cИгрок не находится на этом сервере!" -spectate-return: "\n%prefix% &fНажмите здесь, чтобы вернуться на предыдущее место\n" +spectate-return: "\n%prefix% &fНажмите здесь, чтобы вернуться на предыдущее место\n" cannot-spectate-return: "%prefix% &cВы можете сделать это только после наблюдения за игроком" cannot-run-on-self: "%prefix% &cВы не можете использовать эту команду на себе!" upload-log: "%prefix% &fОтладка была загружена на: %url%" diff --git a/src/main/resources/messages/tr.yml b/src/main/resources/messages/tr.yml index 3e9b271ef4..ff1aff54c1 100644 --- a/src/main/resources/messages/tr.yml +++ b/src/main/resources/messages/tr.yml @@ -7,6 +7,9 @@ alerts-enabled: "%prefix% &fUyarılar aktif edildi." alerts-disabled: "%prefix% &fUyarılar deaktif edildi." client-brand-format: "%prefix% &f%player% adlı oyuncu %brand% kullanarak giriş yaptı." console-specify-target: "%prefix% &cKonsol olarak bir hedef belirtmelisiniz!" +reloading: "%prefix% &7Reloading config..." +reloaded: "%prefix% &fConfig has been reloaded." +reload-failed: "%prefix% &cFailed to reload config." player-not-found: "%prefix% &cOyuncu bulunamadı veya aktif değil!" player-not-this-server: "%prefix% &cBu oyuncu sunucuda değil!" spectate-return: "\n%prefix% &fBir önceki konuma dönmek için buraya tıklayın.\n" diff --git a/src/main/resources/messages/zh.yml b/src/main/resources/messages/zh.yml index c84137a366..2437d9c235 100644 --- a/src/main/resources/messages/zh.yml +++ b/src/main/resources/messages/zh.yml @@ -7,9 +7,12 @@ alerts-enabled: "%prefix% &f警报已开启" alerts-disabled: "%prefix% &f警报已禁用" client-brand-format: "%prefix% &f%player% 用 %brand% 加入了游戏" console-specify-target: "%prefix% &c您必须指定一个目标作为控制台!" +reloading: "%prefix% &7Reloading config..." +reloaded: "%prefix% &fConfig has been reloaded." +reload-failed: "%prefix% &cFailed to reload config." player-not-found: "%prefix% &c玩家不存在或离线!" player-not-this-server: "%prefix% &c玩家不在此服务器上!" -spectate-return: "\n%prefix% &f点击这里返回之前的位置\n" +spectate-return: "\n%prefix% &f点击这里返回之前的位置\n" cannot-spectate-return: "%prefix% &c您只能在观看玩家后执行此操作" cannot-run-on-self: "%prefix% &c你不能对自己使用此命令!" upload-log: "%prefix% &f已经将日志文件上传至: %url%"