diff --git a/buildSrc/src/main/kotlin/CommonConfig.kt b/buildSrc/src/main/kotlin/CommonConfig.kt index f0ce03904..e8f5ab4c2 100644 --- a/buildSrc/src/main/kotlin/CommonConfig.kt +++ b/buildSrc/src/main/kotlin/CommonConfig.kt @@ -27,12 +27,12 @@ fun Project.applyCommonConfiguration() { } } - // Only set Java 1.8 for non-Fabric modules + // Set Java 17 for non-Fabric modules // Fabric uses toolchain configuration in its build.gradle.kts plugins.withId("java") { if (!plugins.hasPlugin("fabric-loom")) { - the().setSourceCompatibility("1.8") - the().setTargetCompatibility("1.8") + the().setSourceCompatibility("17") + the().setTargetCompatibility("17") } } } diff --git a/buildSrc/src/main/kotlin/LibsConfig.kt b/buildSrc/src/main/kotlin/LibsConfig.kt index 6d7670891..95f47871d 100644 --- a/buildSrc/src/main/kotlin/LibsConfig.kt +++ b/buildSrc/src/main/kotlin/LibsConfig.kt @@ -38,8 +38,8 @@ fun Project.applyLibrariesConfiguration() { } plugins.withId("java") { - the().setSourceCompatibility("1.8") - the().setTargetCompatibility("1.8") + the().setSourceCompatibility("17") + the().setTargetCompatibility("17") } group = "${rootProject.group}.BanManagerLibs" @@ -100,7 +100,7 @@ fun Project.applyLibrariesConfiguration() { attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.LIBRARY)) attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.SHADOWED)) attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(LibraryElements.JAR)) - attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 8) + attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 17) } outgoing.artifact(tasks.named("jar")) } @@ -115,7 +115,7 @@ fun Project.applyLibrariesConfiguration() { attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.LIBRARY)) attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.SHADOWED)) attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(LibraryElements.JAR)) - attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 8) + attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 17) } outgoing.artifact(tasks.named("jar")) } diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index e6a67a496..3a969842c 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -1,5 +1,5 @@ object Versions { const val JUNIT = "4.13" const val MOCKITO = "3.7.7" - const val ADVENTURE = "4.9.3" + const val ADVENTURE = "4.21.0" } diff --git a/bukkit/build.gradle.kts b/bukkit/build.gradle.kts index f037b407b..c494940b0 100644 --- a/bukkit/build.gradle.kts +++ b/bukkit/build.gradle.kts @@ -80,6 +80,9 @@ dependencies { "compileOnly"("org.spigotmc:spigot-api:1.17.1-R0.1-SNAPSHOT") { exclude("junit", "junit") } + "compileOnly"("net.kyori:adventure-api:${Versions.ADVENTURE}") + "compileOnly"("net.kyori:adventure-text-serializer-gson:${Versions.ADVENTURE}") + "compileOnly"("net.kyori:adventure-text-serializer-json:${Versions.ADVENTURE}") "compileOnly"("me.clip:placeholderapi:2.10.9") "shadeOnly"("org.bstats:bstats-bukkit:2.2.1") "shadeOnly"("org.slf4j:slf4j-api:1.7.36") diff --git a/bukkit/src/main/java/me/confuser/banmanager/bukkit/BMBukkitPlugin.java b/bukkit/src/main/java/me/confuser/banmanager/bukkit/BMBukkitPlugin.java index a9dc048f1..735710449 100644 --- a/bukkit/src/main/java/me/confuser/banmanager/bukkit/BMBukkitPlugin.java +++ b/bukkit/src/main/java/me/confuser/banmanager/bukkit/BMBukkitPlugin.java @@ -38,7 +38,7 @@ public class BMBukkitPlugin extends JavaPlugin { "webhooks.yml", "exemptions.yml", "geoip.yml", - "messages.yml", + "notifications.yml", "reasons.yml", "schedules.yml" }; diff --git a/bukkit/src/main/java/me/confuser/banmanager/bukkit/BukkitPlayer.java b/bukkit/src/main/java/me/confuser/banmanager/bukkit/BukkitPlayer.java index 92d063378..b0557e077 100644 --- a/bukkit/src/main/java/me/confuser/banmanager/bukkit/BukkitPlayer.java +++ b/bukkit/src/main/java/me/confuser/banmanager/bukkit/BukkitPlayer.java @@ -4,14 +4,18 @@ import me.confuser.banmanager.common.CommonPlayer; import me.confuser.banmanager.common.CommonWorld; import me.confuser.banmanager.common.data.PlayerData; +import me.confuser.banmanager.common.kyori.text.Component; import me.confuser.banmanager.common.kyori.text.TextComponent; import me.confuser.banmanager.common.kyori.text.serializer.gson.GsonComponentSerializer; import me.confuser.banmanager.common.util.Message; +import me.confuser.banmanager.common.util.MessageRenderer; import me.confuser.banmanager.common.util.MessageRegistry; import me.confuser.banmanager.common.util.UUIDUtils; +import net.md_5.bungee.api.ChatMessageType; import net.md_5.bungee.chat.ComponentSerializer; import org.bukkit.Bukkit; import org.bukkit.Location; +import org.bukkit.Sound; import org.bukkit.entity.Player; import java.net.InetAddress; @@ -19,6 +23,18 @@ import java.util.UUID; public class BukkitPlayer implements CommonPlayer { + private static final boolean PAPER_ADVENTURE; + + static { + boolean paper = false; + try { + Class.forName("io.papermc.paper.adventure.PaperAdventure"); + paper = true; + } catch (ClassNotFoundException ignored) { + } + PAPER_ADVENTURE = paper; + } + private Player player; private final UUID uuid; private InetAddress address; @@ -45,6 +61,15 @@ public void kick(String message) { getPlayer().kickPlayer(BukkitServer.formatMessage(message)); } + @Override + public void kick(Component component) { + if (PAPER_ADVENTURE) { + PaperAdventureHelper.kick(getPlayer(), component); + } else { + kick(MessageRenderer.getInstance().toLegacy(component)); + } + } + public void sendMessage(String message) { if(message.isEmpty()) return; @@ -55,8 +80,47 @@ public void sendMessage(String message) { } } - public void sendMessage(Message message) { - sendMessage(message.toString()); + @Override + public void sendMessage(Component component) { + if (PAPER_ADVENTURE) { + PaperAdventureHelper.sendMessage(getPlayer(), component); + } else { + String json = MessageRenderer.getInstance().toJson(component); + getPlayer().spigot().sendMessage(ComponentSerializer.parse(json)); + } + } + + @Override + public void sendActionBar(Component component) { + if (PAPER_ADVENTURE) { + PaperAdventureHelper.sendActionBar(getPlayer(), component); + } else { + String json = MessageRenderer.getInstance().toJson(component); + getPlayer().spigot().sendMessage(ChatMessageType.ACTION_BAR, ComponentSerializer.parse(json)); + } + } + + @Override + public void showTitle(Component title, Component subtitle, int fadeIn, int stay, int fadeOut) { + if (PAPER_ADVENTURE) { + PaperAdventureHelper.showTitle(getPlayer(), title, subtitle, fadeIn, stay, fadeOut); + } else { + MessageRenderer renderer = MessageRenderer.getInstance(); + String legacyTitle = title != null ? renderer.toLegacy(title) : ""; + String legacySubtitle = subtitle != null ? renderer.toLegacy(subtitle) : ""; + getPlayer().sendTitle(legacyTitle, legacySubtitle, fadeIn, stay, fadeOut); + } + } + + @Override + public void playSound(String sound, float volume, float pitch) { + Player p = getPlayer(); + if (p == null) return; + try { + p.playSound(p.getLocation(), sound, volume, pitch); + } catch (IllegalArgumentException ignored) { + // Invalid sound key -- silently ignore + } } @Override diff --git a/bukkit/src/main/java/me/confuser/banmanager/bukkit/BukkitSender.java b/bukkit/src/main/java/me/confuser/banmanager/bukkit/BukkitSender.java index c767f29e2..1e88df583 100644 --- a/bukkit/src/main/java/me/confuser/banmanager/bukkit/BukkitSender.java +++ b/bukkit/src/main/java/me/confuser/banmanager/bukkit/BukkitSender.java @@ -35,11 +35,6 @@ public void sendMessage(String message) { sender.sendMessage(BukkitServer.formatMessage(message)); } - @Override - public void sendMessage(Message message) { - sendMessage(message.toString()); - } - @Override public boolean isConsole() { return !(sender instanceof Player); diff --git a/bukkit/src/main/java/me/confuser/banmanager/bukkit/BukkitServer.java b/bukkit/src/main/java/me/confuser/banmanager/bukkit/BukkitServer.java index e6d070ac7..a2cabe782 100644 --- a/bukkit/src/main/java/me/confuser/banmanager/bukkit/BukkitServer.java +++ b/bukkit/src/main/java/me/confuser/banmanager/bukkit/BukkitServer.java @@ -5,7 +5,6 @@ import me.confuser.banmanager.common.api.events.CommonEvent; import me.confuser.banmanager.common.commands.CommonSender; import me.confuser.banmanager.common.data.*; -import me.confuser.banmanager.common.kyori.text.TextComponent; import me.confuser.banmanager.common.util.ColorUtils; import me.confuser.banmanager.common.util.Message; import org.bukkit.Bukkit; @@ -17,7 +16,6 @@ import org.bukkit.entity.Player; import org.bukkit.permissions.Permissible; -import java.util.Arrays; import java.util.Set; import java.util.UUID; import java.util.stream.Collectors; @@ -82,13 +80,6 @@ public void broadcast(String message, String permission) { } } - @Override - public void broadcastJSON(TextComponent message, String permission) { - Arrays.stream(getOnlinePlayers()).forEach(player -> { - if (player.hasPermission(permission)) player.sendJSONMessage(message); - }); - } - @Override public void broadcast(String message, String permission, CommonSender sender) { broadcast(message, permission); diff --git a/bukkit/src/main/java/me/confuser/banmanager/bukkit/PaperAdventureHelper.java b/bukkit/src/main/java/me/confuser/banmanager/bukkit/PaperAdventureHelper.java new file mode 100644 index 000000000..632b58d35 --- /dev/null +++ b/bukkit/src/main/java/me/confuser/banmanager/bukkit/PaperAdventureHelper.java @@ -0,0 +1,74 @@ +package me.confuser.banmanager.bukkit; + +import me.confuser.banmanager.common.kyori.text.Component; +import me.confuser.banmanager.common.util.MessageRenderer; +import net.kyori.adventure.audience.Audience; +import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; +import net.kyori.adventure.title.Title; +import org.bukkit.entity.Player; + +import java.time.Duration; + +/** + * Paper-only helper that uses native Adventure API for zero-overhead Component delivery. + * Paper's Player implements Audience, so we cast to Audience for Adventure methods. + * This class must only be loaded when Paper's Adventure API is on the classpath. + */ +class PaperAdventureHelper { + + private static final java.lang.reflect.Method KICK_METHOD; + + static { + java.lang.reflect.Method m = null; + try { + m = Player.class.getMethod("kick", net.kyori.adventure.text.Component.class); + } catch (NoSuchMethodException e) { + // Expected on older Paper/Spigot versions without Component-based kick + } + KICK_METHOD = m; + } + + private PaperAdventureHelper() {} + + static void sendMessage(Player player, Component component) { + ((Audience) player).sendMessage(convertToNative(component)); + } + + static void sendActionBar(Player player, Component component) { + ((Audience) player).sendActionBar(convertToNative(component)); + } + + static void showTitle(Player player, Component title, Component subtitle, + int fadeIn, int stay, int fadeOut) { + net.kyori.adventure.text.Component nativeTitle = title != null + ? convertToNative(title) : net.kyori.adventure.text.Component.empty(); + net.kyori.adventure.text.Component nativeSubtitle = subtitle != null + ? convertToNative(subtitle) : net.kyori.adventure.text.Component.empty(); + + Title.Times times = Title.Times.times( + Duration.ofMillis(fadeIn * 50L), + Duration.ofMillis(stay * 50L), + Duration.ofMillis(fadeOut * 50L) + ); + ((Audience) player).showTitle(Title.title(nativeTitle, nativeSubtitle, times)); + } + + static void kick(Player player, Component component) { + if (KICK_METHOD != null) { + try { + KICK_METHOD.invoke(player, convertToNative(component)); + return; + } catch (IllegalAccessException e) { + java.util.logging.Logger.getLogger("BanManager").warning("Failed to invoke Paper kick method, falling back to legacy: " + e.getMessage()); + } catch (java.lang.reflect.InvocationTargetException e) { + throw new IllegalStateException("Failed to kick player", e.getCause()); + } + } + player.kickPlayer(MessageRenderer.getInstance().toLegacy(component)); + } + + private static net.kyori.adventure.text.Component convertToNative(Component component) { + String json = MessageRenderer.getInstance().toJson(component); + return GsonComponentSerializer.gson().deserialize(json); + } +} diff --git a/bukkit/src/main/java/me/confuser/banmanager/bukkit/listeners/JoinListener.java b/bukkit/src/main/java/me/confuser/banmanager/bukkit/listeners/JoinListener.java index 94b53202a..4c7fbe8f3 100644 --- a/bukkit/src/main/java/me/confuser/banmanager/bukkit/listeners/JoinListener.java +++ b/bukkit/src/main/java/me/confuser/banmanager/bukkit/listeners/JoinListener.java @@ -62,13 +62,13 @@ public void handlePlayerDeny(PlayerData player, Message message) { plugin.getServer().callEvent("PlayerDeniedEvent", player, message); String locale = player.getLocale() != null ? player.getLocale() : "en"; event.setLoginResult(AsyncPlayerPreLoginEvent.Result.KICK_BANNED); - event.setKickMessage(BukkitServer.formatMessage(message.resolve(locale))); + event.setKickMessage(BukkitServer.formatMessage(MessageRenderer.getInstance().toLegacy(message.resolveComponent(locale)))); } @Override public void handleDeny(Message message) { event.setLoginResult(AsyncPlayerPreLoginEvent.Result.KICK_BANNED); - event.setKickMessage(BukkitServer.formatMessage(message.toString())); + event.setKickMessage(BukkitServer.formatMessage(MessageRenderer.getInstance().toLegacy(message.resolveComponent()))); } } @@ -83,7 +83,8 @@ public void handlePlayerDeny(PlayerData player, Message message) { @Override public void handleDeny(Message message) { - event.disallow(PlayerLoginEvent.Result.KICK_BANNED, message.toString()); + event.disallow(PlayerLoginEvent.Result.KICK_BANNED, + BukkitServer.formatMessage(MessageRenderer.getInstance().toLegacy(message.resolveComponent()))); } } } diff --git a/bungee/src/main/java/me/confuser/banmanager/bungee/BMBungeePlugin.java b/bungee/src/main/java/me/confuser/banmanager/bungee/BMBungeePlugin.java index 5e1b66d55..ea4b96d18 100755 --- a/bungee/src/main/java/me/confuser/banmanager/bungee/BMBungeePlugin.java +++ b/bungee/src/main/java/me/confuser/banmanager/bungee/BMBungeePlugin.java @@ -33,7 +33,7 @@ public class BMBungeePlugin extends Plugin { "webhooks.yml", "exemptions.yml", "geoip.yml", - "messages.yml", + "notifications.yml", "reasons.yml", "schedules.yml" }; diff --git a/bungee/src/main/java/me/confuser/banmanager/bungee/BungeePlayer.java b/bungee/src/main/java/me/confuser/banmanager/bungee/BungeePlayer.java index 820be083b..2a573ce03 100755 --- a/bungee/src/main/java/me/confuser/banmanager/bungee/BungeePlayer.java +++ b/bungee/src/main/java/me/confuser/banmanager/bungee/BungeePlayer.java @@ -4,9 +4,12 @@ import me.confuser.banmanager.common.CommonWorld; import me.confuser.banmanager.common.commands.CommonCommand; import me.confuser.banmanager.common.data.PlayerData; +import me.confuser.banmanager.common.kyori.text.Component; import me.confuser.banmanager.common.kyori.text.TextComponent; import me.confuser.banmanager.common.util.Message; +import me.confuser.banmanager.common.util.MessageRenderer; import me.confuser.banmanager.common.util.MessageRegistry; +import net.md_5.bungee.api.ChatMessageType; import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.chat.ComponentSerializer; @@ -30,6 +33,12 @@ public void kick(String message) { player.disconnect(BungeeServer.formatMessage(message)); } + @Override + public void kick(Component component) { + String json = MessageRenderer.getInstance().toJson(component); + player.disconnect(ComponentSerializer.parse(json)); + } + @Override public void sendMessage(String message) { if(message.isEmpty()) return; @@ -42,8 +51,15 @@ public void sendMessage(String message) { } @Override - public void sendMessage(Message message) { - sendMessage(message.toString()); + public void sendMessage(Component component) { + String json = MessageRenderer.getInstance().toJson(component); + player.sendMessage(ComponentSerializer.parse(json)); + } + + @Override + public void sendActionBar(Component component) { + String json = MessageRenderer.getInstance().toJson(component); + player.sendMessage(ChatMessageType.ACTION_BAR, ComponentSerializer.parse(json)); } @Override diff --git a/bungee/src/main/java/me/confuser/banmanager/bungee/BungeeSender.java b/bungee/src/main/java/me/confuser/banmanager/bungee/BungeeSender.java index 9eb5beba0..7c5c46992 100755 --- a/bungee/src/main/java/me/confuser/banmanager/bungee/BungeeSender.java +++ b/bungee/src/main/java/me/confuser/banmanager/bungee/BungeeSender.java @@ -4,7 +4,6 @@ import me.confuser.banmanager.common.commands.CommonCommand; import me.confuser.banmanager.common.commands.CommonSender; import me.confuser.banmanager.common.data.PlayerData; -import me.confuser.banmanager.common.util.Message; import net.md_5.bungee.api.CommandSender; import net.md_5.bungee.api.connection.ProxiedPlayer; @@ -33,11 +32,6 @@ public void sendMessage(String message) { sender.sendMessage(BungeeServer.formatMessage(message)); } - @Override - public void sendMessage(Message message) { - sendMessage(message.toString()); - } - @Override public boolean isConsole() { return !(sender instanceof ProxiedPlayer); diff --git a/bungee/src/main/java/me/confuser/banmanager/bungee/BungeeServer.java b/bungee/src/main/java/me/confuser/banmanager/bungee/BungeeServer.java index a325a374c..496a47786 100755 --- a/bungee/src/main/java/me/confuser/banmanager/bungee/BungeeServer.java +++ b/bungee/src/main/java/me/confuser/banmanager/bungee/BungeeServer.java @@ -5,7 +5,7 @@ import me.confuser.banmanager.common.api.events.CommonEvent; import me.confuser.banmanager.common.commands.CommonSender; import me.confuser.banmanager.common.data.*; -import me.confuser.banmanager.common.kyori.text.TextComponent; +import me.confuser.banmanager.common.kyori.text.Component; import me.confuser.banmanager.common.kyori.text.serializer.gson.GsonComponentSerializer; import me.confuser.banmanager.common.util.ColorUtils; import me.confuser.banmanager.common.util.Message; @@ -69,15 +69,6 @@ public void broadcast(String message, String permission) { } } - @Override - public void broadcastJSON(TextComponent message, String permission) { - for (ProxiedPlayer player : ProxyServer.getInstance().getPlayers()) { - if (player != null && player.hasPermission(permission)) { - player.sendMessage(formatMessage(message)); - } - } - } - @Override public void broadcast(String message, String permission, CommonSender sender) { broadcast(message, permission); @@ -237,7 +228,7 @@ public static BaseComponent[] formatMessage(String message) { return ComponentSerializer.parse(json); } - public static BaseComponent[] formatMessage(TextComponent message) { + public static BaseComponent[] formatMessage(Component message) { return ComponentSerializer.parse(GsonComponentSerializer.gson().serialize(message)); } diff --git a/bungee/src/main/java/me/confuser/banmanager/bungee/listeners/JoinListener.java b/bungee/src/main/java/me/confuser/banmanager/bungee/listeners/JoinListener.java index 032d2f249..43f3f861d 100755 --- a/bungee/src/main/java/me/confuser/banmanager/bungee/listeners/JoinListener.java +++ b/bungee/src/main/java/me/confuser/banmanager/bungee/listeners/JoinListener.java @@ -60,13 +60,13 @@ public void handlePlayerDeny(PlayerData player, Message message) { plugin.getServer().callEvent("PlayerDeniedEvent", player, message); String locale = player.getLocale() != null ? player.getLocale() : "en"; event.setCancelled(true); - event.setCancelReason(BungeeServer.formatMessage(message.resolve(locale))); + event.setCancelReason(BungeeServer.formatMessage(message.resolveComponent(locale))); } @Override public void handleDeny(Message message) { event.setCancelled(true); - event.setCancelReason(BungeeServer.formatMessage(message.toString())); + event.setCancelReason(BungeeServer.formatMessage(message.resolveComponent())); } } @@ -81,7 +81,7 @@ public void handlePlayerDeny(PlayerData player, Message message) { @Override public void handleDeny(Message message) { - event.getPlayer().disconnect(BungeeServer.formatMessage(message.toString())); + event.getPlayer().disconnect(BungeeServer.formatMessage(message.resolveComponent())); } } } diff --git a/common/src/main/java/me/confuser/banmanager/common/BanManagerPlugin.java b/common/src/main/java/me/confuser/banmanager/common/BanManagerPlugin.java index 04396fb83..5a72929e9 100644 --- a/common/src/main/java/me/confuser/banmanager/common/BanManagerPlugin.java +++ b/common/src/main/java/me/confuser/banmanager/common/BanManagerPlugin.java @@ -24,16 +24,40 @@ import me.confuser.banmanager.common.util.DriverManagerUtil; import me.confuser.banmanager.common.util.Message; import me.confuser.banmanager.common.util.MessageRegistry; +import me.confuser.banmanager.common.util.MessageRenderer; import java.io.*; import java.nio.file.Files; import java.sql.SQLException; +import java.util.*; import static java.lang.Long.parseLong; public class BanManagerPlugin { private static BanManagerPlugin self; + // Token names used by commands/listeners via Message.set(). Hardcoded because these are + // defined across many source files and not available at runtime as a registry. Used only + // to warn admins when a static token in messages.yml collides with a built-in name. + private static final Set BUILTIN_TOKENS; + + static { + String[] rawNames = {"player", "playerId", "actor", "reason", "expires", "id", + "message", "displayName", "ip", "players", "name", "type", "created", + "amount", "bans", "mutes", "warns", "warnPoints", "kicks", "notes", + "reports", "count", "page", "maxPage", "state", "from", "to", + "from_ip", "to_ip", "index", "uuid", "size", "remaining", + "firstSeen", "lastSeen", "updated", "country", "countryIso", "city", + "meta", "file", "rows", "command", "comment", "world", "x", "y", "z", + "hashtag", "points", "join", "leave", "lastChecked", "types", + "rangebans", "action"}; + Set normalised = new HashSet<>(); + for (String name : rawNames) { + normalised.add(MessageRenderer.normaliseTagName(name)); + } + BUILTIN_TOKENS = Collections.unmodifiableSet(normalised); + } + /* * This block prevents the Maven Shade plugin to remove the specified classes */ @@ -67,6 +91,8 @@ public class BanManagerPlugin { private GeoIpConfig geoIpConfig; @Getter private WebhookConfig webhookConfig; + @Getter + private NotificationsConfig notificationsConfig; // Connections @Getter @@ -281,6 +307,7 @@ public void setupConfigs() { reasonsConfig = reloadConfig(new ReasonsConfig(dataFolder, logger), reasonsConfig, "reasons.yml"); geoIpConfig = reloadConfig(new GeoIpConfig(dataFolder, logger), geoIpConfig, "geoip.yml"); webhookConfig = reloadConfig(new WebhookConfig(dataFolder, logger), webhookConfig, "webhooks.yml"); + notificationsConfig = reloadConfig(new NotificationsConfig(dataFolder, logger), notificationsConfig, "notifications.yml"); loadMessages(); } @@ -289,6 +316,10 @@ private void loadMessages() { String defaultLocale = config != null ? config.getDefaultLocale() : "en"; MessageRegistry newRegistry = new MessageRegistry(defaultLocale); + // Clear static tokens before loading so removed tokens don't persist across reloads + MessageRenderer renderer = MessageRenderer.getInstance(); + renderer.loadStaticTokens(Collections.emptyMap()); + copyMessagesDirectory(); File messagesDir = new File(dataFolder, "messages"); @@ -325,13 +356,21 @@ private void loadMessages() { Message.init(messageRegistry, logger); + if (renderer.getStaticTokens() != null) { + for (String tokenName : renderer.getStaticTokens().keySet()) { + if (BUILTIN_TOKENS.contains(tokenName)) { + logger.warning("Static token '" + tokenName + "' collides with a built-in token and will be overridden at runtime"); + } + } + } + logLocaleInfo(); } private void logLocaleInfo() { if (messageRegistry == null) return; - java.util.Set locales = messageRegistry.getAvailableLocales(); + Set locales = messageRegistry.getAvailableLocales(); logger.info("Loaded " + locales.size() + " locale(s): " + String.join(", ", locales)); String defaultLocale = messageRegistry.getDefaultLocale(); @@ -354,25 +393,52 @@ private void loadLocaleFile(MessageRegistry registry, File file, String locale) return; } - java.util.Map messages = new java.util.HashMap<>(); + Map messages = new HashMap<>(); + MessageRenderer renderer = MessageRenderer.getInstance(); + int rejectedCount = 0; for (String key : conf.getConfigurationSection("messages").getKeys(true)) { String value = conf.getString("messages." + key); if (value != null) { - messages.put(key, value.replace("\\n", "\n").replaceAll("(?<=\\n)(?=\\n)", " ")); + String processed = value.replace("\\n", "\n").replaceAll("(?<=\\n)(?=\\n)", " "); + if (renderer.isLegacyFormat(processed)) { + logger.severe("Message '" + key + "' in " + file.getName() + " contains legacy &-code formatting and has been skipped. Please convert to MiniMessage format: https://docs.advntr.dev/minimessage/format.html"); + rejectedCount++; + continue; + } + messages.put(key, processed); } } + if (rejectedCount > 0) { + logger.severe(rejectedCount + " message(s) in " + file.getName() + " were rejected due to legacy formatting. Bundled defaults will be used for those keys."); + } + if (!messages.isEmpty()) { - java.util.Map existing = registry.getMessages(locale); + Map existing = registry.getMessages(locale); if (!existing.isEmpty()) { - java.util.Map merged = new java.util.HashMap<>(existing); + Map merged = new HashMap<>(existing); merged.putAll(messages); registry.loadLocale(locale, merged); } else { registry.loadLocale(locale, messages); } } + + if (conf.getConfigurationSection("tokens") != null) { + Map tokens = new HashMap<>(); + for (String key : conf.getConfigurationSection("tokens").getKeys(false)) { + String value = conf.getString("tokens." + key); + if (value != null) { + tokens.put(key, value); + } + } + if (!tokens.isEmpty()) { + Map existing = new HashMap<>(renderer.getStaticTokens()); + existing.putAll(tokens); + renderer.loadStaticTokens(existing); + } + } } catch (Exception e) { logger.warning("Failed to load " + file.getName(), e); } @@ -596,7 +662,8 @@ public CommonCommand[] getCommands() { new UnmuteCommand(this), new UnmuteIpCommand(this), new UtilsCommand(this), - new WarnCommand(this) + new WarnCommand(this), + new BmCommand(this) }; } diff --git a/common/src/main/java/me/confuser/banmanager/common/CommonPlayer.java b/common/src/main/java/me/confuser/banmanager/common/CommonPlayer.java index 0ad1fc2dc..769b7ba74 100644 --- a/common/src/main/java/me/confuser/banmanager/common/CommonPlayer.java +++ b/common/src/main/java/me/confuser/banmanager/common/CommonPlayer.java @@ -2,8 +2,10 @@ import me.confuser.banmanager.common.commands.CommonSender; import me.confuser.banmanager.common.data.PlayerData; +import me.confuser.banmanager.common.kyori.text.Component; import me.confuser.banmanager.common.kyori.text.TextComponent; import me.confuser.banmanager.common.util.Message; +import me.confuser.banmanager.common.util.MessageRenderer; import java.net.InetAddress; import java.util.UUID; @@ -13,12 +15,35 @@ public interface CommonPlayer extends CommonSender { void kick(String message); default void kick(Message message) { - kick(message.resolveFor(this)); + kick(message.resolveComponentFor(this)); + } + + default void kick(Component component) { + kick(MessageRenderer.getInstance().toLegacy(component)); } void sendMessage(String message); - void sendMessage(Message message); + @Override + default void sendMessage(Message message) { + sendMessage(message.resolveComponentFor(this)); + } + + @Override + default void sendMessage(Component component) { + sendMessage(MessageRenderer.getInstance().toLegacy(component)); + } + + default void sendActionBar(Component component) { + sendMessage(component); + } + + default void showTitle(Component title, Component subtitle, int fadeIn, int stay, int fadeOut) { + if (title != null) sendMessage(title); + if (subtitle != null) sendMessage(subtitle); + } + + default void playSound(String sound, float volume, float pitch) { } void sendJSONMessage(TextComponent jsonString); diff --git a/common/src/main/java/me/confuser/banmanager/common/CommonServer.java b/common/src/main/java/me/confuser/banmanager/common/CommonServer.java index 212857aef..4fc39b669 100644 --- a/common/src/main/java/me/confuser/banmanager/common/CommonServer.java +++ b/common/src/main/java/me/confuser/banmanager/common/CommonServer.java @@ -2,8 +2,9 @@ import me.confuser.banmanager.common.api.events.CommonEvent; import me.confuser.banmanager.common.commands.CommonSender; -import me.confuser.banmanager.common.kyori.text.TextComponent; +import me.confuser.banmanager.common.kyori.text.Component; import me.confuser.banmanager.common.util.Message; +import me.confuser.banmanager.common.util.MessageRenderer; import java.util.UUID; @@ -21,13 +22,21 @@ public interface CommonServer { default void broadcast(Message message, String permission) { for (CommonPlayer player : getOnlinePlayers()) { if (player.hasPermission(permission)) { - player.sendMessage(message.resolveFor(player)); + player.sendMessage(message.resolveComponentFor(player)); } } - getConsoleSender().sendMessage(message.toString()); + getConsoleSender().sendMessage(MessageRenderer.getInstance().toPlainText(message.resolveComponent())); } - void broadcastJSON(TextComponent message, String permission); + // Console receives plain text since it cannot render Components with hover/click events + default void broadcast(Component message, String permission) { + for (CommonPlayer player : getOnlinePlayers()) { + if (player.hasPermission(permission)) { + player.sendMessage(message); + } + } + getConsoleSender().sendMessage(MessageRenderer.getInstance().toPlainText(message)); + } void broadcast(String message, String permission, CommonSender sender); diff --git a/common/src/main/java/me/confuser/banmanager/common/api/BmAPI.java b/common/src/main/java/me/confuser/banmanager/common/api/BmAPI.java index 37e808a0b..6808bd251 100644 --- a/common/src/main/java/me/confuser/banmanager/common/api/BmAPI.java +++ b/common/src/main/java/me/confuser/banmanager/common/api/BmAPI.java @@ -615,7 +615,7 @@ public static String getPlayerNameAt(UUID uuid, long timestamp) throws SQLExcept /** * @param key The message config node within messages.yml, e.g. "ban.notify" - * @return String + * @return A Message instance that can be resolved to a Component via resolveComponent() */ public static Message getMessage(String key) { return Message.get(key); diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/ActivityCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/ActivityCommand.java index d567b643d..fb81a73b5 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/ActivityCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/ActivityCommand.java @@ -55,7 +55,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { } if (player == null) { - sender.sendMessage(Message.get("sender.error.notFound").set("player", parser.args[1]).toString()); + Message.get("sender.error.notFound").set("player", parser.args[1]).sendTo(sender); return; } diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/AddNoteCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/AddNoteCommand.java index 1e2a876a0..ba8e6bea3 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/AddNoteCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/AddNoteCommand.java @@ -39,7 +39,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { final PlayerData player = getPlayer(sender, playerName, true); if (player == null) { - sender.sendMessage(Message.get("sender.error.notFound").set("player", playerName).toString()); + Message.get("sender.error.notFound").set("player", playerName).sendTo(sender); return; } @@ -49,7 +49,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { try { getPlugin().getPlayerNoteStorage().addNote(warning); } catch (SQLException e) { - sender.sendMessage(Message.get("sender.error.exception").toString()); + Message.get("sender.error.exception").sendTo(sender); getPlugin().getLogger().warning("Failed to execute addnote command", e); } }); diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/BanCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/BanCommand.java index 33de448f7..cc1aa1171 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/BanCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/BanCommand.java @@ -40,12 +40,12 @@ public boolean onCommand(CommonSender sender, CommandParser parser) { final TargetResolver.TargetResult target = TargetResolver.resolveTarget(getPlugin().getServer(), playerName); if (target.getStatus() == TargetResolver.TargetStatus.NOT_FOUND) { - sender.sendMessage(Message.get("sender.error.notFound").set("player", playerName).toString()); + Message.get("sender.error.notFound").set("player", playerName).sendTo(sender); return true; } if (target.getStatus() == TargetResolver.TargetStatus.AMBIGUOUS) { - sender.sendMessage(Message.get("sender.error.ambiguousPlayer").set("player", playerName).toString()); + Message.get("sender.error.ambiguousPlayer").set("player", playerName).sendTo(sender); return true; } @@ -64,7 +64,7 @@ public boolean onCommand(CommonSender sender, CommandParser parser) { try { isBanned = getPlugin().getPlayerBanStorage().isBanned(UUID.fromString(playerName)); } catch (IllegalArgumentException e) { - sender.sendMessage(Message.get("sender.error.notFound").set("player", playerName).toString()); + Message.get("sender.error.notFound").set("player", playerName).sendTo(sender); return true; } } else { @@ -75,7 +75,7 @@ public boolean onCommand(CommonSender sender, CommandParser parser) { Message message = Message.get("ban.error.exists"); message.set("player", targetName); - sender.sendMessage(message.toString()); + message.sendTo(sender); return true; } @@ -93,12 +93,12 @@ public boolean onCommand(CommonSender sender, CommandParser parser) { final PlayerData player = getPlayer(sender, targetName, true); if (player == null) { - sender.sendMessage(Message.get("sender.error.notFound").set("player", targetName).toString()); + Message.get("sender.error.notFound").set("player", targetName).sendTo(sender); return; } if (getPlugin().getExemptionsConfig().isExempt(player, "ban")) { - sender.sendMessage(Message.get("sender.error.exempt").set("player", targetName).toString()); + Message.get("sender.error.exempt").set("player", targetName).sendTo(sender); return; } @@ -108,7 +108,7 @@ public boolean onCommand(CommonSender sender, CommandParser parser) { return; } } catch (SQLException e) { - sender.sendMessage(Message.get("sender.error.exception").toString()); + Message.get("sender.error.exception").sendTo(sender); getPlugin().getLogger().warning("Failed to execute ban command", e); return; } @@ -130,7 +130,7 @@ public boolean onCommand(CommonSender sender, CommandParser parser) { try { getPlugin().getPlayerBanStorage().unban(ban, actor); } catch (SQLException e) { - sender.sendMessage(Message.get("sender.error.exception").toString()); + Message.get("sender.error.exception").sendTo(sender); getPlugin().getLogger().warning("Failed to execute ban command", e); return; } diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/BanIpCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/BanIpCommand.java index 9d663386d..f4669779d 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/BanIpCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/BanIpCommand.java @@ -48,7 +48,7 @@ public boolean onCommand(CommonSender sender, CommandParser parser) { Message message = Message.get("sender.error.invalidIp"); message.set("ip", ipStr); - sender.sendMessage(message.toString()); + message.sendTo(sender); return true; } @@ -66,7 +66,7 @@ public boolean onCommand(CommonSender sender, CommandParser parser) { final IPAddress ip = getIp(ipStr); if (ip == null) { - sender.sendMessage(Message.get("sender.error.notFound").set("player", ipStr).toString()); + Message.get("sender.error.notFound").set("player", ipStr).sendTo(sender); return; } @@ -76,7 +76,7 @@ public boolean onCommand(CommonSender sender, CommandParser parser) { Message message = Message.get("banip.error.exists"); message.set("ip", ipStr); - sender.sendMessage(message.toString()); + message.sendTo(sender); return; } @@ -86,7 +86,7 @@ public boolean onCommand(CommonSender sender, CommandParser parser) { return; } } catch (SQLException e) { - sender.sendMessage(Message.get("sender.error.exception").toString()); + Message.get("sender.error.exception").sendTo(sender); getPlugin().getLogger().warning("Failed to execute banip command", e); return; } @@ -100,7 +100,7 @@ public boolean onCommand(CommonSender sender, CommandParser parser) { try { getPlugin().getIpBanStorage().unban(ban, actor); } catch (SQLException e) { - sender.sendMessage(Message.get("sender.error.exception").toString()); + Message.get("sender.error.exception").sendTo(sender); getPlugin().getLogger().warning("Failed to execute banip command", e); return; } diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/BanListCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/BanListCommand.java index 398284b1f..50df49260 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/BanListCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/BanListCommand.java @@ -4,7 +4,12 @@ import me.confuser.banmanager.common.data.IpBanData; import me.confuser.banmanager.common.data.IpRangeBanData; import me.confuser.banmanager.common.data.PlayerBanData; +import me.confuser.banmanager.common.kyori.text.Component; import me.confuser.banmanager.common.util.Message; +import me.confuser.banmanager.common.util.PaginatedView; + +import java.util.ArrayList; +import java.util.List; public class BanListCommand extends CommonCommand { @@ -14,16 +19,23 @@ public BanListCommand(BanManagerPlugin plugin) { @Override public boolean onCommand(CommonSender sender, CommandParser parser) { - if (parser.args.length > 1) return false; + if (parser.args.length > 2) return false; String type = "players"; + int page = 1; - if (parser.args.length == 1) { + if (parser.args.length >= 1) { type = parser.args[0]; } + if (parser.args.length == 2) { + try { + page = Integer.parseInt(parser.args[1]); + } catch (NumberFormatException e) { + return false; + } + } - StringBuilder list = new StringBuilder(); - int total = 0; + List items = new ArrayList<>(); if (type.startsWith("play")) { if (!sender.hasPermission(getPermission() + ".players")) { @@ -32,10 +44,10 @@ public boolean onCommand(CommonSender sender, CommandParser parser) { } for (PlayerBanData ban : getPlugin().getPlayerBanStorage().getBans().values()) { - list.append(ban.getPlayer().getName()); - list.append(", "); - - total++; + items.add(Message.get("banlist.row.player") + .set("name", ban.getPlayer().getName()) + .set("reason", ban.getReason()) + .resolveComponent()); } } else if (type.startsWith("ipr")) { if (!sender.hasPermission(getPermission() + ".ipranges")) { @@ -44,12 +56,11 @@ public boolean onCommand(CommonSender sender, CommandParser parser) { } for (IpRangeBanData ban : getPlugin().getIpRangeBanStorage().getBans().values()) { - list.append(ban.getFromIp().toString()); - list.append(" - "); - list.append(ban.getToIp().toString()); - list.append(", "); - - total++; + items.add(Message.get("banlist.row.iprange") + .set("from_ip", ban.getFromIp().toString()) + .set("to_ip", ban.getToIp().toString()) + .set("reason", ban.getReason()) + .resolveComponent()); } } else if (type.startsWith("ip")) { if (!sender.hasPermission(getPermission() + ".ips")) { @@ -58,19 +69,18 @@ public boolean onCommand(CommonSender sender, CommandParser parser) { } for (IpBanData ban : getPlugin().getIpBanStorage().getBans().values()) { - list.append(ban.getIp().toString()); - list.append(", "); - - total++; + items.add(Message.get("banlist.row.ip") + .set("ip", ban.getIp().toString()) + .set("reason", ban.getReason()) + .resolveComponent()); } } else { return false; } - if (list.length() >= 2) list.setLength(list.length() - 2); - - Message.get("banlist.header").set("bans", total).set("type", type).sendTo(sender); - if (list.length() > 0) sender.sendMessage(list.toString()); + Component header = Message.get("banlist.header").set("bans", items.size()).set("type", type).resolveComponent(); + PaginatedView view = new PaginatedView(items, "/banlist " + type); + view.send(sender, page, header, null); return true; } diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/BanNameCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/BanNameCommand.java index abb288aad..2b03357db 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/BanNameCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/BanNameCommand.java @@ -44,7 +44,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { Message message = Message.get("banname.error.exists"); message.set("name", name); - sender.sendMessage(message.toString()); + message.sendTo(sender); return; } @@ -59,7 +59,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { try { getPlugin().getNameBanStorage().unban(ban, actor); } catch (SQLException e) { - sender.sendMessage(Message.get("sender.error.exception").toString()); + Message.get("sender.error.exception").sendTo(sender); getPlugin().getLogger().warning("Failed to execute banname command", e); return; } diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/BmCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/BmCommand.java new file mode 100644 index 000000000..c4a845129 --- /dev/null +++ b/common/src/main/java/me/confuser/banmanager/common/commands/BmCommand.java @@ -0,0 +1,16 @@ +package me.confuser.banmanager.common.commands; + +import me.confuser.banmanager.common.BanManagerPlugin; + +public class BmCommand extends MultiCommonCommand { + + public BmCommand(BanManagerPlugin plugin) { + super(plugin, "bm"); + registerCommands(); + } + + @Override + public void registerCommands() { + registerCommonSubCommand(new DashboardSubCommand(getPlugin())); + } +} diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/ClearCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/ClearCommand.java index f31ac4e28..e2439d7b8 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/ClearCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/ClearCommand.java @@ -38,7 +38,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { final PlayerData player = getPlayer(sender, playerName, true); if (player == null) { - sender.sendMessage(Message.get("sender.error.notFound").set("player", playerName).toString()); + Message.get("sender.error.notFound").set("player", playerName).sendTo(sender); return; } @@ -96,7 +96,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { break; } } catch (SQLException e) { - sender.sendMessage(Message.get("sender.error.exception").toString()); + Message.get("sender.error.exception").sendTo(sender); getPlugin().getLogger().warning("Failed to execute clear command", e); return; } diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/CommonCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/CommonCommand.java index d75997b83..2ce90c6a7 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/CommonCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/CommonCommand.java @@ -89,7 +89,7 @@ public static PlayerData getPlayer(CommonSender sender, String playerName, boole try { player = BanManagerPlugin.getInstance().getPlayerStorage().queryForId(UUIDUtils.toBytes(UUID.fromString(playerName))); } catch (SQLException e) { - sender.sendMessage(Message.get("sender.error.exception").toString()); + Message.get("sender.error.exception").sendTo(sender); BanManagerPlugin.getInstance().getLogger().warning("Failed to execute command", e); } } else { @@ -171,6 +171,8 @@ public CommandParser getParser(List args) throws NoSuchMethodException, return getParser(args.toArray(new String[0])); } + private static final String[] DURATION_PRESETS = {"1h", "6h", "12h", "1d", "3d", "7d", "14d", "30d", "90d", "1y"}; + public List handlePlayerNameTabComplete(CommonSender sender, String[] args) { ArrayList mostLike = new ArrayList<>(); if(args.length == 1) { @@ -199,8 +201,6 @@ public List handlePlayerNameTabComplete(CommonSender sender, String[] ar } } if(args.length > 1) { - // Reasons? - // TODO: Only allow reasons for valid commands. String lookup = args[args.length - 1]; if(lookup.startsWith("#")) { return plugin.getReasonsConfig().getReasons().keySet().stream().map(k -> "#" + k) @@ -213,6 +213,21 @@ public List handlePlayerNameTabComplete(CommonSender sender, String[] ar return mostLike; } + public List handleDurationTabComplete(CommonSender sender, String[] args, int durationArgIndex) { + ArrayList completions = new ArrayList<>(handlePlayerNameTabComplete(sender, args)); + + if (args.length == durationArgIndex + 1) { + String partial = args[durationArgIndex].toLowerCase(); + for (String preset : DURATION_PRESETS) { + if (preset.startsWith(partial)) { + completions.add(preset); + } + } + } + + return completions; + } + public long getCooldown() { return plugin.getConfig().getCooldownsConfig().getCommand(getCommandName()); } diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/CommonSender.java b/common/src/main/java/me/confuser/banmanager/common/commands/CommonSender.java index 81f919361..305c0862d 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/CommonSender.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/CommonSender.java @@ -1,13 +1,22 @@ package me.confuser.banmanager.common.commands; import me.confuser.banmanager.common.data.PlayerData; +import me.confuser.banmanager.common.kyori.text.Component; import me.confuser.banmanager.common.util.Message; +import me.confuser.banmanager.common.util.MessageRenderer; public interface CommonSender { String getName(); boolean hasPermission(String permission); void sendMessage(String message); - void sendMessage(Message message); boolean isConsole(); PlayerData getData(); + + default void sendMessage(Message message) { + sendMessage(message.resolveComponent()); + } + + default void sendMessage(Component component) { + sendMessage(MessageRenderer.getInstance().toLegacy(component)); + } } diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/DashboardSubCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/DashboardSubCommand.java new file mode 100644 index 000000000..458512877 --- /dev/null +++ b/common/src/main/java/me/confuser/banmanager/common/commands/DashboardSubCommand.java @@ -0,0 +1,61 @@ +package me.confuser.banmanager.common.commands; + +import me.confuser.banmanager.common.BanManagerPlugin; +import me.confuser.banmanager.common.util.Message; +import me.confuser.banmanager.common.util.ReportList; + +import java.sql.SQLException; + +public class DashboardSubCommand extends CommonSubCommand { + + private static final String COUNT_TOKEN = "count"; + + public DashboardSubCommand(BanManagerPlugin plugin) { + super(plugin, "dashboard"); + } + + @Override + public boolean onCommand(CommonSender sender, CommandParser args) { + BanManagerPlugin plugin = getPlugin(); + + int activeBans = plugin.getPlayerBanStorage().getBans().size(); + int activeMutes = plugin.getPlayerMuteStorage().getMutes().size(); + int openReports; + + try { + ReportList reports = plugin.getPlayerReportStorage().getReports(1, 1); + openReports = reports != null ? (int) reports.getCount() : 0; + } catch (SQLException e) { + plugin.getLogger().warning("Failed to fetch report count for dashboard", e); + openReports = 0; + } + + Message.get("dashboard.header").sendTo(sender); + + Message.get("dashboard.activeBans") + .set(COUNT_TOKEN, activeBans) + .sendTo(sender); + + Message.get("dashboard.activeMutes") + .set(COUNT_TOKEN, activeMutes) + .sendTo(sender); + + Message.get("dashboard.openReports") + .set(COUNT_TOKEN, openReports) + .sendTo(sender); + + Message.get("dashboard.footer").sendTo(sender); + + return true; + } + + @Override + public String getHelp() { + return "- View staff dashboard summary"; + } + + @Override + public String getPermission() { + return "command.bm.dashboard"; + } +} diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/DeleteCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/DeleteCommand.java index bb117fce1..7d47ff5d9 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/DeleteCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/DeleteCommand.java @@ -90,7 +90,7 @@ public void run() { break; } } catch (SQLException e) { - sender.sendMessage(Message.get("sender.error.exception").toString()); + Message.get("sender.error.exception").sendTo(sender); getPlugin().getLogger().warning("Failed to execute delete command", e); return; } diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/DeleteLastWarningCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/DeleteLastWarningCommand.java index 3116e5b6a..70dad35bb 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/DeleteLastWarningCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/DeleteLastWarningCommand.java @@ -27,7 +27,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { final PlayerData player = getPlayer(sender, playerName, true); if (player == null) { - sender.sendMessage(Message.get("sender.error.notFound").set("player", playerName).toString()); + Message.get("sender.error.notFound").set("player", playerName).sendTo(sender); return; } diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/ExportCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/ExportCommand.java index 113d5be29..3cf44b69c 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/ExportCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/ExportCommand.java @@ -49,7 +49,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { try { exportPlayers(fileName); } catch (IOException e) { - sender.sendMessage(Message.get("sender.error.exception").toString()); + Message.get("sender.error.exception").sendTo(sender); getPlugin().getLogger().warning("Failed to execute export command", e); return; } @@ -64,7 +64,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { try { exportIps(fileName); } catch (IOException e) { - sender.sendMessage(Message.get("sender.error.exception").toString()); + Message.get("sender.error.exception").sendTo(sender); getPlugin().getLogger().warning("Failed to execute export command", e); return; } diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/FindAltsCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/FindAltsCommand.java index d87fa2e37..e7f5940d3 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/FindAltsCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/FindAltsCommand.java @@ -13,7 +13,7 @@ import me.confuser.banmanager.common.kyori.text.format.TextColor; import me.confuser.banmanager.common.util.IPUtils; import me.confuser.banmanager.common.util.Message; - +import me.confuser.banmanager.common.util.MessageRenderer; import java.sql.SQLException; import java.util.*; @@ -38,7 +38,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { Message message = Message.get("sender.error.invalidIp"); message.set("ip", ipStr); - sender.sendMessage(message.toString()); + message.sendTo(sender); return true; } @@ -46,18 +46,18 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { final IPAddress ip = getIp(ipStr); if (ip == null) { - sender.sendMessage(Message.get("alts.header")); - sender.sendMessage(Message.get("none").toString()); + Message.get("alts.header").sendTo(sender); + Message.get("none").sendTo(sender); return; } List players = getPlugin().getPlayerStorage().getDuplicatesInTime(ip, getPlugin().getConfig().getTimeAssociatedAlts()); if (!sender.isConsole()) { - sender.sendMessage(Message.get("alts.header").set("ip", ipStr).toString()); + Message.get("alts.header").set("ip", ipStr).sendTo(sender); if (players.isEmpty()) { - sender.sendMessage(Message.get("none").toString()); + Message.get("none").sendTo(sender); return; } @@ -69,10 +69,10 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { names.add(player.getName()); } - sender.sendMessage(Message.get("alts.header").set("ip", ipStr).toString()); + Message.get("alts.header").set("ip", ipStr).sendTo(sender); if (names.isEmpty()) { - sender.sendMessage(Message.get("none").toString()); + Message.get("none").sendTo(sender); return; } @@ -121,19 +121,28 @@ public static TextComponent alts(List players) { } } + boolean hasEntryTemplate = Message.getRawTemplate("alts.entry") != null; + String separatorRaw = Message.getRawTemplate("alts.separator"); + MessageRenderer renderer = MessageRenderer.getInstance(); + Component separator = separatorRaw != null ? renderer.render(separatorRaw) : Component.text(", "); + int index = 0; for (PlayerData player : players) { TextColor colour = colours.getOrDefault(player.getUUID(), NamedTextColor.GREEN); - message - .append( - Component.text(player.getName()) - .color(colour) - .clickEvent(ClickEvent.runCommand("/bminfo " + player.getName()))); + if (hasEntryTemplate) { + Component entry = Message.get("alts.entry").set("name", player.getName()).resolveComponent(); + message.append(Component.text().color(colour).append(entry)); + } else { + message.append( + Component.text(player.getName()) + .color(colour) + .clickEvent(ClickEvent.runCommand("/bminfo " + player.getName()))); + } if (index != players.size() - 1) { - message.append(Component.text(", ")); + message.append(separator); } index++; diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/InfoCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/InfoCommand.java index 31168c1c8..3e3c2aeb2 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/InfoCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/InfoCommand.java @@ -8,7 +8,7 @@ import me.confuser.banmanager.common.kyori.text.Component; import me.confuser.banmanager.common.kyori.text.TextComponent; import me.confuser.banmanager.common.kyori.text.event.ClickEvent; -import me.confuser.banmanager.common.kyori.text.format.NamedTextColor; + import me.confuser.banmanager.common.maxmind.db.model.CountryResponse; import me.confuser.banmanager.common.ormlite.dao.CloseableIterator; import me.confuser.banmanager.common.ormlite.field.SqlType; @@ -19,6 +19,7 @@ import me.confuser.banmanager.common.util.DateUtils; import me.confuser.banmanager.common.util.IPUtils; import me.confuser.banmanager.common.util.Message; + import me.confuser.banmanager.common.util.StringUtils; import me.confuser.banmanager.common.util.parsers.InfoCommandParser; @@ -98,7 +99,7 @@ public void ipInfo(CommonSender sender, IPAddress ip, InfoCommandParser parser) try { since = DateUtils.parseDateDiff(parser.getTime(), false); } catch (Exception e1) { - sender.sendMessage(Message.get("time.error.invalid").toString()); + Message.get("time.error.invalid").sendTo(sender); return; } } @@ -284,7 +285,7 @@ public void playerInfo(CommonSender sender, String name, Integer index, InfoComm List players = getPlugin().getPlayerStorage().retrieve(name); if (players == null || players.size() == 0) { - sender.sendMessage(Message.get("sender.error.notFound").set("player", name).toString()); + Message.get("sender.error.notFound").set("player", name).sendTo(sender); return; } @@ -324,7 +325,7 @@ public void playerInfo(CommonSender sender, String name, Integer index, InfoComm try { since = DateUtils.parseDateDiff(parser.getTime(), false); } catch (Exception e1) { - sender.sendMessage(Message.get("time.error.invalid").toString()); + Message.get("time.error.invalid").sendTo(sender); return; } } @@ -693,29 +694,6 @@ private void handleIpHistory(ArrayList messages, PlayerData player, long } private TextComponent buildNamesComponent(List names, String dateTimeFormat) { - TextComponent.Builder message = Component.text(); - int index = 0; - - for (PlayerNameSummary nameData : names) { - String hoverText = Message.get("names.row") - .set("name", nameData.getName()) - .set("firstSeen", DateUtils.format(dateTimeFormat, nameData.getFirstSeen())) - .set("lastSeen", DateUtils.format(dateTimeFormat, nameData.getLastSeen())) - .toString(); - - message.append( - Component.text(nameData.getName()) - .color(NamedTextColor.YELLOW) - .clickEvent(ClickEvent.runCommand("/bminfo " + nameData.getName())) - .hoverEvent(Component.text(hoverText))); - - if (index != names.size() - 1) { - message.append(Component.text(", ").color(NamedTextColor.GRAY)); - } - - index++; - } - - return message.build(); + return NamesCommand.buildNamesComponent(names, dateTimeFormat); } } diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/KickAllCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/KickAllCommand.java index cbe571ad9..eb7e0e446 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/KickAllCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/KickAllCommand.java @@ -64,7 +64,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { return null; }); } catch (Exception e) { - sender.sendMessage(Message.get("sender.error.exception").toString()); + Message.get("sender.error.exception").sendTo(sender); getPlugin().getLogger().warning("Failed to execute kickall command", e); } } diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/KickCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/KickCommand.java index 33cebaf20..9a6b563c0 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/KickCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/KickCommand.java @@ -103,7 +103,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { try { created = getPlugin().getPlayerKickStorage().addKick(data, isSilent); } catch (SQLException e) { - sender.sendMessage(Message.get("sender.error.exception").toString()); + Message.get("sender.error.exception").sendTo(sender); getPlugin().getLogger().warning("Failed to execute kick command", e); return; } diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/MuteCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/MuteCommand.java index 12d07829b..e12a389a8 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/MuteCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/MuteCommand.java @@ -47,12 +47,12 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { TargetResolver.TargetResult target = TargetResolver.resolveTarget(getPlugin().getServer(), playerName); if (target.getStatus() == TargetResolver.TargetStatus.NOT_FOUND) { - sender.sendMessage(Message.get("sender.error.notFound").set("player", playerName).toString()); + Message.get("sender.error.notFound").set("player", playerName).sendTo(sender); return true; } if (target.getStatus() == TargetResolver.TargetStatus.AMBIGUOUS) { - sender.sendMessage(Message.get("sender.error.ambiguousPlayer").set("player", playerName).toString()); + Message.get("sender.error.ambiguousPlayer").set("player", playerName).sendTo(sender); return true; } @@ -73,7 +73,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { try { isMuted = getPlugin().getPlayerMuteStorage().isMuted(UUID.fromString(playerName)); } catch (IllegalArgumentException e) { - sender.sendMessage(Message.get("sender.error.notFound").set("player", playerName).toString()); + Message.get("sender.error.notFound").set("player", playerName).sendTo(sender); return true; } } else { @@ -84,7 +84,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { Message message = Message.get("mute.error.exists"); message.set("player", targetName); - sender.sendMessage(message.toString()); + message.sendTo(sender); return true; } @@ -104,12 +104,12 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { final PlayerData player = getPlayer(sender, targetName, true); if (player == null) { - sender.sendMessage(Message.get("sender.error.notFound").set("player", targetName).toString()); + Message.get("sender.error.notFound").set("player", targetName).sendTo(sender); return; } if (getPlugin().getExemptionsConfig().isExempt(player, "mute")) { - sender.sendMessage(Message.get("sender.error.exempt").set("player", targetName).toString()); + Message.get("sender.error.exempt").set("player", targetName).sendTo(sender); return; } @@ -119,7 +119,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { return; } } catch (SQLException e) { - sender.sendMessage(Message.get("sender.error.exception").toString()); + Message.get("sender.error.exception").sendTo(sender); getPlugin().getLogger().warning("Failed to execute mute command", e); return; } @@ -139,7 +139,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { try { getPlugin().getPlayerMuteStorage().unmute(mute, actor); } catch (SQLException e) { - sender.sendMessage(Message.get("sender.error.exception").toString()); + Message.get("sender.error.exception").sendTo(sender); getPlugin().getLogger().warning("Failed to execute mute command", e); return; } @@ -175,7 +175,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { .set("id", mute.getId()) .set("actor", actor.getName()); - commonPlayer.sendMessage(muteMessage.toString()); + muteMessage.sendTo(commonPlayer); }); return true; diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/MuteIpCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/MuteIpCommand.java index f7023189b..d523aab5f 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/MuteIpCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/MuteIpCommand.java @@ -56,7 +56,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { Message message = Message.get("sender.error.invalidIp"); message.set("ip", ipStr); - sender.sendMessage(message.toString()); + message.sendTo(sender); return true; } @@ -76,7 +76,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { final IPAddress ip = getIp(ipStr); if (ip == null) { - sender.sendMessage(Message.get("sender.error.notFound").set("player", ipStr).toString()); + Message.get("sender.error.notFound").set("player", ipStr).sendTo(sender); return; } @@ -86,7 +86,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { Message message = Message.get("muteip.error.exists"); message.set("ip", ipStr); - sender.sendMessage(message.toString()); + message.sendTo(sender); return; } @@ -101,7 +101,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { try { getPlugin().getIpMuteStorage().unmute(mute, actor); } catch (SQLException e) { - sender.sendMessage(Message.get("sender.error.exception").toString()); + Message.get("sender.error.exception").sendTo(sender); getPlugin().getLogger().warning("Failed to execute muteip command", e); return; } diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/NamesCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/NamesCommand.java index ecfacdc42..92c36e977 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/NamesCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/NamesCommand.java @@ -10,6 +10,7 @@ import me.confuser.banmanager.common.kyori.text.format.NamedTextColor; import me.confuser.banmanager.common.util.DateUtils; import me.confuser.banmanager.common.util.Message; +import me.confuser.banmanager.common.util.MessageRenderer; import java.sql.SQLException; import java.util.List; @@ -31,7 +32,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { if (playerName.length() > 16) { Message message = Message.get("sender.error.invalidPlayer"); message.set("player", playerName); - sender.sendMessage(message.toString()); + message.sendTo(sender); return true; } @@ -39,7 +40,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { PlayerData player = getPlugin().getPlayerStorage().retrieve(playerName, true); if (player == null) { - sender.sendMessage(Message.get("sender.error.notFound").set("player", playerName).toString()); + Message.get("sender.error.notFound").set("player", playerName).sendTo(sender); return; } @@ -47,29 +48,29 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { try { names = getPlugin().getPlayerHistoryStorage().getNamesSummary(player); } catch (SQLException e) { - sender.sendMessage(Message.get("sender.error.exception").toString()); + Message.get("sender.error.exception").sendTo(sender); getPlugin().getLogger().warning("Failed to execute names command", e); return; } - sender.sendMessage(Message.get("names.header").set("player", player.getName()).toString()); + Message.get("names.header").set("player", player.getName()).sendTo(sender); if (names.isEmpty()) { - sender.sendMessage(Message.get("names.none").toString()); + Message.get("names.none").sendTo(sender); return; } - String dateTimeFormat = Message.getString("names.dateTimeFormat"); + String dateTimeFormat = Message.getRawTemplate("names.dateTimeFormat"); if (!sender.isConsole()) { ((CommonPlayer) sender).sendJSONMessage(buildNamesComponent(names, dateTimeFormat)); } else { for (PlayerNameSummary nameData : names) { - sender.sendMessage(Message.get("names.row") + Message.get("names.row") .set("name", nameData.getName()) .set("firstSeen", DateUtils.format(dateTimeFormat, nameData.getFirstSeen())) .set("lastSeen", DateUtils.format(dateTimeFormat, nameData.getLastSeen())) - .toString()); + .sendTo(sender); } } }); @@ -77,25 +78,39 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { return true; } - private TextComponent buildNamesComponent(List names, String dateTimeFormat) { + static TextComponent buildNamesComponent(List names, String dateTimeFormat) { TextComponent.Builder message = Component.text(); + boolean hasInteractiveTemplate = Message.getRawTemplate("names.interactive") != null; + String separatorRaw = Message.getRawTemplate("names.separator"); + MessageRenderer renderer = MessageRenderer.getInstance(); + Component separator = separatorRaw != null ? renderer.render(separatorRaw) : Component.text(", ").color(NamedTextColor.GRAY); + int index = 0; for (PlayerNameSummary nameData : names) { - String hoverText = Message.get("names.row") - .set("name", nameData.getName()) - .set("firstSeen", DateUtils.format(dateTimeFormat, nameData.getFirstSeen())) - .set("lastSeen", DateUtils.format(dateTimeFormat, nameData.getLastSeen())) - .toString(); - - message.append( - Component.text(nameData.getName()) - .color(NamedTextColor.YELLOW) - .clickEvent(ClickEvent.runCommand("/bminfo " + nameData.getName())) - .hoverEvent(Component.text(hoverText))); + if (hasInteractiveTemplate) { + Component entry = Message.get("names.interactive") + .set("name", nameData.getName()) + .set("firstSeen", DateUtils.format(dateTimeFormat, nameData.getFirstSeen())) + .set("lastSeen", DateUtils.format(dateTimeFormat, nameData.getLastSeen())) + .resolveComponent(); + message.append(entry); + } else { + String hoverText = Message.get("names.row") + .set("name", nameData.getName()) + .set("firstSeen", DateUtils.format(dateTimeFormat, nameData.getFirstSeen())) + .set("lastSeen", DateUtils.format(dateTimeFormat, nameData.getLastSeen())) + .toString(); + + message.append( + Component.text(nameData.getName()) + .color(NamedTextColor.YELLOW) + .clickEvent(ClickEvent.runCommand("/bminfo " + nameData.getName())) + .hoverEvent(Component.text(hoverText))); + } if (index != names.size() - 1) { - message.append(Component.text(", ").color(NamedTextColor.GRAY)); + message.append(separator); } index++; diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/NotesCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/NotesCommand.java index d981267e2..523d85a82 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/NotesCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/NotesCommand.java @@ -4,6 +4,7 @@ import me.confuser.banmanager.common.CommonPlayer; import me.confuser.banmanager.common.data.PlayerData; import me.confuser.banmanager.common.data.PlayerNoteData; +import me.confuser.banmanager.common.kyori.text.Component; import me.confuser.banmanager.common.kyori.text.TextComponent; import me.confuser.banmanager.common.kyori.text.event.ClickEvent; import me.confuser.banmanager.common.kyori.text.serializer.legacy.LegacyComponentSerializer; @@ -41,7 +42,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { PlayerData player = getPlugin().getPlayerStorage().retrieve(name, false); if (player == null) { - sender.sendMessage(Message.get("sender.error.notFound").set("player", name).toString()); + Message.get("sender.error.notFound").set("player", name).sendTo(sender); return; } @@ -140,9 +141,7 @@ public void run() { return true; } - public static TextComponent notesAmountMessage(String playerName, Message text) { - return LegacyComponentSerializer.legacy('&').deserialize( - text.set("player", playerName).toString()) - .clickEvent(ClickEvent.runCommand("/notes " + playerName)); + public static Component notesAmountMessage(String playerName, Message text) { + return text.set("player", playerName).resolveComponent(); } } diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/ReloadCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/ReloadCommand.java index f8ad114cb..278a98dd9 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/ReloadCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/ReloadCommand.java @@ -15,7 +15,7 @@ public boolean onCommand(CommonSender sender, CommandParser parser) { getPlugin().getServer().callEvent("PluginReloadedEvent", sender.getData()); - sender.sendMessage(Message.get("configReloaded").toString()); + Message.get("configReloaded").sendTo(sender); return true; } diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/ReportCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/ReportCommand.java index faa4eefd4..bc2f63b9d 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/ReportCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/ReportCommand.java @@ -38,12 +38,12 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { final TargetResolver.TargetResult target = TargetResolver.resolveTarget(getPlugin().getServer(), playerName); if (target.getStatus() == TargetResolver.TargetStatus.NOT_FOUND) { - sender.sendMessage(Message.get("sender.error.notFound").set("player", playerName).toString()); + Message.get("sender.error.notFound").set("player", playerName).sendTo(sender); return true; } if (target.getStatus() == TargetResolver.TargetStatus.AMBIGUOUS) { - sender.sendMessage(Message.get("sender.error.ambiguousPlayer").set("player", playerName).toString()); + Message.get("sender.error.ambiguousPlayer").set("player", playerName).sendTo(sender); return true; } @@ -72,12 +72,12 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { final PlayerData player = getPlayer(sender, targetName, false); if (player == null) { - sender.sendMessage(Message.get("sender.error.notFound").set("player", targetName).toString()); + Message.get("sender.error.notFound").set("player", targetName).sendTo(sender); return; } if (getPlugin().getExemptionsConfig().isExempt(player, "report")) { - sender.sendMessage(Message.get("sender.error.exempt").set("player", targetName).toString()); + Message.get("sender.error.exempt").set("player", targetName).sendTo(sender); return; } @@ -87,7 +87,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { return; } } catch (SQLException e) { - sender.sendMessage(Message.get("sender.error.exception").toString()); + Message.get("sender.error.exception").sendTo(sender); getPlugin().getLogger().warning("Failed to execute report command", e); return; } @@ -101,7 +101,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { .queryForId(1)); getPlugin().getPlayerReportStorage().report(report, isSilent); } catch (SQLException e) { - sender.sendMessage(Message.get("sender.error.exception").toString()); + Message.get("sender.error.exception").sendTo(sender); getPlugin().getLogger().warning("Failed to execute report command", e); } diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/RollbackCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/RollbackCommand.java index 19e43ddb1..2ee473314 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/RollbackCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/RollbackCommand.java @@ -49,7 +49,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { try { expiresCheck = DateUtils.parseDateDiff(parser.args[1], false); } catch (Exception e) { - sender.sendMessage(Message.get("time.error.invalid").toString()); + Message.get("time.error.invalid").sendTo(sender); return true; } @@ -67,7 +67,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { final PlayerData player = getPlayer(sender, playerName, false); if (player == null) { - sender.sendMessage(Message.get("sender.error.notFound").set("player", playerName).toString()); + Message.get("sender.error.notFound").set("player", playerName).sendTo(sender); return; } @@ -266,7 +266,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { .sendTo(sender); } } catch (SQLException e) { - sender.sendMessage(Message.get("sender.error.exception").toString()); + Message.get("sender.error.exception").sendTo(sender); getPlugin().getLogger().warning("Failed to execute rollback command", e); } }); diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/TempBanCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/TempBanCommand.java index 46264416c..a3fd3fda1 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/TempBanCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/TempBanCommand.java @@ -42,12 +42,12 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { final TargetResolver.TargetResult target = TargetResolver.resolveTarget(getPlugin().getServer(), playerName); if (target.getStatus() == TargetResolver.TargetStatus.NOT_FOUND) { - sender.sendMessage(Message.get("sender.error.notFound").set("player", playerName).toString()); + Message.get("sender.error.notFound").set("player", playerName).sendTo(sender); return true; } if (target.getStatus() == TargetResolver.TargetStatus.AMBIGUOUS) { - sender.sendMessage(Message.get("sender.error.ambiguousPlayer").set("player", playerName).toString()); + Message.get("sender.error.ambiguousPlayer").set("player", playerName).sendTo(sender); return true; } @@ -66,7 +66,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { try { isBanned = getPlugin().getPlayerBanStorage().isBanned(UUID.fromString(playerName)); } catch (IllegalArgumentException e) { - sender.sendMessage(Message.get("sender.error.notFound").set("player", playerName).toString()); + Message.get("sender.error.notFound").set("player", playerName).sendTo(sender); return true; } } else { @@ -77,7 +77,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { Message message = Message.get("ban.error.exists"); message.set("player", targetName); - sender.sendMessage(message.toString()); + message.sendTo(sender); return true; } @@ -96,7 +96,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { try { expiresCheck = DateUtils.parseDateDiff(parser.args[1], true); } catch (Exception e1) { - sender.sendMessage(Message.get("time.error.invalid").toString()); + Message.get("time.error.invalid").sendTo(sender); return true; } @@ -115,12 +115,12 @@ public void run() { final PlayerData player = getPlayer(sender, targetName, true); if (player == null) { - sender.sendMessage(Message.get("sender.error.notFound").set("player", targetName).toString()); + Message.get("sender.error.notFound").set("player", targetName).sendTo(sender); return; } if (getPlugin().getExemptionsConfig().isExempt(player, "tempban")) { - sender.sendMessage(Message.get("sender.error.exempt").set("player", targetName).toString()); + Message.get("sender.error.exempt").set("player", targetName).sendTo(sender); return; } @@ -130,7 +130,7 @@ public void run() { return; } } catch (SQLException e) { - sender.sendMessage(Message.get("sender.error.exception").toString()); + Message.get("sender.error.exception").sendTo(sender); getPlugin().getLogger().warning("Failed to execute tempban command", e); return; } @@ -152,7 +152,7 @@ public void run() { try { getPlugin().getPlayerBanStorage().unban(ban, actor); } catch (SQLException e) { - sender.sendMessage(Message.get("sender.error.exception").toString()); + Message.get("sender.error.exception").sendTo(sender); getPlugin().getLogger().warning("Failed to execute tempban command", e); return; } diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/TempIpBanCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/TempIpBanCommand.java index c358e80ba..adab6626a 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/TempIpBanCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/TempIpBanCommand.java @@ -45,7 +45,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { Message message = Message.get("sender.error.invalidIp"); message.set("ip", ipStr); - sender.sendMessage(message.toString()); + message.sendTo(sender); return true; } @@ -64,7 +64,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { try { expiresCheck = DateUtils.parseDateDiff(parser.args[1], true); } catch (Exception e1) { - sender.sendMessage(Message.get("time.error.invalid").toString()); + Message.get("time.error.invalid").sendTo(sender); return true; } @@ -80,7 +80,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { final IPAddress ip = getIp(ipStr); if (ip == null) { - sender.sendMessage(Message.get("sender.error.notFound").set("player", ipStr).toString()); + Message.get("sender.error.notFound").set("player", ipStr).sendTo(sender); return; } @@ -90,7 +90,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { Message message = Message.get("banip.error.exists"); message.set("ip", ipStr); - sender.sendMessage(message.toString()); + message.sendTo(sender); return; } @@ -100,7 +100,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { return; } } catch (SQLException e) { - sender.sendMessage(Message.get("sender.error.exception").toString()); + Message.get("sender.error.exception").sendTo(sender); getPlugin().getLogger().warning("Failed to execute tempbanip command", e); return; } @@ -116,7 +116,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { try { getPlugin().getIpBanStorage().unban(ban, actor); } catch (SQLException e) { - sender.sendMessage(Message.get("sender.error.exception").toString()); + Message.get("sender.error.exception").sendTo(sender); getPlugin().getLogger().warning("Failed to execute tempbanip command", e); return; } diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/TempIpMuteCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/TempIpMuteCommand.java index f986727c1..6a33ec419 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/TempIpMuteCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/TempIpMuteCommand.java @@ -57,7 +57,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { Message message = Message.get("sender.error.invalidIp"); message.set("ip", ipStr); - sender.sendMessage(message.toString()); + message.sendTo(sender); return true; } @@ -76,7 +76,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { try { expiresCheck = DateUtils.parseDateDiff(parser.args[1], true); } catch (Exception e1) { - sender.sendMessage(Message.get("time.error.invalid").toString()); + Message.get("time.error.invalid").sendTo(sender); return true; } @@ -92,7 +92,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { final IPAddress ip = getIp(ipStr); if (ip == null) { - sender.sendMessage(Message.get("sender.error.notFound").set("player", ipStr).toString()); + Message.get("sender.error.notFound").set("player", ipStr).sendTo(sender); return; } @@ -102,7 +102,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { Message message = Message.get("muteip.error.exists"); message.set("ip", ipStr); - sender.sendMessage(message.toString()); + message.sendTo(sender); return; } @@ -116,7 +116,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { try { getPlugin().getIpMuteStorage().unmute(mute, actor); } catch (SQLException e) { - sender.sendMessage(Message.get("sender.error.exception").toString()); + Message.get("sender.error.exception").sendTo(sender); getPlugin().getLogger().warning("Failed to execute tempmuteip command", e); return; } diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/TempIpRangeBanCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/TempIpRangeBanCommand.java index 51831b09c..9da0fcd19 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/TempIpRangeBanCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/TempIpRangeBanCommand.java @@ -62,7 +62,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { try { expiresCheck = DateUtils.parseDateDiff(parser.args[1], true); } catch (Exception e1) { - sender.sendMessage(Message.get("time.error.invalid").toString()); + Message.get("time.error.invalid").sendTo(sender); return true; } diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/TempMuteCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/TempMuteCommand.java index 7b9c90bcb..440ae02b0 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/TempMuteCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/TempMuteCommand.java @@ -57,12 +57,12 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { TargetResolver.TargetResult target = TargetResolver.resolveTarget(getPlugin().getServer(), playerName); if (target.getStatus() == TargetResolver.TargetStatus.NOT_FOUND) { - sender.sendMessage(Message.get("sender.error.notFound").set("player", playerName).toString()); + Message.get("sender.error.notFound").set("player", playerName).sendTo(sender); return true; } if (target.getStatus() == TargetResolver.TargetStatus.AMBIGUOUS) { - sender.sendMessage(Message.get("sender.error.ambiguousPlayer").set("player", playerName).toString()); + Message.get("sender.error.ambiguousPlayer").set("player", playerName).sendTo(sender); return true; } @@ -83,7 +83,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { try { isMuted = getPlugin().getPlayerMuteStorage().isMuted(UUID.fromString(playerName)); } catch (IllegalArgumentException e) { - sender.sendMessage(Message.get("sender.error.notFound").set("player", playerName).toString()); + Message.get("sender.error.notFound").set("player", playerName).sendTo(sender); return true; } } else { @@ -94,7 +94,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { Message message = Message.get("mute.error.exists"); message.set("player", targetName); - sender.sendMessage(message.toString()); + message.sendTo(sender); return true; } @@ -114,7 +114,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { try { expiresCheck = DateUtils.parseDateDiff(parser.args[1], true); } catch (Exception e1) { - sender.sendMessage(Message.get("time.error.invalid").toString()); + Message.get("time.error.invalid").sendTo(sender); return true; } @@ -130,12 +130,12 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { final PlayerData player = getPlayer(sender, targetName, true); if (player == null) { - sender.sendMessage(Message.get("sender.error.notFound").set("player", targetName).toString()); + Message.get("sender.error.notFound").set("player", targetName).sendTo(sender); return; } if (getPlugin().getExemptionsConfig().isExempt(player, "tempmute")) { - sender.sendMessage(Message.get("sender.error.exempt").set("player", targetName).toString()); + Message.get("sender.error.exempt").set("player", targetName).sendTo(sender); return; } @@ -145,7 +145,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { return; } } catch (SQLException e) { - sender.sendMessage(Message.get("sender.error.exception").toString()); + Message.get("sender.error.exception").sendTo(sender); getPlugin().getLogger().warning("Failed to execute tempmute command", e); return; } @@ -167,7 +167,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { try { getPlugin().getPlayerMuteStorage().unmute(mute, actor); } catch (SQLException e) { - sender.sendMessage(Message.get("sender.error.exception").toString()); + Message.get("sender.error.exception").sendTo(sender); getPlugin().getLogger().warning("Failed to execute tempmute command", e); return; } @@ -220,7 +220,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { muteMessage.set("expires", DateUtils.getDifferenceFormat(mute.getExpires())); } - onlinePlayer1.sendMessage(muteMessage.toString()); + muteMessage.sendTo(onlinePlayer1); }); diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/TempNameBanCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/TempNameBanCommand.java index f9501f327..6e3e1011f 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/TempNameBanCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/TempNameBanCommand.java @@ -42,7 +42,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { try { expiresCheck = DateUtils.parseDateDiff(parser.args[1], true); } catch (Exception e1) { - sender.sendMessage(Message.get("time.error.invalid").toString()); + Message.get("time.error.invalid").sendTo(sender); return true; } @@ -65,7 +65,7 @@ public void run() { Message message = Message.get("banname.error.exists"); message.set("name", name); - sender.sendMessage(message.toString()); + message.sendTo(sender); return; } @@ -80,7 +80,7 @@ public void run() { try { getPlugin().getNameBanStorage().unban(ban, actor); } catch (SQLException e) { - sender.sendMessage(Message.get("sender.error.exception").toString()); + Message.get("sender.error.exception").sendTo(sender); getPlugin().getLogger().warning("Failed to execute tempnameban command", e); return; } diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/TempWarnCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/TempWarnCommand.java index 3276a734d..6d3b2cf71 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/TempWarnCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/TempWarnCommand.java @@ -52,12 +52,12 @@ public boolean onCommand(final CommonSender sender, CommandParser originalParser TargetResolver.TargetResult target = TargetResolver.resolveTarget(getPlugin().getServer(), playerName); if (target.getStatus() == TargetResolver.TargetStatus.NOT_FOUND) { - sender.sendMessage(Message.get("sender.error.notFound").set("player", playerName).toString()); + Message.get("sender.error.notFound").set("player", playerName).sendTo(sender); return true; } if (target.getStatus() == TargetResolver.TargetStatus.AMBIGUOUS) { - sender.sendMessage(Message.get("sender.error.ambiguousPlayer").set("player", playerName).toString()); + Message.get("sender.error.ambiguousPlayer").set("player", playerName).sendTo(sender); return true; } @@ -86,7 +86,7 @@ public boolean onCommand(final CommonSender sender, CommandParser originalParser try { expiresCheck = DateUtils.parseDateDiff(parsedArgs[1], true); } catch (Exception e1) { - sender.sendMessage(Message.get("time.error.invalid").toString()); + Message.get("time.error.invalid").sendTo(sender); return true; } @@ -102,12 +102,12 @@ public boolean onCommand(final CommonSender sender, CommandParser originalParser final PlayerData player = getPlayer(sender, targetName, true); if (player == null) { - sender.sendMessage(Message.get("sender.error.notFound").set("player", targetName).toString()); + Message.get("sender.error.notFound").set("player", targetName).sendTo(sender); return; } if (getPlugin().getExemptionsConfig().isExempt(player, "tempwarn")) { - sender.sendMessage(Message.get("sender.error.exempt").set("player", targetName).toString()); + Message.get("sender.error.exempt").set("player", targetName).sendTo(sender); return; } @@ -117,7 +117,7 @@ public boolean onCommand(final CommonSender sender, CommandParser originalParser return; } } catch (SQLException e) { - sender.sendMessage(Message.get("sender.error.exception").toString()); + Message.get("sender.error.exception").sendTo(sender); getPlugin().getLogger().warning("Failed to execute tempwarn command", e); return; } @@ -134,7 +134,7 @@ public boolean onCommand(final CommonSender sender, CommandParser originalParser try { created = getPlugin().getPlayerWarnStorage().addWarning(warning, isSilent); } catch (SQLException e) { - sender.sendMessage(Message.get("sender.error.exception").toString()); + Message.get("sender.error.exception").sendTo(sender); getPlugin().getLogger().warning("Failed to execute tempwarn command", e); return; } @@ -156,7 +156,7 @@ public boolean onCommand(final CommonSender sender, CommandParser originalParser .set("id", warning.getId()) .set("points", parser.getPoints()); - onlinePlayer.sendMessage(warningMessage.toString()); + warningMessage.sendTo(onlinePlayer); } Message message = Message.get("tempwarn.notify") diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/UnbanCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/UnbanCommand.java index 44235e227..ff236504f 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/UnbanCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/UnbanCommand.java @@ -39,7 +39,7 @@ public boolean onCommand(final CommonSender sender, CommandParser originalParser try { isBanned = getPlugin().getPlayerBanStorage().isBanned(UUID.fromString(playerName)); } catch (IllegalArgumentException e) { - sender.sendMessage(Message.get("sender.error.notFound").set("player", playerName).toString()); + Message.get("sender.error.notFound").set("player", playerName).sendTo(sender); return true; } } else { @@ -50,7 +50,7 @@ public boolean onCommand(final CommonSender sender, CommandParser originalParser Message message = Message.get("unban.error.noExists"); message.set("player", playerName); - sender.sendMessage(message.toString()); + message.sendTo(sender); return true; } @@ -68,7 +68,7 @@ public boolean onCommand(final CommonSender sender, CommandParser originalParser } if (ban == null) { - sender.sendMessage(Message.get("sender.error.notFound").set("player", playerName).toString()); + Message.get("sender.error.notFound").set("player", playerName).sendTo(sender); return; } @@ -84,7 +84,7 @@ public boolean onCommand(final CommonSender sender, CommandParser originalParser try { unbanned = getPlugin().getPlayerBanStorage().unban(ban, actor, reason, isDelete, parser.isSilent()); } catch (SQLException e) { - sender.sendMessage(Message.get("sender.error.exception").toString()); + Message.get("sender.error.exception").sendTo(sender); getPlugin().getLogger().warning("Failed to execute unban command", e); return; } diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/UnbanIpCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/UnbanIpCommand.java index 7df20c8d8..df804d5a8 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/UnbanIpCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/UnbanIpCommand.java @@ -39,7 +39,7 @@ public boolean onCommand(final CommonSender sender, CommandParser originalParser Message message = Message.get("sender.error.invalidIp"); message.set("ip", ipStr); - sender.sendMessage(message.toString()); + message.sendTo(sender); return true; } @@ -51,8 +51,8 @@ public boolean onCommand(final CommonSender sender, CommandParser originalParser if (isName) { PlayerData player = getPlugin().getPlayerStorage().retrieve(ipStr, false); if (player == null) { - sender.sendMessage(Message.get("sender.error.notFound").set("player", ipStr) - .toString()); + Message.get("sender.error.notFound").set("player", ipStr) + .sendTo(sender); return; } @@ -61,7 +61,7 @@ public boolean onCommand(final CommonSender sender, CommandParser originalParser try { ip = new IPAddressString(ipStr).toAddress(); } catch (AddressStringException e) { - sender.sendMessage(Message.get("sender.error.exception").toString()); + Message.get("sender.error.exception").sendTo(sender); getPlugin().getLogger().warning("Failed to execute unbanip command", e); return; } @@ -71,7 +71,7 @@ public boolean onCommand(final CommonSender sender, CommandParser originalParser Message message = Message.get("unbanip.error.noExists"); message.set("ip", ipStr); - sender.sendMessage(message.toString()); + message.sendTo(sender); return; } @@ -89,7 +89,7 @@ public boolean onCommand(final CommonSender sender, CommandParser originalParser try { unbanned = getPlugin().getIpBanStorage().unban(ban, actor, reason, isDelete, parser.isSilent()); } catch (SQLException e) { - sender.sendMessage(Message.get("sender.error.exception").toString()); + Message.get("sender.error.exception").sendTo(sender); getPlugin().getLogger().warning("Failed to execute unbanip command", e); return; } diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/UnbanIpRangeCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/UnbanIpRangeCommand.java index a83e72ff8..17e4c6242 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/UnbanIpRangeCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/UnbanIpRangeCommand.java @@ -47,8 +47,8 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { if (isName) { PlayerData player = getPlugin().getPlayerStorage().retrieve(parser.args[0], false); if (player == null) { - sender.sendMessage(Message.get("sender.error.notFound").set("player", parser.args[0]) - .toString()); + Message.get("sender.error.notFound").set("player", parser.args[0]) + .sendTo(sender); return; } @@ -61,7 +61,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { Message message = Message.get("unbanip.error.noExists"); message.set("ip", parser.args[0]); - sender.sendMessage(message.toString()); + message.sendTo(sender); return; } @@ -76,7 +76,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { try { unbanned = getPlugin().getIpRangeBanStorage().unban(ban, actor, reason, parser.isSilent()); } catch (SQLException e) { - sender.sendMessage(Message.get("sender.error.exception").toString()); + Message.get("sender.error.exception").sendTo(sender); getPlugin().getLogger().warning("Failed to execute unbaniprange command", e); return; } diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/UnbanNameCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/UnbanNameCommand.java index 5b24ab88c..c2c41fe1d 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/UnbanNameCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/UnbanNameCommand.java @@ -39,7 +39,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { Message message = Message.get("unbanname.error.noExists"); message.set("name", name); - sender.sendMessage(message.toString()); + message.sendTo(sender); return; } @@ -53,7 +53,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { try { unbanned = getPlugin().getNameBanStorage().unban(ban, actor, reason, false, parser.isSilent()); } catch (SQLException e) { - sender.sendMessage(Message.get("sender.error.exception").toString()); + Message.get("sender.error.exception").sendTo(sender); getPlugin().getLogger().warning("Failed to execute unbanname command", e); return; } diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/UnmuteCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/UnmuteCommand.java index d2804b9bf..6b458f77d 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/UnmuteCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/UnmuteCommand.java @@ -40,7 +40,7 @@ public boolean onCommand(final CommonSender sender, CommandParser originalParser try { isMuted = getPlugin().getPlayerMuteStorage().isMuted(UUID.fromString(playerName)); } catch (IllegalArgumentException e) { - sender.sendMessage(Message.get("sender.error.notFound").set("player", playerName).toString()); + Message.get("sender.error.notFound").set("player", playerName).sendTo(sender); return true; } } else { @@ -51,7 +51,7 @@ public boolean onCommand(final CommonSender sender, CommandParser originalParser Message message = Message.get("unmute.error.noExists"); message.set("player", playerName); - sender.sendMessage(message.toString()); + message.sendTo(sender); return true; } @@ -72,8 +72,7 @@ public void run() { } if (mute == null) { - sender.sendMessage(Message.get("sender.error.notFound").set("player", playerName).toString - ()); + Message.get("sender.error.notFound").set("player", playerName).sendTo(sender); return; } @@ -89,7 +88,7 @@ public void run() { try { unmuted = getPlugin().getPlayerMuteStorage().unmute(mute, actor, reason, isDelete, parser.isSilent()); } catch (SQLException e) { - sender.sendMessage(Message.get("sender.error.exception").toString()); + Message.get("sender.error.exception").sendTo(sender); getPlugin().getLogger().warning("Failed to execute unmute command", e); return; } diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/UnmuteIpCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/UnmuteIpCommand.java index b2178e24f..ad9a260c6 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/UnmuteIpCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/UnmuteIpCommand.java @@ -29,7 +29,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { Message message = Message.get("sender.error.invalidIp"); message.set("ip", ipStr); - sender.sendMessage(message.toString()); + message.sendTo(sender); return true; } @@ -50,7 +50,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { final IPAddress ip = getIp(ipStr); if (ip == null) { - sender.sendMessage(Message.get("sender.error.notFound").set("player", ipStr).toString()); + Message.get("sender.error.notFound").set("player", ipStr).sendTo(sender); return; } @@ -58,7 +58,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { Message message = Message.get("unmuteip.error.noExists"); message.set("ip", ipStr); - sender.sendMessage(message.toString()); + message.sendTo(sender); return; } @@ -77,7 +77,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { try { unmuted = getPlugin().getIpMuteStorage().unmute(mute, actor, reason, parser.isSilent()); } catch (SQLException e) { - sender.sendMessage(Message.get("sender.error.exception").toString()); + Message.get("sender.error.exception").sendTo(sender); getPlugin().getLogger().warning("Failed to execute unmuteip command", e); return; } diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/WarnCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/WarnCommand.java index ecfbb9ac2..074b336c6 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/WarnCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/WarnCommand.java @@ -51,12 +51,12 @@ public boolean onCommand(final CommonSender sender, CommandParser originalParser TargetResolver.TargetResult target = TargetResolver.resolveTarget(getPlugin().getServer(), playerName); if (target.getStatus() == TargetResolver.TargetStatus.NOT_FOUND) { - sender.sendMessage(Message.get("sender.error.notFound").set("player", playerName).toString()); + Message.get("sender.error.notFound").set("player", playerName).sendTo(sender); return true; } if (target.getStatus() == TargetResolver.TargetStatus.AMBIGUOUS) { - sender.sendMessage(Message.get("sender.error.ambiguousPlayer").set("player", playerName).toString()); + Message.get("sender.error.ambiguousPlayer").set("player", playerName).sendTo(sender); return true; } @@ -83,12 +83,12 @@ public boolean onCommand(final CommonSender sender, CommandParser originalParser final PlayerData player = getPlayer(sender, targetName, true); if (player == null) { - sender.sendMessage(Message.get("sender.error.notFound").set("player", targetName).toString()); + Message.get("sender.error.notFound").set("player", targetName).sendTo(sender); return; } if (getPlugin().getExemptionsConfig().isExempt(player, "warn")) { - sender.sendMessage(Message.get("sender.error.exempt").set("player", targetName).toString()); + Message.get("sender.error.exempt").set("player", targetName).sendTo(sender); return; } @@ -98,7 +98,7 @@ public boolean onCommand(final CommonSender sender, CommandParser originalParser return; } } catch (SQLException e) { - sender.sendMessage(Message.get("sender.error.exception").toString()); + Message.get("sender.error.exception").sendTo(sender); getPlugin().getLogger().warning("Failed to execute warn command", e); return; } @@ -115,7 +115,7 @@ public boolean onCommand(final CommonSender sender, CommandParser originalParser try { created = getPlugin().getPlayerWarnStorage().addWarning(warning, isSilent); } catch (SQLException e) { - sender.sendMessage(Message.get("sender.error.exception").toString()); + Message.get("sender.error.exception").sendTo(sender); getPlugin().getLogger().warning("Failed to execute warn command", e); return; } @@ -136,7 +136,7 @@ public boolean onCommand(final CommonSender sender, CommandParser originalParser .set("id", warning.getId()) .set("points", parser.getPoints()); - onlinePlayer.sendMessage(warningMessage.toString()); + warningMessage.sendTo(onlinePlayer); } Message message = Message.get("warn.notify") diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/global/AddNoteAllCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/global/AddNoteAllCommand.java index aaa5c1f6d..0970d3120 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/global/AddNoteAllCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/global/AddNoteAllCommand.java @@ -44,7 +44,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { final PlayerData player = getPlayer(sender, playerName, true); if (player == null) { - sender.sendMessage(Message.get("sender.error.notFound").set("player", playerName).toString()); + Message.get("sender.error.notFound").set("player", playerName).sendTo(sender); return; } @@ -61,7 +61,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { new GlobalLocalApplyHelper(getPlugin()).applyNote(note, false); } } catch (SQLException e) { - sender.sendMessage(Message.get("sender.error.exception").toString()); + Message.get("sender.error.exception").sendTo(sender); getPlugin().getLogger().warning("Failed to execute addnoteall command", e); return; } diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/global/BanAllCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/global/BanAllCommand.java index 369c9ff4e..06b4a5830 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/global/BanAllCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/global/BanAllCommand.java @@ -44,7 +44,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { final PlayerData player = getPlayer(sender, playerName, true); if (player == null) { - sender.sendMessage(Message.get("sender.error.notFound").set("player", playerName).toString()); + Message.get("sender.error.notFound").set("player", playerName).sendTo(sender); return; } @@ -61,7 +61,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { new GlobalLocalApplyHelper(getPlugin()).applyBan(ban, false); } } catch (SQLException e) { - sender.sendMessage(Message.get("sender.error.exception").toString()); + Message.get("sender.error.exception").sendTo(sender); getPlugin().getLogger().warning("Failed to execute banall command", e); return; } diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/global/BanIpAllCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/global/BanIpAllCommand.java index 72c96f060..4877efd96 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/global/BanIpAllCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/global/BanIpAllCommand.java @@ -40,7 +40,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { Message message = Message.get("sender.error.invalidIp"); message.set("ip", ipStr); - sender.sendMessage(message.toString()); + message.sendTo(sender); return true; } @@ -59,7 +59,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { new GlobalLocalApplyHelper(getPlugin()).applyIpBan(ban, false); } } catch (SQLException e) { - sender.sendMessage(Message.get("sender.error.exception").toString()); + Message.get("sender.error.exception").sendTo(sender); getPlugin().getLogger().warning("Failed to execute banipall command", e); return; } diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/global/MuteAllCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/global/MuteAllCommand.java index 9f3ce9d7f..bfefe9612 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/global/MuteAllCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/global/MuteAllCommand.java @@ -51,7 +51,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { final PlayerData player = getPlayer(sender, playerName, true); if (player == null) { - sender.sendMessage(Message.get("sender.error.notFound").set("player", playerName).toString()); + Message.get("sender.error.notFound").set("player", playerName).sendTo(sender); return; } @@ -68,7 +68,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { new GlobalLocalApplyHelper(getPlugin()).applyMute(ban, false); } } catch (SQLException e) { - sender.sendMessage(Message.get("sender.error.exception").toString()); + Message.get("sender.error.exception").sendTo(sender); getPlugin().getLogger().warning("Failed to execute muteall command", e); return; } diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/global/TempBanAllCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/global/TempBanAllCommand.java index 2455961e8..6780cb25e 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/global/TempBanAllCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/global/TempBanAllCommand.java @@ -45,7 +45,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { try { expiresCheck = DateUtils.parseDateDiff(parser.getArgs()[1], true); } catch (Exception e1) { - sender.sendMessage(Message.get("time.error.invalid").toString()); + Message.get("time.error.invalid").sendTo(sender); return true; } @@ -62,7 +62,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { final PlayerData player = getPlayer(sender, playerName, true); if (player == null) { - sender.sendMessage(Message.get("sender.error.notFound").set("player", playerName).toString()); + Message.get("sender.error.notFound").set("player", playerName).sendTo(sender); return; } @@ -79,7 +79,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { new GlobalLocalApplyHelper(getPlugin()).applyBan(ban, false); } } catch (SQLException e) { - sender.sendMessage(Message.get("sender.error.exception").toString()); + Message.get("sender.error.exception").sendTo(sender); getPlugin().getLogger().warning("Failed to execute tempbanall command", e); return; } diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/global/TempBanIpAllCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/global/TempBanIpAllCommand.java index f00ce4102..ae543a812 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/global/TempBanIpAllCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/global/TempBanIpAllCommand.java @@ -42,7 +42,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { Message message = Message.get("sender.error.invalidIp"); message.set("ip", ipStr); - sender.sendMessage(message.toString()); + message.sendTo(sender); return true; } @@ -51,7 +51,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { try { expiresCheck = DateUtils.parseDateDiff(parser.getArgs()[1], true); } catch (Exception e1) { - sender.sendMessage(Message.get("time.error.invalid").toString()); + Message.get("time.error.invalid").sendTo(sender); return true; } @@ -77,7 +77,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { new GlobalLocalApplyHelper(getPlugin()).applyIpBan(ban, false); } } catch (SQLException e) { - sender.sendMessage(Message.get("sender.error.exception").toString()); + Message.get("sender.error.exception").sendTo(sender); getPlugin().getLogger().warning("Failed to execute tempbanipall command", e); return; } diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/global/TempMuteAllCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/global/TempMuteAllCommand.java index aef1d2ddf..aad91289b 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/global/TempMuteAllCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/global/TempMuteAllCommand.java @@ -52,7 +52,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { try { expiresCheck = DateUtils.parseDateDiff(parser.getArgs()[1], true); } catch (Exception e1) { - sender.sendMessage(Message.get("invalidTime").toString()); + Message.get("invalidTime").sendTo(sender); return true; } @@ -69,7 +69,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { final PlayerData player = getPlayer(sender, playerName, true); if (player == null) { - sender.sendMessage(Message.get("sender.error.notFound").set("player", playerName).toString()); + Message.get("sender.error.notFound").set("player", playerName).sendTo(sender); return; } @@ -83,7 +83,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { new GlobalLocalApplyHelper(getPlugin()).applyMute(mute, false); } } catch (SQLException e) { - sender.sendMessage(Message.get("sender.error.exception").toString()); + Message.get("sender.error.exception").sendTo(sender); getPlugin().getLogger().warning("Failed to execute tempmuteall command", e); return; } diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/global/UnbanAllCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/global/UnbanAllCommand.java index d6f5128e4..870b32aa5 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/global/UnbanAllCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/global/UnbanAllCommand.java @@ -41,7 +41,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { Message message = Message.get("unban.error.noExists"); message.set("player", playerName); - sender.sendMessage(message.toString()); + message.sendTo(sender); return true; } @@ -55,7 +55,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { } if (ban == null) { - sender.sendMessage(Message.get("sender.error.notFound").set("player", playerName).toString()); + Message.get("sender.error.notFound").set("player", playerName).sendTo(sender); return; } @@ -70,7 +70,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { new GlobalLocalApplyHelper(getPlugin()).applyUnban(record, false); } } catch (SQLException e) { - sender.sendMessage(Message.get("errorOccurred").toString()); + Message.get("errorOccurred").sendTo(sender); getPlugin().getLogger().warning("Failed to execute unbanall command", e); return; } diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/global/UnbanIpAllCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/global/UnbanIpAllCommand.java index 29fc7f9ae..6f1bd75c7 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/global/UnbanIpAllCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/global/UnbanIpAllCommand.java @@ -35,7 +35,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { Message message = Message.get("invalidIp"); message.set("ip", ipStr); - sender.sendMessage(message.toString()); + message.sendTo(sender); return true; } @@ -48,7 +48,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { Message message = Message.get("unbanip.error.noExists"); message.set("ip", ipStr); - sender.sendMessage(message.toString()); + message.sendTo(sender); return; } @@ -63,7 +63,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { new GlobalLocalApplyHelper(getPlugin()).applyIpUnban(record, false); } } catch (SQLException e) { - sender.sendMessage(Message.get("errorOccurred").toString()); + Message.get("errorOccurred").sendTo(sender); getPlugin().getLogger().warning("Failed to execute unbanipall command", e); return; } diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/global/UnmuteAllCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/global/UnmuteAllCommand.java index 2fb79e043..5cb278363 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/global/UnmuteAllCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/global/UnmuteAllCommand.java @@ -41,7 +41,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { Message message = Message.get("unmute.error.noExists"); message.set("player", playerName); - sender.sendMessage(message.toString()); + message.sendTo(sender); return true; } @@ -55,7 +55,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { } if (mute == null) { - sender.sendMessage(Message.get("sender.error.notFound").set("player", playerName).toString()); + Message.get("sender.error.notFound").set("player", playerName).sendTo(sender); return; } @@ -70,7 +70,7 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { new GlobalLocalApplyHelper(getPlugin()).applyUnmute(record, false); } } catch (SQLException e) { - sender.sendMessage(Message.get("errorOccurred").toString()); + Message.get("errorOccurred").sendTo(sender); getPlugin().getLogger().warning("Failed to execute unmuteall command", e); return; } diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/report/AssignSubCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/report/AssignSubCommand.java index c120a7c84..18ec0eb02 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/report/AssignSubCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/report/AssignSubCommand.java @@ -68,7 +68,7 @@ public boolean onCommand(final CommonSender sender, final CommandParser parser) } if (player == null) { - sender.sendMessage(Message.get("sender.error.notFound").toString()); + Message.get("sender.error.notFound").sendTo(sender); return; } @@ -88,22 +88,25 @@ public boolean onCommand(final CommonSender sender, final CommandParser parser) .set("player", player.getName()) .sendTo(sender); - getPlugin().getScheduler().runSync(new Runnable() { - - @Override - public void run() { - CommonPlayer bukkitPlayer = getPlugin().getServer().getPlayer(player.getUUID()); - - if (bukkitPlayer == null || !bukkitPlayer.isOnline()) return; + getPlugin().getScheduler().runSync(() -> { + CommonPlayer assignee = getPlugin().getServer().getPlayer(player.getUUID()); + if (assignee != null && assignee.isOnline()) { Message.get("report.assign.notify") .set("id", data.getId()) - .set("displayName", bukkitPlayer.getDisplayName()) + .set("displayName", assignee.getDisplayName()) .set("player", player.getName()) .set("playerId", player.getUUID().toString()) .set("reason", data.getReason()) - .set("actor", sender.getName()).sendTo(bukkitPlayer); + .set("actor", sender.getName()).sendTo(assignee); + } + CommonPlayer reporter = getPlugin().getServer().getPlayer(data.getActor().getUUID()); + if (reporter != null && reporter.isOnline()) { + Message.get("report.actions.feedback.assigned") + .set("id", data.getId()) + .set("actor", player.getName()) + .sendTo(reporter); } }); }); diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/report/CloseSubCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/report/CloseSubCommand.java index dc33873a7..8adc5b190 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/report/CloseSubCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/report/CloseSubCommand.java @@ -58,6 +58,8 @@ public boolean onCommand(final CommonSender sender, final CommandParser parser) return; } + notifyReporter(data, sender.getName()); + if (parser.getArgs().length == 1) { String message = Message.get("report.close.notify.closed") .set("actor", sender.getName()) @@ -127,6 +129,19 @@ public boolean onCommand(final CommonSender sender, final CommandParser parser) return true; } + private void notifyReporter(PlayerReportData data, String actorName) { + getPlugin().getScheduler().runSync(() -> { + me.confuser.banmanager.common.CommonPlayer reporter = + getPlugin().getServer().getPlayer(data.getActor().getUUID()); + if (reporter != null && reporter.isOnline()) { + Message.get("report.actions.feedback.closed") + .set("id", data.getId()) + .set("actor", actorName) + .sendTo(reporter); + } + }); + } + @Override public String getHelp() { return " [/command || comment]"; diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/report/InfoSubCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/report/InfoSubCommand.java index 9960d8149..c35bba0f5 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/report/InfoSubCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/report/InfoSubCommand.java @@ -67,14 +67,22 @@ public boolean onCommand(final CommonSender sender, CommandParser parser) { return; } - if (location == null) return; + if (location != null) { + Message.get("report.info.notify.location") + .set("world", location.getWorld()) + .set("x", location.getX()) + .set("y", location.getY()) + .set("z", location.getZ()) + .sendTo(sender); + } - Message.get("report.info.notify.location") - .set("world", location.getWorld()) - .set("x", location.getX()) - .set("y", location.getY()) - .set("z", location.getZ()) - .sendTo(sender); + if (!sender.isConsole()) { + Message.get("report.actions.assign").set("id", data.getId()).sendTo(sender); + Message.get("report.actions.close").set("id", data.getId()).sendTo(sender); + if (location != null) { + Message.get("report.actions.tp").set("id", data.getId()).sendTo(sender); + } + } }); diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/report/ListSubCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/report/ListSubCommand.java index 47afedfec..91d885a36 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/report/ListSubCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/report/ListSubCommand.java @@ -45,7 +45,7 @@ public boolean onCommand(final CommonSender sender, final CommandParser parser) state = states.get(0).getId(); } catch (SQLException e) { - sender.sendMessage(Message.get("sender.error.exception").toString()); + Message.get("sender.error.exception").sendTo(sender); getPlugin().getLogger().warning("Failed to execute report list", e); return; } @@ -61,7 +61,7 @@ public boolean onCommand(final CommonSender sender, final CommandParser parser) .getReports(page, state, sender.getData().getUUID()); } } catch (SQLException e) { - sender.sendMessage(Message.get("sender.error.exception").toString()); + Message.get("sender.error.exception").sendTo(sender); getPlugin().getLogger().warning("Failed to execute report list", e); return; } diff --git a/common/src/main/java/me/confuser/banmanager/common/configs/NotificationsConfig.java b/common/src/main/java/me/confuser/banmanager/common/configs/NotificationsConfig.java new file mode 100644 index 000000000..838d3eda2 --- /dev/null +++ b/common/src/main/java/me/confuser/banmanager/common/configs/NotificationsConfig.java @@ -0,0 +1,101 @@ +package me.confuser.banmanager.common.configs; + +import lombok.Getter; +import me.confuser.banmanager.common.CommonLogger; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; + +public class NotificationsConfig extends Config { + + @Getter + private Map staffChannels = new HashMap<>(); + @Getter + private boolean mutedActionBar = true; + @Getter + private String warnedSound = "entity.villager.no"; + @Getter + private float warnedSoundVolume = 1.0f; + @Getter + private float warnedSoundPitch = 1.0f; + + public NotificationsConfig(File dataFolder, CommonLogger logger) { + super(dataFolder, "notifications.yml", logger); + } + + @Override + public void afterLoad() { + staffChannels.clear(); + + if (conf.getConfigurationSection("staff") != null) { + for (String key : conf.getConfigurationSection("staff").getKeys(false)) { + String path = "staff." + key; + NotificationChannel channel = new NotificationChannel( + conf.getBoolean(path + ".chat", true), + conf.getBoolean(path + ".actionbar", false), + conf.getBoolean(path + ".title", false), + conf.getString(path + ".sound", ""), + (float) conf.getDouble(path + ".soundVolume", 1.0), + (float) conf.getDouble(path + ".soundPitch", 1.0), + conf.getInt(path + ".titleFadeIn", 10), + conf.getInt(path + ".titleStay", 70), + conf.getInt(path + ".titleFadeOut", 20) + ); + staffChannels.put(key, channel); + } + } + + if (conf.getConfigurationSection("player") != null) { + if (conf.getConfigurationSection("player.muted") != null) { + mutedActionBar = conf.getBoolean("player.muted.actionbar", true); + } + if (conf.getConfigurationSection("player.warned") != null) { + warnedSound = conf.getString("player.warned.sound", "entity.villager.no"); + warnedSoundVolume = (float) conf.getDouble("player.warned.soundVolume", 1.0); + warnedSoundPitch = (float) conf.getDouble("player.warned.soundPitch", 1.0); + } + } + } + + @Override + public void onSave() { + } + + public NotificationChannel getStaffChannel(String event) { + return staffChannels.getOrDefault(event, NotificationChannel.CHAT_ONLY); + } + + @Getter + public static class NotificationChannel { + static final NotificationChannel CHAT_ONLY = new NotificationChannel(true, false, false, "", 1.0f, 1.0f, 10, 70, 20); + + private final boolean chat; + private final boolean actionbar; + private final boolean title; + private final String sound; + private final float soundVolume; + private final float soundPitch; + private final int titleFadeIn; + private final int titleStay; + private final int titleFadeOut; + + public NotificationChannel(boolean chat, boolean actionbar, boolean title, + String sound, float soundVolume, float soundPitch, + int titleFadeIn, int titleStay, int titleFadeOut) { + this.chat = chat; + this.actionbar = actionbar; + this.title = title; + this.sound = sound; + this.soundVolume = soundVolume; + this.soundPitch = soundPitch; + this.titleFadeIn = titleFadeIn; + this.titleStay = titleStay; + this.titleFadeOut = titleFadeOut; + } + + public boolean hasSound() { + return sound != null && !sound.isEmpty(); + } + } +} diff --git a/common/src/main/java/me/confuser/banmanager/common/configs/WebhookConfig.java b/common/src/main/java/me/confuser/banmanager/common/configs/WebhookConfig.java index 42baf85b3..b4c2ded74 100644 --- a/common/src/main/java/me/confuser/banmanager/common/configs/WebhookConfig.java +++ b/common/src/main/java/me/confuser/banmanager/common/configs/WebhookConfig.java @@ -191,16 +191,6 @@ public List getHooks(String type) { return hooks != null ? hooks : Collections.emptyList(); } - /** - * @deprecated Use {@link #getHooks(String)} instead for multi-webhook support. - * This method returns the first webhook config for backwards compatibility. - */ - @Deprecated - public WebhookHookConfig getType(String type) { - List hooks = hookTypes.get(type); - return (hooks != null && !hooks.isEmpty()) ? hooks.get(0) : null; - } - @AllArgsConstructor public static class WebhookHookConfig { @Getter diff --git a/common/src/main/java/me/confuser/banmanager/common/listeners/CommonBanListener.java b/common/src/main/java/me/confuser/banmanager/common/listeners/CommonBanListener.java index c994082db..c764bfc84 100755 --- a/common/src/main/java/me/confuser/banmanager/common/listeners/CommonBanListener.java +++ b/common/src/main/java/me/confuser/banmanager/common/listeners/CommonBanListener.java @@ -5,6 +5,7 @@ import me.confuser.banmanager.common.data.*; import me.confuser.banmanager.common.util.DateUtils; import me.confuser.banmanager.common.util.Message; +import me.confuser.banmanager.common.util.NotificationUtils; import java.util.List; @@ -17,13 +18,16 @@ public CommonBanListener(BanManagerPlugin plugin) { public void notifyOnBan(PlayerBanData data, boolean silent) { String broadcastPermission; + String event; Message message; if (data.getExpires() == 0) { broadcastPermission = "bm.notify.ban"; + event = "ban"; message = Message.get("ban.notify"); } else { broadcastPermission = "bm.notify.tempban"; + event = "tempban"; message = Message.get("tempban.notify"); message.set("expires", DateUtils.getDifferenceFormat(data.getExpires())); } @@ -36,14 +40,12 @@ public void notifyOnBan(PlayerBanData data, boolean silent) { .set("reason", data.getReason()); if (!silent) { - plugin.getServer().broadcast(message, broadcastPermission); + NotificationUtils.notifyStaff(plugin, event, message, broadcastPermission); } else if (plugin.getPlayerStorage().getConsole().getUUID().equals(data.getActor().getUUID())) { plugin.getServer().getConsoleSender().sendMessage(message); return; } - // Check if the sender is online and does not have the - // broadcastPermission CommonPlayer player = plugin.getServer().getPlayer(data.getActor().getUUID()); if (player == null || !player.isOnline()) { @@ -57,13 +59,16 @@ public void notifyOnBan(PlayerBanData data, boolean silent) { public void notifyOnBan(IpBanData data, boolean silent) { String broadcastPermission; + String event; Message message; if (data.getExpires() == 0) { broadcastPermission = "bm.notify.banip"; + event = "ban"; message = Message.get("banip.notify"); } else { broadcastPermission = "bm.notify.tempbanip"; + event = "tempban"; message = Message.get("tempbanip.notify"); message.set("expires", DateUtils.getDifferenceFormat(data.getExpires())); } @@ -86,14 +91,12 @@ public void notifyOnBan(IpBanData data, boolean silent) { .set("players", playerNames.toString()); if (!silent) { - plugin.getServer().broadcast(message, broadcastPermission); + NotificationUtils.notifyStaff(plugin, event, message, broadcastPermission); } else if (plugin.getPlayerStorage().getConsole().getUUID().equals(data.getActor().getUUID())) { plugin.getServer().getConsoleSender().sendMessage(message); return; } - // Check if the sender is online and does not have the - // broadcastPermission CommonPlayer player = plugin.getServer().getPlayer(data.getActor().getUUID()); if (player == null || !player.isOnline()) { @@ -107,13 +110,16 @@ public void notifyOnBan(IpBanData data, boolean silent) { public void notifyOnBan(IpRangeBanData data, boolean silent) { String broadcastPermission; + String event; Message message; if (data.getExpires() == 0) { broadcastPermission = "bm.notify.baniprange"; + event = "ban"; message = Message.get("baniprange.notify"); } else { broadcastPermission = "bm.notify.tempbaniprange"; + event = "tempban"; message = Message.get("tempbaniprange.notify"); message.set("expires", DateUtils.getDifferenceFormat(data.getExpires())); } @@ -126,14 +132,12 @@ public void notifyOnBan(IpRangeBanData data, boolean silent) { .set("reason", data.getReason()); if (!silent) { - plugin.getServer().broadcast(message, broadcastPermission); + NotificationUtils.notifyStaff(plugin, event, message, broadcastPermission); } else if (plugin.getPlayerStorage().getConsole().getUUID().equals(data.getActor().getUUID())) { plugin.getServer().getConsoleSender().sendMessage(message); return; } - // Check if the sender is online and does not have the - // broadcastPermission CommonPlayer player = plugin.getServer().getPlayer(data.getActor().getUUID()); if (player == null || !player.isOnline()) { @@ -147,13 +151,16 @@ public void notifyOnBan(IpRangeBanData data, boolean silent) { public void notifyOnBan(NameBanData data, boolean silent) { String broadcastPermission; + String event; Message message; if (data.getExpires() == 0) { broadcastPermission = "bm.notify.banname"; + event = "ban"; message = Message.get("banname.notify"); } else { broadcastPermission = "bm.notify.tempbanname"; + event = "tempban"; message = Message.get("tempbanname.notify"); message.set("expires", DateUtils.getDifferenceFormat(data.getExpires())); } @@ -165,14 +172,12 @@ public void notifyOnBan(NameBanData data, boolean silent) { .set("reason", data.getReason()); if (!silent) { - plugin.getServer().broadcast(message, broadcastPermission); + NotificationUtils.notifyStaff(plugin, event, message, broadcastPermission); } else if (plugin.getPlayerStorage().getConsole().getUUID().equals(data.getActor().getUUID())) { plugin.getServer().getConsoleSender().sendMessage(message); return; } - // Check if the sender is online and does not have the - // broadcastPermission CommonPlayer player = plugin.getServer().getPlayer(data.getActor().getUUID()); if (player == null || !player.isOnline()) { diff --git a/common/src/main/java/me/confuser/banmanager/common/listeners/CommonChatListener.java b/common/src/main/java/me/confuser/banmanager/common/listeners/CommonChatListener.java index b0b49d7b1..b7c71da50 100755 --- a/common/src/main/java/me/confuser/banmanager/common/listeners/CommonChatListener.java +++ b/common/src/main/java/me/confuser/banmanager/common/listeners/CommonChatListener.java @@ -7,6 +7,7 @@ import me.confuser.banmanager.common.data.PlayerWarnData; import me.confuser.banmanager.common.util.DateUtils; import me.confuser.banmanager.common.util.Message; +import me.confuser.banmanager.common.util.NotificationUtils; import java.net.InetAddress; import java.sql.SQLException; @@ -32,6 +33,8 @@ public boolean onPlayerChat(CommonPlayer player, CommonChatHandler handler, Stri } else { Message.get("warn.player.disallowed.header").sendTo(player); Message.get("warn.player.disallowed.reason").set("reason", warning.getReason()).sendTo(player); + + NotificationUtils.playWarnedSound(plugin, player); } return true; @@ -88,6 +91,10 @@ public boolean onPlayerChat(CommonPlayer player, CommonChatHandler handler, Stri player.sendMessage(message); + if (plugin.getNotificationsConfig().isMutedActionBar()) { + player.sendActionBar(message.resolveComponentFor(player)); + } + return true; } @@ -145,7 +152,7 @@ public boolean onIpChat(CommonPlayer player, InetAddress address, CommonChatHand .set("id", mute.getId()) .set("ip", mute.getIp().toString()); - player.sendMessage(message.toString()); + message.sendTo(player); return true; } diff --git a/common/src/main/java/me/confuser/banmanager/common/listeners/CommonCommandListener.java b/common/src/main/java/me/confuser/banmanager/common/listeners/CommonCommandListener.java index 6a149aae2..1e0394d8c 100755 --- a/common/src/main/java/me/confuser/banmanager/common/listeners/CommonCommandListener.java +++ b/common/src/main/java/me/confuser/banmanager/common/listeners/CommonCommandListener.java @@ -45,7 +45,7 @@ public boolean onCommand(CommonPlayer player, String cmd, String[] args) { if (!shouldCancel) return false; } - if (!isSoft) player.sendMessage(Message.get("mute.player.blocked").set("command", cmd).toString()); + if (!isSoft) Message.get("mute.player.blocked").set("command", cmd).sendTo(player); return true; } diff --git a/common/src/main/java/me/confuser/banmanager/common/listeners/CommonJoinListener.java b/common/src/main/java/me/confuser/banmanager/common/listeners/CommonJoinListener.java index c69f85655..10653ddf6 100755 --- a/common/src/main/java/me/confuser/banmanager/common/listeners/CommonJoinListener.java +++ b/common/src/main/java/me/confuser/banmanager/common/listeners/CommonJoinListener.java @@ -314,7 +314,7 @@ public void onJoin(final CommonPlayer player) { .set("amount", notes.size()) .set("player", player.getName()); - plugin.getServer().broadcastJSON(NotesCommand.notesAmountMessage(player.getName(), noteJoinMessage), "bm.notify.notes.joinAmount"); + plugin.getServer().broadcast(NotesCommand.notesAmountMessage(player.getName(), noteJoinMessage), "bm.notify.notes.joinAmount"); Message header = Message.get("notes.header") .set("player", player.getName()); diff --git a/common/src/main/java/me/confuser/banmanager/common/listeners/CommonMuteListener.java b/common/src/main/java/me/confuser/banmanager/common/listeners/CommonMuteListener.java index c82ab19e7..59596a10f 100755 --- a/common/src/main/java/me/confuser/banmanager/common/listeners/CommonMuteListener.java +++ b/common/src/main/java/me/confuser/banmanager/common/listeners/CommonMuteListener.java @@ -7,6 +7,7 @@ import me.confuser.banmanager.common.data.PlayerMuteData; import me.confuser.banmanager.common.util.DateUtils; import me.confuser.banmanager.common.util.Message; +import me.confuser.banmanager.common.util.NotificationUtils; import java.util.List; @@ -19,13 +20,16 @@ public CommonMuteListener(BanManagerPlugin plugin) { public void notifyOnMute(PlayerMuteData data, boolean silent) { String broadcastPermission; + String event; Message message; if (data.getExpires() == 0 && !data.isOnlineOnly()) { broadcastPermission = "bm.notify.mute"; + event = "mute"; message = Message.get("mute.notify"); } else if (data.isOnlineOnly()) { broadcastPermission = "bm.notify.tempmute"; + event = "tempmute"; message = Message.get("tempmute.notifyOnline"); if (data.isPaused()) { message.set("expires", DateUtils.formatDifference(data.getPausedRemaining())); @@ -34,6 +38,7 @@ public void notifyOnMute(PlayerMuteData data, boolean silent) { } } else { broadcastPermission = "bm.notify.tempmute"; + event = "tempmute"; message = Message.get("tempmute.notify"); message.set("expires", DateUtils.getDifferenceFormat(data.getExpires())); } @@ -46,14 +51,12 @@ public void notifyOnMute(PlayerMuteData data, boolean silent) { .set("reason", data.getReason()); if (!silent) { - plugin.getServer().broadcast(message, broadcastPermission); + NotificationUtils.notifyStaff(plugin, event, message, broadcastPermission); } else if (plugin.getPlayerStorage().getConsole().getUUID().equals(data.getActor().getUUID())) { plugin.getServer().getConsoleSender().sendMessage(message); return; } - // Check if the sender is online and does not have the - // broadcastPermission CommonPlayer player = plugin.getServer().getPlayer(data.getActor().getUUID()); if (player == null || !player.isOnline()) { @@ -67,13 +70,16 @@ public void notifyOnMute(PlayerMuteData data, boolean silent) { public void notifyOnMute(IpMuteData data, boolean silent) { String broadcastPermission; + String event; Message message; if (data.getExpires() == 0) { broadcastPermission = "bm.notify.muteip"; + event = "mute"; message = Message.get("muteip.notify"); } else { broadcastPermission = "bm.notify.tempmuteip"; + event = "tempmute"; message = Message.get("tempmuteip.notify"); message.set("expires", DateUtils.getDifferenceFormat(data.getExpires())); } @@ -97,14 +103,12 @@ public void notifyOnMute(IpMuteData data, boolean silent) { .set("players", playerNames.toString()); if (!silent) { - plugin.getServer().broadcast(message, broadcastPermission); + NotificationUtils.notifyStaff(plugin, event, message, broadcastPermission); } else if (plugin.getPlayerStorage().getConsole().getUUID().equals(data.getActor().getUUID())) { plugin.getServer().getConsoleSender().sendMessage(message); return; } - // Check if the sender is online and does not have the - // broadcastPermission CommonPlayer player = plugin.getServer().getPlayer(data.getActor().getUUID()); if (player == null || !player.isOnline()) { diff --git a/common/src/main/java/me/confuser/banmanager/common/util/ColorUtils.java b/common/src/main/java/me/confuser/banmanager/common/util/ColorUtils.java index d6fba1559..185e7aa3a 100644 --- a/common/src/main/java/me/confuser/banmanager/common/util/ColorUtils.java +++ b/common/src/main/java/me/confuser/banmanager/common/util/ColorUtils.java @@ -28,7 +28,7 @@ public class ColorUtils { // Outputs JSON with NO hex colors - safe for pre-1.16 clients private static final GsonComponentSerializer DOWNSAMPLING_JSON = - GsonComponentSerializer.colorDownsamplingGson(); + GsonComponentSerializer.builder().downsampleColors().build(); /** * Convert Spigot-style &x&r&r&g&g&b&b to &#rrggbb format @@ -97,6 +97,6 @@ public static String toDownsampledJson(String message) { */ public static String toJson(String message) { Component component = parse(message); - return GsonComponentSerializer.gson().serialize(component); + return GsonComponentSerializer.builder().build().serialize(component); } } diff --git a/common/src/main/java/me/confuser/banmanager/common/util/Message.java b/common/src/main/java/me/confuser/banmanager/common/util/Message.java index e8cccd492..3c78bdf30 100644 --- a/common/src/main/java/me/confuser/banmanager/common/util/Message.java +++ b/common/src/main/java/me/confuser/banmanager/common/util/Message.java @@ -6,16 +6,22 @@ import me.confuser.banmanager.common.CommonPlayer; import me.confuser.banmanager.common.PlaceholderResolver; import me.confuser.banmanager.common.commands.CommonSender; -import me.confuser.banmanager.common.configs.Config; -import me.confuser.banmanager.common.configuration.file.YamlConfiguration; +import me.confuser.banmanager.common.kyori.text.Component; import java.util.LinkedHashMap; import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public class Message { private static volatile MessageRegistry registry; private static volatile CommonLogger logger; + // Matches PlaceholderAPI %placeholder% tokens. May also match non-PAPI patterns like %100%, + // but the resolver's no-op return for unrecognised placeholders makes this harmless. + private static final Pattern PAPI_PATTERN = Pattern.compile("%([^%]+)%"); + + private static final String REPLACE_PREFIX = "__replace__"; @Getter private String key; @@ -24,8 +30,8 @@ public class Message { public Message(String key) { this.key = key; - if (registry != null && registry.getMessage(key) == null) { - if (logger != null) logger.warning("Missing " + key + " message"); + if (registry != null && registry.getMessage(key) == null && logger != null) { + logger.warning("Missing " + key + " message"); } } @@ -50,49 +56,61 @@ public static Message get(String key) { return new Message(key); } + /** + * Resolve a message template to a Component using the default locale. + * Convenience for static messages with no dynamic tokens. + */ + public static Component component(String key) { + return get(key).resolveComponent(); + } + + /** + * Resolve a message template to a Component using the specified locale. + */ + public static Component component(String key, String locale) { + return get(key).resolveComponent(locale); + } + public static String getString(String key) { if (registry == null) return null; - return registry.getMessage(key); + String template = registry.getMessage(key); + if (template == null) return null; + MessageRenderer renderer = MessageRenderer.getInstance(); + return renderer.toLegacy(renderer.render(template)); } public static String getString(String key, String locale) { if (registry == null) return null; - return registry.getMessage(key, locale); + String template = registry.getMessage(key, locale); + if (template == null) return null; + MessageRenderer renderer = MessageRenderer.getInstance(); + return renderer.toLegacy(renderer.render(template)); } /** - * @deprecated Use {@link #init(MessageRegistry, CommonLogger)} instead. - * Loads messages from the YAML config into the active registry for backwards compatibility. + * Get the raw, unrendered template string for a message key. + * Use this when you need to check for key existence or render + * the template separately with dynamic context. */ - @Deprecated - public static void load(YamlConfiguration config, CommonLogger commonLogger) { - logger = commonLogger; - - if (registry != null && config.getConfigurationSection("messages") != null) { - for (String key : config.getConfigurationSection("messages").getKeys(true)) { - String value = config.getString("messages." + key); - if (value != null) { - registry.putMessage(key, value.replace("\\n", "\n").replaceAll("(?<=\\n)(?=\\n)", " ")); - } - } - } + public static String getRawTemplate(String key) { + if (registry == null) return null; + return registry.getMessage(key); } /** - * @deprecated Use {@link #init(MessageRegistry, CommonLogger)} instead. + * Get the raw, unrendered template string for this message's key. */ - @Deprecated - public static void load(Config config) { - load(config.conf, config.getLogger()); + public String getRawTemplate() { + return getRawTemplate(this.key); } public Message replace(CharSequence oldChar, CharSequence newChar) { - replacements.put("__replace__" + replacements.size(), new String[]{oldChar.toString(), newChar.toString()}); + replacements.put(REPLACE_PREFIX + replacements.size(), new String[]{oldChar.toString(), newChar.toString()}); return this; } public Message set(String token, String replace) { - replacements.put(token, new String[]{"[" + token + "]", replace}); + replacements.put(token, new String[]{token, replace}); return this; } @@ -112,29 +130,84 @@ public Message set(String token, Float replace) { return set(token, replace.toString()); } + /** + * Resolve the message template to a legacy &-code string using the specified locale. + */ public String resolve(String locale) { - if (registry == null) return ""; + Component component = resolveComponent(locale); + return MessageRenderer.getInstance().toLegacy(component); + } + + /** + * Resolve the message template to a Component using the default locale. + */ + public Component resolveComponent() { + return resolveComponent(getDefaultLocale()); + } + + /** + * Resolve the message template to a Component using MiniMessage. + * Pipeline: raw template -> .replace() subs -> PAPI -> token replacement -> MiniMessage parse + */ + public Component resolveComponent(String locale) { + return resolveComponent(locale, null); + } + + /** + * Resolve the message template to a Component using MiniMessage, with optional PAPI resolution. + */ + public Component resolveComponent(String locale, CommonPlayer player) { + if (registry == null) return Component.empty(); String template = registry.getMessage(key, locale); - if (template == null) return ""; + if (template == null) return Component.empty(); + + MessageRenderer renderer = MessageRenderer.getInstance(); + + // Step 1: Apply .replace() substitutions on the raw string + template = applyRawReplacements(template); + + // Step 2: Resolve PAPI placeholders individually, escaping MiniMessage tags in output + if (player != null && BanManagerPlugin.getInstance() != null) { + PlaceholderResolver papiResolver = BanManagerPlugin.getInstance().getPlaceholderResolver(); + if (papiResolver != null) { + template = resolvePapiSafe(papiResolver, player, template); + } + } + + // Step 3: Apply static and dynamic tokens as raw string replacements so they + // resolve correctly inside click/hover arguments (MiniMessage TagResolvers + // produce Components which can't be used as click event string values) + template = applyTokenReplacements(template, renderer); - return applyReplacements(template); + // Step 4: Parse with MiniMessage (standard tags only, tokens already replaced) + return renderer.render(template); } - public String resolveFor(CommonPlayer player) { - if (player == null) return resolve(getDefaultLocale()); + /** + * Resolve the Component for a specific player, respecting per-player locale. + */ + public Component resolveComponentFor(CommonPlayer player) { + if (player == null) return resolveComponent(getDefaultLocale()); BanManagerPlugin plugin = BanManagerPlugin.getInstance(); + String locale = getDefaultLocale(); if (plugin != null && plugin.getConfig() != null && plugin.getConfig().isPerPlayerLocale()) { - return resolve(player.getLocale()); + locale = player.getLocale(); } - return resolve(getDefaultLocale()); + return resolveComponent(locale, player); + } + + public String resolveFor(CommonPlayer player) { + Component component = resolveComponentFor(player); + return MessageRenderer.getInstance().toLegacy(component); } public boolean sendTo(CommonSender sender) { if (sender == null) return false; - sender.sendMessage(resolve(getDefaultLocale())); + Component component = resolveComponent(getDefaultLocale()); + sender.sendMessage(component); return true; } @@ -143,13 +216,8 @@ public boolean sendTo(CommonPlayer player) { if (player == null) return false; if (!player.isOnline()) return false; - String resolved = resolveFor(player); - PlaceholderResolver resolver = BanManagerPlugin.getInstance().getPlaceholderResolver(); - if (resolver != null) { - resolved = resolver.resolve(player, resolved); - } - - player.sendMessage(resolved); + Component component = resolveComponentFor(player); + player.sendMessage(component); return true; } @@ -163,12 +231,58 @@ public String toString() { return resolve(getDefaultLocale()); } - private String applyReplacements(String template) { + /** + * Apply .replace() raw substitutions on the template string before MiniMessage parsing. + */ + private String applyRawReplacements(String template) { + String result = template; + for (Map.Entry entry : replacements.entrySet()) { + if (entry.getKey().startsWith(REPLACE_PREFIX)) { + String[] pair = entry.getValue(); + result = result.replace(pair[0], pair[1]); + } + } + return result; + } + + /** + * Resolve PAPI placeholders individually, escaping MiniMessage tags in each resolved value + * to prevent injection of formatting/click/hover tags from external placeholder plugins. + */ + private static String resolvePapiSafe(PlaceholderResolver resolver, CommonPlayer player, String template) { + MessageRenderer renderer = MessageRenderer.getInstance(); + Matcher matcher = PAPI_PATTERN.matcher(template); + StringBuffer sb = new StringBuffer(); + while (matcher.find()) { + String placeholder = matcher.group(0); + String resolved = resolver.resolve(player, placeholder); + if (!resolved.equals(placeholder)) { + matcher.appendReplacement(sb, Matcher.quoteReplacement(renderer.escapeTags(resolved))); + } + } + matcher.appendTail(sb); + return sb.toString(); + } + + /** + * Apply static and dynamic token replacements as raw string substitutions. + * Values are tag-escaped to prevent MiniMessage injection. + */ + private String applyTokenReplacements(String template, MessageRenderer renderer) { String result = template; + + for (Map.Entry entry : renderer.getStaticTokens().entrySet()) { + result = result.replace("<" + entry.getKey() + ">", renderer.escapeTags(entry.getValue())); + } + for (Map.Entry entry : replacements.entrySet()) { - String[] pair = entry.getValue(); - result = result.replace(pair[0], pair[1]); + if (!entry.getKey().startsWith(REPLACE_PREFIX)) { + String tokenName = MessageRenderer.normaliseTagName(entry.getKey()); + String value = entry.getValue()[1]; + result = result.replace("<" + tokenName + ">", renderer.escapeTags(value)); + } } + return result; } diff --git a/common/src/main/java/me/confuser/banmanager/common/util/MessageRenderer.java b/common/src/main/java/me/confuser/banmanager/common/util/MessageRenderer.java new file mode 100644 index 000000000..ad8481a74 --- /dev/null +++ b/common/src/main/java/me/confuser/banmanager/common/util/MessageRenderer.java @@ -0,0 +1,284 @@ +package me.confuser.banmanager.common.util; + +import me.confuser.banmanager.common.kyori.text.Component; +import me.confuser.banmanager.common.kyori.text.minimessage.MiniMessage; +import me.confuser.banmanager.common.kyori.text.minimessage.tag.Tag; +import me.confuser.banmanager.common.kyori.text.minimessage.tag.resolver.Placeholder; +import me.confuser.banmanager.common.kyori.text.minimessage.tag.resolver.TagResolver; +import me.confuser.banmanager.common.kyori.text.serializer.gson.GsonComponentSerializer; +import me.confuser.banmanager.common.kyori.text.serializer.legacy.LegacyComponentSerializer; +import me.confuser.banmanager.common.kyori.text.serializer.plain.PlainTextComponentSerializer; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; + +public class MessageRenderer { + + private static MessageRenderer instance; // guarded by class-level synchronization + + private final MiniMessage miniMessage; + private final LegacyComponentSerializer legacySerializer; + private final PlainTextComponentSerializer plainTextSerializer; + private volatile GsonComponentSerializer gsonSerializer; + private volatile TagResolver staticTokenResolver = TagResolver.empty(); + private volatile Map staticTokens = Collections.emptyMap(); + + private static final Pattern LEGACY_COLOR_PATTERN = Pattern.compile("&[0-9a-fk-or]", Pattern.CASE_INSENSITIVE); + private static final Pattern LEGACY_HEX_PATTERN = Pattern.compile("&#[0-9a-fA-F]{6}"); + + private static final Map LEGACY_CODE_MAP = new HashMap<>(); + + static { + LEGACY_CODE_MAP.put('0', ""); + LEGACY_CODE_MAP.put('1', ""); + LEGACY_CODE_MAP.put('2', ""); + LEGACY_CODE_MAP.put('3', ""); + LEGACY_CODE_MAP.put('4', ""); + LEGACY_CODE_MAP.put('5', ""); + LEGACY_CODE_MAP.put('6', ""); + LEGACY_CODE_MAP.put('7', ""); + LEGACY_CODE_MAP.put('8', ""); + LEGACY_CODE_MAP.put('9', ""); + LEGACY_CODE_MAP.put('a', ""); + LEGACY_CODE_MAP.put('b', ""); + LEGACY_CODE_MAP.put('c', ""); + LEGACY_CODE_MAP.put('d', ""); + LEGACY_CODE_MAP.put('e', ""); + LEGACY_CODE_MAP.put('f', ""); + LEGACY_CODE_MAP.put('k', ""); + LEGACY_CODE_MAP.put('l', ""); + LEGACY_CODE_MAP.put('m', ""); + LEGACY_CODE_MAP.put('n', ""); + LEGACY_CODE_MAP.put('o', ""); + LEGACY_CODE_MAP.put('r', ""); + } + + public MessageRenderer() { + this.miniMessage = MiniMessage.miniMessage(); + this.legacySerializer = LegacyComponentSerializer.builder() + .character('&') + .hexColors() + .build(); + this.plainTextSerializer = PlainTextComponentSerializer.plainText(); + } + + public static synchronized MessageRenderer getInstance() { + if (instance == null) { + instance = new MessageRenderer(); + } + return instance; + } + + public static synchronized void setInstance(MessageRenderer renderer) { + instance = renderer; + } + + /** + * Reset the singleton instance. Intended for test teardown. + */ + public static synchronized void reset() { + instance = null; + } + + /** + * Render a MiniMessage template with additional tag resolvers. + */ + public Component render(String template, TagResolver... extraResolvers) { + if (template == null || template.isEmpty()) { + return Component.empty(); + } + + TagResolver combined = buildResolver(extraResolvers); + return miniMessage.deserialize(template, combined); + } + + /** + * Render a MiniMessage template with string placeholder replacements. + * Values are inserted as literal text (safe from injection). + */ + public Component render(String template, Map placeholders) { + if (placeholders == null || placeholders.isEmpty()) { + return render(template); + } + + List resolvers = new ArrayList<>(); + for (Map.Entry entry : placeholders.entrySet()) { + resolvers.add(Placeholder.unparsed(entry.getKey(), entry.getValue())); + } + return render(template, TagResolver.resolver(resolvers)); + } + + /** + * Serialize a Component to legacy &-code string. + */ + public String toLegacy(Component component) { + if (component == null) return ""; + return legacySerializer.serialize(component); + } + + /** + * Serialize a Component to JSON string. + */ + public String toJson(Component component) { + if (component == null) return "{}"; + return getGsonSerializer().serialize(component); + } + + private GsonComponentSerializer getGsonSerializer() { + if (gsonSerializer == null) { + synchronized (this) { + if (gsonSerializer == null) { + gsonSerializer = GsonComponentSerializer.builder().build(); + } + } + } + return gsonSerializer; + } + + /** + * Serialize a Component to plain text (no formatting). + */ + public String toPlainText(Component component) { + if (component == null) return ""; + return plainTextSerializer.serialize(component); + } + + /** + * Detect whether a string uses legacy &-code formatting. + */ + public boolean isLegacyFormat(String template) { + if (template == null) return false; + return LEGACY_COLOR_PATTERN.matcher(template).find() + || LEGACY_HEX_PATTERN.matcher(template).find(); + } + + /** + * Convert a legacy &-code string to MiniMessage format. + * Only converts color/formatting codes, not [token] placeholders. + */ + public String convertLegacyToMiniMessage(String legacy) { + if (legacy == null) return ""; + + String result = legacy; + + // Convert &#rrggbb to <#rrggbb> + result = result.replaceAll("&#([0-9a-fA-F]{6})", "<#$1>"); + + // Convert &x&r&r&g&g&b&b (Spigot-style) to <#rrggbb> + result = result.replaceAll( + "&x&([0-9a-fA-F])&([0-9a-fA-F])&([0-9a-fA-F])&([0-9a-fA-F])&([0-9a-fA-F])&([0-9a-fA-F])", + "<#$1$2$3$4$5$6>" + ); + + // Convert &0-&f, &k-&o, &r to MiniMessage tags + StringBuilder sb = new StringBuilder(); + int i = 0; + while (i < result.length()) { + if (result.charAt(i) == '&' && i + 1 < result.length()) { + char code = Character.toLowerCase(result.charAt(i + 1)); + String replacement = LEGACY_CODE_MAP.get(code); + if (replacement != null) { + sb.append(replacement); + i += 2; + continue; + } + } + sb.append(result.charAt(i)); + i++; + } + + return sb.toString(); + } + + /** + * Load user-defined static tokens from the messages file tokens section. + */ + public void loadStaticTokens(Map tokens) { + if (tokens == null || tokens.isEmpty()) { + this.staticTokens = Collections.emptyMap(); + this.staticTokenResolver = TagResolver.empty(); + return; + } + + Map normalised = new HashMap<>(); + List resolvers = new ArrayList<>(); + for (Map.Entry entry : tokens.entrySet()) { + String key = normaliseTagName(entry.getKey()); + normalised.put(key, entry.getValue()); + resolvers.add(Placeholder.unparsed(key, entry.getValue())); + } + this.staticTokens = Collections.unmodifiableMap(normalised); + this.staticTokenResolver = TagResolver.resolver(resolvers); + } + + /** + * Get the current static tokens map (for collision detection). + */ + public Map getStaticTokens() { + return staticTokens; + } + + /** + * Build a combined TagResolver with proper priority: + * 1. Dynamic tokens (from extraResolvers) -- highest priority + * 2. Static user-defined tokens + * 3. MiniMessage standard tags (colors, formatting, etc.) + */ + private TagResolver buildResolver(TagResolver... extraResolvers) { + if (extraResolvers == null || extraResolvers.length == 0) { + return TagResolver.resolver(staticTokenResolver, TagResolver.standard()); + } + + TagResolver[] all = new TagResolver[extraResolvers.length + 2]; + System.arraycopy(extraResolvers, 0, all, 0, extraResolvers.length); + all[extraResolvers.length] = staticTokenResolver; + all[extraResolvers.length + 1] = TagResolver.standard(); + return TagResolver.resolver(all); + } + + /** + * Escape MiniMessage tags in a string so it renders as literal text. + */ + public String escapeTags(String input) { + if (input == null) return ""; + return miniMessage.escapeTags(input); + } + + /** + * Convert a relocated Component to a JSON string suitable for native Adventure deserialization. + * Platform adapters can use this for JSON-based bridging to native Adventure. + */ + public String toNativeJson(Component component) { + return toJson(component); + } + + /** + * Normalise a tag name to match MiniMessage's [a-z0-9_-]* pattern. + * Handles acronyms correctly: "playerIP" -> "player_ip", "serverURL" -> "server_url", + * "firstName" -> "first_name", "HTMLParser" -> "html_parser". + */ + public static String normaliseTagName(String name) { + StringBuilder sb = new StringBuilder(name.length() + 4); + for (int i = 0; i < name.length(); i++) { + char c = name.charAt(i); + if (Character.isUpperCase(c)) { + boolean prevUpper = i > 0 && Character.isUpperCase(name.charAt(i - 1)); + boolean nextLower = i + 1 < name.length() && Character.isLowerCase(name.charAt(i + 1)); + if (i > 0 && (!prevUpper || nextLower)) { + sb.append('_'); + } + sb.append(Character.toLowerCase(c)); + } else if (c == ' ') { + sb.append('_'); + } else { + sb.append(c); + } + } + return sb.toString(); + } + +} diff --git a/common/src/main/java/me/confuser/banmanager/common/util/NotificationUtils.java b/common/src/main/java/me/confuser/banmanager/common/util/NotificationUtils.java new file mode 100644 index 000000000..54a370d8f --- /dev/null +++ b/common/src/main/java/me/confuser/banmanager/common/util/NotificationUtils.java @@ -0,0 +1,55 @@ +package me.confuser.banmanager.common.util; + +import me.confuser.banmanager.common.BanManagerPlugin; +import me.confuser.banmanager.common.CommonPlayer; +import me.confuser.banmanager.common.configs.NotificationsConfig; +import me.confuser.banmanager.common.kyori.text.Component; + +public class NotificationUtils { + + private NotificationUtils() {} + + public static void notifyStaff(BanManagerPlugin plugin, String event, Message message, String permission) { + if (!plugin.getConfig().isDisplayNotificationsEnabled()) return; + + NotificationsConfig.NotificationChannel channel = plugin.getNotificationsConfig().getStaffChannel(event); + + for (CommonPlayer player : plugin.getServer().getOnlinePlayers()) { + if (!player.hasPermission(permission)) continue; + + Component resolved = message.resolveComponentFor(player); + + if (channel.isChat()) { + player.sendMessage(resolved); + } + if (channel.isActionbar()) { + player.sendActionBar(resolved); + } + if (channel.isTitle()) { + player.showTitle(resolved, Component.empty(), + channel.getTitleFadeIn(), channel.getTitleStay(), channel.getTitleFadeOut()); + } + if (channel.hasSound()) { + player.playSound(channel.getSound(), channel.getSoundVolume(), channel.getSoundPitch()); + } + } + + plugin.getServer().getConsoleSender().sendMessage( + MessageRenderer.getInstance().toPlainText(message.resolveComponent())); + } + + public static void notifyPlayer(CommonPlayer player, Message message) { + message.sendTo(player); + } + + /** + * Play the warned sound for a player without re-sending the message. + */ + public static void playWarnedSound(BanManagerPlugin plugin, CommonPlayer player) { + NotificationsConfig config = plugin.getNotificationsConfig(); + String sound = config.getWarnedSound(); + if (sound != null && !sound.isEmpty()) { + player.playSound(sound, config.getWarnedSoundVolume(), config.getWarnedSoundPitch()); + } + } +} diff --git a/common/src/main/java/me/confuser/banmanager/common/util/PaginatedView.java b/common/src/main/java/me/confuser/banmanager/common/util/PaginatedView.java new file mode 100644 index 000000000..486156fcb --- /dev/null +++ b/common/src/main/java/me/confuser/banmanager/common/util/PaginatedView.java @@ -0,0 +1,82 @@ +package me.confuser.banmanager.common.util; + +import me.confuser.banmanager.common.commands.CommonSender; +import me.confuser.banmanager.common.kyori.text.Component; + +import java.util.List; + +public class PaginatedView { + + private static final int DEFAULT_PAGE_SIZE = 8; + + private final List items; + private final int pageSize; + private final String command; + + public PaginatedView(List items, String command) { + this(items, command, DEFAULT_PAGE_SIZE); + } + + public PaginatedView(List items, String command, int pageSize) { + this.items = items; + this.command = command; + this.pageSize = pageSize; + } + + public int getTotalPages() { + return Math.max(1, (int) Math.ceil((double) items.size() / pageSize)); + } + + public void send(CommonSender sender, int page) { + send(sender, page, null, null); + } + + public void send(CommonSender sender, int page, Component header, Component footer) { + int totalPages = getTotalPages(); + int safePage = Math.max(1, Math.min(page, totalPages)); + int start = (safePage - 1) * pageSize; + int end = Math.min(start + pageSize, items.size()); + + if (header != null) { + sender.sendMessage(header); + } + + for (int i = start; i < end; i++) { + sender.sendMessage(items.get(i)); + } + + if (totalPages > 1 && !sender.isConsole()) { + sender.sendMessage(buildNavigation(safePage, totalPages)); + } else if (totalPages > 1) { + // Console doesn't support click events, so send a plain legacy string instead + sender.sendMessage(MessageRenderer.getInstance().toLegacy( + MessageRenderer.getInstance().render("Page " + safePage + " of " + totalPages + ""))); + } + + if (footer != null) { + sender.sendMessage(footer); + } + } + + private Component buildNavigation(int currentPage, int totalPages) { + MessageRenderer renderer = MessageRenderer.getInstance(); + String escapedCommand = renderer.escapeTags(command); + + StringBuilder nav = new StringBuilder(); + + if (currentPage > 1) { + nav.append("Previous page\">« "); + } + + nav.append("Page ").append(currentPage).append(" of ") + .append(totalPages).append(""); + + if (currentPage < totalPages) { + nav.append(" Next page\">»"); + } + + return renderer.render(nav.toString()); + } +} diff --git a/common/src/main/java/me/confuser/banmanager/common/util/ReportList.java b/common/src/main/java/me/confuser/banmanager/common/util/ReportList.java index 1e1ea38e7..721fa8bd8 100644 --- a/common/src/main/java/me/confuser/banmanager/common/util/ReportList.java +++ b/common/src/main/java/me/confuser/banmanager/common/util/ReportList.java @@ -1,12 +1,11 @@ package me.confuser.banmanager.common.util; import lombok.Getter; -import me.confuser.banmanager.common.CommonPlayer; import me.confuser.banmanager.common.commands.CommonSender; import me.confuser.banmanager.common.data.PlayerReportData; -import me.confuser.banmanager.common.kyori.text.event.ClickEvent; -import me.confuser.banmanager.common.kyori.text.serializer.legacy.LegacyComponentSerializer; +import me.confuser.banmanager.common.kyori.text.Component; +import java.util.ArrayList; import java.util.List; public class ReportList { @@ -25,32 +24,31 @@ public ReportList(List list, long count, long maxPage) { } public void send(CommonSender sender, int page) { - String dateTimeFormat = Message.getString("report.list.row.dateTimeFormat"); + String dateTimeFormat = Message.getRawTemplate("report.list.row.dateTimeFormat"); - Message.get("report.list.row.header") + Component header = Message.get("report.list.row.header") .set("page", page) .set("maxPage", getMaxPage()) .set("count", getCount()) - .sendTo(sender); + .resolveComponent(); + + List items = new ArrayList<>(); for (PlayerReportData report : getList()) { - String message = Message.get("report.list.row.all") + Component row = Message.get("report.list.row.all") .set("id", report.getId()) .set("state", report.getState().getName()) .set("player", report.getPlayer().getName()) .set("actor", report.getActor().getName()) .set("reason", report.getReason()) .set("created", DateUtils.format(dateTimeFormat, report.getCreated())) - .set("updated", DateUtils.format(dateTimeFormat, report.getUpdated())).toString(); - - if (sender.isConsole()) { - sender.sendMessage(message); - } else { - ((CommonPlayer) sender).sendJSONMessage( - LegacyComponentSerializer.legacy('&').deserialize( - message).clickEvent(ClickEvent.runCommand("/reports info " + report.getId() - ))); - } + .set("updated", DateUtils.format(dateTimeFormat, report.getUpdated())) + .resolveComponent(); + + items.add(row); } + + PaginatedView view = new PaginatedView(items, "/reports list"); + view.send(sender, page, header, null); } } diff --git a/common/src/main/resources/messages.yml b/common/src/main/resources/messages.yml index 205a94c13..494d65579 100644 --- a/common/src/main/resources/messages.yml +++ b/common/src/main/resources/messages.yml @@ -1,20 +1,22 @@ -# Variables -# [reason] = Ban/Mute reason -# [player] = The name of the player -# [ip] = The banned ip -# [actor] = Who banned/muted -# [expires] = How long until the ban/mute ends +# Message templates use MiniMessage formatting: https://docs.advntr.dev/minimessage/format.html +# Placeholders use angle brackets, e.g. , , , , + +tokens: + appeal_url: 'https://yourdomain.com/appeal' + server_name: 'My Server' + discord_url: 'https://discord.gg/example' + rules_url: 'https://yourdomain.com/rules' messages: - duplicateIP: '&cWarning: [player] has the same IP as the following banned players:\n&6[players]' - duplicateIPAlts: '&cWarning: [player] has the same IP as the following players:\n&6[players]' - configReloaded: '&aConfiguration reloaded successfully!' + duplicateIP: 'Warning: has the same IP as the following banned players:\n' + duplicateIPAlts: 'Warning: has the same IP as the following players:\n' + configReloaded: 'Configuration reloaded successfully!' deniedNotify: - player: '&cWarning: [player] attempted to join the server but was denied due to &4[reason]' - ip: '&cWarning: [ip] attempted to join the server but was denied due to &4[reason]' - deniedMaxIp: '&cToo many players with your ip address online' - deniedMultiaccounts: '&cToo many players with your ip address logged in recently' - deniedCountry: '&cYou may not connect from your region' + player: 'Warning: attempted to join the server but was denied due to ' + ip: 'Warning: attempted to join the server but was denied due to ' + deniedMaxIp: 'Too many players with your ip address online' + deniedMultiaccounts: 'Too many players with your ip address logged in recently' + deniedCountry: 'You may not connect from your region' time: now: 'now' @@ -34,415 +36,439 @@ messages: seconds: 'seconds' never: 'never' error: - invalid: '&cYour time length is invalid' - limit: '&cYou cannot perform this action for that length of time' + invalid: 'Your time length is invalid' + limit: 'You cannot perform this action for that length of time' none: 'none' # General command text sender: error: - notFound: '&c[player] not found, are you sure they exist?' - offline: '&c[player] is offline' - noSelf: '&cYou cannot perform that action on yourself!' - exception: '&cAn error occured whilst attempting to perform this command. Please check the console for further details.' - invalidIp: '&cInvalid IP address, expecting w.x.y.z format' - offlinePermission: '&cYou are not allowed to perform this action on an offline player' - ambiguousPlayer: '&cMultiple players match "[player]". Please use their full name.' - exempt: '&c[player] is exempt from that action' - noPermission: '&cYou do not have permission to perform that action' - invalidReason: '&c[reason] is no valid reason.' + notFound: ' not found, are you sure they exist?' + offline: ' is offline' + noSelf: 'You cannot perform that action on yourself!' + exception: 'An error occured whilst attempting to perform this command. Please check the console for further details.' + invalidIp: 'Invalid IP address, expecting w.x.y.z format' + offlinePermission: 'You are not allowed to perform this action on an offline player' + ambiguousPlayer: 'Multiple players match "". Please use their full name.' + exempt: ' is exempt from that action' + noPermission: 'You do not have permission to perform that action' + noConsole: 'This command cannot be used from console' + invalidReason: ' is no valid reason.' # Commands alts: header: 'Possible alts found:' + entry: '">' + separator: ', ' names: - header: 'Known names for [player]:' - row: '&e[name] &7(first: [firstSeen], last: [lastSeen])' + header: 'Known names for :' + row: ' (first: , last: )' + interactive: ' (first: , last: )">">' + separator: ', ' dateTimeFormat: 'dd-MM-yyyy' - none: '&7No name history found' + none: 'No name history found' export: error: - inProgress: '&cAn export is already in progress, please wait' + inProgress: 'An export is already in progress, please wait' player: - started: '&aPlayer ban export started' - finished: '&aPlayer ban export finished, file [file] created' + started: 'Player ban export started' + finished: 'Player ban export finished, file created' ip: - started: '&aIP ban export started' - finished: '&aIP ban export finished, file [file] created' + started: 'IP ban export started' + finished: 'IP ban export finished, file created' import: error: - inProgress: '&cAn import is already in progress, please wait' + inProgress: 'An import is already in progress, please wait' player: - started: '&aPlayer ban import started' - finished: '&aPlayer ban import finished' + started: 'Player ban import started' + finished: 'Player ban import finished' ip: - started: '&aIP ban import started' - finished: '&aIP ban import finished' + started: 'IP ban import started' + finished: 'IP ban import finished' advancedban: - started: '&aAdvancedBan import started' - finished: '&aAdvancedBan import finished' + started: 'AdvancedBan import started' + finished: 'AdvancedBan import finished' h2: - started: '&aH2 import started' - finished: '&aH2 import finished, please restart the server' + started: 'H2 import started' + finished: 'H2 import finished, please restart the server' litebans: - started: '&aLiteBans import started' - finished: '&aLiteBans import finished' + started: 'LiteBans import started' + finished: 'LiteBans import finished' info: error: - invalidIndex: '&cInvalid player option used' - indexRequired: '&cMultiple players named [name] found, please select a player by providing an index between 1 and [size], e.g. /bminfo [name] 1' - index: '&7#[index] - &6[name] - &4[uuid]' + invalidIndex: 'Invalid player option used' + indexRequired: 'Multiple players named found, please select a player by providing an index between 1 and , e.g. /bminfo 1' + index: '# - - ' stats: - player: '&6[player] has been banned [bans] times, muted [mutes] times, kicked [kicks] times and warned [warns] - times ([warnPoints] Points), has [notes] notes and been reported [reports] times' - ip: '&6This ip has been banned [bans] times, muted [mutes] times and range banned [rangebans] times' - connection: '&6Their last connection was with [ip] on [lastSeen]' - geoip: 'Country: [country] City: [city]' + player: ' has been banned times, muted times, kicked times and warned + times ( Points), has notes and been reported times' + ip: 'This ip has been banned times, muted times and range banned times' + connection: 'Their last connection was with on ' + geoip: 'Country: City: ' ban: - permanent: '&6Currently banned for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently banned for &4[reason]&6 by [actor] at [created] which expires in [expires]' + permanent: 'Currently banned for by at ' + temporary: 'Currently banned for by at which expires in ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' ipban: - permanent: '&6Currently banned for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently banned for &4[reason]&6 by [actor] at [created] which expires in [expires]' + permanent: 'Currently banned for by at ' + temporary: 'Currently banned for by at which expires in ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' iprangeban: - permanent: '&6[from] - [to] banned for &4[reason]&6 by [actor] at [created]' - temporary: '&6[from] - [to] banned for &4[reason]&6 by [actor] at [created] which expires in [expires]' + permanent: ' - banned for by at ' + temporary: ' - banned for by at which expires in ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' ipmute: - permanent: '&6Currently muted for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently muted for &4[reason]&6 by [actor] at [created] which expires in [expires]' + permanent: 'Currently muted for by at ' + temporary: 'Currently muted for by at which expires in ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' mute: - permanent: '&6Currently muted for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently muted for &4[reason]&6 by [actor] at [created] which expires in [expires]' - temporaryOnline: '&6Currently muted for &4[reason]&6 by [actor] at [created] which expires in [expires] (online time)' - temporaryOnlinePaused: '&6Currently muted for &4[reason]&6 by [actor] at [created] with [remaining] remaining (online time, paused)' + permanent: 'Currently muted for by at ' + temporary: 'Currently muted for by at which expires in ' + temporaryOnline: 'Currently muted for by at which expires in (online time)' + temporaryOnlinePaused: 'Currently muted for by at with remaining (online time, paused)' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' website: - player: 'https://yourdomain.com/player/[uuid]' - ip: 'http://yourdomain.com/index.php?action=viewip&ip=[ip]&server=0' + player: 'https://yourdomain.com/player/' + ip: 'http://yourdomain.com/index.php?action=viewip&ip=&server=0' history: - row: '&7#[id] &a[&f[type]&a] &6[actor]&f [meta] [reason] - &e[created]' + row: '# [] - ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' - noResults: '&cNo results found' + noResults: 'No results found' ips: - row: '&e[ip] - &6[join] - [leave]' + row: ' - - ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' kick: player: - noReason: '&6You have been kicked' - reason: '&6You have been kicked for &4[reason]' + noReason: 'You have been kicked' + reason: 'You have been kicked for ' notify: - noReason: '&6[player] has been kicked by [actor]' - reason: '&6[player] has been kicked by [actor] for &4[reason]' + noReason: ' has been kicked by ">View player info">[Info]' + reason: ' has been kicked by for ">View player info">[Info]' kickall: player: - noReason: '&6You have been kicked' - reason: '&6You have been kicked for &4[reason]' + noReason: 'You have been kicked' + reason: 'You have been kicked for ' notify: - noReason: 'All players have been kicked by [actor]' - reason: 'All players have been kicked by [actor] for &4[reason]' + noReason: 'All players have been kicked by ' + reason: 'All players have been kicked by for ' ban: player: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' + disallowed: 'You are banned from this server\n \nReason: \nBanned by: \nDate: \n \nAppeal at ' + kick: 'You have been banned\n \nReason: \nBanned by: ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[player] has been permanently banned by [actor] for &4[reason]' + notify: ' has been permanently banned by for ">View player info">[Info] ">Unban player">[Unban]' error: - exists: '&c[player] is already banned' - cooldown: '&cThis player was banned too recently, try again later' + exists: ' is already banned' + cooldown: 'This player was banned too recently, try again later' banall: - notify: '&6[player] will be permanently banned by [actor] for &4[reason]' + notify: ' will be permanently banned by for ' tempban: player: - disallowed: '&6You have been temporarily banned from this server for &4[reason] \n&6It expires in [expires]' - kick: '&6You have been temporarily banned for &4[reason]' + disallowed: 'You are temporarily banned from this server\n \nReason: \nBanned by: \nExpires: \nDate: \n \nAppeal at ' + kick: 'You have been temporarily banned\n \nReason: \nBanned by: \nExpires: ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[player] has been temporarily banned for [expires] by [actor] for &4[reason]' + notify: ' has been temporarily banned for by for ">View player info">[Info] ">Unban player">[Unban]' tempbanall: - notify: '&6[player] will be temporarily banned for [expires] by [actor] for &4[reason]' + notify: ' will be temporarily banned for by for ' unban: - notify: '&6[player] has been unbanned by [actor]' + notify: ' has been unbanned by ' error: - noExists: '&c[player] is not banned' - notOwn: '&c[player] was not banned by you, unable to unban' + noExists: ' is not banned' + notOwn: ' was not banned by you, unable to unban' unbanall: - notify: '&6[player] will be unbanned by [actor]' + notify: ' will be unbanned by ' mute: player: - blocked: '&cYou may not use the [command] command whilst muted!' - disallowed: '&6You have been permanently muted for &4[reason] &6by [actor]' - broadcast: '&4[Muted] [player]&7 [message]' - notify: '&6[player] has been permanently muted by [actor] for &4[reason]' + blocked: 'You may not use the command whilst muted!' + disallowed: 'You have been permanently muted for by ' + broadcast: '[Muted] ' + notify: ' has been permanently muted by for ">View player info">[Info] ">Unmute player">[Unmute]' error: - exists: '&c[player] is already muted' - cooldown: '&cThis player was muted too recently, try again later' + exists: ' is already muted' + cooldown: 'This player was muted too recently, try again later' muteip: ip: - disallowed: '&6You have been permanently muted for &4[reason] &6by [actor]' - broadcast: '&4[Muted] [player]&7 [message]' - notify: '&6[ip] ([players]) have been permanently muted by [actor] for &4[reason]' + disallowed: 'You have been permanently muted for by ' + broadcast: '[Muted] ' + notify: ' () have been permanently muted by for ' error: - exists: '&c[ip] is already muted' + exists: ' is already muted' muteall: - notify: '&6[player] will be permanently muted by [actor] for &4[reason]' + notify: ' will be permanently muted by for ' tempmute: player: - disallowed: '&6You have been temporarily muted for &4[reason] &6by [actor] which expires in [expires]' - disallowedOnline: '&6You have been temporarily muted for &4[reason] &6by [actor] which expires in [expires] (online time)' - notify: '&6[player] has been temporarily muted for [expires] by [actor] for &4[reason]' - notifyOnline: '&6[player] has been temporarily muted for [expires] (online time) by [actor] for &4[reason]' + disallowed: 'You have been temporarily muted for by which expires in ' + disallowedOnline: 'You have been temporarily muted for by which expires in (online time)' + notify: ' has been temporarily muted for by for ">View player info">[Info] ">Unmute player">[Unmute]' + notifyOnline: ' has been temporarily muted for (online time) by for ' error: - exists: '&c[player] is already muted' + exists: ' is already muted' tempmuteip: ip: - disallowed: '&6You have been temporarily muted for &4[reason] &6by [actor] which expires in [expires]' - notify: '&6[ip] ([players]) have been temporarily muted for [expires] by [actor] for &4[reason]' + disallowed: 'You have been temporarily muted for by which expires in ' + notify: ' () have been temporarily muted for by for ' error: - exists: '&c[ip] is already muted' + exists: ' is already muted' tempmuteall: - notify: '&6[player] will be temporarily muted for [expires] by [actor] for &4[reason]' + notify: ' will be temporarily muted for by for ' unmute: - notify: '&6[player] has been unmuted by [actor]' - player: '&6You have been unmuted by [actor]' + notify: ' has been unmuted by ' + player: 'You have been unmuted by ' error: - noExists: '&c[player] is not muted' - notOwn: '&c[player] was not muted by you, unable to unmute' + noExists: ' is not muted' + notOwn: ' was not muted by you, unable to unmute' unmuteip: - notify: '&6[ip] has been unmuted by [actor]' + notify: ' has been unmuted by ' error: - noExists: '&c[ip] is not muted' - notOwn: '&c[ip] was not muted by you, unable to unmute' + noExists: ' is not muted' + notOwn: ' was not muted by you, unable to unmute' unmuteall: - notify: '&6[player] will be unmuted by [actor]' + notify: ' will be unmuted by ' banname: name: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' + disallowed: 'You have been banned from this server for ' + kick: 'You have been banned permanently for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6Name [name] has been permanently banned by [actor] for &4[reason]' + notify: 'Name has been permanently banned by for ' error: - exists: '&cName [name] is already banned' + exists: 'Name is already banned' tempbanname: name: - disallowed: '&6You have been banned from this server for &4[reason] \n&6It expires in [expires]' - kick: '&6You have been temporarily banned for &4[reason]' + disallowed: 'You have been banned from this server for \nIt expires in ' + kick: 'You have been temporarily banned for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6Name [name] has been temporarily banned for [expires] by [actor] for &4[reason]' + notify: 'Name has been temporarily banned for by for ' unbanname: - notify: '&6Name [name] has been unbanned by [actor]' + notify: 'Name has been unbanned by ' error: - noExists: '&cName [name] is not banned' + noExists: 'Name is not banned' banip: ip: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' + disallowed: 'You have been banned from this server for ' + kick: 'You have been banned permanently for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[ip] ([players]) has been permanently banned by [actor] for &4[reason]' + notify: ' () has been permanently banned by for ' error: - exists: '&c[ip] is already banned' - cooldown: '&cThis ip was banned too recently, try again later' + exists: ' is already banned' + cooldown: 'This ip was banned too recently, try again later' baniprange: error: - invalid: '&cInvalid range, please use cidr notation 192.168.0.1/16 or wildcard 192.168.*.*' - minMax: '&cRange must be lowest to highest' - exists: '&cA ban containing those ranges already exists' + invalid: 'Invalid range, please use cidr notation 192.168.0.1/16 or wildcard 192.168.*.*' + minMax: 'Range must be lowest to highest' + exists: 'A ban containing those ranges already exists' ip: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' + disallowed: 'You have been banned from this server for ' + kick: 'You have been banned permanently for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[from] - [to] have been banned by [actor]' + notify: ' - have been banned by ' tempbaniprange: - notify: '&6[from] - [to] has been temporarily banned for [expires] by [actor]' + notify: ' - has been temporarily banned for by ' ip: - disallowed: '&6You have been banned from this server for &4[reason] \n&6It expires in [expires]' - kick: '&6You have been temporarily banned for [expires] by [actor] for &4[reason]' + disallowed: 'You have been banned from this server for \nIt expires in ' + kick: 'You have been temporarily banned for by for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' unbaniprange: - notify: '&6[from] - [to] has been unbanned by [actor]' + notify: ' - has been unbanned by ' banipall: - notify: '&6[ip] will be permanently banned by [actor] for &4[reason]' + notify: ' will be permanently banned by for ' tempbanip: ip: - disallowed: '&6You have been banned from this server for &4[reason] \n&6It expires in [expires]' - kick: '&6You have been temporarily banned for &4[reason]' + disallowed: 'You have been banned from this server for \nIt expires in ' + kick: 'You have been temporarily banned for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[ip] ([players]) has been temporarily banned for [expires] by [actor] for &4[reason]' + notify: ' () has been temporarily banned for by for ' tempbanipall: - notify: '&6[ip] will be temporarily banned for [expires] by [actor] for &4[reason]' + notify: ' will be temporarily banned for by for ' unbanip: - notify: '&6[ip] has been unbanned by [actor]' + notify: ' has been unbanned by ' error: - noExists: '&c[ip] is not banned' - notOwn: '&c[ip] was not banned by you, unable to unban' + noExists: ' is not banned' + notOwn: ' was not banned by you, unable to unban' unbanipall: - notify: '&6[ip] will be unbanned by [actor]' + notify: ' will be unbanned by ' warn: player: - warned: '&6You have been warned by [actor] for &4[reason]' + warned: 'You have been warned by for ' disallowed: - header: '&cYou may not speak until you have accepted your most recent warning. Please type the following:' - reason: '&6[reason]' - removed: '&aThank you for your understanding, you may now speak again' - notify: '&6[player] has been warned by [actor] for &4[reason]' + header: 'You may not speak until you have accepted your most recent warning. Please type the following:' + reason: '' + removed: 'Thank you for your understanding, you may now speak again' + notify: ' has been warned by for ">View player info">[Info]' error: - cooldown: '&cThis player was warned too recently, try again later' + cooldown: 'This player was warned too recently, try again later' tempwarn: player: - warned: '&6You have been warned for [expires] by [actor] for &4[reason]' - notify: '&6[player] has been warned for [expires] by [actor] for &4[reason]' + warned: 'You have been warned for by for ' + notify: ' has been warned for by for ">View player info">[Info]' dwarn: player: - notify: '&6Your most recent warning has been deleted by &4[actor]' - notify: '&cThe most recent warning for [player] has been deleted' + notify: 'Your most recent warning has been deleted by ' + notify: 'The most recent warning for has been deleted' error: - noWarnings: '&c[player] has no warnings to delete' + noWarnings: ' has no warnings to delete' bmclear: - notify: '&c[player] has had their [type] cleared' + notify: ' has had their cleared' error: - invalid: '&cInvalid type, please choose between banrecords, muterecords, kicks, notes or warnings' + invalid: 'Invalid type, please choose between banrecords, muterecords, kicks, notes or warnings' bmutils: missingplayers: - notify: '&c[amount] missing players added' - noneFound: '&a0 missing players found' - found: '&c[amount] missing player data found. Fixing...' + notify: ' missing players added' + noneFound: '0 missing players found' + found: ' missing player data found. Fixing...' error: - failedLookup: '&cFailed to lookup player [uuid], check server logs' - complete: '&a[amount] players resolved, please restart your server for failed punishments to take affect' + failedLookup: 'Failed to lookup player , check server logs' + complete: ' players resolved, please restart your server for failed punishments to take affect' duplicates: lookup: - notFound: '&aNo duplicate player names found' + notFound: 'No duplicate player names found' error: - invalidName: '&cInvalid name, must be 16 characters or less and contain only letters, numbers and an underscore' - nameExists: '&cA player with that name already exists' - success: '&aPlayer name set to [player] successfully' + invalidName: 'Invalid name, must be 16 characters or less and contain only letters, numbers and an underscore' + nameExists: 'A player with that name already exists' + success: 'Player name set to successfully' bmrollback: - notify: '&c[player] has had their [type] actions undone' + notify: ' has had their actions undone' error: - invalid: '&cInvalid type [type], please choose between [types]' + invalid: 'Invalid type , please choose between ' sync: player: - started: '&aStarting force [type] synchronisation' - finished: '&aForced [type] synchronisation complete' + started: 'Starting force synchronisation' + finished: 'Forced synchronisation complete' update: - notify: '&6[BanManager] &aAn update is available' + notify: '[BanManager] An update is available' notes: - header: '&6[player] has the following notes:' - joinAmount: '&6[player] has &e[amount] &6notes, click to view them' - note: '&6[[player]] &e[message] - &e[created]' - playerNote: '&a[[player]] &6[[actor]] &e[message] - &e[created]' + header: ' has the following notes:' + joinAmount: '"> has notes, click to view them' + note: '[] - ' + playerNote: '[] [] - ' dateTimeFormat: 'dd-MM-yyyy' - notify: '[player] has a new note attached by [actor]: [message]' + notify: ' has a new note attached by : ' error: - noNotes: '&c[player] has no notes' - noOnlineNotes: '&cNo online players have notes' + noNotes: ' has no notes' + noOnlineNotes: 'No online players have notes' report: - notify: '&6[player] has been reported by [actor] for &4[reason]' + notify: ' has been reported by for ' error: - cooldown: '&cThis player was reported too recently, try again later' + cooldown: 'This player was reported too recently, try again later' assign: - player: '&aReport [id] assigned to [player]' - notify: '&aYou have been assigned report [id] by [actor]' + player: 'Report assigned to ' + notify: 'You have been assigned report by ' unassign: - player: '&aReport [id] unassigned' + player: 'Report unassigned' close: notify: - closed: '&aReport [id] closed by [actor]' - command: '&aReport [id] closed by [actor] with [command]' - comment: '&aReport [id] closed by [actor] with [comment]' - dispatch: 'Executing command [command]' + closed: 'Report closed by ' + command: 'Report closed by with ' + comment: 'Report closed by with ' + dispatch: 'Executing command ' list: - noResults: '&cNo reports found' + noResults: 'No reports found' error: - invalidState: '&cReport state [state] not found' + invalidState: 'Report state not found' row: dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - header: '&e-- Reports ([count]) -- Page ([page]/[maxPage])' - all: '&7#[id] &e[[state]] &6- [created] - [player]' + header: '-- Reports () -- Page (/)' + all: '">Click to view details"># [] - - ' tp: error: - notFound: '&cReport not found' - worldNotFound: '&cWorld [world] could not be found' - invalidId: '&c[id] is not a valid report id' + notFound: 'Report not found' + worldNotFound: 'World could not be found' + invalidId: ' is not a valid report id' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' notify: - report: '&7#[id] &6[actor] reported [player] for &4[reason]&6 at [created]' - location: '[world] - [x], [y], [z]' + report: '# reported for at ' + location: ' - , , ' info: error: - notFound: '&cReport not found' - invalidId: '&c[id] is not a valid report id' + notFound: 'Report not found' + invalidId: ' is not a valid report id' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' notify: - report: '&7#[id] &6[actor] reported [player] for &4[reason]&6 at [created]' - location: '[world] - [x], [y], [z]' + report: '# reported for at ' + location: ' - , , ' + actions: + assign: '">Assign to yourself">[Assign]' + close: '">Close this report">[Close]' + tp: '">Teleport to location">[TP]' + feedback: + assigned: 'Your report # has been assigned to ' + closed: 'Your report # has been closed by ' addnoteall: - notify: '&c[player] will have a new attached by [actor]: [message]' + notify: ' will have a new attached by : ' banlist: - header: '&6There are [bans] [type] bans:' + header: 'There are bans:' + row: + player: '">Click for info"> - ' + ip: ' - ' + iprange: ' - - ' bmactivity: row: - all: '&a[&f[type]&a] &6[player]&f - &6[actor]&f - &e[created]' - player: '&a[&f[type]&a] &6[player]&f - &e[created]' + all: '[] - - ' + player: '[] - ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' - noResults: '&cNo results found' + noResults: 'No results found' bmdelete: - notify: '&a[rows] rows deleted' + notify: ' rows deleted' error: - invalid: '&cInvalid type, please choose between banrecords, muterecords, kicks, notes or warnings' - invalidId: '&c[id] is not a valid number' + invalid: 'Invalid type, please choose between banrecords, muterecords, kicks, notes or warnings' + invalidId: ' is not a valid number' denyalts: player: - disallowed: '&cThe IP address you are joining from is linked to a banned player' + disallowed: 'The IP address you are joining from is linked to a banned player' reasons: - row: '[hashtag] = [reason]' + row: ' = ' + + dashboard: + header: ' Staff Dashboard ' + activeBans: 'Active Bans: ' + activeMutes: 'Active Mutes: ' + openReports: 'Open Reports: View reports">[View]' + recentActivity: 'Recent Activity (24h): ' + footer: ' ' diff --git a/common/src/main/resources/messages/messages_en.yml b/common/src/main/resources/messages/messages_en.yml index 205a94c13..494d65579 100644 --- a/common/src/main/resources/messages/messages_en.yml +++ b/common/src/main/resources/messages/messages_en.yml @@ -1,20 +1,22 @@ -# Variables -# [reason] = Ban/Mute reason -# [player] = The name of the player -# [ip] = The banned ip -# [actor] = Who banned/muted -# [expires] = How long until the ban/mute ends +# Message templates use MiniMessage formatting: https://docs.advntr.dev/minimessage/format.html +# Placeholders use angle brackets, e.g. , , , , + +tokens: + appeal_url: 'https://yourdomain.com/appeal' + server_name: 'My Server' + discord_url: 'https://discord.gg/example' + rules_url: 'https://yourdomain.com/rules' messages: - duplicateIP: '&cWarning: [player] has the same IP as the following banned players:\n&6[players]' - duplicateIPAlts: '&cWarning: [player] has the same IP as the following players:\n&6[players]' - configReloaded: '&aConfiguration reloaded successfully!' + duplicateIP: 'Warning: has the same IP as the following banned players:\n' + duplicateIPAlts: 'Warning: has the same IP as the following players:\n' + configReloaded: 'Configuration reloaded successfully!' deniedNotify: - player: '&cWarning: [player] attempted to join the server but was denied due to &4[reason]' - ip: '&cWarning: [ip] attempted to join the server but was denied due to &4[reason]' - deniedMaxIp: '&cToo many players with your ip address online' - deniedMultiaccounts: '&cToo many players with your ip address logged in recently' - deniedCountry: '&cYou may not connect from your region' + player: 'Warning: attempted to join the server but was denied due to ' + ip: 'Warning: attempted to join the server but was denied due to ' + deniedMaxIp: 'Too many players with your ip address online' + deniedMultiaccounts: 'Too many players with your ip address logged in recently' + deniedCountry: 'You may not connect from your region' time: now: 'now' @@ -34,415 +36,439 @@ messages: seconds: 'seconds' never: 'never' error: - invalid: '&cYour time length is invalid' - limit: '&cYou cannot perform this action for that length of time' + invalid: 'Your time length is invalid' + limit: 'You cannot perform this action for that length of time' none: 'none' # General command text sender: error: - notFound: '&c[player] not found, are you sure they exist?' - offline: '&c[player] is offline' - noSelf: '&cYou cannot perform that action on yourself!' - exception: '&cAn error occured whilst attempting to perform this command. Please check the console for further details.' - invalidIp: '&cInvalid IP address, expecting w.x.y.z format' - offlinePermission: '&cYou are not allowed to perform this action on an offline player' - ambiguousPlayer: '&cMultiple players match "[player]". Please use their full name.' - exempt: '&c[player] is exempt from that action' - noPermission: '&cYou do not have permission to perform that action' - invalidReason: '&c[reason] is no valid reason.' + notFound: ' not found, are you sure they exist?' + offline: ' is offline' + noSelf: 'You cannot perform that action on yourself!' + exception: 'An error occured whilst attempting to perform this command. Please check the console for further details.' + invalidIp: 'Invalid IP address, expecting w.x.y.z format' + offlinePermission: 'You are not allowed to perform this action on an offline player' + ambiguousPlayer: 'Multiple players match "". Please use their full name.' + exempt: ' is exempt from that action' + noPermission: 'You do not have permission to perform that action' + noConsole: 'This command cannot be used from console' + invalidReason: ' is no valid reason.' # Commands alts: header: 'Possible alts found:' + entry: '">' + separator: ', ' names: - header: 'Known names for [player]:' - row: '&e[name] &7(first: [firstSeen], last: [lastSeen])' + header: 'Known names for :' + row: ' (first: , last: )' + interactive: ' (first: , last: )">">' + separator: ', ' dateTimeFormat: 'dd-MM-yyyy' - none: '&7No name history found' + none: 'No name history found' export: error: - inProgress: '&cAn export is already in progress, please wait' + inProgress: 'An export is already in progress, please wait' player: - started: '&aPlayer ban export started' - finished: '&aPlayer ban export finished, file [file] created' + started: 'Player ban export started' + finished: 'Player ban export finished, file created' ip: - started: '&aIP ban export started' - finished: '&aIP ban export finished, file [file] created' + started: 'IP ban export started' + finished: 'IP ban export finished, file created' import: error: - inProgress: '&cAn import is already in progress, please wait' + inProgress: 'An import is already in progress, please wait' player: - started: '&aPlayer ban import started' - finished: '&aPlayer ban import finished' + started: 'Player ban import started' + finished: 'Player ban import finished' ip: - started: '&aIP ban import started' - finished: '&aIP ban import finished' + started: 'IP ban import started' + finished: 'IP ban import finished' advancedban: - started: '&aAdvancedBan import started' - finished: '&aAdvancedBan import finished' + started: 'AdvancedBan import started' + finished: 'AdvancedBan import finished' h2: - started: '&aH2 import started' - finished: '&aH2 import finished, please restart the server' + started: 'H2 import started' + finished: 'H2 import finished, please restart the server' litebans: - started: '&aLiteBans import started' - finished: '&aLiteBans import finished' + started: 'LiteBans import started' + finished: 'LiteBans import finished' info: error: - invalidIndex: '&cInvalid player option used' - indexRequired: '&cMultiple players named [name] found, please select a player by providing an index between 1 and [size], e.g. /bminfo [name] 1' - index: '&7#[index] - &6[name] - &4[uuid]' + invalidIndex: 'Invalid player option used' + indexRequired: 'Multiple players named found, please select a player by providing an index between 1 and , e.g. /bminfo 1' + index: '# - - ' stats: - player: '&6[player] has been banned [bans] times, muted [mutes] times, kicked [kicks] times and warned [warns] - times ([warnPoints] Points), has [notes] notes and been reported [reports] times' - ip: '&6This ip has been banned [bans] times, muted [mutes] times and range banned [rangebans] times' - connection: '&6Their last connection was with [ip] on [lastSeen]' - geoip: 'Country: [country] City: [city]' + player: ' has been banned times, muted times, kicked times and warned + times ( Points), has notes and been reported times' + ip: 'This ip has been banned times, muted times and range banned times' + connection: 'Their last connection was with on ' + geoip: 'Country: City: ' ban: - permanent: '&6Currently banned for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently banned for &4[reason]&6 by [actor] at [created] which expires in [expires]' + permanent: 'Currently banned for by at ' + temporary: 'Currently banned for by at which expires in ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' ipban: - permanent: '&6Currently banned for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently banned for &4[reason]&6 by [actor] at [created] which expires in [expires]' + permanent: 'Currently banned for by at ' + temporary: 'Currently banned for by at which expires in ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' iprangeban: - permanent: '&6[from] - [to] banned for &4[reason]&6 by [actor] at [created]' - temporary: '&6[from] - [to] banned for &4[reason]&6 by [actor] at [created] which expires in [expires]' + permanent: ' - banned for by at ' + temporary: ' - banned for by at which expires in ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' ipmute: - permanent: '&6Currently muted for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently muted for &4[reason]&6 by [actor] at [created] which expires in [expires]' + permanent: 'Currently muted for by at ' + temporary: 'Currently muted for by at which expires in ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' mute: - permanent: '&6Currently muted for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently muted for &4[reason]&6 by [actor] at [created] which expires in [expires]' - temporaryOnline: '&6Currently muted for &4[reason]&6 by [actor] at [created] which expires in [expires] (online time)' - temporaryOnlinePaused: '&6Currently muted for &4[reason]&6 by [actor] at [created] with [remaining] remaining (online time, paused)' + permanent: 'Currently muted for by at ' + temporary: 'Currently muted for by at which expires in ' + temporaryOnline: 'Currently muted for by at which expires in (online time)' + temporaryOnlinePaused: 'Currently muted for by at with remaining (online time, paused)' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' website: - player: 'https://yourdomain.com/player/[uuid]' - ip: 'http://yourdomain.com/index.php?action=viewip&ip=[ip]&server=0' + player: 'https://yourdomain.com/player/' + ip: 'http://yourdomain.com/index.php?action=viewip&ip=&server=0' history: - row: '&7#[id] &a[&f[type]&a] &6[actor]&f [meta] [reason] - &e[created]' + row: '# [] - ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' - noResults: '&cNo results found' + noResults: 'No results found' ips: - row: '&e[ip] - &6[join] - [leave]' + row: ' - - ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' kick: player: - noReason: '&6You have been kicked' - reason: '&6You have been kicked for &4[reason]' + noReason: 'You have been kicked' + reason: 'You have been kicked for ' notify: - noReason: '&6[player] has been kicked by [actor]' - reason: '&6[player] has been kicked by [actor] for &4[reason]' + noReason: ' has been kicked by ">View player info">[Info]' + reason: ' has been kicked by for ">View player info">[Info]' kickall: player: - noReason: '&6You have been kicked' - reason: '&6You have been kicked for &4[reason]' + noReason: 'You have been kicked' + reason: 'You have been kicked for ' notify: - noReason: 'All players have been kicked by [actor]' - reason: 'All players have been kicked by [actor] for &4[reason]' + noReason: 'All players have been kicked by ' + reason: 'All players have been kicked by for ' ban: player: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' + disallowed: 'You are banned from this server\n \nReason: \nBanned by: \nDate: \n \nAppeal at ' + kick: 'You have been banned\n \nReason: \nBanned by: ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[player] has been permanently banned by [actor] for &4[reason]' + notify: ' has been permanently banned by for ">View player info">[Info] ">Unban player">[Unban]' error: - exists: '&c[player] is already banned' - cooldown: '&cThis player was banned too recently, try again later' + exists: ' is already banned' + cooldown: 'This player was banned too recently, try again later' banall: - notify: '&6[player] will be permanently banned by [actor] for &4[reason]' + notify: ' will be permanently banned by for ' tempban: player: - disallowed: '&6You have been temporarily banned from this server for &4[reason] \n&6It expires in [expires]' - kick: '&6You have been temporarily banned for &4[reason]' + disallowed: 'You are temporarily banned from this server\n \nReason: \nBanned by: \nExpires: \nDate: \n \nAppeal at ' + kick: 'You have been temporarily banned\n \nReason: \nBanned by: \nExpires: ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[player] has been temporarily banned for [expires] by [actor] for &4[reason]' + notify: ' has been temporarily banned for by for ">View player info">[Info] ">Unban player">[Unban]' tempbanall: - notify: '&6[player] will be temporarily banned for [expires] by [actor] for &4[reason]' + notify: ' will be temporarily banned for by for ' unban: - notify: '&6[player] has been unbanned by [actor]' + notify: ' has been unbanned by ' error: - noExists: '&c[player] is not banned' - notOwn: '&c[player] was not banned by you, unable to unban' + noExists: ' is not banned' + notOwn: ' was not banned by you, unable to unban' unbanall: - notify: '&6[player] will be unbanned by [actor]' + notify: ' will be unbanned by ' mute: player: - blocked: '&cYou may not use the [command] command whilst muted!' - disallowed: '&6You have been permanently muted for &4[reason] &6by [actor]' - broadcast: '&4[Muted] [player]&7 [message]' - notify: '&6[player] has been permanently muted by [actor] for &4[reason]' + blocked: 'You may not use the command whilst muted!' + disallowed: 'You have been permanently muted for by ' + broadcast: '[Muted] ' + notify: ' has been permanently muted by for ">View player info">[Info] ">Unmute player">[Unmute]' error: - exists: '&c[player] is already muted' - cooldown: '&cThis player was muted too recently, try again later' + exists: ' is already muted' + cooldown: 'This player was muted too recently, try again later' muteip: ip: - disallowed: '&6You have been permanently muted for &4[reason] &6by [actor]' - broadcast: '&4[Muted] [player]&7 [message]' - notify: '&6[ip] ([players]) have been permanently muted by [actor] for &4[reason]' + disallowed: 'You have been permanently muted for by ' + broadcast: '[Muted] ' + notify: ' () have been permanently muted by for ' error: - exists: '&c[ip] is already muted' + exists: ' is already muted' muteall: - notify: '&6[player] will be permanently muted by [actor] for &4[reason]' + notify: ' will be permanently muted by for ' tempmute: player: - disallowed: '&6You have been temporarily muted for &4[reason] &6by [actor] which expires in [expires]' - disallowedOnline: '&6You have been temporarily muted for &4[reason] &6by [actor] which expires in [expires] (online time)' - notify: '&6[player] has been temporarily muted for [expires] by [actor] for &4[reason]' - notifyOnline: '&6[player] has been temporarily muted for [expires] (online time) by [actor] for &4[reason]' + disallowed: 'You have been temporarily muted for by which expires in ' + disallowedOnline: 'You have been temporarily muted for by which expires in (online time)' + notify: ' has been temporarily muted for by for ">View player info">[Info] ">Unmute player">[Unmute]' + notifyOnline: ' has been temporarily muted for (online time) by for ' error: - exists: '&c[player] is already muted' + exists: ' is already muted' tempmuteip: ip: - disallowed: '&6You have been temporarily muted for &4[reason] &6by [actor] which expires in [expires]' - notify: '&6[ip] ([players]) have been temporarily muted for [expires] by [actor] for &4[reason]' + disallowed: 'You have been temporarily muted for by which expires in ' + notify: ' () have been temporarily muted for by for ' error: - exists: '&c[ip] is already muted' + exists: ' is already muted' tempmuteall: - notify: '&6[player] will be temporarily muted for [expires] by [actor] for &4[reason]' + notify: ' will be temporarily muted for by for ' unmute: - notify: '&6[player] has been unmuted by [actor]' - player: '&6You have been unmuted by [actor]' + notify: ' has been unmuted by ' + player: 'You have been unmuted by ' error: - noExists: '&c[player] is not muted' - notOwn: '&c[player] was not muted by you, unable to unmute' + noExists: ' is not muted' + notOwn: ' was not muted by you, unable to unmute' unmuteip: - notify: '&6[ip] has been unmuted by [actor]' + notify: ' has been unmuted by ' error: - noExists: '&c[ip] is not muted' - notOwn: '&c[ip] was not muted by you, unable to unmute' + noExists: ' is not muted' + notOwn: ' was not muted by you, unable to unmute' unmuteall: - notify: '&6[player] will be unmuted by [actor]' + notify: ' will be unmuted by ' banname: name: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' + disallowed: 'You have been banned from this server for ' + kick: 'You have been banned permanently for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6Name [name] has been permanently banned by [actor] for &4[reason]' + notify: 'Name has been permanently banned by for ' error: - exists: '&cName [name] is already banned' + exists: 'Name is already banned' tempbanname: name: - disallowed: '&6You have been banned from this server for &4[reason] \n&6It expires in [expires]' - kick: '&6You have been temporarily banned for &4[reason]' + disallowed: 'You have been banned from this server for \nIt expires in ' + kick: 'You have been temporarily banned for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6Name [name] has been temporarily banned for [expires] by [actor] for &4[reason]' + notify: 'Name has been temporarily banned for by for ' unbanname: - notify: '&6Name [name] has been unbanned by [actor]' + notify: 'Name has been unbanned by ' error: - noExists: '&cName [name] is not banned' + noExists: 'Name is not banned' banip: ip: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' + disallowed: 'You have been banned from this server for ' + kick: 'You have been banned permanently for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[ip] ([players]) has been permanently banned by [actor] for &4[reason]' + notify: ' () has been permanently banned by for ' error: - exists: '&c[ip] is already banned' - cooldown: '&cThis ip was banned too recently, try again later' + exists: ' is already banned' + cooldown: 'This ip was banned too recently, try again later' baniprange: error: - invalid: '&cInvalid range, please use cidr notation 192.168.0.1/16 or wildcard 192.168.*.*' - minMax: '&cRange must be lowest to highest' - exists: '&cA ban containing those ranges already exists' + invalid: 'Invalid range, please use cidr notation 192.168.0.1/16 or wildcard 192.168.*.*' + minMax: 'Range must be lowest to highest' + exists: 'A ban containing those ranges already exists' ip: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' + disallowed: 'You have been banned from this server for ' + kick: 'You have been banned permanently for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[from] - [to] have been banned by [actor]' + notify: ' - have been banned by ' tempbaniprange: - notify: '&6[from] - [to] has been temporarily banned for [expires] by [actor]' + notify: ' - has been temporarily banned for by ' ip: - disallowed: '&6You have been banned from this server for &4[reason] \n&6It expires in [expires]' - kick: '&6You have been temporarily banned for [expires] by [actor] for &4[reason]' + disallowed: 'You have been banned from this server for \nIt expires in ' + kick: 'You have been temporarily banned for by for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' unbaniprange: - notify: '&6[from] - [to] has been unbanned by [actor]' + notify: ' - has been unbanned by ' banipall: - notify: '&6[ip] will be permanently banned by [actor] for &4[reason]' + notify: ' will be permanently banned by for ' tempbanip: ip: - disallowed: '&6You have been banned from this server for &4[reason] \n&6It expires in [expires]' - kick: '&6You have been temporarily banned for &4[reason]' + disallowed: 'You have been banned from this server for \nIt expires in ' + kick: 'You have been temporarily banned for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[ip] ([players]) has been temporarily banned for [expires] by [actor] for &4[reason]' + notify: ' () has been temporarily banned for by for ' tempbanipall: - notify: '&6[ip] will be temporarily banned for [expires] by [actor] for &4[reason]' + notify: ' will be temporarily banned for by for ' unbanip: - notify: '&6[ip] has been unbanned by [actor]' + notify: ' has been unbanned by ' error: - noExists: '&c[ip] is not banned' - notOwn: '&c[ip] was not banned by you, unable to unban' + noExists: ' is not banned' + notOwn: ' was not banned by you, unable to unban' unbanipall: - notify: '&6[ip] will be unbanned by [actor]' + notify: ' will be unbanned by ' warn: player: - warned: '&6You have been warned by [actor] for &4[reason]' + warned: 'You have been warned by for ' disallowed: - header: '&cYou may not speak until you have accepted your most recent warning. Please type the following:' - reason: '&6[reason]' - removed: '&aThank you for your understanding, you may now speak again' - notify: '&6[player] has been warned by [actor] for &4[reason]' + header: 'You may not speak until you have accepted your most recent warning. Please type the following:' + reason: '' + removed: 'Thank you for your understanding, you may now speak again' + notify: ' has been warned by for ">View player info">[Info]' error: - cooldown: '&cThis player was warned too recently, try again later' + cooldown: 'This player was warned too recently, try again later' tempwarn: player: - warned: '&6You have been warned for [expires] by [actor] for &4[reason]' - notify: '&6[player] has been warned for [expires] by [actor] for &4[reason]' + warned: 'You have been warned for by for ' + notify: ' has been warned for by for ">View player info">[Info]' dwarn: player: - notify: '&6Your most recent warning has been deleted by &4[actor]' - notify: '&cThe most recent warning for [player] has been deleted' + notify: 'Your most recent warning has been deleted by ' + notify: 'The most recent warning for has been deleted' error: - noWarnings: '&c[player] has no warnings to delete' + noWarnings: ' has no warnings to delete' bmclear: - notify: '&c[player] has had their [type] cleared' + notify: ' has had their cleared' error: - invalid: '&cInvalid type, please choose between banrecords, muterecords, kicks, notes or warnings' + invalid: 'Invalid type, please choose between banrecords, muterecords, kicks, notes or warnings' bmutils: missingplayers: - notify: '&c[amount] missing players added' - noneFound: '&a0 missing players found' - found: '&c[amount] missing player data found. Fixing...' + notify: ' missing players added' + noneFound: '0 missing players found' + found: ' missing player data found. Fixing...' error: - failedLookup: '&cFailed to lookup player [uuid], check server logs' - complete: '&a[amount] players resolved, please restart your server for failed punishments to take affect' + failedLookup: 'Failed to lookup player , check server logs' + complete: ' players resolved, please restart your server for failed punishments to take affect' duplicates: lookup: - notFound: '&aNo duplicate player names found' + notFound: 'No duplicate player names found' error: - invalidName: '&cInvalid name, must be 16 characters or less and contain only letters, numbers and an underscore' - nameExists: '&cA player with that name already exists' - success: '&aPlayer name set to [player] successfully' + invalidName: 'Invalid name, must be 16 characters or less and contain only letters, numbers and an underscore' + nameExists: 'A player with that name already exists' + success: 'Player name set to successfully' bmrollback: - notify: '&c[player] has had their [type] actions undone' + notify: ' has had their actions undone' error: - invalid: '&cInvalid type [type], please choose between [types]' + invalid: 'Invalid type , please choose between ' sync: player: - started: '&aStarting force [type] synchronisation' - finished: '&aForced [type] synchronisation complete' + started: 'Starting force synchronisation' + finished: 'Forced synchronisation complete' update: - notify: '&6[BanManager] &aAn update is available' + notify: '[BanManager] An update is available' notes: - header: '&6[player] has the following notes:' - joinAmount: '&6[player] has &e[amount] &6notes, click to view them' - note: '&6[[player]] &e[message] - &e[created]' - playerNote: '&a[[player]] &6[[actor]] &e[message] - &e[created]' + header: ' has the following notes:' + joinAmount: '"> has notes, click to view them' + note: '[] - ' + playerNote: '[] [] - ' dateTimeFormat: 'dd-MM-yyyy' - notify: '[player] has a new note attached by [actor]: [message]' + notify: ' has a new note attached by : ' error: - noNotes: '&c[player] has no notes' - noOnlineNotes: '&cNo online players have notes' + noNotes: ' has no notes' + noOnlineNotes: 'No online players have notes' report: - notify: '&6[player] has been reported by [actor] for &4[reason]' + notify: ' has been reported by for ' error: - cooldown: '&cThis player was reported too recently, try again later' + cooldown: 'This player was reported too recently, try again later' assign: - player: '&aReport [id] assigned to [player]' - notify: '&aYou have been assigned report [id] by [actor]' + player: 'Report assigned to ' + notify: 'You have been assigned report by ' unassign: - player: '&aReport [id] unassigned' + player: 'Report unassigned' close: notify: - closed: '&aReport [id] closed by [actor]' - command: '&aReport [id] closed by [actor] with [command]' - comment: '&aReport [id] closed by [actor] with [comment]' - dispatch: 'Executing command [command]' + closed: 'Report closed by ' + command: 'Report closed by with ' + comment: 'Report closed by with ' + dispatch: 'Executing command ' list: - noResults: '&cNo reports found' + noResults: 'No reports found' error: - invalidState: '&cReport state [state] not found' + invalidState: 'Report state not found' row: dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - header: '&e-- Reports ([count]) -- Page ([page]/[maxPage])' - all: '&7#[id] &e[[state]] &6- [created] - [player]' + header: '-- Reports () -- Page (/)' + all: '">Click to view details"># [] - - ' tp: error: - notFound: '&cReport not found' - worldNotFound: '&cWorld [world] could not be found' - invalidId: '&c[id] is not a valid report id' + notFound: 'Report not found' + worldNotFound: 'World could not be found' + invalidId: ' is not a valid report id' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' notify: - report: '&7#[id] &6[actor] reported [player] for &4[reason]&6 at [created]' - location: '[world] - [x], [y], [z]' + report: '# reported for at ' + location: ' - , , ' info: error: - notFound: '&cReport not found' - invalidId: '&c[id] is not a valid report id' + notFound: 'Report not found' + invalidId: ' is not a valid report id' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' notify: - report: '&7#[id] &6[actor] reported [player] for &4[reason]&6 at [created]' - location: '[world] - [x], [y], [z]' + report: '# reported for at ' + location: ' - , , ' + actions: + assign: '">Assign to yourself">[Assign]' + close: '">Close this report">[Close]' + tp: '">Teleport to location">[TP]' + feedback: + assigned: 'Your report # has been assigned to ' + closed: 'Your report # has been closed by ' addnoteall: - notify: '&c[player] will have a new attached by [actor]: [message]' + notify: ' will have a new attached by : ' banlist: - header: '&6There are [bans] [type] bans:' + header: 'There are bans:' + row: + player: '">Click for info"> - ' + ip: ' - ' + iprange: ' - - ' bmactivity: row: - all: '&a[&f[type]&a] &6[player]&f - &6[actor]&f - &e[created]' - player: '&a[&f[type]&a] &6[player]&f - &e[created]' + all: '[] - - ' + player: '[] - ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' - noResults: '&cNo results found' + noResults: 'No results found' bmdelete: - notify: '&a[rows] rows deleted' + notify: ' rows deleted' error: - invalid: '&cInvalid type, please choose between banrecords, muterecords, kicks, notes or warnings' - invalidId: '&c[id] is not a valid number' + invalid: 'Invalid type, please choose between banrecords, muterecords, kicks, notes or warnings' + invalidId: ' is not a valid number' denyalts: player: - disallowed: '&cThe IP address you are joining from is linked to a banned player' + disallowed: 'The IP address you are joining from is linked to a banned player' reasons: - row: '[hashtag] = [reason]' + row: ' = ' + + dashboard: + header: ' Staff Dashboard ' + activeBans: 'Active Bans: ' + activeMutes: 'Active Mutes: ' + openReports: 'Open Reports: View reports">[View]' + recentActivity: 'Recent Activity (24h): ' + footer: ' ' diff --git a/common/src/main/resources/notifications.yml b/common/src/main/resources/notifications.yml new file mode 100644 index 000000000..75b1fb646 --- /dev/null +++ b/common/src/main/resources/notifications.yml @@ -0,0 +1,81 @@ +# Notifications Configuration +# Controls how punishment notifications are delivered to staff and players +# +# Each notification event can specify delivery channels: +# chat: true/false - Send via chat message (default: true) +# actionbar: true/false - Send via action bar (disappears after a few seconds) +# title: true/false - Send via title/subtitle overlay +# sound: '' - Sound to play (empty to disable). Use Minecraft sound names e.g. entity.experience_orb.pickup +# +# Title settings (only used when title: true): +# titleFadeIn: ticks for fade in (20 ticks = 1 second) +# titleStay: ticks to stay on screen +# titleFadeOut: ticks for fade out +# +# Sound settings: +# soundVolume: 0.0 - 1.0 +# soundPitch: 0.0 - 2.0 +# +# Platform notes: +# - BungeeCord: title, showTitle and playSound are not supported (ignored silently) +# - Sponge API7: playSound is not supported (ignored silently) +# - All other platforms (Bukkit/Paper, Velocity, Fabric, Sponge API8+) support all channels + +staff: + ban: + chat: true + actionbar: false + title: false + sound: 'entity.experience_orb.pickup' + soundVolume: 1.0 + soundPitch: 1.0 + tempban: + chat: true + actionbar: false + title: false + sound: 'entity.experience_orb.pickup' + soundVolume: 1.0 + soundPitch: 1.0 + mute: + chat: true + actionbar: false + title: false + sound: '' + soundVolume: 1.0 + soundPitch: 1.0 + tempmute: + chat: true + actionbar: false + title: false + sound: '' + soundVolume: 1.0 + soundPitch: 1.0 + warn: + chat: true + actionbar: false + title: false + sound: 'entity.experience_orb.pickup' + soundVolume: 1.0 + soundPitch: 1.0 + report: + chat: true + actionbar: false + title: false + sound: 'block.note_block.pling' + soundVolume: 1.0 + soundPitch: 1.0 + duplicateIp: + chat: true + actionbar: false + title: false + sound: '' + soundVolume: 1.0 + soundPitch: 1.0 + +player: + muted: + actionbar: true + warned: + sound: 'entity.villager.no' + soundVolume: 1.0 + soundPitch: 1.0 diff --git a/common/src/main/resources/plugin.yml b/common/src/main/resources/plugin.yml index 6250f1d94..02fac42ce 100644 --- a/common/src/main/resources/plugin.yml +++ b/common/src/main/resources/plugin.yml @@ -255,6 +255,10 @@ commands: usage: "/unbanname [reason]" alias: [bmunbanname] permission: bm.command.unbanname + bm: + description: "BanManager core commands (dashboard)" + usage: "/bm " + permission: bm.command.bm bmutils: description: "BanManager utility commands" usage: "/bmutils help" @@ -268,6 +272,7 @@ permissions: bm.command.*: description: Gives access to all BanManager commands children: + bm.command.bm: true bm.command.alts: true bm.command.ban: true bm.command.ban.offline: true diff --git a/common/src/main/resources/webhooks.yml b/common/src/main/resources/webhooks.yml index 33e924148..aa82fd755 100644 --- a/common/src/main/resources/webhooks.yml +++ b/common/src/main/resources/webhooks.yml @@ -1,6 +1,10 @@ # Webhooks Configuration # More info at https://banmanagement.com/docs/banmanager/configuration/webhooks-yml # +# NOTE: Webhook placeholders use [token] format (e.g. [player], [reason], [actor]). +# This is intentionally separate from MiniMessage's format used in messages. +# Webhooks send JSON to external services and do not use MiniMessage formatting. +# # Each punishment type can have multiple webhooks. Use the array format: # ban: # - name: discord diff --git a/common/src/test/java/me/confuser/banmanager/common/BasePluginTest.java b/common/src/test/java/me/confuser/banmanager/common/BasePluginTest.java index dd9aa68fc..720924bc2 100644 --- a/common/src/test/java/me/confuser/banmanager/common/BasePluginTest.java +++ b/common/src/test/java/me/confuser/banmanager/common/BasePluginTest.java @@ -40,7 +40,7 @@ public static PluginInfo setupConfigs(TemporaryFolder folder) { "webhooks.yml", "exemptions.yml", "geoip.yml", - "messages.yml", + "notifications.yml", "reasons.yml", "schedules.yml" }; diff --git a/common/src/test/java/me/confuser/banmanager/common/TestPlayer.java b/common/src/test/java/me/confuser/banmanager/common/TestPlayer.java index a8125b60d..7a00bd3d9 100644 --- a/common/src/test/java/me/confuser/banmanager/common/TestPlayer.java +++ b/common/src/test/java/me/confuser/banmanager/common/TestPlayer.java @@ -2,7 +2,6 @@ import me.confuser.banmanager.common.data.PlayerData; import me.confuser.banmanager.common.kyori.text.TextComponent; -import me.confuser.banmanager.common.util.Message; import java.net.InetAddress; import java.util.UUID; @@ -37,10 +36,6 @@ public void kick(String message) { public void sendMessage(String message) { } - @Override - public void sendMessage(Message message) { - } - @Override public void sendJSONMessage(TextComponent jsonString) { } diff --git a/common/src/test/java/me/confuser/banmanager/common/TestSender.java b/common/src/test/java/me/confuser/banmanager/common/TestSender.java index 75599ac4f..7c63c6ed4 100644 --- a/common/src/test/java/me/confuser/banmanager/common/TestSender.java +++ b/common/src/test/java/me/confuser/banmanager/common/TestSender.java @@ -3,8 +3,6 @@ import me.confuser.banmanager.common.commands.CommonCommand; import me.confuser.banmanager.common.commands.CommonSender; import me.confuser.banmanager.common.data.PlayerData; -import me.confuser.banmanager.common.util.Message; - import java.util.UUID; public class TestSender implements CommonSender { @@ -34,11 +32,6 @@ public void sendMessage(String message) { } - @Override - public void sendMessage(Message message) { - - } - @Override public boolean isConsole() { return true; diff --git a/common/src/test/java/me/confuser/banmanager/common/TestServer.java b/common/src/test/java/me/confuser/banmanager/common/TestServer.java index b3588c106..b8276661c 100644 --- a/common/src/test/java/me/confuser/banmanager/common/TestServer.java +++ b/common/src/test/java/me/confuser/banmanager/common/TestServer.java @@ -3,7 +3,6 @@ import me.confuser.banmanager.common.api.events.CommonEvent; import me.confuser.banmanager.common.commands.CommonSender; import me.confuser.banmanager.common.data.PlayerData; -import me.confuser.banmanager.common.kyori.text.TextComponent; import me.confuser.banmanager.common.util.Message; import me.confuser.banmanager.common.util.UUIDUtils; @@ -109,10 +108,6 @@ public void broadcast(String message, String permission) { public void broadcast(Message message, String permission) { } - @Override - public void broadcastJSON(TextComponent message, String permission) { - } - @Override public void broadcast(String message, String permission, CommonSender sender) { } diff --git a/common/src/test/java/me/confuser/banmanager/common/commands/KickCommandTest.java b/common/src/test/java/me/confuser/banmanager/common/commands/KickCommandTest.java index 97a0e3b2c..d1222145b 100644 --- a/common/src/test/java/me/confuser/banmanager/common/commands/KickCommandTest.java +++ b/common/src/test/java/me/confuser/banmanager/common/commands/KickCommandTest.java @@ -92,7 +92,7 @@ public void shouldKickPlayerWithoutAReason() { ArgumentCaptor msgCaptor = ArgumentCaptor.forClass(Message.class); verify(server).broadcast(msgCaptor.capture(), eq("bm.notify.kick")); - assertEquals("&6" + args[0] + " has been kicked by Console", msgCaptor.getValue().toString()); + assertEquals("&6" + args[0] + " has been kicked by Console &3[Info]", msgCaptor.getValue().toString()); } @Test @@ -111,7 +111,7 @@ public void shouldKickPlayerWithAReason() { ArgumentCaptor msgCaptor = ArgumentCaptor.forClass(Message.class); verify(server).broadcast(msgCaptor.capture(), eq("bm.notify.kick")); - assertEquals("&6" + args[0] + " has been kicked by Console for &4" + args[1], msgCaptor.getValue().toString()); + assertEquals("&6" + args[0] + " has been kicked by Console for &4" + args[1] + " &3[Info]", msgCaptor.getValue().toString()); } @Test diff --git a/common/src/test/java/me/confuser/banmanager/common/configs/MessagesConfigTest.java b/common/src/test/java/me/confuser/banmanager/common/configs/MessagesConfigTest.java index 839a76f3d..383898832 100644 --- a/common/src/test/java/me/confuser/banmanager/common/configs/MessagesConfigTest.java +++ b/common/src/test/java/me/confuser/banmanager/common/configs/MessagesConfigTest.java @@ -3,22 +3,30 @@ import me.confuser.banmanager.common.BasePluginTest; import me.confuser.banmanager.common.TestLogger; import me.confuser.banmanager.common.configuration.file.YamlConfiguration; +import me.confuser.banmanager.common.kyori.text.Component; import me.confuser.banmanager.common.util.Message; +import me.confuser.banmanager.common.util.MessageRenderer; import me.confuser.banmanager.common.util.MessageRegistry; import org.junit.Test; import java.io.StringReader; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; +import static org.junit.Assert.*; + public class MessagesConfigTest extends BasePluginTest { @Test public void isValid() { - assertEquals("&6Currently banned for &4abc&6 by def at 8th July which expires in 1d", Message - .get("info.ban.temporary").set("reason", "abc").set("actor", "def").set("created", - "8th July").set("expires", "1d").toString()); + Component component = Message.get("info.ban.temporary") + .set("reason", "abc") + .set("actor", "def") + .set("created", "8th July") + .set("expires", "1d") + .resolveComponent(); + + String plain = MessageRenderer.getInstance().toPlainText(component); + assertEquals("Currently banned for abc by def at 8th July which expires in 1d", plain); } private void loadTestMessages(String yaml) { diff --git a/common/src/test/java/me/confuser/banmanager/common/configs/NotificationsConfigTest.java b/common/src/test/java/me/confuser/banmanager/common/configs/NotificationsConfigTest.java new file mode 100644 index 000000000..171eac588 --- /dev/null +++ b/common/src/test/java/me/confuser/banmanager/common/configs/NotificationsConfigTest.java @@ -0,0 +1,43 @@ +package me.confuser.banmanager.common.configs; + +import me.confuser.banmanager.common.BasePluginTest; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class NotificationsConfigTest extends BasePluginTest { + + @Test + public void loadsStaffChannels() { + NotificationsConfig config = plugin.getNotificationsConfig(); + assertNotNull(config); + assertFalse(config.getStaffChannels().isEmpty()); + } + + @Test + public void banChannelHasChat() { + NotificationsConfig.NotificationChannel channel = plugin.getNotificationsConfig().getStaffChannel("ban"); + assertTrue(channel.isChat()); + } + + @Test + public void banChannelHasSound() { + NotificationsConfig.NotificationChannel channel = plugin.getNotificationsConfig().getStaffChannel("ban"); + assertTrue(channel.hasSound()); + assertEquals("entity.experience_orb.pickup", channel.getSound()); + } + + @Test + public void unknownEventReturnsChatOnly() { + NotificationsConfig.NotificationChannel channel = plugin.getNotificationsConfig().getStaffChannel("nonexistent"); + assertTrue(channel.isChat()); + assertFalse(channel.isActionbar()); + assertFalse(channel.isTitle()); + assertFalse(channel.hasSound()); + } + + @Test + public void mutedActionBarDefaults() { + assertTrue(plugin.getNotificationsConfig().isMutedActionBar()); + } +} diff --git a/common/src/test/java/me/confuser/banmanager/common/listeners/CommonJoinListenerTest.java b/common/src/test/java/me/confuser/banmanager/common/listeners/CommonJoinListenerTest.java index 608e20fb8..cd6f9d8c6 100644 --- a/common/src/test/java/me/confuser/banmanager/common/listeners/CommonJoinListenerTest.java +++ b/common/src/test/java/me/confuser/banmanager/common/listeners/CommonJoinListenerTest.java @@ -295,9 +295,6 @@ public void kick(String message) {} @Override public void sendMessage(String message) {} - @Override - public void sendMessage(Message message) {} - @Override public void sendJSONMessage(me.confuser.banmanager.common.kyori.text.TextComponent jsonString) {} diff --git a/common/src/test/java/me/confuser/banmanager/common/util/MessageDeferredTest.java b/common/src/test/java/me/confuser/banmanager/common/util/MessageDeferredTest.java index a50be3c40..39152fa04 100644 --- a/common/src/test/java/me/confuser/banmanager/common/util/MessageDeferredTest.java +++ b/common/src/test/java/me/confuser/banmanager/common/util/MessageDeferredTest.java @@ -2,6 +2,7 @@ import me.confuser.banmanager.common.TestLogger; import me.confuser.banmanager.common.TestPlayer; +import me.confuser.banmanager.common.kyori.text.Component; import org.junit.Before; import org.junit.Test; @@ -18,13 +19,13 @@ public void setUp() { MessageRegistry registry = new MessageRegistry("en"); Map en = new HashMap<>(); - en.put("ban.kick", "You are banned by [actor] for [reason]"); - en.put("greeting", "Hello [player]"); + en.put("ban.kick", "You are banned by for "); + en.put("greeting", "Hello "); registry.loadLocale("en", en); Map de = new HashMap<>(); - de.put("ban.kick", "Du wurdest von [actor] gebannt: [reason]"); - de.put("greeting", "Hallo [player]"); + de.put("ban.kick", "Du wurdest von gebannt: "); + de.put("greeting", "Hallo "); registry.loadLocale("de", de); Message.init(registry, new TestLogger()); @@ -32,67 +33,73 @@ public void setUp() { @Test public void resolveWithDefaultLocale() { - String result = Message.get("ban.kick") + Component component = Message.get("ban.kick") .set("actor", "Admin") .set("reason", "griefing") - .resolve("en"); + .resolveComponent("en"); - assertEquals("You are banned by Admin for griefing", result); + String plain = MessageRenderer.getInstance().toPlainText(component); + assertEquals("You are banned by Admin for griefing", plain); } @Test public void resolveWithSpecificLocale() { - String result = Message.get("ban.kick") + Component component = Message.get("ban.kick") .set("actor", "Admin") .set("reason", "griefing") - .resolve("de"); + .resolveComponent("de"); - assertEquals("Du wurdest von Admin gebannt: griefing", result); + String plain = MessageRenderer.getInstance().toPlainText(component); + assertEquals("Du wurdest von Admin gebannt: griefing", plain); } @Test public void toStringUsesDefaultLocale() { - String result = Message.get("greeting") + Component component = Message.get("greeting") .set("player", "Steve") - .toString(); + .resolveComponent(); - assertEquals("Hello Steve", result); + String plain = MessageRenderer.getInstance().toPlainText(component); + assertEquals("Hello Steve", plain); } @Test public void resolveWithPlayerLocale() { TestPlayer player = new TestPlayer(UUID.randomUUID(), "Steve", true, "de"); - String result = Message.get("greeting") + Component component = Message.get("greeting") .set("player", "Steve") - .resolve(player.getLocale()); + .resolveComponent(player.getLocale()); - assertEquals("Hallo Steve", result); + String plain = MessageRenderer.getInstance().toPlainText(component); + assertEquals("Hallo Steve", plain); } @Test public void resolveForFallsBackWithoutPlugin() { TestPlayer player = new TestPlayer(UUID.randomUUID(), "Steve", true, "de"); - String result = Message.get("greeting") + Component component = Message.get("greeting") .set("player", "Steve") - .resolveFor(player); + .resolveComponentFor(player); - assertEquals("Hello Steve", result); + String plain = MessageRenderer.getInstance().toPlainText(component); + assertEquals("Hello Steve", plain); } @Test public void tokenReplacementOrderPreserved() { MessageRegistry registry = new MessageRegistry("en"); Map en = new HashMap<>(); - en.put("test.order", "[a] [b] [a]"); + en.put("test.order", " "); registry.loadLocale("en", en); Message.init(registry, new TestLogger()); - String result = Message.get("test.order") - .set("a", "X") - .set("b", "Y") - .toString(); + Component component = Message.get("test.order") + .set("first", "X") + .set("second", "Y") + .resolveComponent(); - assertEquals("X Y X", result); + String plain = MessageRenderer.getInstance().toPlainText(component); + assertEquals("X Y X", plain); } @Test @@ -105,16 +112,19 @@ public void missingKeyReturnsEmptyString() { public void dynamicRegistrationWritesToDefaultLocale() { new Message("custom.key", "Custom message"); - assertEquals("Custom message", Message.getString("custom.key")); + String result = Message.getString("custom.key"); + assertNotNull("Dynamic registration should produce a non-null result", result); + assertEquals("Custom message", result); } @Test public void replaceMethodWorks() { - String result = Message.get("greeting") + Component component = Message.get("greeting") .set("player", "Steve") .replace("Hello", "Hey") - .toString(); + .resolveComponent(); - assertEquals("Hey Steve", result); + String plain = MessageRenderer.getInstance().toPlainText(component); + assertEquals("Hey Steve", plain); } } diff --git a/common/src/test/java/me/confuser/banmanager/common/util/MessageRendererTest.java b/common/src/test/java/me/confuser/banmanager/common/util/MessageRendererTest.java new file mode 100644 index 000000000..c2d20aa2b --- /dev/null +++ b/common/src/test/java/me/confuser/banmanager/common/util/MessageRendererTest.java @@ -0,0 +1,118 @@ +package me.confuser.banmanager.common.util; + +import me.confuser.banmanager.common.kyori.text.Component; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.*; + +public class MessageRendererTest { + + private MessageRenderer renderer; + + @Before + public void setUp() { + renderer = MessageRenderer.getInstance(); + } + + @After + public void tearDown() { + renderer.loadStaticTokens(new HashMap<>()); + } + + @Test + public void renderPlainText() { + Component result = renderer.render("Hello world"); + String plain = renderer.toPlainText(result); + assertEquals("Hello world", plain); + } + + @Test + public void renderWithPlaceholders() { + Map placeholders = new HashMap<>(); + placeholders.put("player", "Steve"); + Component result = renderer.render(" joined", placeholders); + String plain = renderer.toPlainText(result); + assertEquals("Steve joined", plain); + } + + @Test + public void renderMiniMessageFormatting() { + Component result = renderer.render("Error: Something went wrong"); + String plain = renderer.toPlainText(result); + assertEquals("Error: Something went wrong", plain); + } + + @Test + public void toLegacyPreservesColors() { + Component result = renderer.render("Red text"); + String legacy = renderer.toLegacy(result); + assertTrue(legacy.contains("Red text")); + } + + @Test + public void toJsonProducesValidJson() { + Component result = renderer.render("Success"); + String json = renderer.toJson(result); + assertTrue(json.startsWith("{") || json.startsWith("[")); + assertTrue(json.contains("Success")); + } + + @Test + public void isLegacyFormatDetectsAmpersandCodes() { + assertTrue(renderer.isLegacyFormat("&cHello &eworld")); + assertFalse(renderer.isLegacyFormat("Hello world")); + assertFalse(renderer.isLegacyFormat("Plain text")); + } + + @Test + public void convertLegacyToMiniMessage() { + String result = renderer.convertLegacyToMiniMessage("&cRed &lbold &agreen"); + assertFalse(result.contains("&c")); + assertFalse(result.contains("&l")); + assertFalse(result.contains("&a")); + } + + @Test + public void staticTokensAreResolved() { + Map tokens = new HashMap<>(); + tokens.put("server_name", "TestServer"); + renderer.loadStaticTokens(tokens); + + Component result = renderer.render("Welcome to !"); + String plain = renderer.toPlainText(result); + assertEquals("Welcome to TestServer!", plain); + } + + @Test + public void camelCaseTokensAreNormalised() { + Map tokens = new HashMap<>(); + tokens.put("serverName", "TestServer"); + renderer.loadStaticTokens(tokens); + + Component result = renderer.render("Welcome to !"); + String plain = renderer.toPlainText(result); + assertEquals("Welcome to TestServer!", plain); + } + + @Test + public void legacyConvertedExplicitlyThenRenders() { + String mini = renderer.convertLegacyToMiniMessage("&cThis is legacy"); + Component result = renderer.render(mini); + String plain = renderer.toPlainText(result); + assertEquals("This is legacy", plain); + } + + @Test + public void escapeTagsPreventsInjection() { + String malicious = "injected"; + String escaped = renderer.escapeTags(malicious); + Component result = renderer.render("" + escaped); + String plain = renderer.toPlainText(result); + assertTrue("Escaped tags should render as literal text", plain.contains("injected")); + } +} diff --git a/common/src/test/java/me/confuser/banmanager/common/util/PaginatedViewTest.java b/common/src/test/java/me/confuser/banmanager/common/util/PaginatedViewTest.java new file mode 100644 index 000000000..b79bac6d9 --- /dev/null +++ b/common/src/test/java/me/confuser/banmanager/common/util/PaginatedViewTest.java @@ -0,0 +1,60 @@ +package me.confuser.banmanager.common.util; + +import me.confuser.banmanager.common.kyori.text.Component; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.*; + +public class PaginatedViewTest { + + @Test + public void totalPagesCalculation() { + List items = createItems(25); + + PaginatedView view = new PaginatedView(items, "/test"); + assertEquals(4, view.getTotalPages()); + } + + @Test + public void totalPagesWithExactFit() { + List items = createItems(16); + + PaginatedView view = new PaginatedView(items, "/test"); + assertEquals(2, view.getTotalPages()); + } + + @Test + public void totalPagesWithSinglePage() { + List items = createItems(5); + + PaginatedView view = new PaginatedView(items, "/test"); + assertEquals(1, view.getTotalPages()); + } + + @Test + public void emptyListGivesOnePage() { + List items = new ArrayList<>(); + + PaginatedView view = new PaginatedView(items, "/test"); + assertEquals(1, view.getTotalPages()); + } + + @Test + public void customPageSize() { + List items = createItems(10); + + PaginatedView view = new PaginatedView(items, "/test", 5); + assertEquals(2, view.getTotalPages()); + } + + private List createItems(int count) { + List items = new ArrayList<>(); + for (int i = 0; i < count; i++) { + items.add(Component.text("Item " + i)); + } + return items; + } +} diff --git a/common/src/test/resources/plugin.yml b/common/src/test/resources/plugin.yml index 6250f1d94..fff172788 100644 --- a/common/src/test/resources/plugin.yml +++ b/common/src/test/resources/plugin.yml @@ -264,10 +264,15 @@ commands: usage: "/bmnames " aliases: [names] permission: bm.command.bmnames + bm: + description: "BanManager core commands (dashboard)" + usage: "/bm " + permission: bm.command.bm permissions: bm.command.*: description: Gives access to all BanManager commands children: + bm.command.bm: true bm.command.alts: true bm.command.ban: true bm.command.ban.offline: true diff --git a/e2e/platforms/bukkit/configs/messages.yml b/e2e/platforms/bukkit/configs/messages.yml index 09382e935..ce8bb1a82 100644 --- a/e2e/platforms/bukkit/configs/messages.yml +++ b/e2e/platforms/bukkit/configs/messages.yml @@ -1,20 +1,22 @@ -# Variables -# [reason] = Ban/Mute reason -# [player] = The name of the player -# [ip] = The banned ip -# [actor] = Who banned/muted -# [expires] = How long until the ban/mute ends +# Message templates use MiniMessage formatting: https://docs.advntr.dev/minimessage/format.html +# Placeholders use angle brackets, e.g. , , , , + +tokens: + appeal_url: 'https://yourdomain.com/appeal' + server_name: 'My Server' + discord_url: 'https://discord.gg/example' + rules_url: 'https://yourdomain.com/rules' messages: - duplicateIP: '&cWarning: [player] has the same IP as the following banned players:\n&6[players]' - duplicateIPAlts: '&cWarning: [player] has the same IP as the following players:\n&6[players]' - configReloaded: '�ff00Configuration &#ff5733reloaded &asuccessfully!' + duplicateIP: 'Warning: has the same IP as the following banned players:\n' + duplicateIPAlts: 'Warning: has the same IP as the following players:\n' + configReloaded: 'Configuration reloaded successfully!' deniedNotify: - player: '&cWarning: [player] attempted to join the server but was denied due to &4[reason]' - ip: '&cWarning: [ip] attempted to join the server but was denied due to &4[reason]' - deniedMaxIp: '&cToo many players with your ip address online' - deniedMultiaccounts: '&cToo many players with your ip address logged in recently' - deniedCountry: '&cYou may not connect from your region' + player: 'Warning: attempted to join the server but was denied due to ' + ip: 'Warning: attempted to join the server but was denied due to ' + deniedMaxIp: 'Too many players with your ip address online' + deniedMultiaccounts: 'Too many players with your ip address logged in recently' + deniedCountry: 'You may not connect from your region' time: now: 'now' @@ -34,408 +36,440 @@ messages: seconds: 'seconds' never: 'never' error: - invalid: '&cYour time length is invalid' - limit: '&cYou cannot perform this action for that length of time' + invalid: 'Your time length is invalid' + limit: 'You cannot perform this action for that length of time' none: 'none' # General command text sender: error: - notFound: '&c[player] not found, are you sure they exist?' - offline: '&c[player] is offline' - noSelf: '&cYou cannot perform that action on yourself!' - exception: '&cAn error occured whilst attempting to perform this command. Please check the console for further details.' - invalidIp: '&cInvalid IP address, expecting w.x.y.z format' - offlinePermission: '&cYou are not allowed to perform this action on an offline player' - exempt: '&c[player] is exempt from that action' - noPermission: '&cYou do not have permission to perform that action' - invalidReason: '&c[reason] is no valid reason.' + notFound: ' not found, are you sure they exist?' + offline: ' is offline' + noSelf: 'You cannot perform that action on yourself!' + exception: 'An error occured whilst attempting to perform this command. Please check the console for further details.' + invalidIp: 'Invalid IP address, expecting w.x.y.z format' + offlinePermission: 'You are not allowed to perform this action on an offline player' + ambiguousPlayer: 'Multiple players match "". Please use their full name.' + exempt: ' is exempt from that action' + noPermission: 'You do not have permission to perform that action' + noConsole: 'This command cannot be used from console' + invalidReason: ' is no valid reason.' # Commands alts: header: 'Possible alts found:' + entry: '">' + separator: ', ' + + names: + header: 'Known names for :' + row: ' (first: , last: )' + interactive: ' (first: , last: )">">' + separator: ', ' + dateTimeFormat: 'dd-MM-yyyy' + none: 'No name history found' export: error: - inProgress: '&cAn export is already in progress, please wait' + inProgress: 'An export is already in progress, please wait' player: - started: '&aPlayer ban export started' - finished: '&aPlayer ban export finished, file [file] created' + started: 'Player ban export started' + finished: 'Player ban export finished, file created' ip: - started: '&aIP ban export started' - finished: '&aIP ban export finished, file [file] created' + started: 'IP ban export started' + finished: 'IP ban export finished, file created' import: error: - inProgress: '&cAn import is already in progress, please wait' + inProgress: 'An import is already in progress, please wait' player: - started: '&aPlayer ban import started' - finished: '&aPlayer ban import finished' + started: 'Player ban import started' + finished: 'Player ban import finished' ip: - started: '&aIP ban import started' - finished: '&aIP ban import finished' + started: 'IP ban import started' + finished: 'IP ban import finished' advancedban: - started: '&aAdvancedBan import started' - finished: '&aAdvancedBan import finished' + started: 'AdvancedBan import started' + finished: 'AdvancedBan import finished' h2: - started: '&aH2 import started' - finished: '&aH2 import finished, please restart the server' + started: 'H2 import started' + finished: 'H2 import finished, please restart the server' litebans: - started: '&aLiteBans import started' - finished: '&aLiteBans import finished' + started: 'LiteBans import started' + finished: 'LiteBans import finished' info: error: - invalidIndex: '&cInvalid player option used' - indexRequired: '&cMultiple players named [name] found, please select a player by providing an index between 1 and [size], e.g. /bminfo [name] 1' - index: '&7#[index] - &6[name] - &4[uuid]' + invalidIndex: 'Invalid player option used' + indexRequired: 'Multiple players named found, please select a player by providing an index between 1 and , e.g. /bminfo 1' + index: '# - - ' stats: - player: '&6[player] has been banned [bans] times, muted [mutes] times, kicked [kicks] times and warned [warns] - times ([warnPoints] Points), has [notes] notes and been reported [reports] times' - ip: '&6This ip has been banned [bans] times, muted [mutes] times and range banned [rangebans] times' - connection: '&6Their last connection was with [ip] on [lastSeen]' - geoip: 'Country: [country] City: [city]' + player: ' has been banned times, muted times, kicked times and warned + times ( Points), has notes and been reported times' + ip: 'This ip has been banned times, muted times and range banned times' + connection: 'Their last connection was with on ' + geoip: 'Country: City: ' ban: - permanent: '&6Currently banned for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently banned for &4[reason]&6 by [actor] at [created] which expires in [expires]' + permanent: 'Currently banned for by at ' + temporary: 'Currently banned for by at which expires in ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' ipban: - permanent: '&6Currently banned for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently banned for &4[reason]&6 by [actor] at [created] which expires in [expires]' + permanent: 'Currently banned for by at ' + temporary: 'Currently banned for by at which expires in ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' iprangeban: - permanent: '&6[from] - [to] banned for &4[reason]&6 by [actor] at [created]' - temporary: '&6[from] - [to] banned for &4[reason]&6 by [actor] at [created] which expires in [expires]' + permanent: ' - banned for by at ' + temporary: ' - banned for by at which expires in ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' ipmute: - permanent: '&6Currently muted for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently muted for &4[reason]&6 by [actor] at [created] which expires in [expires]' + permanent: 'Currently muted for by at ' + temporary: 'Currently muted for by at which expires in ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' mute: - permanent: '&6Currently muted for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently muted for &4[reason]&6 by [actor] at [created] which expires in [expires]' - temporaryOnline: '&6Currently muted for &4[reason]&6 by [actor] at [created] which expires in [expires] (online time)' - temporaryOnlinePaused: '&6Currently muted for &4[reason]&6 by [actor] at [created] with [remaining] remaining (online time, paused)' + permanent: 'Currently muted for by at ' + temporary: 'Currently muted for by at which expires in ' + temporaryOnline: 'Currently muted for by at which expires in (online time)' + temporaryOnlinePaused: 'Currently muted for by at with remaining (online time, paused)' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' website: - player: 'https://yourdomain.com/player/[uuid]' - ip: 'http://yourdomain.com/index.php?action=viewip&ip=[ip]&server=0' + player: 'https://yourdomain.com/player/' + ip: 'http://yourdomain.com/index.php?action=viewip&ip=&server=0' history: - row: '&7#[id] &a[&f[type]&a] &6[actor]&f [meta] [reason] - &e[created]' + row: '# [] - ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' - noResults: '&cNo results found' + noResults: 'No results found' ips: - row: '&e[ip] - &6[join] - [leave]' + row: ' - - ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' kick: player: - noReason: '&6You have been kicked' - reason: '&6You have been kicked for &4[reason]' + noReason: 'You have been kicked' + reason: 'You have been kicked for ' notify: - noReason: '&6[player] has been kicked by [actor]' - reason: '&6[player] has been kicked by [actor] for &4[reason]' + noReason: ' has been kicked by ">View player info">[Info]' + reason: ' has been kicked by for ">View player info">[Info]' kickall: player: - noReason: '&6You have been kicked' - reason: '&6You have been kicked for &4[reason]' + noReason: 'You have been kicked' + reason: 'You have been kicked for ' notify: - noReason: 'All players have been kicked by [actor]' - reason: 'All players have been kicked by [actor] for &4[reason]' + noReason: 'All players have been kicked by ' + reason: 'All players have been kicked by for ' ban: player: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' + disallowed: 'You are banned from this server\n \nReason: \nBanned by: \nDate: \n \nAppeal at ' + kick: 'You have been banned\n \nReason: \nBanned by: ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[player] has been permanently banned by [actor] for &4[reason]' + notify: ' has been permanently banned by for ">View player info">[Info] ">Unban player">[Unban]' error: - exists: '&c[player] is already banned' - cooldown: '&cThis player was banned too recently, try again later' + exists: ' is already banned' + cooldown: 'This player was banned too recently, try again later' banall: - notify: '&6[player] will be permanently banned by [actor] for &4[reason]' + notify: ' will be permanently banned by for ' tempban: player: - disallowed: '&6You have been temporarily banned from this server for &4[reason] \n&6It expires in [expires]' - kick: '&6You have been temporarily banned for &4[reason]' + disallowed: 'You are temporarily banned from this server\n \nReason: \nBanned by: \nExpires: \nDate: \n \nAppeal at ' + kick: 'You have been temporarily banned\n \nReason: \nBanned by: \nExpires: ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[player] has been temporarily banned for [expires] by [actor] for &4[reason]' + notify: ' has been temporarily banned for by for ">View player info">[Info] ">Unban player">[Unban]' tempbanall: - notify: '&6[player] will be temporarily banned for [expires] by [actor] for &4[reason]' + notify: ' will be temporarily banned for by for ' unban: - notify: '&6[player] has been unbanned by [actor]' + notify: ' has been unbanned by ' error: - noExists: '&c[player] is not banned' - notOwn: '&c[player] was not banned by you, unable to unban' + noExists: ' is not banned' + notOwn: ' was not banned by you, unable to unban' unbanall: - notify: '&6[player] will be unbanned by [actor]' + notify: ' will be unbanned by ' mute: player: - blocked: '&cYou may not use the [command] command whilst muted!' - disallowed: '&6You have been permanently muted for &4[reason] &6by [actor]' - broadcast: '&4[Muted] [player]&7 [message]' - notify: '&6[player] has been permanently muted by [actor] for &4[reason]' + blocked: 'You may not use the command whilst muted!' + disallowed: 'You have been permanently muted for by ' + broadcast: '[Muted] ' + notify: ' has been permanently muted by for ">View player info">[Info] ">Unmute player">[Unmute]' error: - exists: '&c[player] is already muted' - cooldown: '&cThis player was muted too recently, try again later' + exists: ' is already muted' + cooldown: 'This player was muted too recently, try again later' muteip: ip: - disallowed: '&6You have been permanently muted for &4[reason] &6by [actor]' - broadcast: '&4[Muted] [player]&7 [message]' - notify: '&6[ip] ([players]) have been permanently muted by [actor] for &4[reason]' + disallowed: 'You have been permanently muted for by ' + broadcast: '[Muted] ' + notify: ' () have been permanently muted by for ' error: - exists: '&c[ip] is already muted' + exists: ' is already muted' muteall: - notify: '&6[player] will be permanently muted by [actor] for &4[reason]' + notify: ' will be permanently muted by for ' tempmute: player: - disallowed: '&6You have been temporarily muted for &4[reason] &6by [actor] which expires in [expires]' - disallowedOnline: '&6You have been temporarily muted for &4[reason] &6by [actor] which expires in [expires] (online time)' - notify: '&6[player] has been temporarily muted for [expires] by [actor] for &4[reason]' - notifyOnline: '&6[player] has been temporarily muted for [expires] (online time) by [actor] for &4[reason]' + disallowed: 'You have been temporarily muted for by which expires in ' + disallowedOnline: 'You have been temporarily muted for by which expires in (online time)' + notify: ' has been temporarily muted for by for ">View player info">[Info] ">Unmute player">[Unmute]' + notifyOnline: ' has been temporarily muted for (online time) by for ' error: - exists: '&c[player] is already muted' + exists: ' is already muted' tempmuteip: ip: - disallowed: '&6You have been temporarily muted for &4[reason] &6by [actor] which expires in [expires]' - notify: '&6[ip] ([players]) have been temporarily muted for [expires] by [actor] for &4[reason]' + disallowed: 'You have been temporarily muted for by which expires in ' + notify: ' () have been temporarily muted for by for ' error: - exists: '&c[ip] is already muted' + exists: ' is already muted' tempmuteall: - notify: '&6[player] will be temporarily muted for [expires] by [actor] for &4[reason]' + notify: ' will be temporarily muted for by for ' unmute: - notify: '&6[player] has been unmuted by [actor]' - player: '&6You have been unmuted by [actor]' + notify: ' has been unmuted by ' + player: 'You have been unmuted by ' error: - noExists: '&c[player] is not muted' - notOwn: '&c[player] was not muted by you, unable to unmute' + noExists: ' is not muted' + notOwn: ' was not muted by you, unable to unmute' unmuteip: - notify: '&6[ip] has been unmuted by [actor]' + notify: ' has been unmuted by ' error: - noExists: '&c[ip] is not muted' - notOwn: '&c[ip] was not muted by you, unable to unmute' + noExists: ' is not muted' + notOwn: ' was not muted by you, unable to unmute' unmuteall: - notify: '&6[player] will be unmuted by [actor]' + notify: ' will be unmuted by ' banname: name: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' + disallowed: 'You have been banned from this server for ' + kick: 'You have been banned permanently for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6Name [name] has been permanently banned by [actor] for &4[reason]' + notify: 'Name has been permanently banned by for ' error: - exists: '&cName [name] is already banned' + exists: 'Name is already banned' tempbanname: name: - disallowed: '&6You have been banned from this server for &4[reason] \n&6It expires in [expires]' - kick: '&6You have been temporarily banned for &4[reason]' + disallowed: 'You have been banned from this server for \nIt expires in ' + kick: 'You have been temporarily banned for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6Name [name] has been temporarily banned for [expires] by [actor] for &4[reason]' + notify: 'Name has been temporarily banned for by for ' unbanname: - notify: '&6Name [name] has been unbanned by [actor]' + notify: 'Name has been unbanned by ' error: - noExists: '&cName [name] is not banned' + noExists: 'Name is not banned' banip: ip: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' + disallowed: 'You have been banned from this server for ' + kick: 'You have been banned permanently for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[ip] ([players]) has been permanently banned by [actor] for &4[reason]' + notify: ' () has been permanently banned by for ' error: - exists: '&c[ip] is already banned' - cooldown: '&cThis ip was banned too recently, try again later' + exists: ' is already banned' + cooldown: 'This ip was banned too recently, try again later' baniprange: error: - invalid: '&cInvalid range, please use cidr notation 192.168.0.1/16 or wildcard 192.168.*.*' - minMax: '&cRange must be lowest to highest' - exists: '&cA ban containing those ranges already exists' + invalid: 'Invalid range, please use cidr notation 192.168.0.1/16 or wildcard 192.168.*.*' + minMax: 'Range must be lowest to highest' + exists: 'A ban containing those ranges already exists' ip: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' + disallowed: 'You have been banned from this server for ' + kick: 'You have been banned permanently for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[from] - [to] have been banned by [actor]' + notify: ' - have been banned by ' tempbaniprange: - notify: '&6[from] - [to] has been temporarily banned for [expires] by [actor]' + notify: ' - has been temporarily banned for by ' ip: - disallowed: '&6You have been banned from this server for &4[reason] \n&6It expires in [expires]' - kick: '&6You have been temporarily banned for [expires] by [actor] for &4[reason]' + disallowed: 'You have been banned from this server for \nIt expires in ' + kick: 'You have been temporarily banned for by for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' unbaniprange: - notify: '&6[from] - [to] has been unbanned by [actor]' + notify: ' - has been unbanned by ' banipall: - notify: '&6[ip] will be permanently banned by [actor] for &4[reason]' + notify: ' will be permanently banned by for ' tempbanip: ip: - disallowed: '&6You have been banned from this server for &4[reason] \n&6It expires in [expires]' - kick: '&6You have been temporarily banned for &4[reason]' + disallowed: 'You have been banned from this server for \nIt expires in ' + kick: 'You have been temporarily banned for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[ip] ([players]) has been temporarily banned for [expires] by [actor] for &4[reason]' + notify: ' () has been temporarily banned for by for ' tempbanipall: - notify: '&6[ip] will be temporarily banned for [expires] by [actor] for &4[reason]' + notify: ' will be temporarily banned for by for ' unbanip: - notify: '&6[ip] has been unbanned by [actor]' + notify: ' has been unbanned by ' error: - noExists: '&c[ip] is not banned' - notOwn: '&c[ip] was not banned by you, unable to unban' + noExists: ' is not banned' + notOwn: ' was not banned by you, unable to unban' unbanipall: - notify: '&6[ip] will be unbanned by [actor]' + notify: ' will be unbanned by ' warn: player: - warned: '&6You have been warned by [actor] for &4[reason]' + warned: 'You have been warned by for ' disallowed: - header: '&cYou may not speak until you have accepted your most recent warning. Please type the following:' - reason: '&6[reason]' - removed: '&aThank you for your understanding, you may now speak again' - notify: '&6[player] has been warned by [actor] for &4[reason]' + header: 'You may not speak until you have accepted your most recent warning. Please type the following:' + reason: '' + removed: 'Thank you for your understanding, you may now speak again' + notify: ' has been warned by for ">View player info">[Info]' error: - cooldown: '&cThis player was warned too recently, try again later' + cooldown: 'This player was warned too recently, try again later' tempwarn: player: - warned: '&6You have been warned for [expires] by [actor] for &4[reason]' - notify: '&6[player] has been warned for [expires] by [actor] for &4[reason]' + warned: 'You have been warned for by for ' + notify: ' has been warned for by for ">View player info">[Info]' dwarn: player: - notify: '&6Your most recent warning has been deleted by &4[actor]' - notify: '&cThe most recent warning for [player] has been deleted' + notify: 'Your most recent warning has been deleted by ' + notify: 'The most recent warning for has been deleted' error: - noWarnings: '&c[player] has no warnings to delete' + noWarnings: ' has no warnings to delete' bmclear: - notify: '&c[player] has had their [type] cleared' + notify: ' has had their cleared' error: - invalid: '&cInvalid type, please choose between banrecords, muterecords, kicks, notes or warnings' + invalid: 'Invalid type, please choose between banrecords, muterecords, kicks, notes or warnings' bmutils: missingplayers: - notify: '&c[amount] missing players added' - noneFound: '&a0 missing players found' - found: '&c[amount] missing player data found. Fixing...' + notify: ' missing players added' + noneFound: '0 missing players found' + found: ' missing player data found. Fixing...' error: - failedLookup: '&cFailed to lookup player [uuid], check server logs' - complete: '&a[amount] players resolved, please restart your server for failed punishments to take affect' + failedLookup: 'Failed to lookup player , check server logs' + complete: ' players resolved, please restart your server for failed punishments to take affect' duplicates: lookup: - notFound: '&aNo duplicate player names found' + notFound: 'No duplicate player names found' error: - invalidName: '&cInvalid name, must be 16 characters or less and contain only letters, numbers and an underscore' - nameExists: '&cA player with that name already exists' - success: '&aPlayer name set to [player] successfully' + invalidName: 'Invalid name, must be 16 characters or less and contain only letters, numbers and an underscore' + nameExists: 'A player with that name already exists' + success: 'Player name set to successfully' bmrollback: - notify: '&c[player] has had their [type] actions undone' + notify: ' has had their actions undone' error: - invalid: '&cInvalid type [type], please choose between [types]' + invalid: 'Invalid type , please choose between ' sync: player: - started: '&aStarting force [type] synchronisation' - finished: '&aForced [type] synchronisation complete' + started: 'Starting force synchronisation' + finished: 'Forced synchronisation complete' update: - notify: '&6[BanManager] &aAn update is available' + notify: '[BanManager] An update is available' notes: - header: '&6[player] has the following notes:' - joinAmount: '&6[player] has &e[amount] &6notes, click to view them' - note: '&6[[player]] &e[message] - &e[created]' - playerNote: '&a[[player]] &6[[actor]] &e[message] - &e[created]' + header: ' has the following notes:' + joinAmount: '"> has notes, click to view them' + note: '[] - ' + playerNote: '[] [] - ' dateTimeFormat: 'dd-MM-yyyy' - notify: '[player] has a new note attached by [actor]: [message]' + notify: ' has a new note attached by : ' error: - noNotes: '&c[player] has no notes' - noOnlineNotes: '&cNo online players have notes' + noNotes: ' has no notes' + noOnlineNotes: 'No online players have notes' report: - notify: '&6[player] has been reported by [actor] for &4[reason]' + notify: ' has been reported by for ' error: - cooldown: '&cThis player was reported too recently, try again later' + cooldown: 'This player was reported too recently, try again later' assign: - player: '&aReport [id] assigned to [player]' - notify: '&aYou have been assigned report [id] by [actor]' + player: 'Report assigned to ' + notify: 'You have been assigned report by ' unassign: - player: '&aReport [id] unassigned' + player: 'Report unassigned' close: notify: - closed: '&aReport [id] closed by [actor]' - command: '&aReport [id] closed by [actor] with [command]' - comment: '&aReport [id] closed by [actor] with [comment]' - dispatch: 'Executing command [command]' + closed: 'Report closed by ' + command: 'Report closed by with ' + comment: 'Report closed by with ' + dispatch: 'Executing command ' list: - noResults: '&cNo reports found' + noResults: 'No reports found' error: - invalidState: '&cReport state [state] not found' + invalidState: 'Report state not found' row: dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - header: '&e-- Reports ([count]) -- Page ([page]/[maxPage])' - all: '&7#[id] &e[[state]] &6- [created] - [player]' + header: '-- Reports () -- Page (/)' + all: '">Click to view details"># [] - - ' tp: error: - notFound: '&cReport not found' - worldNotFound: '&cWorld [world] could not be found' - invalidId: '&c[id] is not a valid report id' + notFound: 'Report not found' + worldNotFound: 'World could not be found' + invalidId: ' is not a valid report id' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' notify: - report: '&7#[id] &6[actor] reported [player] for &4[reason]&6 at [created]' - location: '[world] - [x], [y], [z]' + report: '# reported for at ' + location: ' - , , ' info: error: - notFound: '&cReport not found' - invalidId: '&c[id] is not a valid report id' + notFound: 'Report not found' + invalidId: ' is not a valid report id' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' notify: - report: '&7#[id] &6[actor] reported [player] for &4[reason]&6 at [created]' - location: '[world] - [x], [y], [z]' + report: '# reported for at ' + location: ' - , , ' + + actions: + assign: '">Assign to yourself">[Assign]' + close: '">Close this report">[Close]' + tp: '">Teleport to location">[TP]' + feedback: + assigned: 'Your report # has been assigned to ' + closed: 'Your report # has been closed by ' addnoteall: - notify: '&c[player] will have a new attached by [actor]: [message]' + notify: ' will have a new attached by : ' banlist: - header: '&6There are [bans] [type] bans:' + header: 'There are bans:' + row: + player: '">Click for info"> - ' + ip: ' - ' + iprange: ' - - ' bmactivity: row: - all: '&a[&f[type]&a] &6[player]&f - &6[actor]&f - &e[created]' - player: '&a[&f[type]&a] &6[player]&f - &e[created]' + all: '[] - - ' + player: '[] - ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' - noResults: '&cNo results found' + noResults: 'No results found' bmdelete: - notify: '&a[rows] rows deleted' + notify: ' rows deleted' error: - invalid: '&cInvalid type, please choose between banrecords, muterecords, kicks, notes or warnings' - invalidId: '&c[id] is not a valid number' + invalid: 'Invalid type, please choose between banrecords, muterecords, kicks, notes or warnings' + invalidId: ' is not a valid number' denyalts: player: - disallowed: '&cThe IP address you are joining from is linked to a banned player' + disallowed: 'The IP address you are joining from is linked to a banned player' reasons: - row: '[hashtag] = [reason]' + row: ' = ' + + dashboard: + header: ' Staff Dashboard ' + activeBans: 'Active Bans: ' + activeMutes: 'Active Mutes: ' + openReports: 'Open Reports: View reports">[View]' + recentActivity: 'Recent Activity (24h): ' + footer: ' ' diff --git a/e2e/platforms/bukkit/configs/messages/messages_en.yml b/e2e/platforms/bukkit/configs/messages/messages_en.yml index 205a94c13..ce8bb1a82 100644 --- a/e2e/platforms/bukkit/configs/messages/messages_en.yml +++ b/e2e/platforms/bukkit/configs/messages/messages_en.yml @@ -1,20 +1,22 @@ -# Variables -# [reason] = Ban/Mute reason -# [player] = The name of the player -# [ip] = The banned ip -# [actor] = Who banned/muted -# [expires] = How long until the ban/mute ends +# Message templates use MiniMessage formatting: https://docs.advntr.dev/minimessage/format.html +# Placeholders use angle brackets, e.g. , , , , + +tokens: + appeal_url: 'https://yourdomain.com/appeal' + server_name: 'My Server' + discord_url: 'https://discord.gg/example' + rules_url: 'https://yourdomain.com/rules' messages: - duplicateIP: '&cWarning: [player] has the same IP as the following banned players:\n&6[players]' - duplicateIPAlts: '&cWarning: [player] has the same IP as the following players:\n&6[players]' - configReloaded: '&aConfiguration reloaded successfully!' + duplicateIP: 'Warning: has the same IP as the following banned players:\n' + duplicateIPAlts: 'Warning: has the same IP as the following players:\n' + configReloaded: 'Configuration reloaded successfully!' deniedNotify: - player: '&cWarning: [player] attempted to join the server but was denied due to &4[reason]' - ip: '&cWarning: [ip] attempted to join the server but was denied due to &4[reason]' - deniedMaxIp: '&cToo many players with your ip address online' - deniedMultiaccounts: '&cToo many players with your ip address logged in recently' - deniedCountry: '&cYou may not connect from your region' + player: 'Warning: attempted to join the server but was denied due to ' + ip: 'Warning: attempted to join the server but was denied due to ' + deniedMaxIp: 'Too many players with your ip address online' + deniedMultiaccounts: 'Too many players with your ip address logged in recently' + deniedCountry: 'You may not connect from your region' time: now: 'now' @@ -34,415 +36,440 @@ messages: seconds: 'seconds' never: 'never' error: - invalid: '&cYour time length is invalid' - limit: '&cYou cannot perform this action for that length of time' + invalid: 'Your time length is invalid' + limit: 'You cannot perform this action for that length of time' none: 'none' # General command text sender: error: - notFound: '&c[player] not found, are you sure they exist?' - offline: '&c[player] is offline' - noSelf: '&cYou cannot perform that action on yourself!' - exception: '&cAn error occured whilst attempting to perform this command. Please check the console for further details.' - invalidIp: '&cInvalid IP address, expecting w.x.y.z format' - offlinePermission: '&cYou are not allowed to perform this action on an offline player' - ambiguousPlayer: '&cMultiple players match "[player]". Please use their full name.' - exempt: '&c[player] is exempt from that action' - noPermission: '&cYou do not have permission to perform that action' - invalidReason: '&c[reason] is no valid reason.' + notFound: ' not found, are you sure they exist?' + offline: ' is offline' + noSelf: 'You cannot perform that action on yourself!' + exception: 'An error occured whilst attempting to perform this command. Please check the console for further details.' + invalidIp: 'Invalid IP address, expecting w.x.y.z format' + offlinePermission: 'You are not allowed to perform this action on an offline player' + ambiguousPlayer: 'Multiple players match "". Please use their full name.' + exempt: ' is exempt from that action' + noPermission: 'You do not have permission to perform that action' + noConsole: 'This command cannot be used from console' + invalidReason: ' is no valid reason.' # Commands alts: header: 'Possible alts found:' + entry: '">' + separator: ', ' names: - header: 'Known names for [player]:' - row: '&e[name] &7(first: [firstSeen], last: [lastSeen])' + header: 'Known names for :' + row: ' (first: , last: )' + interactive: ' (first: , last: )">">' + separator: ', ' dateTimeFormat: 'dd-MM-yyyy' - none: '&7No name history found' + none: 'No name history found' export: error: - inProgress: '&cAn export is already in progress, please wait' + inProgress: 'An export is already in progress, please wait' player: - started: '&aPlayer ban export started' - finished: '&aPlayer ban export finished, file [file] created' + started: 'Player ban export started' + finished: 'Player ban export finished, file created' ip: - started: '&aIP ban export started' - finished: '&aIP ban export finished, file [file] created' + started: 'IP ban export started' + finished: 'IP ban export finished, file created' import: error: - inProgress: '&cAn import is already in progress, please wait' + inProgress: 'An import is already in progress, please wait' player: - started: '&aPlayer ban import started' - finished: '&aPlayer ban import finished' + started: 'Player ban import started' + finished: 'Player ban import finished' ip: - started: '&aIP ban import started' - finished: '&aIP ban import finished' + started: 'IP ban import started' + finished: 'IP ban import finished' advancedban: - started: '&aAdvancedBan import started' - finished: '&aAdvancedBan import finished' + started: 'AdvancedBan import started' + finished: 'AdvancedBan import finished' h2: - started: '&aH2 import started' - finished: '&aH2 import finished, please restart the server' + started: 'H2 import started' + finished: 'H2 import finished, please restart the server' litebans: - started: '&aLiteBans import started' - finished: '&aLiteBans import finished' + started: 'LiteBans import started' + finished: 'LiteBans import finished' info: error: - invalidIndex: '&cInvalid player option used' - indexRequired: '&cMultiple players named [name] found, please select a player by providing an index between 1 and [size], e.g. /bminfo [name] 1' - index: '&7#[index] - &6[name] - &4[uuid]' + invalidIndex: 'Invalid player option used' + indexRequired: 'Multiple players named found, please select a player by providing an index between 1 and , e.g. /bminfo 1' + index: '# - - ' stats: - player: '&6[player] has been banned [bans] times, muted [mutes] times, kicked [kicks] times and warned [warns] - times ([warnPoints] Points), has [notes] notes and been reported [reports] times' - ip: '&6This ip has been banned [bans] times, muted [mutes] times and range banned [rangebans] times' - connection: '&6Their last connection was with [ip] on [lastSeen]' - geoip: 'Country: [country] City: [city]' + player: ' has been banned times, muted times, kicked times and warned + times ( Points), has notes and been reported times' + ip: 'This ip has been banned times, muted times and range banned times' + connection: 'Their last connection was with on ' + geoip: 'Country: City: ' ban: - permanent: '&6Currently banned for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently banned for &4[reason]&6 by [actor] at [created] which expires in [expires]' + permanent: 'Currently banned for by at ' + temporary: 'Currently banned for by at which expires in ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' ipban: - permanent: '&6Currently banned for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently banned for &4[reason]&6 by [actor] at [created] which expires in [expires]' + permanent: 'Currently banned for by at ' + temporary: 'Currently banned for by at which expires in ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' iprangeban: - permanent: '&6[from] - [to] banned for &4[reason]&6 by [actor] at [created]' - temporary: '&6[from] - [to] banned for &4[reason]&6 by [actor] at [created] which expires in [expires]' + permanent: ' - banned for by at ' + temporary: ' - banned for by at which expires in ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' ipmute: - permanent: '&6Currently muted for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently muted for &4[reason]&6 by [actor] at [created] which expires in [expires]' + permanent: 'Currently muted for by at ' + temporary: 'Currently muted for by at which expires in ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' mute: - permanent: '&6Currently muted for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently muted for &4[reason]&6 by [actor] at [created] which expires in [expires]' - temporaryOnline: '&6Currently muted for &4[reason]&6 by [actor] at [created] which expires in [expires] (online time)' - temporaryOnlinePaused: '&6Currently muted for &4[reason]&6 by [actor] at [created] with [remaining] remaining (online time, paused)' + permanent: 'Currently muted for by at ' + temporary: 'Currently muted for by at which expires in ' + temporaryOnline: 'Currently muted for by at which expires in (online time)' + temporaryOnlinePaused: 'Currently muted for by at with remaining (online time, paused)' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' website: - player: 'https://yourdomain.com/player/[uuid]' - ip: 'http://yourdomain.com/index.php?action=viewip&ip=[ip]&server=0' + player: 'https://yourdomain.com/player/' + ip: 'http://yourdomain.com/index.php?action=viewip&ip=&server=0' history: - row: '&7#[id] &a[&f[type]&a] &6[actor]&f [meta] [reason] - &e[created]' + row: '# [] - ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' - noResults: '&cNo results found' + noResults: 'No results found' ips: - row: '&e[ip] - &6[join] - [leave]' + row: ' - - ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' kick: player: - noReason: '&6You have been kicked' - reason: '&6You have been kicked for &4[reason]' + noReason: 'You have been kicked' + reason: 'You have been kicked for ' notify: - noReason: '&6[player] has been kicked by [actor]' - reason: '&6[player] has been kicked by [actor] for &4[reason]' + noReason: ' has been kicked by ">View player info">[Info]' + reason: ' has been kicked by for ">View player info">[Info]' kickall: player: - noReason: '&6You have been kicked' - reason: '&6You have been kicked for &4[reason]' + noReason: 'You have been kicked' + reason: 'You have been kicked for ' notify: - noReason: 'All players have been kicked by [actor]' - reason: 'All players have been kicked by [actor] for &4[reason]' + noReason: 'All players have been kicked by ' + reason: 'All players have been kicked by for ' ban: player: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' + disallowed: 'You are banned from this server\n \nReason: \nBanned by: \nDate: \n \nAppeal at ' + kick: 'You have been banned\n \nReason: \nBanned by: ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[player] has been permanently banned by [actor] for &4[reason]' + notify: ' has been permanently banned by for ">View player info">[Info] ">Unban player">[Unban]' error: - exists: '&c[player] is already banned' - cooldown: '&cThis player was banned too recently, try again later' + exists: ' is already banned' + cooldown: 'This player was banned too recently, try again later' banall: - notify: '&6[player] will be permanently banned by [actor] for &4[reason]' + notify: ' will be permanently banned by for ' tempban: player: - disallowed: '&6You have been temporarily banned from this server for &4[reason] \n&6It expires in [expires]' - kick: '&6You have been temporarily banned for &4[reason]' + disallowed: 'You are temporarily banned from this server\n \nReason: \nBanned by: \nExpires: \nDate: \n \nAppeal at ' + kick: 'You have been temporarily banned\n \nReason: \nBanned by: \nExpires: ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[player] has been temporarily banned for [expires] by [actor] for &4[reason]' + notify: ' has been temporarily banned for by for ">View player info">[Info] ">Unban player">[Unban]' tempbanall: - notify: '&6[player] will be temporarily banned for [expires] by [actor] for &4[reason]' + notify: ' will be temporarily banned for by for ' unban: - notify: '&6[player] has been unbanned by [actor]' + notify: ' has been unbanned by ' error: - noExists: '&c[player] is not banned' - notOwn: '&c[player] was not banned by you, unable to unban' + noExists: ' is not banned' + notOwn: ' was not banned by you, unable to unban' unbanall: - notify: '&6[player] will be unbanned by [actor]' + notify: ' will be unbanned by ' mute: player: - blocked: '&cYou may not use the [command] command whilst muted!' - disallowed: '&6You have been permanently muted for &4[reason] &6by [actor]' - broadcast: '&4[Muted] [player]&7 [message]' - notify: '&6[player] has been permanently muted by [actor] for &4[reason]' + blocked: 'You may not use the command whilst muted!' + disallowed: 'You have been permanently muted for by ' + broadcast: '[Muted] ' + notify: ' has been permanently muted by for ">View player info">[Info] ">Unmute player">[Unmute]' error: - exists: '&c[player] is already muted' - cooldown: '&cThis player was muted too recently, try again later' + exists: ' is already muted' + cooldown: 'This player was muted too recently, try again later' muteip: ip: - disallowed: '&6You have been permanently muted for &4[reason] &6by [actor]' - broadcast: '&4[Muted] [player]&7 [message]' - notify: '&6[ip] ([players]) have been permanently muted by [actor] for &4[reason]' + disallowed: 'You have been permanently muted for by ' + broadcast: '[Muted] ' + notify: ' () have been permanently muted by for ' error: - exists: '&c[ip] is already muted' + exists: ' is already muted' muteall: - notify: '&6[player] will be permanently muted by [actor] for &4[reason]' + notify: ' will be permanently muted by for ' tempmute: player: - disallowed: '&6You have been temporarily muted for &4[reason] &6by [actor] which expires in [expires]' - disallowedOnline: '&6You have been temporarily muted for &4[reason] &6by [actor] which expires in [expires] (online time)' - notify: '&6[player] has been temporarily muted for [expires] by [actor] for &4[reason]' - notifyOnline: '&6[player] has been temporarily muted for [expires] (online time) by [actor] for &4[reason]' + disallowed: 'You have been temporarily muted for by which expires in ' + disallowedOnline: 'You have been temporarily muted for by which expires in (online time)' + notify: ' has been temporarily muted for by for ">View player info">[Info] ">Unmute player">[Unmute]' + notifyOnline: ' has been temporarily muted for (online time) by for ' error: - exists: '&c[player] is already muted' + exists: ' is already muted' tempmuteip: ip: - disallowed: '&6You have been temporarily muted for &4[reason] &6by [actor] which expires in [expires]' - notify: '&6[ip] ([players]) have been temporarily muted for [expires] by [actor] for &4[reason]' + disallowed: 'You have been temporarily muted for by which expires in ' + notify: ' () have been temporarily muted for by for ' error: - exists: '&c[ip] is already muted' + exists: ' is already muted' tempmuteall: - notify: '&6[player] will be temporarily muted for [expires] by [actor] for &4[reason]' + notify: ' will be temporarily muted for by for ' unmute: - notify: '&6[player] has been unmuted by [actor]' - player: '&6You have been unmuted by [actor]' + notify: ' has been unmuted by ' + player: 'You have been unmuted by ' error: - noExists: '&c[player] is not muted' - notOwn: '&c[player] was not muted by you, unable to unmute' + noExists: ' is not muted' + notOwn: ' was not muted by you, unable to unmute' unmuteip: - notify: '&6[ip] has been unmuted by [actor]' + notify: ' has been unmuted by ' error: - noExists: '&c[ip] is not muted' - notOwn: '&c[ip] was not muted by you, unable to unmute' + noExists: ' is not muted' + notOwn: ' was not muted by you, unable to unmute' unmuteall: - notify: '&6[player] will be unmuted by [actor]' + notify: ' will be unmuted by ' banname: name: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' + disallowed: 'You have been banned from this server for ' + kick: 'You have been banned permanently for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6Name [name] has been permanently banned by [actor] for &4[reason]' + notify: 'Name has been permanently banned by for ' error: - exists: '&cName [name] is already banned' + exists: 'Name is already banned' tempbanname: name: - disallowed: '&6You have been banned from this server for &4[reason] \n&6It expires in [expires]' - kick: '&6You have been temporarily banned for &4[reason]' + disallowed: 'You have been banned from this server for \nIt expires in ' + kick: 'You have been temporarily banned for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6Name [name] has been temporarily banned for [expires] by [actor] for &4[reason]' + notify: 'Name has been temporarily banned for by for ' unbanname: - notify: '&6Name [name] has been unbanned by [actor]' + notify: 'Name has been unbanned by ' error: - noExists: '&cName [name] is not banned' + noExists: 'Name is not banned' banip: ip: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' + disallowed: 'You have been banned from this server for ' + kick: 'You have been banned permanently for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[ip] ([players]) has been permanently banned by [actor] for &4[reason]' + notify: ' () has been permanently banned by for ' error: - exists: '&c[ip] is already banned' - cooldown: '&cThis ip was banned too recently, try again later' + exists: ' is already banned' + cooldown: 'This ip was banned too recently, try again later' baniprange: error: - invalid: '&cInvalid range, please use cidr notation 192.168.0.1/16 or wildcard 192.168.*.*' - minMax: '&cRange must be lowest to highest' - exists: '&cA ban containing those ranges already exists' + invalid: 'Invalid range, please use cidr notation 192.168.0.1/16 or wildcard 192.168.*.*' + minMax: 'Range must be lowest to highest' + exists: 'A ban containing those ranges already exists' ip: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' + disallowed: 'You have been banned from this server for ' + kick: 'You have been banned permanently for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[from] - [to] have been banned by [actor]' + notify: ' - have been banned by ' tempbaniprange: - notify: '&6[from] - [to] has been temporarily banned for [expires] by [actor]' + notify: ' - has been temporarily banned for by ' ip: - disallowed: '&6You have been banned from this server for &4[reason] \n&6It expires in [expires]' - kick: '&6You have been temporarily banned for [expires] by [actor] for &4[reason]' + disallowed: 'You have been banned from this server for \nIt expires in ' + kick: 'You have been temporarily banned for by for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' unbaniprange: - notify: '&6[from] - [to] has been unbanned by [actor]' + notify: ' - has been unbanned by ' banipall: - notify: '&6[ip] will be permanently banned by [actor] for &4[reason]' + notify: ' will be permanently banned by for ' tempbanip: ip: - disallowed: '&6You have been banned from this server for &4[reason] \n&6It expires in [expires]' - kick: '&6You have been temporarily banned for &4[reason]' + disallowed: 'You have been banned from this server for \nIt expires in ' + kick: 'You have been temporarily banned for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[ip] ([players]) has been temporarily banned for [expires] by [actor] for &4[reason]' + notify: ' () has been temporarily banned for by for ' tempbanipall: - notify: '&6[ip] will be temporarily banned for [expires] by [actor] for &4[reason]' + notify: ' will be temporarily banned for by for ' unbanip: - notify: '&6[ip] has been unbanned by [actor]' + notify: ' has been unbanned by ' error: - noExists: '&c[ip] is not banned' - notOwn: '&c[ip] was not banned by you, unable to unban' + noExists: ' is not banned' + notOwn: ' was not banned by you, unable to unban' unbanipall: - notify: '&6[ip] will be unbanned by [actor]' + notify: ' will be unbanned by ' warn: player: - warned: '&6You have been warned by [actor] for &4[reason]' + warned: 'You have been warned by for ' disallowed: - header: '&cYou may not speak until you have accepted your most recent warning. Please type the following:' - reason: '&6[reason]' - removed: '&aThank you for your understanding, you may now speak again' - notify: '&6[player] has been warned by [actor] for &4[reason]' + header: 'You may not speak until you have accepted your most recent warning. Please type the following:' + reason: '' + removed: 'Thank you for your understanding, you may now speak again' + notify: ' has been warned by for ">View player info">[Info]' error: - cooldown: '&cThis player was warned too recently, try again later' + cooldown: 'This player was warned too recently, try again later' tempwarn: player: - warned: '&6You have been warned for [expires] by [actor] for &4[reason]' - notify: '&6[player] has been warned for [expires] by [actor] for &4[reason]' + warned: 'You have been warned for by for ' + notify: ' has been warned for by for ">View player info">[Info]' dwarn: player: - notify: '&6Your most recent warning has been deleted by &4[actor]' - notify: '&cThe most recent warning for [player] has been deleted' + notify: 'Your most recent warning has been deleted by ' + notify: 'The most recent warning for has been deleted' error: - noWarnings: '&c[player] has no warnings to delete' + noWarnings: ' has no warnings to delete' bmclear: - notify: '&c[player] has had their [type] cleared' + notify: ' has had their cleared' error: - invalid: '&cInvalid type, please choose between banrecords, muterecords, kicks, notes or warnings' + invalid: 'Invalid type, please choose between banrecords, muterecords, kicks, notes or warnings' bmutils: missingplayers: - notify: '&c[amount] missing players added' - noneFound: '&a0 missing players found' - found: '&c[amount] missing player data found. Fixing...' + notify: ' missing players added' + noneFound: '0 missing players found' + found: ' missing player data found. Fixing...' error: - failedLookup: '&cFailed to lookup player [uuid], check server logs' - complete: '&a[amount] players resolved, please restart your server for failed punishments to take affect' + failedLookup: 'Failed to lookup player , check server logs' + complete: ' players resolved, please restart your server for failed punishments to take affect' duplicates: lookup: - notFound: '&aNo duplicate player names found' + notFound: 'No duplicate player names found' error: - invalidName: '&cInvalid name, must be 16 characters or less and contain only letters, numbers and an underscore' - nameExists: '&cA player with that name already exists' - success: '&aPlayer name set to [player] successfully' + invalidName: 'Invalid name, must be 16 characters or less and contain only letters, numbers and an underscore' + nameExists: 'A player with that name already exists' + success: 'Player name set to successfully' bmrollback: - notify: '&c[player] has had their [type] actions undone' + notify: ' has had their actions undone' error: - invalid: '&cInvalid type [type], please choose between [types]' + invalid: 'Invalid type , please choose between ' sync: player: - started: '&aStarting force [type] synchronisation' - finished: '&aForced [type] synchronisation complete' + started: 'Starting force synchronisation' + finished: 'Forced synchronisation complete' update: - notify: '&6[BanManager] &aAn update is available' + notify: '[BanManager] An update is available' notes: - header: '&6[player] has the following notes:' - joinAmount: '&6[player] has &e[amount] &6notes, click to view them' - note: '&6[[player]] &e[message] - &e[created]' - playerNote: '&a[[player]] &6[[actor]] &e[message] - &e[created]' + header: ' has the following notes:' + joinAmount: '"> has notes, click to view them' + note: '[] - ' + playerNote: '[] [] - ' dateTimeFormat: 'dd-MM-yyyy' - notify: '[player] has a new note attached by [actor]: [message]' + notify: ' has a new note attached by : ' error: - noNotes: '&c[player] has no notes' - noOnlineNotes: '&cNo online players have notes' + noNotes: ' has no notes' + noOnlineNotes: 'No online players have notes' report: - notify: '&6[player] has been reported by [actor] for &4[reason]' + notify: ' has been reported by for ' error: - cooldown: '&cThis player was reported too recently, try again later' + cooldown: 'This player was reported too recently, try again later' assign: - player: '&aReport [id] assigned to [player]' - notify: '&aYou have been assigned report [id] by [actor]' + player: 'Report assigned to ' + notify: 'You have been assigned report by ' unassign: - player: '&aReport [id] unassigned' + player: 'Report unassigned' close: notify: - closed: '&aReport [id] closed by [actor]' - command: '&aReport [id] closed by [actor] with [command]' - comment: '&aReport [id] closed by [actor] with [comment]' - dispatch: 'Executing command [command]' + closed: 'Report closed by ' + command: 'Report closed by with ' + comment: 'Report closed by with ' + dispatch: 'Executing command ' list: - noResults: '&cNo reports found' + noResults: 'No reports found' error: - invalidState: '&cReport state [state] not found' + invalidState: 'Report state not found' row: dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - header: '&e-- Reports ([count]) -- Page ([page]/[maxPage])' - all: '&7#[id] &e[[state]] &6- [created] - [player]' + header: '-- Reports () -- Page (/)' + all: '">Click to view details"># [] - - ' tp: error: - notFound: '&cReport not found' - worldNotFound: '&cWorld [world] could not be found' - invalidId: '&c[id] is not a valid report id' + notFound: 'Report not found' + worldNotFound: 'World could not be found' + invalidId: ' is not a valid report id' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' notify: - report: '&7#[id] &6[actor] reported [player] for &4[reason]&6 at [created]' - location: '[world] - [x], [y], [z]' + report: '# reported for at ' + location: ' - , , ' info: error: - notFound: '&cReport not found' - invalidId: '&c[id] is not a valid report id' + notFound: 'Report not found' + invalidId: ' is not a valid report id' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' notify: - report: '&7#[id] &6[actor] reported [player] for &4[reason]&6 at [created]' - location: '[world] - [x], [y], [z]' + report: '# reported for at ' + location: ' - , , ' + + actions: + assign: '">Assign to yourself">[Assign]' + close: '">Close this report">[Close]' + tp: '">Teleport to location">[TP]' + feedback: + assigned: 'Your report # has been assigned to ' + closed: 'Your report # has been closed by ' addnoteall: - notify: '&c[player] will have a new attached by [actor]: [message]' + notify: ' will have a new attached by : ' banlist: - header: '&6There are [bans] [type] bans:' + header: 'There are bans:' + row: + player: '">Click for info"> - ' + ip: ' - ' + iprange: ' - - ' bmactivity: row: - all: '&a[&f[type]&a] &6[player]&f - &6[actor]&f - &e[created]' - player: '&a[&f[type]&a] &6[player]&f - &e[created]' + all: '[] - - ' + player: '[] - ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' - noResults: '&cNo results found' + noResults: 'No results found' bmdelete: - notify: '&a[rows] rows deleted' + notify: ' rows deleted' error: - invalid: '&cInvalid type, please choose between banrecords, muterecords, kicks, notes or warnings' - invalidId: '&c[id] is not a valid number' + invalid: 'Invalid type, please choose between banrecords, muterecords, kicks, notes or warnings' + invalidId: ' is not a valid number' denyalts: player: - disallowed: '&cThe IP address you are joining from is linked to a banned player' + disallowed: 'The IP address you are joining from is linked to a banned player' reasons: - row: '[hashtag] = [reason]' + row: ' = ' + + dashboard: + header: ' Staff Dashboard ' + activeBans: 'Active Bans: ' + activeMutes: 'Active Mutes: ' + openReports: 'Open Reports: View reports">[View]' + recentActivity: 'Recent Activity (24h): ' + footer: ' ' diff --git a/e2e/platforms/bukkit/configs/notifications.yml b/e2e/platforms/bukkit/configs/notifications.yml new file mode 100644 index 000000000..75b1fb646 --- /dev/null +++ b/e2e/platforms/bukkit/configs/notifications.yml @@ -0,0 +1,81 @@ +# Notifications Configuration +# Controls how punishment notifications are delivered to staff and players +# +# Each notification event can specify delivery channels: +# chat: true/false - Send via chat message (default: true) +# actionbar: true/false - Send via action bar (disappears after a few seconds) +# title: true/false - Send via title/subtitle overlay +# sound: '' - Sound to play (empty to disable). Use Minecraft sound names e.g. entity.experience_orb.pickup +# +# Title settings (only used when title: true): +# titleFadeIn: ticks for fade in (20 ticks = 1 second) +# titleStay: ticks to stay on screen +# titleFadeOut: ticks for fade out +# +# Sound settings: +# soundVolume: 0.0 - 1.0 +# soundPitch: 0.0 - 2.0 +# +# Platform notes: +# - BungeeCord: title, showTitle and playSound are not supported (ignored silently) +# - Sponge API7: playSound is not supported (ignored silently) +# - All other platforms (Bukkit/Paper, Velocity, Fabric, Sponge API8+) support all channels + +staff: + ban: + chat: true + actionbar: false + title: false + sound: 'entity.experience_orb.pickup' + soundVolume: 1.0 + soundPitch: 1.0 + tempban: + chat: true + actionbar: false + title: false + sound: 'entity.experience_orb.pickup' + soundVolume: 1.0 + soundPitch: 1.0 + mute: + chat: true + actionbar: false + title: false + sound: '' + soundVolume: 1.0 + soundPitch: 1.0 + tempmute: + chat: true + actionbar: false + title: false + sound: '' + soundVolume: 1.0 + soundPitch: 1.0 + warn: + chat: true + actionbar: false + title: false + sound: 'entity.experience_orb.pickup' + soundVolume: 1.0 + soundPitch: 1.0 + report: + chat: true + actionbar: false + title: false + sound: 'block.note_block.pling' + soundVolume: 1.0 + soundPitch: 1.0 + duplicateIp: + chat: true + actionbar: false + title: false + sound: '' + soundVolume: 1.0 + soundPitch: 1.0 + +player: + muted: + actionbar: true + warned: + sound: 'entity.villager.no' + soundVolume: 1.0 + soundPitch: 1.0 diff --git a/e2e/platforms/bungee/configs/banmanager/messages.yml b/e2e/platforms/bungee/configs/banmanager/messages.yml index 689b5c8c8..494d65579 100644 --- a/e2e/platforms/bungee/configs/banmanager/messages.yml +++ b/e2e/platforms/bungee/configs/banmanager/messages.yml @@ -1,424 +1,474 @@ -# Variables -# [reason] = Ban/Mute reason -# [player] = The name of the player -# [ip] = The banned ip -# [actor] = Who banned/muted -# [expires] = How long until the ban/mute ends +# Message templates use MiniMessage formatting: https://docs.advntr.dev/minimessage/format.html +# Placeholders use angle brackets, e.g. , , , , + +tokens: + appeal_url: 'https://yourdomain.com/appeal' + server_name: 'My Server' + discord_url: 'https://discord.gg/example' + rules_url: 'https://yourdomain.com/rules' messages: - duplicateIP: '&cWarning: [player] has the same IP as the following banned players:\n&6[players]' - duplicateIPAlts: '&cWarning: [player] has the same IP as the following players:\n&6[players]' - configReloaded: '�ff00Configuration &#ff5733reloaded &asuccessfully!' + duplicateIP: 'Warning: has the same IP as the following banned players:\n' + duplicateIPAlts: 'Warning: has the same IP as the following players:\n' + configReloaded: 'Configuration reloaded successfully!' deniedNotify: - player: '&cWarning: [player] attempted to join the server but was denied due to - &4[reason]' - ip: '&cWarning: [ip] attempted to join the server but was denied due to &4[reason]' - deniedMaxIp: '&cToo many players with your ip address online' - deniedMultiaccounts: '&cToo many players with your ip address logged in recently' - deniedCountry: '&cYou may not connect from your region' + player: 'Warning: attempted to join the server but was denied due to ' + ip: 'Warning: attempted to join the server but was denied due to ' + deniedMaxIp: 'Too many players with your ip address online' + deniedMultiaccounts: 'Too many players with your ip address logged in recently' + deniedCountry: 'You may not connect from your region' + time: - now: now - year: year - years: years - month: month - months: months - week: week - weeks: weeks - day: day - days: days - hour: hour - hours: hours - minute: minute - minutes: minutes - second: second - seconds: seconds - never: never + now: 'now' + year: 'year' + years: 'years' + month: 'month' + months: 'months' + week: 'week' + weeks: 'weeks' + day: 'day' + days: 'days' + hour: 'hour' + hours: 'hours' + minute: 'minute' + minutes: 'minutes' + second: 'second' + seconds: 'seconds' + never: 'never' error: - invalid: '&cYour time length is invalid' - limit: '&cYou cannot perform this action for that length of time' - none: none + invalid: 'Your time length is invalid' + limit: 'You cannot perform this action for that length of time' + + none: 'none' + # General command text sender: error: - notFound: '&c[player] not found, are you sure they exist?' - offline: '&c[player] is offline' - noSelf: '&cYou cannot perform that action on yourself!' - exception: '&cAn error occured whilst attempting to perform this command. Please - check the console for further details.' - invalidIp: '&cInvalid IP address, expecting w.x.y.z format' - offlinePermission: '&cYou are not allowed to perform this action on an offline - player' - exempt: '&c[player] is exempt from that action' - noPermission: '&cYou do not have permission to perform that action' - invalidReason: '&c[reason] is no valid reason.' + notFound: ' not found, are you sure they exist?' + offline: ' is offline' + noSelf: 'You cannot perform that action on yourself!' + exception: 'An error occured whilst attempting to perform this command. Please check the console for further details.' + invalidIp: 'Invalid IP address, expecting w.x.y.z format' + offlinePermission: 'You are not allowed to perform this action on an offline player' + ambiguousPlayer: 'Multiple players match "". Please use their full name.' + exempt: ' is exempt from that action' + noPermission: 'You do not have permission to perform that action' + noConsole: 'This command cannot be used from console' + invalidReason: ' is no valid reason.' + # Commands alts: header: 'Possible alts found:' + entry: '">' + separator: ', ' + names: - header: 'Known names for [player]:' - row: '&e[name] &7(first: [firstSeen], last: [lastSeen])' - dateTimeFormat: dd-MM-yyyy - none: '&7No name history found' + header: 'Known names for :' + row: ' (first: , last: )' + interactive: ' (first: , last: )">">' + separator: ', ' + dateTimeFormat: 'dd-MM-yyyy' + none: 'No name history found' + export: error: - inProgress: '&cAn export is already in progress, please wait' + inProgress: 'An export is already in progress, please wait' player: - started: '&aPlayer ban export started' - finished: '&aPlayer ban export finished, file [file] created' + started: 'Player ban export started' + finished: 'Player ban export finished, file created' ip: - started: '&aIP ban export started' - finished: '&aIP ban export finished, file [file] created' + started: 'IP ban export started' + finished: 'IP ban export finished, file created' + import: error: - inProgress: '&cAn import is already in progress, please wait' + inProgress: 'An import is already in progress, please wait' player: - started: '&aPlayer ban import started' - finished: '&aPlayer ban import finished' + started: 'Player ban import started' + finished: 'Player ban import finished' ip: - started: '&aIP ban import started' - finished: '&aIP ban import finished' + started: 'IP ban import started' + finished: 'IP ban import finished' advancedban: - started: '&aAdvancedBan import started' - finished: '&aAdvancedBan import finished' + started: 'AdvancedBan import started' + finished: 'AdvancedBan import finished' h2: - started: '&aH2 import started' - finished: '&aH2 import finished, please restart the server' + started: 'H2 import started' + finished: 'H2 import finished, please restart the server' litebans: - started: '&aLiteBans import started' - finished: '&aLiteBans import finished' + started: 'LiteBans import started' + finished: 'LiteBans import finished' + info: error: - invalidIndex: '&cInvalid player option used' - indexRequired: '&cMultiple players named [name] found, please select a player - by providing an index between 1 and [size], e.g. /bminfo [name] 1' - index: '&7#[index] - &6[name] - &4[uuid]' + invalidIndex: 'Invalid player option used' + indexRequired: 'Multiple players named found, please select a player by providing an index between 1 and , e.g. /bminfo 1' + index: '# - - ' stats: - player: '&6[player] has been banned [bans] times, muted [mutes] times, kicked - [kicks] times and warned [warns] times ([warnPoints] Points), has [notes] - notes and been reported [reports] times' - ip: '&6This ip has been banned [bans] times, muted [mutes] times and range banned - [rangebans] times' - connection: '&6Their last connection was with [ip] on [lastSeen]' - geoip: 'Country: [country] City: [city]' + player: ' has been banned times, muted times, kicked times and warned + times ( Points), has notes and been reported times' + ip: 'This ip has been banned times, muted times and range banned times' + connection: 'Their last connection was with on ' + geoip: 'Country: City: ' ban: - permanent: '&6Currently banned for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently banned for &4[reason]&6 by [actor] at [created] which - expires in [expires]' - dateTimeFormat: dd-MM-yyyy HH:mm:ss + permanent: 'Currently banned for by at ' + temporary: 'Currently banned for by at which expires in ' + dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' ipban: - permanent: '&6Currently banned for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently banned for &4[reason]&6 by [actor] at [created] which - expires in [expires]' - dateTimeFormat: dd-MM-yyyy HH:mm:ss + permanent: 'Currently banned for by at ' + temporary: 'Currently banned for by at which expires in ' + dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' iprangeban: - permanent: '&6[from] - [to] banned for &4[reason]&6 by [actor] at [created]' - temporary: '&6[from] - [to] banned for &4[reason]&6 by [actor] at [created] - which expires in [expires]' - dateTimeFormat: dd-MM-yyyy HH:mm:ss + permanent: ' - banned for by at ' + temporary: ' - banned for by at which expires in ' + dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' ipmute: - permanent: '&6Currently muted for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently muted for &4[reason]&6 by [actor] at [created] which - expires in [expires]' - dateTimeFormat: dd-MM-yyyy HH:mm:ss + permanent: 'Currently muted for by at ' + temporary: 'Currently muted for by at which expires in ' + dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' mute: - permanent: '&6Currently muted for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently muted for &4[reason]&6 by [actor] at [created] which - expires in [expires]' - temporaryOnline: '&6Currently muted for &4[reason]&6 by [actor] at [created] - which expires in [expires] (online time)' - temporaryOnlinePaused: '&6Currently muted for &4[reason]&6 by [actor] at [created] - with [remaining] remaining (online time, paused)' - dateTimeFormat: dd-MM-yyyy HH:mm:ss + permanent: 'Currently muted for by at ' + temporary: 'Currently muted for by at which expires in ' + temporaryOnline: 'Currently muted for by at which expires in (online time)' + temporaryOnlinePaused: 'Currently muted for by at with remaining (online time, paused)' + dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' website: - player: https://yourdomain.com/player/[uuid] - ip: http://yourdomain.com/index.php?action=viewip&ip=[ip]&server=0 + player: 'https://yourdomain.com/player/' + ip: 'http://yourdomain.com/index.php?action=viewip&ip=&server=0' history: - row: '&7#[id] &a[&f[type]&a] &6[actor]&f [meta] [reason] - &e[created]' - dateTimeFormat: dd-MM-yyyy HH:mm:ss - noResults: '&cNo results found' + row: '# [] - ' + dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' + noResults: 'No results found' ips: - row: '&e[ip] - &6[join] - [leave]' - dateTimeFormat: dd-MM-yyyy HH:mm:ss + row: ' - - ' + dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' + kick: player: - noReason: '&6You have been kicked' - reason: '&6You have been kicked for &4[reason]' + noReason: 'You have been kicked' + reason: 'You have been kicked for ' notify: - noReason: '&6[player] has been kicked by [actor]' - reason: '&6[player] has been kicked by [actor] for &4[reason]' + noReason: ' has been kicked by ">View player info">[Info]' + reason: ' has been kicked by for ">View player info">[Info]' + kickall: player: - noReason: '&6You have been kicked' - reason: '&6You have been kicked for &4[reason]' + noReason: 'You have been kicked' + reason: 'You have been kicked for ' notify: - noReason: All players have been kicked by [actor] - reason: All players have been kicked by [actor] for &4[reason] + noReason: 'All players have been kicked by ' + reason: 'All players have been kicked by for ' + ban: player: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' - dateTimeFormat: yyyy-MM-dd HH:mm:ss - notify: '&6[player] has been permanently banned by [actor] for &4[reason]' + disallowed: 'You are banned from this server\n \nReason: \nBanned by: \nDate: \n \nAppeal at ' + kick: 'You have been banned\n \nReason: \nBanned by: ' + dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' + notify: ' has been permanently banned by for ">View player info">[Info] ">Unban player">[Unban]' error: - exists: '&c[player] is already banned' - cooldown: '&cThis player was banned too recently, try again later' + exists: ' is already banned' + cooldown: 'This player was banned too recently, try again later' + banall: - notify: '&6[player] will be permanently banned by [actor] for &4[reason]' + notify: ' will be permanently banned by for ' + tempban: player: - disallowed: '&6You have been temporarily banned from this server for &4[reason] - \n&6It expires in [expires]' - kick: '&6You have been temporarily banned for &4[reason]' - dateTimeFormat: yyyy-MM-dd HH:mm:ss - notify: '&6[player] has been temporarily banned for [expires] by [actor] for &4[reason]' + disallowed: 'You are temporarily banned from this server\n \nReason: \nBanned by: \nExpires: \nDate: \n \nAppeal at ' + kick: 'You have been temporarily banned\n \nReason: \nBanned by: \nExpires: ' + dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' + notify: ' has been temporarily banned for by for ">View player info">[Info] ">Unban player">[Unban]' + tempbanall: - notify: '&6[player] will be temporarily banned for [expires] by [actor] for &4[reason]' + notify: ' will be temporarily banned for by for ' + unban: - notify: '&6[player] has been unbanned by [actor]' + notify: ' has been unbanned by ' error: - noExists: '&c[player] is not banned' - notOwn: '&c[player] was not banned by you, unable to unban' + noExists: ' is not banned' + notOwn: ' was not banned by you, unable to unban' + unbanall: - notify: '&6[player] will be unbanned by [actor]' + notify: ' will be unbanned by ' + mute: player: - blocked: '&cYou may not use the [command] command whilst muted!' - disallowed: '&6You have been permanently muted for &4[reason] &6by [actor]' - broadcast: '&4[Muted] [player]&7 [message]' - notify: '&6[player] has been permanently muted by [actor] for &4[reason]' + blocked: 'You may not use the command whilst muted!' + disallowed: 'You have been permanently muted for by ' + broadcast: '[Muted] ' + notify: ' has been permanently muted by for ">View player info">[Info] ">Unmute player">[Unmute]' error: - exists: '&c[player] is already muted' - cooldown: '&cThis player was muted too recently, try again later' + exists: ' is already muted' + cooldown: 'This player was muted too recently, try again later' + muteip: ip: - disallowed: '&6You have been permanently muted for &4[reason] &6by [actor]' - broadcast: '&4[Muted] [player]&7 [message]' - notify: '&6[ip] ([players]) have been permanently muted by [actor] for &4[reason]' + disallowed: 'You have been permanently muted for by ' + broadcast: '[Muted] ' + notify: ' () have been permanently muted by for ' error: - exists: '&c[ip] is already muted' + exists: ' is already muted' + muteall: - notify: '&6[player] will be permanently muted by [actor] for &4[reason]' + notify: ' will be permanently muted by for ' + tempmute: player: - disallowed: '&6You have been temporarily muted for &4[reason] &6by [actor] which - expires in [expires]' - disallowedOnline: '&6You have been temporarily muted for &4[reason] &6by [actor] - which expires in [expires] (online time)' - notify: '&6[player] has been temporarily muted for [expires] by [actor] for &4[reason]' - notifyOnline: '&6[player] has been temporarily muted for [expires] (online time) - by [actor] for &4[reason]' + disallowed: 'You have been temporarily muted for by which expires in ' + disallowedOnline: 'You have been temporarily muted for by which expires in (online time)' + notify: ' has been temporarily muted for by for ">View player info">[Info] ">Unmute player">[Unmute]' + notifyOnline: ' has been temporarily muted for (online time) by for ' error: - exists: '&c[player] is already muted' + exists: ' is already muted' + tempmuteip: ip: - disallowed: '&6You have been temporarily muted for &4[reason] &6by [actor] which - expires in [expires]' - notify: '&6[ip] ([players]) have been temporarily muted for [expires] by [actor] - for &4[reason]' + disallowed: 'You have been temporarily muted for by which expires in ' + notify: ' () have been temporarily muted for by for ' error: - exists: '&c[ip] is already muted' + exists: ' is already muted' + tempmuteall: - notify: '&6[player] will be temporarily muted for [expires] by [actor] for &4[reason]' + notify: ' will be temporarily muted for by for ' + unmute: - notify: '&6[player] has been unmuted by [actor]' - player: '&6You have been unmuted by [actor]' + notify: ' has been unmuted by ' + player: 'You have been unmuted by ' error: - noExists: '&c[player] is not muted' - notOwn: '&c[player] was not muted by you, unable to unmute' + noExists: ' is not muted' + notOwn: ' was not muted by you, unable to unmute' + unmuteip: - notify: '&6[ip] has been unmuted by [actor]' + notify: ' has been unmuted by ' error: - noExists: '&c[ip] is not muted' - notOwn: '&c[ip] was not muted by you, unable to unmute' + noExists: ' is not muted' + notOwn: ' was not muted by you, unable to unmute' + unmuteall: - notify: '&6[player] will be unmuted by [actor]' + notify: ' will be unmuted by ' + banname: name: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' - dateTimeFormat: yyyy-MM-dd HH:mm:ss - notify: '&6Name [name] has been permanently banned by [actor] for &4[reason]' + disallowed: 'You have been banned from this server for ' + kick: 'You have been banned permanently for ' + dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' + notify: 'Name has been permanently banned by for ' error: - exists: '&cName [name] is already banned' + exists: 'Name is already banned' + tempbanname: name: - disallowed: '&6You have been banned from this server for &4[reason] \n&6It expires - in [expires]' - kick: '&6You have been temporarily banned for &4[reason]' - dateTimeFormat: yyyy-MM-dd HH:mm:ss - notify: '&6Name [name] has been temporarily banned for [expires] by [actor] for - &4[reason]' + disallowed: 'You have been banned from this server for \nIt expires in ' + kick: 'You have been temporarily banned for ' + dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' + notify: 'Name has been temporarily banned for by for ' + unbanname: - notify: '&6Name [name] has been unbanned by [actor]' + notify: 'Name has been unbanned by ' error: - noExists: '&cName [name] is not banned' + noExists: 'Name is not banned' + banip: ip: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' - dateTimeFormat: yyyy-MM-dd HH:mm:ss - notify: '&6[ip] ([players]) has been permanently banned by [actor] for &4[reason]' + disallowed: 'You have been banned from this server for ' + kick: 'You have been banned permanently for ' + dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' + notify: ' () has been permanently banned by for ' error: - exists: '&c[ip] is already banned' - cooldown: '&cThis ip was banned too recently, try again later' + exists: ' is already banned' + cooldown: 'This ip was banned too recently, try again later' + baniprange: error: - invalid: '&cInvalid range, please use cidr notation 192.168.0.1/16 or wildcard - 192.168.*.*' - minMax: '&cRange must be lowest to highest' - exists: '&cA ban containing those ranges already exists' + invalid: 'Invalid range, please use cidr notation 192.168.0.1/16 or wildcard 192.168.*.*' + minMax: 'Range must be lowest to highest' + exists: 'A ban containing those ranges already exists' ip: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' - dateTimeFormat: yyyy-MM-dd HH:mm:ss - notify: '&6[from] - [to] have been banned by [actor]' + disallowed: 'You have been banned from this server for ' + kick: 'You have been banned permanently for ' + dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' + notify: ' - have been banned by ' + tempbaniprange: - notify: '&6[from] - [to] has been temporarily banned for [expires] by [actor]' + notify: ' - has been temporarily banned for by ' ip: - disallowed: '&6You have been banned from this server for &4[reason] \n&6It expires - in [expires]' - kick: '&6You have been temporarily banned for [expires] by [actor] for &4[reason]' - dateTimeFormat: yyyy-MM-dd HH:mm:ss + disallowed: 'You have been banned from this server for \nIt expires in ' + kick: 'You have been temporarily banned for by for ' + dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' + unbaniprange: - notify: '&6[from] - [to] has been unbanned by [actor]' + notify: ' - has been unbanned by ' + banipall: - notify: '&6[ip] will be permanently banned by [actor] for &4[reason]' + notify: ' will be permanently banned by for ' + tempbanip: ip: - disallowed: '&6You have been banned from this server for &4[reason] \n&6It expires - in [expires]' - kick: '&6You have been temporarily banned for &4[reason]' - dateTimeFormat: yyyy-MM-dd HH:mm:ss - notify: '&6[ip] ([players]) has been temporarily banned for [expires] by [actor] - for &4[reason]' + disallowed: 'You have been banned from this server for \nIt expires in ' + kick: 'You have been temporarily banned for ' + dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' + notify: ' () has been temporarily banned for by for ' + tempbanipall: - notify: '&6[ip] will be temporarily banned for [expires] by [actor] for &4[reason]' + notify: ' will be temporarily banned for by for ' + unbanip: - notify: '&6[ip] has been unbanned by [actor]' + notify: ' has been unbanned by ' error: - noExists: '&c[ip] is not banned' - notOwn: '&c[ip] was not banned by you, unable to unban' + noExists: ' is not banned' + notOwn: ' was not banned by you, unable to unban' + unbanipall: - notify: '&6[ip] will be unbanned by [actor]' + notify: ' will be unbanned by ' + warn: player: - warned: '&6You have been warned by [actor] for &4[reason]' + warned: 'You have been warned by for ' disallowed: - header: '&cYou may not speak until you have accepted your most recent warning. - Please type the following:' - reason: '&6[reason]' - removed: '&aThank you for your understanding, you may now speak again' - notify: '&6[player] has been warned by [actor] for &4[reason]' + header: 'You may not speak until you have accepted your most recent warning. Please type the following:' + reason: '' + removed: 'Thank you for your understanding, you may now speak again' + notify: ' has been warned by for ">View player info">[Info]' error: - cooldown: '&cThis player was warned too recently, try again later' + cooldown: 'This player was warned too recently, try again later' + tempwarn: player: - warned: '&6You have been warned for [expires] by [actor] for &4[reason]' - notify: '&6[player] has been warned for [expires] by [actor] for &4[reason]' + warned: 'You have been warned for by for ' + notify: ' has been warned for by for ">View player info">[Info]' + dwarn: player: - notify: '&6Your most recent warning has been deleted by &4[actor]' - notify: '&cThe most recent warning for [player] has been deleted' + notify: 'Your most recent warning has been deleted by ' + notify: 'The most recent warning for has been deleted' error: - noWarnings: '&c[player] has no warnings to delete' + noWarnings: ' has no warnings to delete' + bmclear: - notify: '&c[player] has had their [type] cleared' + notify: ' has had their cleared' error: - invalid: '&cInvalid type, please choose between banrecords, muterecords, kicks, - notes or warnings' + invalid: 'Invalid type, please choose between banrecords, muterecords, kicks, notes or warnings' + bmutils: missingplayers: - notify: '&c[amount] missing players added' - noneFound: '&a0 missing players found' - found: '&c[amount] missing player data found. Fixing...' + notify: ' missing players added' + noneFound: '0 missing players found' + found: ' missing player data found. Fixing...' error: - failedLookup: '&cFailed to lookup player [uuid], check server logs' - complete: '&a[amount] players resolved, please restart your server for failed - punishments to take affect' + failedLookup: 'Failed to lookup player , check server logs' + complete: ' players resolved, please restart your server for failed punishments to take affect' duplicates: lookup: - notFound: '&aNo duplicate player names found' + notFound: 'No duplicate player names found' error: - invalidName: '&cInvalid name, must be 16 characters or less and contain only - letters, numbers and an underscore' - nameExists: '&cA player with that name already exists' - success: '&aPlayer name set to [player] successfully' + invalidName: 'Invalid name, must be 16 characters or less and contain only letters, numbers and an underscore' + nameExists: 'A player with that name already exists' + success: 'Player name set to successfully' + bmrollback: - notify: '&c[player] has had their [type] actions undone' + notify: ' has had their actions undone' error: - invalid: '&cInvalid type [type], please choose between [types]' + invalid: 'Invalid type , please choose between ' + sync: player: - started: '&aStarting force [type] synchronisation' - finished: '&aForced [type] synchronisation complete' + started: 'Starting force synchronisation' + finished: 'Forced synchronisation complete' + update: - notify: '&6[BanManager] &aAn update is available' + notify: '[BanManager] An update is available' + notes: - header: '&6[player] has the following notes:' - joinAmount: '&6[player] has &e[amount] &6notes, click to view them' - note: '&6[[player]] &e[message] - &e[created]' - playerNote: '&a[[player]] &6[[actor]] &e[message] - &e[created]' - dateTimeFormat: dd-MM-yyyy - notify: '[player] has a new note attached by [actor]: [message]' + header: ' has the following notes:' + joinAmount: '"> has notes, click to view them' + note: '[] - ' + playerNote: '[] [] - ' + dateTimeFormat: 'dd-MM-yyyy' + notify: ' has a new note attached by : ' error: - noNotes: '&c[player] has no notes' - noOnlineNotes: '&cNo online players have notes' + noNotes: ' has no notes' + noOnlineNotes: 'No online players have notes' + report: - notify: '&6[player] has been reported by [actor] for &4[reason]' + notify: ' has been reported by for ' error: - cooldown: '&cThis player was reported too recently, try again later' + cooldown: 'This player was reported too recently, try again later' assign: - player: '&aReport [id] assigned to [player]' - notify: '&aYou have been assigned report [id] by [actor]' + player: 'Report assigned to ' + notify: 'You have been assigned report by ' unassign: - player: '&aReport [id] unassigned' + player: 'Report unassigned' close: notify: - closed: '&aReport [id] closed by [actor]' - command: '&aReport [id] closed by [actor] with [command]' - comment: '&aReport [id] closed by [actor] with [comment]' - dispatch: Executing command [command] + closed: 'Report closed by ' + command: 'Report closed by with ' + comment: 'Report closed by with ' + dispatch: 'Executing command ' list: - noResults: '&cNo reports found' + noResults: 'No reports found' error: - invalidState: '&cReport state [state] not found' + invalidState: 'Report state not found' row: - dateTimeFormat: yyyy-MM-dd HH:mm:ss - header: '&e-- Reports ([count]) -- Page ([page]/[maxPage])' - all: '&7#[id] &e[[state]] &6- [created] - [player]' + dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' + header: '-- Reports () -- Page (/)' + all: '">Click to view details"># [] - - ' tp: error: - notFound: '&cReport not found' - worldNotFound: '&cWorld [world] could not be found' - invalidId: '&c[id] is not a valid report id' - dateTimeFormat: yyyy-MM-dd HH:mm:ss + notFound: 'Report not found' + worldNotFound: 'World could not be found' + invalidId: ' is not a valid report id' + dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' notify: - report: '&7#[id] &6[actor] reported [player] for &4[reason]&6 at [created]' - location: '[world] - [x], [y], [z]' + report: '# reported for at ' + location: ' - , , ' info: error: - notFound: '&cReport not found' - invalidId: '&c[id] is not a valid report id' - dateTimeFormat: yyyy-MM-dd HH:mm:ss + notFound: 'Report not found' + invalidId: ' is not a valid report id' + dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' notify: - report: '&7#[id] &6[actor] reported [player] for &4[reason]&6 at [created]' - location: '[world] - [x], [y], [z]' + report: '# reported for at ' + location: ' - , , ' + actions: + assign: '">Assign to yourself">[Assign]' + close: '">Close this report">[Close]' + tp: '">Teleport to location">[TP]' + feedback: + assigned: 'Your report # has been assigned to ' + closed: 'Your report # has been closed by ' + addnoteall: - notify: '&c[player] will have a new attached by [actor]: [message]' + notify: ' will have a new attached by : ' + banlist: - header: '&6There are [bans] [type] bans:' + header: 'There are bans:' + row: + player: '">Click for info"> - ' + ip: ' - ' + iprange: ' - - ' + bmactivity: row: - all: '&a[&f[type]&a] &6[player]&f - &6[actor]&f - &e[created]' - player: '&a[&f[type]&a] &6[player]&f - &e[created]' - dateTimeFormat: dd-MM-yyyy HH:mm:ss - noResults: '&cNo results found' + all: '[] - - ' + player: '[] - ' + dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' + noResults: 'No results found' + bmdelete: - notify: '&a[rows] rows deleted' + notify: ' rows deleted' error: - invalid: '&cInvalid type, please choose between banrecords, muterecords, kicks, - notes or warnings' - invalidId: '&c[id] is not a valid number' + invalid: 'Invalid type, please choose between banrecords, muterecords, kicks, notes or warnings' + invalidId: ' is not a valid number' + denyalts: player: - disallowed: '&cThe IP address you are joining from is linked to a banned player' + disallowed: 'The IP address you are joining from is linked to a banned player' + reasons: - row: '[hashtag] = [reason]' + row: ' = ' + + dashboard: + header: ' Staff Dashboard ' + activeBans: 'Active Bans: ' + activeMutes: 'Active Mutes: ' + openReports: 'Open Reports: View reports">[View]' + recentActivity: 'Recent Activity (24h): ' + footer: ' ' diff --git a/e2e/platforms/bungee/configs/banmanager/messages/messages_en.yml b/e2e/platforms/bungee/configs/banmanager/messages/messages_en.yml index 205a94c13..494d65579 100644 --- a/e2e/platforms/bungee/configs/banmanager/messages/messages_en.yml +++ b/e2e/platforms/bungee/configs/banmanager/messages/messages_en.yml @@ -1,20 +1,22 @@ -# Variables -# [reason] = Ban/Mute reason -# [player] = The name of the player -# [ip] = The banned ip -# [actor] = Who banned/muted -# [expires] = How long until the ban/mute ends +# Message templates use MiniMessage formatting: https://docs.advntr.dev/minimessage/format.html +# Placeholders use angle brackets, e.g. , , , , + +tokens: + appeal_url: 'https://yourdomain.com/appeal' + server_name: 'My Server' + discord_url: 'https://discord.gg/example' + rules_url: 'https://yourdomain.com/rules' messages: - duplicateIP: '&cWarning: [player] has the same IP as the following banned players:\n&6[players]' - duplicateIPAlts: '&cWarning: [player] has the same IP as the following players:\n&6[players]' - configReloaded: '&aConfiguration reloaded successfully!' + duplicateIP: 'Warning: has the same IP as the following banned players:\n' + duplicateIPAlts: 'Warning: has the same IP as the following players:\n' + configReloaded: 'Configuration reloaded successfully!' deniedNotify: - player: '&cWarning: [player] attempted to join the server but was denied due to &4[reason]' - ip: '&cWarning: [ip] attempted to join the server but was denied due to &4[reason]' - deniedMaxIp: '&cToo many players with your ip address online' - deniedMultiaccounts: '&cToo many players with your ip address logged in recently' - deniedCountry: '&cYou may not connect from your region' + player: 'Warning: attempted to join the server but was denied due to ' + ip: 'Warning: attempted to join the server but was denied due to ' + deniedMaxIp: 'Too many players with your ip address online' + deniedMultiaccounts: 'Too many players with your ip address logged in recently' + deniedCountry: 'You may not connect from your region' time: now: 'now' @@ -34,415 +36,439 @@ messages: seconds: 'seconds' never: 'never' error: - invalid: '&cYour time length is invalid' - limit: '&cYou cannot perform this action for that length of time' + invalid: 'Your time length is invalid' + limit: 'You cannot perform this action for that length of time' none: 'none' # General command text sender: error: - notFound: '&c[player] not found, are you sure they exist?' - offline: '&c[player] is offline' - noSelf: '&cYou cannot perform that action on yourself!' - exception: '&cAn error occured whilst attempting to perform this command. Please check the console for further details.' - invalidIp: '&cInvalid IP address, expecting w.x.y.z format' - offlinePermission: '&cYou are not allowed to perform this action on an offline player' - ambiguousPlayer: '&cMultiple players match "[player]". Please use their full name.' - exempt: '&c[player] is exempt from that action' - noPermission: '&cYou do not have permission to perform that action' - invalidReason: '&c[reason] is no valid reason.' + notFound: ' not found, are you sure they exist?' + offline: ' is offline' + noSelf: 'You cannot perform that action on yourself!' + exception: 'An error occured whilst attempting to perform this command. Please check the console for further details.' + invalidIp: 'Invalid IP address, expecting w.x.y.z format' + offlinePermission: 'You are not allowed to perform this action on an offline player' + ambiguousPlayer: 'Multiple players match "". Please use their full name.' + exempt: ' is exempt from that action' + noPermission: 'You do not have permission to perform that action' + noConsole: 'This command cannot be used from console' + invalidReason: ' is no valid reason.' # Commands alts: header: 'Possible alts found:' + entry: '">' + separator: ', ' names: - header: 'Known names for [player]:' - row: '&e[name] &7(first: [firstSeen], last: [lastSeen])' + header: 'Known names for :' + row: ' (first: , last: )' + interactive: ' (first: , last: )">">' + separator: ', ' dateTimeFormat: 'dd-MM-yyyy' - none: '&7No name history found' + none: 'No name history found' export: error: - inProgress: '&cAn export is already in progress, please wait' + inProgress: 'An export is already in progress, please wait' player: - started: '&aPlayer ban export started' - finished: '&aPlayer ban export finished, file [file] created' + started: 'Player ban export started' + finished: 'Player ban export finished, file created' ip: - started: '&aIP ban export started' - finished: '&aIP ban export finished, file [file] created' + started: 'IP ban export started' + finished: 'IP ban export finished, file created' import: error: - inProgress: '&cAn import is already in progress, please wait' + inProgress: 'An import is already in progress, please wait' player: - started: '&aPlayer ban import started' - finished: '&aPlayer ban import finished' + started: 'Player ban import started' + finished: 'Player ban import finished' ip: - started: '&aIP ban import started' - finished: '&aIP ban import finished' + started: 'IP ban import started' + finished: 'IP ban import finished' advancedban: - started: '&aAdvancedBan import started' - finished: '&aAdvancedBan import finished' + started: 'AdvancedBan import started' + finished: 'AdvancedBan import finished' h2: - started: '&aH2 import started' - finished: '&aH2 import finished, please restart the server' + started: 'H2 import started' + finished: 'H2 import finished, please restart the server' litebans: - started: '&aLiteBans import started' - finished: '&aLiteBans import finished' + started: 'LiteBans import started' + finished: 'LiteBans import finished' info: error: - invalidIndex: '&cInvalid player option used' - indexRequired: '&cMultiple players named [name] found, please select a player by providing an index between 1 and [size], e.g. /bminfo [name] 1' - index: '&7#[index] - &6[name] - &4[uuid]' + invalidIndex: 'Invalid player option used' + indexRequired: 'Multiple players named found, please select a player by providing an index between 1 and , e.g. /bminfo 1' + index: '# - - ' stats: - player: '&6[player] has been banned [bans] times, muted [mutes] times, kicked [kicks] times and warned [warns] - times ([warnPoints] Points), has [notes] notes and been reported [reports] times' - ip: '&6This ip has been banned [bans] times, muted [mutes] times and range banned [rangebans] times' - connection: '&6Their last connection was with [ip] on [lastSeen]' - geoip: 'Country: [country] City: [city]' + player: ' has been banned times, muted times, kicked times and warned + times ( Points), has notes and been reported times' + ip: 'This ip has been banned times, muted times and range banned times' + connection: 'Their last connection was with on ' + geoip: 'Country: City: ' ban: - permanent: '&6Currently banned for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently banned for &4[reason]&6 by [actor] at [created] which expires in [expires]' + permanent: 'Currently banned for by at ' + temporary: 'Currently banned for by at which expires in ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' ipban: - permanent: '&6Currently banned for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently banned for &4[reason]&6 by [actor] at [created] which expires in [expires]' + permanent: 'Currently banned for by at ' + temporary: 'Currently banned for by at which expires in ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' iprangeban: - permanent: '&6[from] - [to] banned for &4[reason]&6 by [actor] at [created]' - temporary: '&6[from] - [to] banned for &4[reason]&6 by [actor] at [created] which expires in [expires]' + permanent: ' - banned for by at ' + temporary: ' - banned for by at which expires in ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' ipmute: - permanent: '&6Currently muted for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently muted for &4[reason]&6 by [actor] at [created] which expires in [expires]' + permanent: 'Currently muted for by at ' + temporary: 'Currently muted for by at which expires in ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' mute: - permanent: '&6Currently muted for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently muted for &4[reason]&6 by [actor] at [created] which expires in [expires]' - temporaryOnline: '&6Currently muted for &4[reason]&6 by [actor] at [created] which expires in [expires] (online time)' - temporaryOnlinePaused: '&6Currently muted for &4[reason]&6 by [actor] at [created] with [remaining] remaining (online time, paused)' + permanent: 'Currently muted for by at ' + temporary: 'Currently muted for by at which expires in ' + temporaryOnline: 'Currently muted for by at which expires in (online time)' + temporaryOnlinePaused: 'Currently muted for by at with remaining (online time, paused)' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' website: - player: 'https://yourdomain.com/player/[uuid]' - ip: 'http://yourdomain.com/index.php?action=viewip&ip=[ip]&server=0' + player: 'https://yourdomain.com/player/' + ip: 'http://yourdomain.com/index.php?action=viewip&ip=&server=0' history: - row: '&7#[id] &a[&f[type]&a] &6[actor]&f [meta] [reason] - &e[created]' + row: '# [] - ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' - noResults: '&cNo results found' + noResults: 'No results found' ips: - row: '&e[ip] - &6[join] - [leave]' + row: ' - - ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' kick: player: - noReason: '&6You have been kicked' - reason: '&6You have been kicked for &4[reason]' + noReason: 'You have been kicked' + reason: 'You have been kicked for ' notify: - noReason: '&6[player] has been kicked by [actor]' - reason: '&6[player] has been kicked by [actor] for &4[reason]' + noReason: ' has been kicked by ">View player info">[Info]' + reason: ' has been kicked by for ">View player info">[Info]' kickall: player: - noReason: '&6You have been kicked' - reason: '&6You have been kicked for &4[reason]' + noReason: 'You have been kicked' + reason: 'You have been kicked for ' notify: - noReason: 'All players have been kicked by [actor]' - reason: 'All players have been kicked by [actor] for &4[reason]' + noReason: 'All players have been kicked by ' + reason: 'All players have been kicked by for ' ban: player: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' + disallowed: 'You are banned from this server\n \nReason: \nBanned by: \nDate: \n \nAppeal at ' + kick: 'You have been banned\n \nReason: \nBanned by: ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[player] has been permanently banned by [actor] for &4[reason]' + notify: ' has been permanently banned by for ">View player info">[Info] ">Unban player">[Unban]' error: - exists: '&c[player] is already banned' - cooldown: '&cThis player was banned too recently, try again later' + exists: ' is already banned' + cooldown: 'This player was banned too recently, try again later' banall: - notify: '&6[player] will be permanently banned by [actor] for &4[reason]' + notify: ' will be permanently banned by for ' tempban: player: - disallowed: '&6You have been temporarily banned from this server for &4[reason] \n&6It expires in [expires]' - kick: '&6You have been temporarily banned for &4[reason]' + disallowed: 'You are temporarily banned from this server\n \nReason: \nBanned by: \nExpires: \nDate: \n \nAppeal at ' + kick: 'You have been temporarily banned\n \nReason: \nBanned by: \nExpires: ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[player] has been temporarily banned for [expires] by [actor] for &4[reason]' + notify: ' has been temporarily banned for by for ">View player info">[Info] ">Unban player">[Unban]' tempbanall: - notify: '&6[player] will be temporarily banned for [expires] by [actor] for &4[reason]' + notify: ' will be temporarily banned for by for ' unban: - notify: '&6[player] has been unbanned by [actor]' + notify: ' has been unbanned by ' error: - noExists: '&c[player] is not banned' - notOwn: '&c[player] was not banned by you, unable to unban' + noExists: ' is not banned' + notOwn: ' was not banned by you, unable to unban' unbanall: - notify: '&6[player] will be unbanned by [actor]' + notify: ' will be unbanned by ' mute: player: - blocked: '&cYou may not use the [command] command whilst muted!' - disallowed: '&6You have been permanently muted for &4[reason] &6by [actor]' - broadcast: '&4[Muted] [player]&7 [message]' - notify: '&6[player] has been permanently muted by [actor] for &4[reason]' + blocked: 'You may not use the command whilst muted!' + disallowed: 'You have been permanently muted for by ' + broadcast: '[Muted] ' + notify: ' has been permanently muted by for ">View player info">[Info] ">Unmute player">[Unmute]' error: - exists: '&c[player] is already muted' - cooldown: '&cThis player was muted too recently, try again later' + exists: ' is already muted' + cooldown: 'This player was muted too recently, try again later' muteip: ip: - disallowed: '&6You have been permanently muted for &4[reason] &6by [actor]' - broadcast: '&4[Muted] [player]&7 [message]' - notify: '&6[ip] ([players]) have been permanently muted by [actor] for &4[reason]' + disallowed: 'You have been permanently muted for by ' + broadcast: '[Muted] ' + notify: ' () have been permanently muted by for ' error: - exists: '&c[ip] is already muted' + exists: ' is already muted' muteall: - notify: '&6[player] will be permanently muted by [actor] for &4[reason]' + notify: ' will be permanently muted by for ' tempmute: player: - disallowed: '&6You have been temporarily muted for &4[reason] &6by [actor] which expires in [expires]' - disallowedOnline: '&6You have been temporarily muted for &4[reason] &6by [actor] which expires in [expires] (online time)' - notify: '&6[player] has been temporarily muted for [expires] by [actor] for &4[reason]' - notifyOnline: '&6[player] has been temporarily muted for [expires] (online time) by [actor] for &4[reason]' + disallowed: 'You have been temporarily muted for by which expires in ' + disallowedOnline: 'You have been temporarily muted for by which expires in (online time)' + notify: ' has been temporarily muted for by for ">View player info">[Info] ">Unmute player">[Unmute]' + notifyOnline: ' has been temporarily muted for (online time) by for ' error: - exists: '&c[player] is already muted' + exists: ' is already muted' tempmuteip: ip: - disallowed: '&6You have been temporarily muted for &4[reason] &6by [actor] which expires in [expires]' - notify: '&6[ip] ([players]) have been temporarily muted for [expires] by [actor] for &4[reason]' + disallowed: 'You have been temporarily muted for by which expires in ' + notify: ' () have been temporarily muted for by for ' error: - exists: '&c[ip] is already muted' + exists: ' is already muted' tempmuteall: - notify: '&6[player] will be temporarily muted for [expires] by [actor] for &4[reason]' + notify: ' will be temporarily muted for by for ' unmute: - notify: '&6[player] has been unmuted by [actor]' - player: '&6You have been unmuted by [actor]' + notify: ' has been unmuted by ' + player: 'You have been unmuted by ' error: - noExists: '&c[player] is not muted' - notOwn: '&c[player] was not muted by you, unable to unmute' + noExists: ' is not muted' + notOwn: ' was not muted by you, unable to unmute' unmuteip: - notify: '&6[ip] has been unmuted by [actor]' + notify: ' has been unmuted by ' error: - noExists: '&c[ip] is not muted' - notOwn: '&c[ip] was not muted by you, unable to unmute' + noExists: ' is not muted' + notOwn: ' was not muted by you, unable to unmute' unmuteall: - notify: '&6[player] will be unmuted by [actor]' + notify: ' will be unmuted by ' banname: name: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' + disallowed: 'You have been banned from this server for ' + kick: 'You have been banned permanently for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6Name [name] has been permanently banned by [actor] for &4[reason]' + notify: 'Name has been permanently banned by for ' error: - exists: '&cName [name] is already banned' + exists: 'Name is already banned' tempbanname: name: - disallowed: '&6You have been banned from this server for &4[reason] \n&6It expires in [expires]' - kick: '&6You have been temporarily banned for &4[reason]' + disallowed: 'You have been banned from this server for \nIt expires in ' + kick: 'You have been temporarily banned for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6Name [name] has been temporarily banned for [expires] by [actor] for &4[reason]' + notify: 'Name has been temporarily banned for by for ' unbanname: - notify: '&6Name [name] has been unbanned by [actor]' + notify: 'Name has been unbanned by ' error: - noExists: '&cName [name] is not banned' + noExists: 'Name is not banned' banip: ip: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' + disallowed: 'You have been banned from this server for ' + kick: 'You have been banned permanently for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[ip] ([players]) has been permanently banned by [actor] for &4[reason]' + notify: ' () has been permanently banned by for ' error: - exists: '&c[ip] is already banned' - cooldown: '&cThis ip was banned too recently, try again later' + exists: ' is already banned' + cooldown: 'This ip was banned too recently, try again later' baniprange: error: - invalid: '&cInvalid range, please use cidr notation 192.168.0.1/16 or wildcard 192.168.*.*' - minMax: '&cRange must be lowest to highest' - exists: '&cA ban containing those ranges already exists' + invalid: 'Invalid range, please use cidr notation 192.168.0.1/16 or wildcard 192.168.*.*' + minMax: 'Range must be lowest to highest' + exists: 'A ban containing those ranges already exists' ip: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' + disallowed: 'You have been banned from this server for ' + kick: 'You have been banned permanently for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[from] - [to] have been banned by [actor]' + notify: ' - have been banned by ' tempbaniprange: - notify: '&6[from] - [to] has been temporarily banned for [expires] by [actor]' + notify: ' - has been temporarily banned for by ' ip: - disallowed: '&6You have been banned from this server for &4[reason] \n&6It expires in [expires]' - kick: '&6You have been temporarily banned for [expires] by [actor] for &4[reason]' + disallowed: 'You have been banned from this server for \nIt expires in ' + kick: 'You have been temporarily banned for by for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' unbaniprange: - notify: '&6[from] - [to] has been unbanned by [actor]' + notify: ' - has been unbanned by ' banipall: - notify: '&6[ip] will be permanently banned by [actor] for &4[reason]' + notify: ' will be permanently banned by for ' tempbanip: ip: - disallowed: '&6You have been banned from this server for &4[reason] \n&6It expires in [expires]' - kick: '&6You have been temporarily banned for &4[reason]' + disallowed: 'You have been banned from this server for \nIt expires in ' + kick: 'You have been temporarily banned for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[ip] ([players]) has been temporarily banned for [expires] by [actor] for &4[reason]' + notify: ' () has been temporarily banned for by for ' tempbanipall: - notify: '&6[ip] will be temporarily banned for [expires] by [actor] for &4[reason]' + notify: ' will be temporarily banned for by for ' unbanip: - notify: '&6[ip] has been unbanned by [actor]' + notify: ' has been unbanned by ' error: - noExists: '&c[ip] is not banned' - notOwn: '&c[ip] was not banned by you, unable to unban' + noExists: ' is not banned' + notOwn: ' was not banned by you, unable to unban' unbanipall: - notify: '&6[ip] will be unbanned by [actor]' + notify: ' will be unbanned by ' warn: player: - warned: '&6You have been warned by [actor] for &4[reason]' + warned: 'You have been warned by for ' disallowed: - header: '&cYou may not speak until you have accepted your most recent warning. Please type the following:' - reason: '&6[reason]' - removed: '&aThank you for your understanding, you may now speak again' - notify: '&6[player] has been warned by [actor] for &4[reason]' + header: 'You may not speak until you have accepted your most recent warning. Please type the following:' + reason: '' + removed: 'Thank you for your understanding, you may now speak again' + notify: ' has been warned by for ">View player info">[Info]' error: - cooldown: '&cThis player was warned too recently, try again later' + cooldown: 'This player was warned too recently, try again later' tempwarn: player: - warned: '&6You have been warned for [expires] by [actor] for &4[reason]' - notify: '&6[player] has been warned for [expires] by [actor] for &4[reason]' + warned: 'You have been warned for by for ' + notify: ' has been warned for by for ">View player info">[Info]' dwarn: player: - notify: '&6Your most recent warning has been deleted by &4[actor]' - notify: '&cThe most recent warning for [player] has been deleted' + notify: 'Your most recent warning has been deleted by ' + notify: 'The most recent warning for has been deleted' error: - noWarnings: '&c[player] has no warnings to delete' + noWarnings: ' has no warnings to delete' bmclear: - notify: '&c[player] has had their [type] cleared' + notify: ' has had their cleared' error: - invalid: '&cInvalid type, please choose between banrecords, muterecords, kicks, notes or warnings' + invalid: 'Invalid type, please choose between banrecords, muterecords, kicks, notes or warnings' bmutils: missingplayers: - notify: '&c[amount] missing players added' - noneFound: '&a0 missing players found' - found: '&c[amount] missing player data found. Fixing...' + notify: ' missing players added' + noneFound: '0 missing players found' + found: ' missing player data found. Fixing...' error: - failedLookup: '&cFailed to lookup player [uuid], check server logs' - complete: '&a[amount] players resolved, please restart your server for failed punishments to take affect' + failedLookup: 'Failed to lookup player , check server logs' + complete: ' players resolved, please restart your server for failed punishments to take affect' duplicates: lookup: - notFound: '&aNo duplicate player names found' + notFound: 'No duplicate player names found' error: - invalidName: '&cInvalid name, must be 16 characters or less and contain only letters, numbers and an underscore' - nameExists: '&cA player with that name already exists' - success: '&aPlayer name set to [player] successfully' + invalidName: 'Invalid name, must be 16 characters or less and contain only letters, numbers and an underscore' + nameExists: 'A player with that name already exists' + success: 'Player name set to successfully' bmrollback: - notify: '&c[player] has had their [type] actions undone' + notify: ' has had their actions undone' error: - invalid: '&cInvalid type [type], please choose between [types]' + invalid: 'Invalid type , please choose between ' sync: player: - started: '&aStarting force [type] synchronisation' - finished: '&aForced [type] synchronisation complete' + started: 'Starting force synchronisation' + finished: 'Forced synchronisation complete' update: - notify: '&6[BanManager] &aAn update is available' + notify: '[BanManager] An update is available' notes: - header: '&6[player] has the following notes:' - joinAmount: '&6[player] has &e[amount] &6notes, click to view them' - note: '&6[[player]] &e[message] - &e[created]' - playerNote: '&a[[player]] &6[[actor]] &e[message] - &e[created]' + header: ' has the following notes:' + joinAmount: '"> has notes, click to view them' + note: '[] - ' + playerNote: '[] [] - ' dateTimeFormat: 'dd-MM-yyyy' - notify: '[player] has a new note attached by [actor]: [message]' + notify: ' has a new note attached by : ' error: - noNotes: '&c[player] has no notes' - noOnlineNotes: '&cNo online players have notes' + noNotes: ' has no notes' + noOnlineNotes: 'No online players have notes' report: - notify: '&6[player] has been reported by [actor] for &4[reason]' + notify: ' has been reported by for ' error: - cooldown: '&cThis player was reported too recently, try again later' + cooldown: 'This player was reported too recently, try again later' assign: - player: '&aReport [id] assigned to [player]' - notify: '&aYou have been assigned report [id] by [actor]' + player: 'Report assigned to ' + notify: 'You have been assigned report by ' unassign: - player: '&aReport [id] unassigned' + player: 'Report unassigned' close: notify: - closed: '&aReport [id] closed by [actor]' - command: '&aReport [id] closed by [actor] with [command]' - comment: '&aReport [id] closed by [actor] with [comment]' - dispatch: 'Executing command [command]' + closed: 'Report closed by ' + command: 'Report closed by with ' + comment: 'Report closed by with ' + dispatch: 'Executing command ' list: - noResults: '&cNo reports found' + noResults: 'No reports found' error: - invalidState: '&cReport state [state] not found' + invalidState: 'Report state not found' row: dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - header: '&e-- Reports ([count]) -- Page ([page]/[maxPage])' - all: '&7#[id] &e[[state]] &6- [created] - [player]' + header: '-- Reports () -- Page (/)' + all: '">Click to view details"># [] - - ' tp: error: - notFound: '&cReport not found' - worldNotFound: '&cWorld [world] could not be found' - invalidId: '&c[id] is not a valid report id' + notFound: 'Report not found' + worldNotFound: 'World could not be found' + invalidId: ' is not a valid report id' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' notify: - report: '&7#[id] &6[actor] reported [player] for &4[reason]&6 at [created]' - location: '[world] - [x], [y], [z]' + report: '# reported for at ' + location: ' - , , ' info: error: - notFound: '&cReport not found' - invalidId: '&c[id] is not a valid report id' + notFound: 'Report not found' + invalidId: ' is not a valid report id' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' notify: - report: '&7#[id] &6[actor] reported [player] for &4[reason]&6 at [created]' - location: '[world] - [x], [y], [z]' + report: '# reported for at ' + location: ' - , , ' + actions: + assign: '">Assign to yourself">[Assign]' + close: '">Close this report">[Close]' + tp: '">Teleport to location">[TP]' + feedback: + assigned: 'Your report # has been assigned to ' + closed: 'Your report # has been closed by ' addnoteall: - notify: '&c[player] will have a new attached by [actor]: [message]' + notify: ' will have a new attached by : ' banlist: - header: '&6There are [bans] [type] bans:' + header: 'There are bans:' + row: + player: '">Click for info"> - ' + ip: ' - ' + iprange: ' - - ' bmactivity: row: - all: '&a[&f[type]&a] &6[player]&f - &6[actor]&f - &e[created]' - player: '&a[&f[type]&a] &6[player]&f - &e[created]' + all: '[] - - ' + player: '[] - ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' - noResults: '&cNo results found' + noResults: 'No results found' bmdelete: - notify: '&a[rows] rows deleted' + notify: ' rows deleted' error: - invalid: '&cInvalid type, please choose between banrecords, muterecords, kicks, notes or warnings' - invalidId: '&c[id] is not a valid number' + invalid: 'Invalid type, please choose between banrecords, muterecords, kicks, notes or warnings' + invalidId: ' is not a valid number' denyalts: player: - disallowed: '&cThe IP address you are joining from is linked to a banned player' + disallowed: 'The IP address you are joining from is linked to a banned player' reasons: - row: '[hashtag] = [reason]' + row: ' = ' + + dashboard: + header: ' Staff Dashboard ' + activeBans: 'Active Bans: ' + activeMutes: 'Active Mutes: ' + openReports: 'Open Reports: View reports">[View]' + recentActivity: 'Recent Activity (24h): ' + footer: ' ' diff --git a/e2e/platforms/bungee/configs/banmanager/notifications.yml b/e2e/platforms/bungee/configs/banmanager/notifications.yml new file mode 100644 index 000000000..75b1fb646 --- /dev/null +++ b/e2e/platforms/bungee/configs/banmanager/notifications.yml @@ -0,0 +1,81 @@ +# Notifications Configuration +# Controls how punishment notifications are delivered to staff and players +# +# Each notification event can specify delivery channels: +# chat: true/false - Send via chat message (default: true) +# actionbar: true/false - Send via action bar (disappears after a few seconds) +# title: true/false - Send via title/subtitle overlay +# sound: '' - Sound to play (empty to disable). Use Minecraft sound names e.g. entity.experience_orb.pickup +# +# Title settings (only used when title: true): +# titleFadeIn: ticks for fade in (20 ticks = 1 second) +# titleStay: ticks to stay on screen +# titleFadeOut: ticks for fade out +# +# Sound settings: +# soundVolume: 0.0 - 1.0 +# soundPitch: 0.0 - 2.0 +# +# Platform notes: +# - BungeeCord: title, showTitle and playSound are not supported (ignored silently) +# - Sponge API7: playSound is not supported (ignored silently) +# - All other platforms (Bukkit/Paper, Velocity, Fabric, Sponge API8+) support all channels + +staff: + ban: + chat: true + actionbar: false + title: false + sound: 'entity.experience_orb.pickup' + soundVolume: 1.0 + soundPitch: 1.0 + tempban: + chat: true + actionbar: false + title: false + sound: 'entity.experience_orb.pickup' + soundVolume: 1.0 + soundPitch: 1.0 + mute: + chat: true + actionbar: false + title: false + sound: '' + soundVolume: 1.0 + soundPitch: 1.0 + tempmute: + chat: true + actionbar: false + title: false + sound: '' + soundVolume: 1.0 + soundPitch: 1.0 + warn: + chat: true + actionbar: false + title: false + sound: 'entity.experience_orb.pickup' + soundVolume: 1.0 + soundPitch: 1.0 + report: + chat: true + actionbar: false + title: false + sound: 'block.note_block.pling' + soundVolume: 1.0 + soundPitch: 1.0 + duplicateIp: + chat: true + actionbar: false + title: false + sound: '' + soundVolume: 1.0 + soundPitch: 1.0 + +player: + muted: + actionbar: true + warned: + sound: 'entity.villager.no' + soundVolume: 1.0 + soundPitch: 1.0 diff --git a/e2e/platforms/fabric/configs/messages.yml b/e2e/platforms/fabric/configs/messages.yml index 09382e935..ce8bb1a82 100644 --- a/e2e/platforms/fabric/configs/messages.yml +++ b/e2e/platforms/fabric/configs/messages.yml @@ -1,20 +1,22 @@ -# Variables -# [reason] = Ban/Mute reason -# [player] = The name of the player -# [ip] = The banned ip -# [actor] = Who banned/muted -# [expires] = How long until the ban/mute ends +# Message templates use MiniMessage formatting: https://docs.advntr.dev/minimessage/format.html +# Placeholders use angle brackets, e.g. , , , , + +tokens: + appeal_url: 'https://yourdomain.com/appeal' + server_name: 'My Server' + discord_url: 'https://discord.gg/example' + rules_url: 'https://yourdomain.com/rules' messages: - duplicateIP: '&cWarning: [player] has the same IP as the following banned players:\n&6[players]' - duplicateIPAlts: '&cWarning: [player] has the same IP as the following players:\n&6[players]' - configReloaded: '�ff00Configuration &#ff5733reloaded &asuccessfully!' + duplicateIP: 'Warning: has the same IP as the following banned players:\n' + duplicateIPAlts: 'Warning: has the same IP as the following players:\n' + configReloaded: 'Configuration reloaded successfully!' deniedNotify: - player: '&cWarning: [player] attempted to join the server but was denied due to &4[reason]' - ip: '&cWarning: [ip] attempted to join the server but was denied due to &4[reason]' - deniedMaxIp: '&cToo many players with your ip address online' - deniedMultiaccounts: '&cToo many players with your ip address logged in recently' - deniedCountry: '&cYou may not connect from your region' + player: 'Warning: attempted to join the server but was denied due to ' + ip: 'Warning: attempted to join the server but was denied due to ' + deniedMaxIp: 'Too many players with your ip address online' + deniedMultiaccounts: 'Too many players with your ip address logged in recently' + deniedCountry: 'You may not connect from your region' time: now: 'now' @@ -34,408 +36,440 @@ messages: seconds: 'seconds' never: 'never' error: - invalid: '&cYour time length is invalid' - limit: '&cYou cannot perform this action for that length of time' + invalid: 'Your time length is invalid' + limit: 'You cannot perform this action for that length of time' none: 'none' # General command text sender: error: - notFound: '&c[player] not found, are you sure they exist?' - offline: '&c[player] is offline' - noSelf: '&cYou cannot perform that action on yourself!' - exception: '&cAn error occured whilst attempting to perform this command. Please check the console for further details.' - invalidIp: '&cInvalid IP address, expecting w.x.y.z format' - offlinePermission: '&cYou are not allowed to perform this action on an offline player' - exempt: '&c[player] is exempt from that action' - noPermission: '&cYou do not have permission to perform that action' - invalidReason: '&c[reason] is no valid reason.' + notFound: ' not found, are you sure they exist?' + offline: ' is offline' + noSelf: 'You cannot perform that action on yourself!' + exception: 'An error occured whilst attempting to perform this command. Please check the console for further details.' + invalidIp: 'Invalid IP address, expecting w.x.y.z format' + offlinePermission: 'You are not allowed to perform this action on an offline player' + ambiguousPlayer: 'Multiple players match "". Please use their full name.' + exempt: ' is exempt from that action' + noPermission: 'You do not have permission to perform that action' + noConsole: 'This command cannot be used from console' + invalidReason: ' is no valid reason.' # Commands alts: header: 'Possible alts found:' + entry: '">' + separator: ', ' + + names: + header: 'Known names for :' + row: ' (first: , last: )' + interactive: ' (first: , last: )">">' + separator: ', ' + dateTimeFormat: 'dd-MM-yyyy' + none: 'No name history found' export: error: - inProgress: '&cAn export is already in progress, please wait' + inProgress: 'An export is already in progress, please wait' player: - started: '&aPlayer ban export started' - finished: '&aPlayer ban export finished, file [file] created' + started: 'Player ban export started' + finished: 'Player ban export finished, file created' ip: - started: '&aIP ban export started' - finished: '&aIP ban export finished, file [file] created' + started: 'IP ban export started' + finished: 'IP ban export finished, file created' import: error: - inProgress: '&cAn import is already in progress, please wait' + inProgress: 'An import is already in progress, please wait' player: - started: '&aPlayer ban import started' - finished: '&aPlayer ban import finished' + started: 'Player ban import started' + finished: 'Player ban import finished' ip: - started: '&aIP ban import started' - finished: '&aIP ban import finished' + started: 'IP ban import started' + finished: 'IP ban import finished' advancedban: - started: '&aAdvancedBan import started' - finished: '&aAdvancedBan import finished' + started: 'AdvancedBan import started' + finished: 'AdvancedBan import finished' h2: - started: '&aH2 import started' - finished: '&aH2 import finished, please restart the server' + started: 'H2 import started' + finished: 'H2 import finished, please restart the server' litebans: - started: '&aLiteBans import started' - finished: '&aLiteBans import finished' + started: 'LiteBans import started' + finished: 'LiteBans import finished' info: error: - invalidIndex: '&cInvalid player option used' - indexRequired: '&cMultiple players named [name] found, please select a player by providing an index between 1 and [size], e.g. /bminfo [name] 1' - index: '&7#[index] - &6[name] - &4[uuid]' + invalidIndex: 'Invalid player option used' + indexRequired: 'Multiple players named found, please select a player by providing an index between 1 and , e.g. /bminfo 1' + index: '# - - ' stats: - player: '&6[player] has been banned [bans] times, muted [mutes] times, kicked [kicks] times and warned [warns] - times ([warnPoints] Points), has [notes] notes and been reported [reports] times' - ip: '&6This ip has been banned [bans] times, muted [mutes] times and range banned [rangebans] times' - connection: '&6Their last connection was with [ip] on [lastSeen]' - geoip: 'Country: [country] City: [city]' + player: ' has been banned times, muted times, kicked times and warned + times ( Points), has notes and been reported times' + ip: 'This ip has been banned times, muted times and range banned times' + connection: 'Their last connection was with on ' + geoip: 'Country: City: ' ban: - permanent: '&6Currently banned for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently banned for &4[reason]&6 by [actor] at [created] which expires in [expires]' + permanent: 'Currently banned for by at ' + temporary: 'Currently banned for by at which expires in ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' ipban: - permanent: '&6Currently banned for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently banned for &4[reason]&6 by [actor] at [created] which expires in [expires]' + permanent: 'Currently banned for by at ' + temporary: 'Currently banned for by at which expires in ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' iprangeban: - permanent: '&6[from] - [to] banned for &4[reason]&6 by [actor] at [created]' - temporary: '&6[from] - [to] banned for &4[reason]&6 by [actor] at [created] which expires in [expires]' + permanent: ' - banned for by at ' + temporary: ' - banned for by at which expires in ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' ipmute: - permanent: '&6Currently muted for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently muted for &4[reason]&6 by [actor] at [created] which expires in [expires]' + permanent: 'Currently muted for by at ' + temporary: 'Currently muted for by at which expires in ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' mute: - permanent: '&6Currently muted for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently muted for &4[reason]&6 by [actor] at [created] which expires in [expires]' - temporaryOnline: '&6Currently muted for &4[reason]&6 by [actor] at [created] which expires in [expires] (online time)' - temporaryOnlinePaused: '&6Currently muted for &4[reason]&6 by [actor] at [created] with [remaining] remaining (online time, paused)' + permanent: 'Currently muted for by at ' + temporary: 'Currently muted for by at which expires in ' + temporaryOnline: 'Currently muted for by at which expires in (online time)' + temporaryOnlinePaused: 'Currently muted for by at with remaining (online time, paused)' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' website: - player: 'https://yourdomain.com/player/[uuid]' - ip: 'http://yourdomain.com/index.php?action=viewip&ip=[ip]&server=0' + player: 'https://yourdomain.com/player/' + ip: 'http://yourdomain.com/index.php?action=viewip&ip=&server=0' history: - row: '&7#[id] &a[&f[type]&a] &6[actor]&f [meta] [reason] - &e[created]' + row: '# [] - ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' - noResults: '&cNo results found' + noResults: 'No results found' ips: - row: '&e[ip] - &6[join] - [leave]' + row: ' - - ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' kick: player: - noReason: '&6You have been kicked' - reason: '&6You have been kicked for &4[reason]' + noReason: 'You have been kicked' + reason: 'You have been kicked for ' notify: - noReason: '&6[player] has been kicked by [actor]' - reason: '&6[player] has been kicked by [actor] for &4[reason]' + noReason: ' has been kicked by ">View player info">[Info]' + reason: ' has been kicked by for ">View player info">[Info]' kickall: player: - noReason: '&6You have been kicked' - reason: '&6You have been kicked for &4[reason]' + noReason: 'You have been kicked' + reason: 'You have been kicked for ' notify: - noReason: 'All players have been kicked by [actor]' - reason: 'All players have been kicked by [actor] for &4[reason]' + noReason: 'All players have been kicked by ' + reason: 'All players have been kicked by for ' ban: player: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' + disallowed: 'You are banned from this server\n \nReason: \nBanned by: \nDate: \n \nAppeal at ' + kick: 'You have been banned\n \nReason: \nBanned by: ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[player] has been permanently banned by [actor] for &4[reason]' + notify: ' has been permanently banned by for ">View player info">[Info] ">Unban player">[Unban]' error: - exists: '&c[player] is already banned' - cooldown: '&cThis player was banned too recently, try again later' + exists: ' is already banned' + cooldown: 'This player was banned too recently, try again later' banall: - notify: '&6[player] will be permanently banned by [actor] for &4[reason]' + notify: ' will be permanently banned by for ' tempban: player: - disallowed: '&6You have been temporarily banned from this server for &4[reason] \n&6It expires in [expires]' - kick: '&6You have been temporarily banned for &4[reason]' + disallowed: 'You are temporarily banned from this server\n \nReason: \nBanned by: \nExpires: \nDate: \n \nAppeal at ' + kick: 'You have been temporarily banned\n \nReason: \nBanned by: \nExpires: ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[player] has been temporarily banned for [expires] by [actor] for &4[reason]' + notify: ' has been temporarily banned for by for ">View player info">[Info] ">Unban player">[Unban]' tempbanall: - notify: '&6[player] will be temporarily banned for [expires] by [actor] for &4[reason]' + notify: ' will be temporarily banned for by for ' unban: - notify: '&6[player] has been unbanned by [actor]' + notify: ' has been unbanned by ' error: - noExists: '&c[player] is not banned' - notOwn: '&c[player] was not banned by you, unable to unban' + noExists: ' is not banned' + notOwn: ' was not banned by you, unable to unban' unbanall: - notify: '&6[player] will be unbanned by [actor]' + notify: ' will be unbanned by ' mute: player: - blocked: '&cYou may not use the [command] command whilst muted!' - disallowed: '&6You have been permanently muted for &4[reason] &6by [actor]' - broadcast: '&4[Muted] [player]&7 [message]' - notify: '&6[player] has been permanently muted by [actor] for &4[reason]' + blocked: 'You may not use the command whilst muted!' + disallowed: 'You have been permanently muted for by ' + broadcast: '[Muted] ' + notify: ' has been permanently muted by for ">View player info">[Info] ">Unmute player">[Unmute]' error: - exists: '&c[player] is already muted' - cooldown: '&cThis player was muted too recently, try again later' + exists: ' is already muted' + cooldown: 'This player was muted too recently, try again later' muteip: ip: - disallowed: '&6You have been permanently muted for &4[reason] &6by [actor]' - broadcast: '&4[Muted] [player]&7 [message]' - notify: '&6[ip] ([players]) have been permanently muted by [actor] for &4[reason]' + disallowed: 'You have been permanently muted for by ' + broadcast: '[Muted] ' + notify: ' () have been permanently muted by for ' error: - exists: '&c[ip] is already muted' + exists: ' is already muted' muteall: - notify: '&6[player] will be permanently muted by [actor] for &4[reason]' + notify: ' will be permanently muted by for ' tempmute: player: - disallowed: '&6You have been temporarily muted for &4[reason] &6by [actor] which expires in [expires]' - disallowedOnline: '&6You have been temporarily muted for &4[reason] &6by [actor] which expires in [expires] (online time)' - notify: '&6[player] has been temporarily muted for [expires] by [actor] for &4[reason]' - notifyOnline: '&6[player] has been temporarily muted for [expires] (online time) by [actor] for &4[reason]' + disallowed: 'You have been temporarily muted for by which expires in ' + disallowedOnline: 'You have been temporarily muted for by which expires in (online time)' + notify: ' has been temporarily muted for by for ">View player info">[Info] ">Unmute player">[Unmute]' + notifyOnline: ' has been temporarily muted for (online time) by for ' error: - exists: '&c[player] is already muted' + exists: ' is already muted' tempmuteip: ip: - disallowed: '&6You have been temporarily muted for &4[reason] &6by [actor] which expires in [expires]' - notify: '&6[ip] ([players]) have been temporarily muted for [expires] by [actor] for &4[reason]' + disallowed: 'You have been temporarily muted for by which expires in ' + notify: ' () have been temporarily muted for by for ' error: - exists: '&c[ip] is already muted' + exists: ' is already muted' tempmuteall: - notify: '&6[player] will be temporarily muted for [expires] by [actor] for &4[reason]' + notify: ' will be temporarily muted for by for ' unmute: - notify: '&6[player] has been unmuted by [actor]' - player: '&6You have been unmuted by [actor]' + notify: ' has been unmuted by ' + player: 'You have been unmuted by ' error: - noExists: '&c[player] is not muted' - notOwn: '&c[player] was not muted by you, unable to unmute' + noExists: ' is not muted' + notOwn: ' was not muted by you, unable to unmute' unmuteip: - notify: '&6[ip] has been unmuted by [actor]' + notify: ' has been unmuted by ' error: - noExists: '&c[ip] is not muted' - notOwn: '&c[ip] was not muted by you, unable to unmute' + noExists: ' is not muted' + notOwn: ' was not muted by you, unable to unmute' unmuteall: - notify: '&6[player] will be unmuted by [actor]' + notify: ' will be unmuted by ' banname: name: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' + disallowed: 'You have been banned from this server for ' + kick: 'You have been banned permanently for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6Name [name] has been permanently banned by [actor] for &4[reason]' + notify: 'Name has been permanently banned by for ' error: - exists: '&cName [name] is already banned' + exists: 'Name is already banned' tempbanname: name: - disallowed: '&6You have been banned from this server for &4[reason] \n&6It expires in [expires]' - kick: '&6You have been temporarily banned for &4[reason]' + disallowed: 'You have been banned from this server for \nIt expires in ' + kick: 'You have been temporarily banned for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6Name [name] has been temporarily banned for [expires] by [actor] for &4[reason]' + notify: 'Name has been temporarily banned for by for ' unbanname: - notify: '&6Name [name] has been unbanned by [actor]' + notify: 'Name has been unbanned by ' error: - noExists: '&cName [name] is not banned' + noExists: 'Name is not banned' banip: ip: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' + disallowed: 'You have been banned from this server for ' + kick: 'You have been banned permanently for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[ip] ([players]) has been permanently banned by [actor] for &4[reason]' + notify: ' () has been permanently banned by for ' error: - exists: '&c[ip] is already banned' - cooldown: '&cThis ip was banned too recently, try again later' + exists: ' is already banned' + cooldown: 'This ip was banned too recently, try again later' baniprange: error: - invalid: '&cInvalid range, please use cidr notation 192.168.0.1/16 or wildcard 192.168.*.*' - minMax: '&cRange must be lowest to highest' - exists: '&cA ban containing those ranges already exists' + invalid: 'Invalid range, please use cidr notation 192.168.0.1/16 or wildcard 192.168.*.*' + minMax: 'Range must be lowest to highest' + exists: 'A ban containing those ranges already exists' ip: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' + disallowed: 'You have been banned from this server for ' + kick: 'You have been banned permanently for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[from] - [to] have been banned by [actor]' + notify: ' - have been banned by ' tempbaniprange: - notify: '&6[from] - [to] has been temporarily banned for [expires] by [actor]' + notify: ' - has been temporarily banned for by ' ip: - disallowed: '&6You have been banned from this server for &4[reason] \n&6It expires in [expires]' - kick: '&6You have been temporarily banned for [expires] by [actor] for &4[reason]' + disallowed: 'You have been banned from this server for \nIt expires in ' + kick: 'You have been temporarily banned for by for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' unbaniprange: - notify: '&6[from] - [to] has been unbanned by [actor]' + notify: ' - has been unbanned by ' banipall: - notify: '&6[ip] will be permanently banned by [actor] for &4[reason]' + notify: ' will be permanently banned by for ' tempbanip: ip: - disallowed: '&6You have been banned from this server for &4[reason] \n&6It expires in [expires]' - kick: '&6You have been temporarily banned for &4[reason]' + disallowed: 'You have been banned from this server for \nIt expires in ' + kick: 'You have been temporarily banned for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[ip] ([players]) has been temporarily banned for [expires] by [actor] for &4[reason]' + notify: ' () has been temporarily banned for by for ' tempbanipall: - notify: '&6[ip] will be temporarily banned for [expires] by [actor] for &4[reason]' + notify: ' will be temporarily banned for by for ' unbanip: - notify: '&6[ip] has been unbanned by [actor]' + notify: ' has been unbanned by ' error: - noExists: '&c[ip] is not banned' - notOwn: '&c[ip] was not banned by you, unable to unban' + noExists: ' is not banned' + notOwn: ' was not banned by you, unable to unban' unbanipall: - notify: '&6[ip] will be unbanned by [actor]' + notify: ' will be unbanned by ' warn: player: - warned: '&6You have been warned by [actor] for &4[reason]' + warned: 'You have been warned by for ' disallowed: - header: '&cYou may not speak until you have accepted your most recent warning. Please type the following:' - reason: '&6[reason]' - removed: '&aThank you for your understanding, you may now speak again' - notify: '&6[player] has been warned by [actor] for &4[reason]' + header: 'You may not speak until you have accepted your most recent warning. Please type the following:' + reason: '' + removed: 'Thank you for your understanding, you may now speak again' + notify: ' has been warned by for ">View player info">[Info]' error: - cooldown: '&cThis player was warned too recently, try again later' + cooldown: 'This player was warned too recently, try again later' tempwarn: player: - warned: '&6You have been warned for [expires] by [actor] for &4[reason]' - notify: '&6[player] has been warned for [expires] by [actor] for &4[reason]' + warned: 'You have been warned for by for ' + notify: ' has been warned for by for ">View player info">[Info]' dwarn: player: - notify: '&6Your most recent warning has been deleted by &4[actor]' - notify: '&cThe most recent warning for [player] has been deleted' + notify: 'Your most recent warning has been deleted by ' + notify: 'The most recent warning for has been deleted' error: - noWarnings: '&c[player] has no warnings to delete' + noWarnings: ' has no warnings to delete' bmclear: - notify: '&c[player] has had their [type] cleared' + notify: ' has had their cleared' error: - invalid: '&cInvalid type, please choose between banrecords, muterecords, kicks, notes or warnings' + invalid: 'Invalid type, please choose between banrecords, muterecords, kicks, notes or warnings' bmutils: missingplayers: - notify: '&c[amount] missing players added' - noneFound: '&a0 missing players found' - found: '&c[amount] missing player data found. Fixing...' + notify: ' missing players added' + noneFound: '0 missing players found' + found: ' missing player data found. Fixing...' error: - failedLookup: '&cFailed to lookup player [uuid], check server logs' - complete: '&a[amount] players resolved, please restart your server for failed punishments to take affect' + failedLookup: 'Failed to lookup player , check server logs' + complete: ' players resolved, please restart your server for failed punishments to take affect' duplicates: lookup: - notFound: '&aNo duplicate player names found' + notFound: 'No duplicate player names found' error: - invalidName: '&cInvalid name, must be 16 characters or less and contain only letters, numbers and an underscore' - nameExists: '&cA player with that name already exists' - success: '&aPlayer name set to [player] successfully' + invalidName: 'Invalid name, must be 16 characters or less and contain only letters, numbers and an underscore' + nameExists: 'A player with that name already exists' + success: 'Player name set to successfully' bmrollback: - notify: '&c[player] has had their [type] actions undone' + notify: ' has had their actions undone' error: - invalid: '&cInvalid type [type], please choose between [types]' + invalid: 'Invalid type , please choose between ' sync: player: - started: '&aStarting force [type] synchronisation' - finished: '&aForced [type] synchronisation complete' + started: 'Starting force synchronisation' + finished: 'Forced synchronisation complete' update: - notify: '&6[BanManager] &aAn update is available' + notify: '[BanManager] An update is available' notes: - header: '&6[player] has the following notes:' - joinAmount: '&6[player] has &e[amount] &6notes, click to view them' - note: '&6[[player]] &e[message] - &e[created]' - playerNote: '&a[[player]] &6[[actor]] &e[message] - &e[created]' + header: ' has the following notes:' + joinAmount: '"> has notes, click to view them' + note: '[] - ' + playerNote: '[] [] - ' dateTimeFormat: 'dd-MM-yyyy' - notify: '[player] has a new note attached by [actor]: [message]' + notify: ' has a new note attached by : ' error: - noNotes: '&c[player] has no notes' - noOnlineNotes: '&cNo online players have notes' + noNotes: ' has no notes' + noOnlineNotes: 'No online players have notes' report: - notify: '&6[player] has been reported by [actor] for &4[reason]' + notify: ' has been reported by for ' error: - cooldown: '&cThis player was reported too recently, try again later' + cooldown: 'This player was reported too recently, try again later' assign: - player: '&aReport [id] assigned to [player]' - notify: '&aYou have been assigned report [id] by [actor]' + player: 'Report assigned to ' + notify: 'You have been assigned report by ' unassign: - player: '&aReport [id] unassigned' + player: 'Report unassigned' close: notify: - closed: '&aReport [id] closed by [actor]' - command: '&aReport [id] closed by [actor] with [command]' - comment: '&aReport [id] closed by [actor] with [comment]' - dispatch: 'Executing command [command]' + closed: 'Report closed by ' + command: 'Report closed by with ' + comment: 'Report closed by with ' + dispatch: 'Executing command ' list: - noResults: '&cNo reports found' + noResults: 'No reports found' error: - invalidState: '&cReport state [state] not found' + invalidState: 'Report state not found' row: dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - header: '&e-- Reports ([count]) -- Page ([page]/[maxPage])' - all: '&7#[id] &e[[state]] &6- [created] - [player]' + header: '-- Reports () -- Page (/)' + all: '">Click to view details"># [] - - ' tp: error: - notFound: '&cReport not found' - worldNotFound: '&cWorld [world] could not be found' - invalidId: '&c[id] is not a valid report id' + notFound: 'Report not found' + worldNotFound: 'World could not be found' + invalidId: ' is not a valid report id' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' notify: - report: '&7#[id] &6[actor] reported [player] for &4[reason]&6 at [created]' - location: '[world] - [x], [y], [z]' + report: '# reported for at ' + location: ' - , , ' info: error: - notFound: '&cReport not found' - invalidId: '&c[id] is not a valid report id' + notFound: 'Report not found' + invalidId: ' is not a valid report id' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' notify: - report: '&7#[id] &6[actor] reported [player] for &4[reason]&6 at [created]' - location: '[world] - [x], [y], [z]' + report: '# reported for at ' + location: ' - , , ' + + actions: + assign: '">Assign to yourself">[Assign]' + close: '">Close this report">[Close]' + tp: '">Teleport to location">[TP]' + feedback: + assigned: 'Your report # has been assigned to ' + closed: 'Your report # has been closed by ' addnoteall: - notify: '&c[player] will have a new attached by [actor]: [message]' + notify: ' will have a new attached by : ' banlist: - header: '&6There are [bans] [type] bans:' + header: 'There are bans:' + row: + player: '">Click for info"> - ' + ip: ' - ' + iprange: ' - - ' bmactivity: row: - all: '&a[&f[type]&a] &6[player]&f - &6[actor]&f - &e[created]' - player: '&a[&f[type]&a] &6[player]&f - &e[created]' + all: '[] - - ' + player: '[] - ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' - noResults: '&cNo results found' + noResults: 'No results found' bmdelete: - notify: '&a[rows] rows deleted' + notify: ' rows deleted' error: - invalid: '&cInvalid type, please choose between banrecords, muterecords, kicks, notes or warnings' - invalidId: '&c[id] is not a valid number' + invalid: 'Invalid type, please choose between banrecords, muterecords, kicks, notes or warnings' + invalidId: ' is not a valid number' denyalts: player: - disallowed: '&cThe IP address you are joining from is linked to a banned player' + disallowed: 'The IP address you are joining from is linked to a banned player' reasons: - row: '[hashtag] = [reason]' + row: ' = ' + + dashboard: + header: ' Staff Dashboard ' + activeBans: 'Active Bans: ' + activeMutes: 'Active Mutes: ' + openReports: 'Open Reports: View reports">[View]' + recentActivity: 'Recent Activity (24h): ' + footer: ' ' diff --git a/e2e/platforms/fabric/configs/messages/messages_en.yml b/e2e/platforms/fabric/configs/messages/messages_en.yml index 205a94c13..ce8bb1a82 100644 --- a/e2e/platforms/fabric/configs/messages/messages_en.yml +++ b/e2e/platforms/fabric/configs/messages/messages_en.yml @@ -1,20 +1,22 @@ -# Variables -# [reason] = Ban/Mute reason -# [player] = The name of the player -# [ip] = The banned ip -# [actor] = Who banned/muted -# [expires] = How long until the ban/mute ends +# Message templates use MiniMessage formatting: https://docs.advntr.dev/minimessage/format.html +# Placeholders use angle brackets, e.g. , , , , + +tokens: + appeal_url: 'https://yourdomain.com/appeal' + server_name: 'My Server' + discord_url: 'https://discord.gg/example' + rules_url: 'https://yourdomain.com/rules' messages: - duplicateIP: '&cWarning: [player] has the same IP as the following banned players:\n&6[players]' - duplicateIPAlts: '&cWarning: [player] has the same IP as the following players:\n&6[players]' - configReloaded: '&aConfiguration reloaded successfully!' + duplicateIP: 'Warning: has the same IP as the following banned players:\n' + duplicateIPAlts: 'Warning: has the same IP as the following players:\n' + configReloaded: 'Configuration reloaded successfully!' deniedNotify: - player: '&cWarning: [player] attempted to join the server but was denied due to &4[reason]' - ip: '&cWarning: [ip] attempted to join the server but was denied due to &4[reason]' - deniedMaxIp: '&cToo many players with your ip address online' - deniedMultiaccounts: '&cToo many players with your ip address logged in recently' - deniedCountry: '&cYou may not connect from your region' + player: 'Warning: attempted to join the server but was denied due to ' + ip: 'Warning: attempted to join the server but was denied due to ' + deniedMaxIp: 'Too many players with your ip address online' + deniedMultiaccounts: 'Too many players with your ip address logged in recently' + deniedCountry: 'You may not connect from your region' time: now: 'now' @@ -34,415 +36,440 @@ messages: seconds: 'seconds' never: 'never' error: - invalid: '&cYour time length is invalid' - limit: '&cYou cannot perform this action for that length of time' + invalid: 'Your time length is invalid' + limit: 'You cannot perform this action for that length of time' none: 'none' # General command text sender: error: - notFound: '&c[player] not found, are you sure they exist?' - offline: '&c[player] is offline' - noSelf: '&cYou cannot perform that action on yourself!' - exception: '&cAn error occured whilst attempting to perform this command. Please check the console for further details.' - invalidIp: '&cInvalid IP address, expecting w.x.y.z format' - offlinePermission: '&cYou are not allowed to perform this action on an offline player' - ambiguousPlayer: '&cMultiple players match "[player]". Please use their full name.' - exempt: '&c[player] is exempt from that action' - noPermission: '&cYou do not have permission to perform that action' - invalidReason: '&c[reason] is no valid reason.' + notFound: ' not found, are you sure they exist?' + offline: ' is offline' + noSelf: 'You cannot perform that action on yourself!' + exception: 'An error occured whilst attempting to perform this command. Please check the console for further details.' + invalidIp: 'Invalid IP address, expecting w.x.y.z format' + offlinePermission: 'You are not allowed to perform this action on an offline player' + ambiguousPlayer: 'Multiple players match "". Please use their full name.' + exempt: ' is exempt from that action' + noPermission: 'You do not have permission to perform that action' + noConsole: 'This command cannot be used from console' + invalidReason: ' is no valid reason.' # Commands alts: header: 'Possible alts found:' + entry: '">' + separator: ', ' names: - header: 'Known names for [player]:' - row: '&e[name] &7(first: [firstSeen], last: [lastSeen])' + header: 'Known names for :' + row: ' (first: , last: )' + interactive: ' (first: , last: )">">' + separator: ', ' dateTimeFormat: 'dd-MM-yyyy' - none: '&7No name history found' + none: 'No name history found' export: error: - inProgress: '&cAn export is already in progress, please wait' + inProgress: 'An export is already in progress, please wait' player: - started: '&aPlayer ban export started' - finished: '&aPlayer ban export finished, file [file] created' + started: 'Player ban export started' + finished: 'Player ban export finished, file created' ip: - started: '&aIP ban export started' - finished: '&aIP ban export finished, file [file] created' + started: 'IP ban export started' + finished: 'IP ban export finished, file created' import: error: - inProgress: '&cAn import is already in progress, please wait' + inProgress: 'An import is already in progress, please wait' player: - started: '&aPlayer ban import started' - finished: '&aPlayer ban import finished' + started: 'Player ban import started' + finished: 'Player ban import finished' ip: - started: '&aIP ban import started' - finished: '&aIP ban import finished' + started: 'IP ban import started' + finished: 'IP ban import finished' advancedban: - started: '&aAdvancedBan import started' - finished: '&aAdvancedBan import finished' + started: 'AdvancedBan import started' + finished: 'AdvancedBan import finished' h2: - started: '&aH2 import started' - finished: '&aH2 import finished, please restart the server' + started: 'H2 import started' + finished: 'H2 import finished, please restart the server' litebans: - started: '&aLiteBans import started' - finished: '&aLiteBans import finished' + started: 'LiteBans import started' + finished: 'LiteBans import finished' info: error: - invalidIndex: '&cInvalid player option used' - indexRequired: '&cMultiple players named [name] found, please select a player by providing an index between 1 and [size], e.g. /bminfo [name] 1' - index: '&7#[index] - &6[name] - &4[uuid]' + invalidIndex: 'Invalid player option used' + indexRequired: 'Multiple players named found, please select a player by providing an index between 1 and , e.g. /bminfo 1' + index: '# - - ' stats: - player: '&6[player] has been banned [bans] times, muted [mutes] times, kicked [kicks] times and warned [warns] - times ([warnPoints] Points), has [notes] notes and been reported [reports] times' - ip: '&6This ip has been banned [bans] times, muted [mutes] times and range banned [rangebans] times' - connection: '&6Their last connection was with [ip] on [lastSeen]' - geoip: 'Country: [country] City: [city]' + player: ' has been banned times, muted times, kicked times and warned + times ( Points), has notes and been reported times' + ip: 'This ip has been banned times, muted times and range banned times' + connection: 'Their last connection was with on ' + geoip: 'Country: City: ' ban: - permanent: '&6Currently banned for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently banned for &4[reason]&6 by [actor] at [created] which expires in [expires]' + permanent: 'Currently banned for by at ' + temporary: 'Currently banned for by at which expires in ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' ipban: - permanent: '&6Currently banned for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently banned for &4[reason]&6 by [actor] at [created] which expires in [expires]' + permanent: 'Currently banned for by at ' + temporary: 'Currently banned for by at which expires in ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' iprangeban: - permanent: '&6[from] - [to] banned for &4[reason]&6 by [actor] at [created]' - temporary: '&6[from] - [to] banned for &4[reason]&6 by [actor] at [created] which expires in [expires]' + permanent: ' - banned for by at ' + temporary: ' - banned for by at which expires in ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' ipmute: - permanent: '&6Currently muted for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently muted for &4[reason]&6 by [actor] at [created] which expires in [expires]' + permanent: 'Currently muted for by at ' + temporary: 'Currently muted for by at which expires in ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' mute: - permanent: '&6Currently muted for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently muted for &4[reason]&6 by [actor] at [created] which expires in [expires]' - temporaryOnline: '&6Currently muted for &4[reason]&6 by [actor] at [created] which expires in [expires] (online time)' - temporaryOnlinePaused: '&6Currently muted for &4[reason]&6 by [actor] at [created] with [remaining] remaining (online time, paused)' + permanent: 'Currently muted for by at ' + temporary: 'Currently muted for by at which expires in ' + temporaryOnline: 'Currently muted for by at which expires in (online time)' + temporaryOnlinePaused: 'Currently muted for by at with remaining (online time, paused)' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' website: - player: 'https://yourdomain.com/player/[uuid]' - ip: 'http://yourdomain.com/index.php?action=viewip&ip=[ip]&server=0' + player: 'https://yourdomain.com/player/' + ip: 'http://yourdomain.com/index.php?action=viewip&ip=&server=0' history: - row: '&7#[id] &a[&f[type]&a] &6[actor]&f [meta] [reason] - &e[created]' + row: '# [] - ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' - noResults: '&cNo results found' + noResults: 'No results found' ips: - row: '&e[ip] - &6[join] - [leave]' + row: ' - - ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' kick: player: - noReason: '&6You have been kicked' - reason: '&6You have been kicked for &4[reason]' + noReason: 'You have been kicked' + reason: 'You have been kicked for ' notify: - noReason: '&6[player] has been kicked by [actor]' - reason: '&6[player] has been kicked by [actor] for &4[reason]' + noReason: ' has been kicked by ">View player info">[Info]' + reason: ' has been kicked by for ">View player info">[Info]' kickall: player: - noReason: '&6You have been kicked' - reason: '&6You have been kicked for &4[reason]' + noReason: 'You have been kicked' + reason: 'You have been kicked for ' notify: - noReason: 'All players have been kicked by [actor]' - reason: 'All players have been kicked by [actor] for &4[reason]' + noReason: 'All players have been kicked by ' + reason: 'All players have been kicked by for ' ban: player: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' + disallowed: 'You are banned from this server\n \nReason: \nBanned by: \nDate: \n \nAppeal at ' + kick: 'You have been banned\n \nReason: \nBanned by: ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[player] has been permanently banned by [actor] for &4[reason]' + notify: ' has been permanently banned by for ">View player info">[Info] ">Unban player">[Unban]' error: - exists: '&c[player] is already banned' - cooldown: '&cThis player was banned too recently, try again later' + exists: ' is already banned' + cooldown: 'This player was banned too recently, try again later' banall: - notify: '&6[player] will be permanently banned by [actor] for &4[reason]' + notify: ' will be permanently banned by for ' tempban: player: - disallowed: '&6You have been temporarily banned from this server for &4[reason] \n&6It expires in [expires]' - kick: '&6You have been temporarily banned for &4[reason]' + disallowed: 'You are temporarily banned from this server\n \nReason: \nBanned by: \nExpires: \nDate: \n \nAppeal at ' + kick: 'You have been temporarily banned\n \nReason: \nBanned by: \nExpires: ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[player] has been temporarily banned for [expires] by [actor] for &4[reason]' + notify: ' has been temporarily banned for by for ">View player info">[Info] ">Unban player">[Unban]' tempbanall: - notify: '&6[player] will be temporarily banned for [expires] by [actor] for &4[reason]' + notify: ' will be temporarily banned for by for ' unban: - notify: '&6[player] has been unbanned by [actor]' + notify: ' has been unbanned by ' error: - noExists: '&c[player] is not banned' - notOwn: '&c[player] was not banned by you, unable to unban' + noExists: ' is not banned' + notOwn: ' was not banned by you, unable to unban' unbanall: - notify: '&6[player] will be unbanned by [actor]' + notify: ' will be unbanned by ' mute: player: - blocked: '&cYou may not use the [command] command whilst muted!' - disallowed: '&6You have been permanently muted for &4[reason] &6by [actor]' - broadcast: '&4[Muted] [player]&7 [message]' - notify: '&6[player] has been permanently muted by [actor] for &4[reason]' + blocked: 'You may not use the command whilst muted!' + disallowed: 'You have been permanently muted for by ' + broadcast: '[Muted] ' + notify: ' has been permanently muted by for ">View player info">[Info] ">Unmute player">[Unmute]' error: - exists: '&c[player] is already muted' - cooldown: '&cThis player was muted too recently, try again later' + exists: ' is already muted' + cooldown: 'This player was muted too recently, try again later' muteip: ip: - disallowed: '&6You have been permanently muted for &4[reason] &6by [actor]' - broadcast: '&4[Muted] [player]&7 [message]' - notify: '&6[ip] ([players]) have been permanently muted by [actor] for &4[reason]' + disallowed: 'You have been permanently muted for by ' + broadcast: '[Muted] ' + notify: ' () have been permanently muted by for ' error: - exists: '&c[ip] is already muted' + exists: ' is already muted' muteall: - notify: '&6[player] will be permanently muted by [actor] for &4[reason]' + notify: ' will be permanently muted by for ' tempmute: player: - disallowed: '&6You have been temporarily muted for &4[reason] &6by [actor] which expires in [expires]' - disallowedOnline: '&6You have been temporarily muted for &4[reason] &6by [actor] which expires in [expires] (online time)' - notify: '&6[player] has been temporarily muted for [expires] by [actor] for &4[reason]' - notifyOnline: '&6[player] has been temporarily muted for [expires] (online time) by [actor] for &4[reason]' + disallowed: 'You have been temporarily muted for by which expires in ' + disallowedOnline: 'You have been temporarily muted for by which expires in (online time)' + notify: ' has been temporarily muted for by for ">View player info">[Info] ">Unmute player">[Unmute]' + notifyOnline: ' has been temporarily muted for (online time) by for ' error: - exists: '&c[player] is already muted' + exists: ' is already muted' tempmuteip: ip: - disallowed: '&6You have been temporarily muted for &4[reason] &6by [actor] which expires in [expires]' - notify: '&6[ip] ([players]) have been temporarily muted for [expires] by [actor] for &4[reason]' + disallowed: 'You have been temporarily muted for by which expires in ' + notify: ' () have been temporarily muted for by for ' error: - exists: '&c[ip] is already muted' + exists: ' is already muted' tempmuteall: - notify: '&6[player] will be temporarily muted for [expires] by [actor] for &4[reason]' + notify: ' will be temporarily muted for by for ' unmute: - notify: '&6[player] has been unmuted by [actor]' - player: '&6You have been unmuted by [actor]' + notify: ' has been unmuted by ' + player: 'You have been unmuted by ' error: - noExists: '&c[player] is not muted' - notOwn: '&c[player] was not muted by you, unable to unmute' + noExists: ' is not muted' + notOwn: ' was not muted by you, unable to unmute' unmuteip: - notify: '&6[ip] has been unmuted by [actor]' + notify: ' has been unmuted by ' error: - noExists: '&c[ip] is not muted' - notOwn: '&c[ip] was not muted by you, unable to unmute' + noExists: ' is not muted' + notOwn: ' was not muted by you, unable to unmute' unmuteall: - notify: '&6[player] will be unmuted by [actor]' + notify: ' will be unmuted by ' banname: name: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' + disallowed: 'You have been banned from this server for ' + kick: 'You have been banned permanently for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6Name [name] has been permanently banned by [actor] for &4[reason]' + notify: 'Name has been permanently banned by for ' error: - exists: '&cName [name] is already banned' + exists: 'Name is already banned' tempbanname: name: - disallowed: '&6You have been banned from this server for &4[reason] \n&6It expires in [expires]' - kick: '&6You have been temporarily banned for &4[reason]' + disallowed: 'You have been banned from this server for \nIt expires in ' + kick: 'You have been temporarily banned for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6Name [name] has been temporarily banned for [expires] by [actor] for &4[reason]' + notify: 'Name has been temporarily banned for by for ' unbanname: - notify: '&6Name [name] has been unbanned by [actor]' + notify: 'Name has been unbanned by ' error: - noExists: '&cName [name] is not banned' + noExists: 'Name is not banned' banip: ip: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' + disallowed: 'You have been banned from this server for ' + kick: 'You have been banned permanently for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[ip] ([players]) has been permanently banned by [actor] for &4[reason]' + notify: ' () has been permanently banned by for ' error: - exists: '&c[ip] is already banned' - cooldown: '&cThis ip was banned too recently, try again later' + exists: ' is already banned' + cooldown: 'This ip was banned too recently, try again later' baniprange: error: - invalid: '&cInvalid range, please use cidr notation 192.168.0.1/16 or wildcard 192.168.*.*' - minMax: '&cRange must be lowest to highest' - exists: '&cA ban containing those ranges already exists' + invalid: 'Invalid range, please use cidr notation 192.168.0.1/16 or wildcard 192.168.*.*' + minMax: 'Range must be lowest to highest' + exists: 'A ban containing those ranges already exists' ip: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' + disallowed: 'You have been banned from this server for ' + kick: 'You have been banned permanently for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[from] - [to] have been banned by [actor]' + notify: ' - have been banned by ' tempbaniprange: - notify: '&6[from] - [to] has been temporarily banned for [expires] by [actor]' + notify: ' - has been temporarily banned for by ' ip: - disallowed: '&6You have been banned from this server for &4[reason] \n&6It expires in [expires]' - kick: '&6You have been temporarily banned for [expires] by [actor] for &4[reason]' + disallowed: 'You have been banned from this server for \nIt expires in ' + kick: 'You have been temporarily banned for by for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' unbaniprange: - notify: '&6[from] - [to] has been unbanned by [actor]' + notify: ' - has been unbanned by ' banipall: - notify: '&6[ip] will be permanently banned by [actor] for &4[reason]' + notify: ' will be permanently banned by for ' tempbanip: ip: - disallowed: '&6You have been banned from this server for &4[reason] \n&6It expires in [expires]' - kick: '&6You have been temporarily banned for &4[reason]' + disallowed: 'You have been banned from this server for \nIt expires in ' + kick: 'You have been temporarily banned for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[ip] ([players]) has been temporarily banned for [expires] by [actor] for &4[reason]' + notify: ' () has been temporarily banned for by for ' tempbanipall: - notify: '&6[ip] will be temporarily banned for [expires] by [actor] for &4[reason]' + notify: ' will be temporarily banned for by for ' unbanip: - notify: '&6[ip] has been unbanned by [actor]' + notify: ' has been unbanned by ' error: - noExists: '&c[ip] is not banned' - notOwn: '&c[ip] was not banned by you, unable to unban' + noExists: ' is not banned' + notOwn: ' was not banned by you, unable to unban' unbanipall: - notify: '&6[ip] will be unbanned by [actor]' + notify: ' will be unbanned by ' warn: player: - warned: '&6You have been warned by [actor] for &4[reason]' + warned: 'You have been warned by for ' disallowed: - header: '&cYou may not speak until you have accepted your most recent warning. Please type the following:' - reason: '&6[reason]' - removed: '&aThank you for your understanding, you may now speak again' - notify: '&6[player] has been warned by [actor] for &4[reason]' + header: 'You may not speak until you have accepted your most recent warning. Please type the following:' + reason: '' + removed: 'Thank you for your understanding, you may now speak again' + notify: ' has been warned by for ">View player info">[Info]' error: - cooldown: '&cThis player was warned too recently, try again later' + cooldown: 'This player was warned too recently, try again later' tempwarn: player: - warned: '&6You have been warned for [expires] by [actor] for &4[reason]' - notify: '&6[player] has been warned for [expires] by [actor] for &4[reason]' + warned: 'You have been warned for by for ' + notify: ' has been warned for by for ">View player info">[Info]' dwarn: player: - notify: '&6Your most recent warning has been deleted by &4[actor]' - notify: '&cThe most recent warning for [player] has been deleted' + notify: 'Your most recent warning has been deleted by ' + notify: 'The most recent warning for has been deleted' error: - noWarnings: '&c[player] has no warnings to delete' + noWarnings: ' has no warnings to delete' bmclear: - notify: '&c[player] has had their [type] cleared' + notify: ' has had their cleared' error: - invalid: '&cInvalid type, please choose between banrecords, muterecords, kicks, notes or warnings' + invalid: 'Invalid type, please choose between banrecords, muterecords, kicks, notes or warnings' bmutils: missingplayers: - notify: '&c[amount] missing players added' - noneFound: '&a0 missing players found' - found: '&c[amount] missing player data found. Fixing...' + notify: ' missing players added' + noneFound: '0 missing players found' + found: ' missing player data found. Fixing...' error: - failedLookup: '&cFailed to lookup player [uuid], check server logs' - complete: '&a[amount] players resolved, please restart your server for failed punishments to take affect' + failedLookup: 'Failed to lookup player , check server logs' + complete: ' players resolved, please restart your server for failed punishments to take affect' duplicates: lookup: - notFound: '&aNo duplicate player names found' + notFound: 'No duplicate player names found' error: - invalidName: '&cInvalid name, must be 16 characters or less and contain only letters, numbers and an underscore' - nameExists: '&cA player with that name already exists' - success: '&aPlayer name set to [player] successfully' + invalidName: 'Invalid name, must be 16 characters or less and contain only letters, numbers and an underscore' + nameExists: 'A player with that name already exists' + success: 'Player name set to successfully' bmrollback: - notify: '&c[player] has had their [type] actions undone' + notify: ' has had their actions undone' error: - invalid: '&cInvalid type [type], please choose between [types]' + invalid: 'Invalid type , please choose between ' sync: player: - started: '&aStarting force [type] synchronisation' - finished: '&aForced [type] synchronisation complete' + started: 'Starting force synchronisation' + finished: 'Forced synchronisation complete' update: - notify: '&6[BanManager] &aAn update is available' + notify: '[BanManager] An update is available' notes: - header: '&6[player] has the following notes:' - joinAmount: '&6[player] has &e[amount] &6notes, click to view them' - note: '&6[[player]] &e[message] - &e[created]' - playerNote: '&a[[player]] &6[[actor]] &e[message] - &e[created]' + header: ' has the following notes:' + joinAmount: '"> has notes, click to view them' + note: '[] - ' + playerNote: '[] [] - ' dateTimeFormat: 'dd-MM-yyyy' - notify: '[player] has a new note attached by [actor]: [message]' + notify: ' has a new note attached by : ' error: - noNotes: '&c[player] has no notes' - noOnlineNotes: '&cNo online players have notes' + noNotes: ' has no notes' + noOnlineNotes: 'No online players have notes' report: - notify: '&6[player] has been reported by [actor] for &4[reason]' + notify: ' has been reported by for ' error: - cooldown: '&cThis player was reported too recently, try again later' + cooldown: 'This player was reported too recently, try again later' assign: - player: '&aReport [id] assigned to [player]' - notify: '&aYou have been assigned report [id] by [actor]' + player: 'Report assigned to ' + notify: 'You have been assigned report by ' unassign: - player: '&aReport [id] unassigned' + player: 'Report unassigned' close: notify: - closed: '&aReport [id] closed by [actor]' - command: '&aReport [id] closed by [actor] with [command]' - comment: '&aReport [id] closed by [actor] with [comment]' - dispatch: 'Executing command [command]' + closed: 'Report closed by ' + command: 'Report closed by with ' + comment: 'Report closed by with ' + dispatch: 'Executing command ' list: - noResults: '&cNo reports found' + noResults: 'No reports found' error: - invalidState: '&cReport state [state] not found' + invalidState: 'Report state not found' row: dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - header: '&e-- Reports ([count]) -- Page ([page]/[maxPage])' - all: '&7#[id] &e[[state]] &6- [created] - [player]' + header: '-- Reports () -- Page (/)' + all: '">Click to view details"># [] - - ' tp: error: - notFound: '&cReport not found' - worldNotFound: '&cWorld [world] could not be found' - invalidId: '&c[id] is not a valid report id' + notFound: 'Report not found' + worldNotFound: 'World could not be found' + invalidId: ' is not a valid report id' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' notify: - report: '&7#[id] &6[actor] reported [player] for &4[reason]&6 at [created]' - location: '[world] - [x], [y], [z]' + report: '# reported for at ' + location: ' - , , ' info: error: - notFound: '&cReport not found' - invalidId: '&c[id] is not a valid report id' + notFound: 'Report not found' + invalidId: ' is not a valid report id' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' notify: - report: '&7#[id] &6[actor] reported [player] for &4[reason]&6 at [created]' - location: '[world] - [x], [y], [z]' + report: '# reported for at ' + location: ' - , , ' + + actions: + assign: '">Assign to yourself">[Assign]' + close: '">Close this report">[Close]' + tp: '">Teleport to location">[TP]' + feedback: + assigned: 'Your report # has been assigned to ' + closed: 'Your report # has been closed by ' addnoteall: - notify: '&c[player] will have a new attached by [actor]: [message]' + notify: ' will have a new attached by : ' banlist: - header: '&6There are [bans] [type] bans:' + header: 'There are bans:' + row: + player: '">Click for info"> - ' + ip: ' - ' + iprange: ' - - ' bmactivity: row: - all: '&a[&f[type]&a] &6[player]&f - &6[actor]&f - &e[created]' - player: '&a[&f[type]&a] &6[player]&f - &e[created]' + all: '[] - - ' + player: '[] - ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' - noResults: '&cNo results found' + noResults: 'No results found' bmdelete: - notify: '&a[rows] rows deleted' + notify: ' rows deleted' error: - invalid: '&cInvalid type, please choose between banrecords, muterecords, kicks, notes or warnings' - invalidId: '&c[id] is not a valid number' + invalid: 'Invalid type, please choose between banrecords, muterecords, kicks, notes or warnings' + invalidId: ' is not a valid number' denyalts: player: - disallowed: '&cThe IP address you are joining from is linked to a banned player' + disallowed: 'The IP address you are joining from is linked to a banned player' reasons: - row: '[hashtag] = [reason]' + row: ' = ' + + dashboard: + header: ' Staff Dashboard ' + activeBans: 'Active Bans: ' + activeMutes: 'Active Mutes: ' + openReports: 'Open Reports: View reports">[View]' + recentActivity: 'Recent Activity (24h): ' + footer: ' ' diff --git a/e2e/platforms/fabric/configs/notifications.yml b/e2e/platforms/fabric/configs/notifications.yml new file mode 100644 index 000000000..75b1fb646 --- /dev/null +++ b/e2e/platforms/fabric/configs/notifications.yml @@ -0,0 +1,81 @@ +# Notifications Configuration +# Controls how punishment notifications are delivered to staff and players +# +# Each notification event can specify delivery channels: +# chat: true/false - Send via chat message (default: true) +# actionbar: true/false - Send via action bar (disappears after a few seconds) +# title: true/false - Send via title/subtitle overlay +# sound: '' - Sound to play (empty to disable). Use Minecraft sound names e.g. entity.experience_orb.pickup +# +# Title settings (only used when title: true): +# titleFadeIn: ticks for fade in (20 ticks = 1 second) +# titleStay: ticks to stay on screen +# titleFadeOut: ticks for fade out +# +# Sound settings: +# soundVolume: 0.0 - 1.0 +# soundPitch: 0.0 - 2.0 +# +# Platform notes: +# - BungeeCord: title, showTitle and playSound are not supported (ignored silently) +# - Sponge API7: playSound is not supported (ignored silently) +# - All other platforms (Bukkit/Paper, Velocity, Fabric, Sponge API8+) support all channels + +staff: + ban: + chat: true + actionbar: false + title: false + sound: 'entity.experience_orb.pickup' + soundVolume: 1.0 + soundPitch: 1.0 + tempban: + chat: true + actionbar: false + title: false + sound: 'entity.experience_orb.pickup' + soundVolume: 1.0 + soundPitch: 1.0 + mute: + chat: true + actionbar: false + title: false + sound: '' + soundVolume: 1.0 + soundPitch: 1.0 + tempmute: + chat: true + actionbar: false + title: false + sound: '' + soundVolume: 1.0 + soundPitch: 1.0 + warn: + chat: true + actionbar: false + title: false + sound: 'entity.experience_orb.pickup' + soundVolume: 1.0 + soundPitch: 1.0 + report: + chat: true + actionbar: false + title: false + sound: 'block.note_block.pling' + soundVolume: 1.0 + soundPitch: 1.0 + duplicateIp: + chat: true + actionbar: false + title: false + sound: '' + soundVolume: 1.0 + soundPitch: 1.0 + +player: + muted: + actionbar: true + warned: + sound: 'entity.villager.no' + soundVolume: 1.0 + soundPitch: 1.0 diff --git a/e2e/platforms/sponge/configs/banmanager/messages.yml b/e2e/platforms/sponge/configs/banmanager/messages.yml index cd7f4290c..494d65579 100644 --- a/e2e/platforms/sponge/configs/banmanager/messages.yml +++ b/e2e/platforms/sponge/configs/banmanager/messages.yml @@ -1,418 +1,474 @@ -# Variables -# [reason] = Ban/Mute reason -# [player] = The name of the player -# [ip] = The banned ip -# [actor] = Who banned/muted -# [expires] = How long until the ban/mute ends +# Message templates use MiniMessage formatting: https://docs.advntr.dev/minimessage/format.html +# Placeholders use angle brackets, e.g. , , , , + +tokens: + appeal_url: 'https://yourdomain.com/appeal' + server_name: 'My Server' + discord_url: 'https://discord.gg/example' + rules_url: 'https://yourdomain.com/rules' messages: - duplicateIP: '&cWarning: [player] has the same IP as the following banned players:\n&6[players]' - duplicateIPAlts: '&cWarning: [player] has the same IP as the following players:\n&6[players]' - configReloaded: '�ff00Configuration &#ff5733reloaded &asuccessfully!' + duplicateIP: 'Warning: has the same IP as the following banned players:\n' + duplicateIPAlts: 'Warning: has the same IP as the following players:\n' + configReloaded: 'Configuration reloaded successfully!' deniedNotify: - player: '&cWarning: [player] attempted to join the server but was denied due to - &4[reason]' - ip: '&cWarning: [ip] attempted to join the server but was denied due to &4[reason]' - deniedMaxIp: '&cToo many players with your ip address online' - deniedMultiaccounts: '&cToo many players with your ip address logged in recently' - deniedCountry: '&cYou may not connect from your region' + player: 'Warning: attempted to join the server but was denied due to ' + ip: 'Warning: attempted to join the server but was denied due to ' + deniedMaxIp: 'Too many players with your ip address online' + deniedMultiaccounts: 'Too many players with your ip address logged in recently' + deniedCountry: 'You may not connect from your region' + time: - now: now - year: year - years: years - month: month - months: months - week: week - weeks: weeks - day: day - days: days - hour: hour - hours: hours - minute: minute - minutes: minutes - second: second - seconds: seconds - never: never + now: 'now' + year: 'year' + years: 'years' + month: 'month' + months: 'months' + week: 'week' + weeks: 'weeks' + day: 'day' + days: 'days' + hour: 'hour' + hours: 'hours' + minute: 'minute' + minutes: 'minutes' + second: 'second' + seconds: 'seconds' + never: 'never' error: - invalid: '&cYour time length is invalid' - limit: '&cYou cannot perform this action for that length of time' - none: none + invalid: 'Your time length is invalid' + limit: 'You cannot perform this action for that length of time' + + none: 'none' + # General command text sender: error: - notFound: '&c[player] not found, are you sure they exist?' - offline: '&c[player] is offline' - noSelf: '&cYou cannot perform that action on yourself!' - exception: '&cAn error occured whilst attempting to perform this command. Please - check the console for further details.' - invalidIp: '&cInvalid IP address, expecting w.x.y.z format' - offlinePermission: '&cYou are not allowed to perform this action on an offline - player' - exempt: '&c[player] is exempt from that action' - noPermission: '&cYou do not have permission to perform that action' - invalidReason: '&c[reason] is no valid reason.' + notFound: ' not found, are you sure they exist?' + offline: ' is offline' + noSelf: 'You cannot perform that action on yourself!' + exception: 'An error occured whilst attempting to perform this command. Please check the console for further details.' + invalidIp: 'Invalid IP address, expecting w.x.y.z format' + offlinePermission: 'You are not allowed to perform this action on an offline player' + ambiguousPlayer: 'Multiple players match "". Please use their full name.' + exempt: ' is exempt from that action' + noPermission: 'You do not have permission to perform that action' + noConsole: 'This command cannot be used from console' + invalidReason: ' is no valid reason.' + # Commands alts: header: 'Possible alts found:' + entry: '">' + separator: ', ' + + names: + header: 'Known names for :' + row: ' (first: , last: )' + interactive: ' (first: , last: )">">' + separator: ', ' + dateTimeFormat: 'dd-MM-yyyy' + none: 'No name history found' + export: error: - inProgress: '&cAn export is already in progress, please wait' + inProgress: 'An export is already in progress, please wait' player: - started: '&aPlayer ban export started' - finished: '&aPlayer ban export finished, file [file] created' + started: 'Player ban export started' + finished: 'Player ban export finished, file created' ip: - started: '&aIP ban export started' - finished: '&aIP ban export finished, file [file] created' + started: 'IP ban export started' + finished: 'IP ban export finished, file created' + import: error: - inProgress: '&cAn import is already in progress, please wait' + inProgress: 'An import is already in progress, please wait' player: - started: '&aPlayer ban import started' - finished: '&aPlayer ban import finished' + started: 'Player ban import started' + finished: 'Player ban import finished' ip: - started: '&aIP ban import started' - finished: '&aIP ban import finished' + started: 'IP ban import started' + finished: 'IP ban import finished' advancedban: - started: '&aAdvancedBan import started' - finished: '&aAdvancedBan import finished' + started: 'AdvancedBan import started' + finished: 'AdvancedBan import finished' h2: - started: '&aH2 import started' - finished: '&aH2 import finished, please restart the server' + started: 'H2 import started' + finished: 'H2 import finished, please restart the server' litebans: - started: '&aLiteBans import started' - finished: '&aLiteBans import finished' + started: 'LiteBans import started' + finished: 'LiteBans import finished' + info: error: - invalidIndex: '&cInvalid player option used' - indexRequired: '&cMultiple players named [name] found, please select a player - by providing an index between 1 and [size], e.g. /bminfo [name] 1' - index: '&7#[index] - &6[name] - &4[uuid]' + invalidIndex: 'Invalid player option used' + indexRequired: 'Multiple players named found, please select a player by providing an index between 1 and , e.g. /bminfo 1' + index: '# - - ' stats: - player: '&6[player] has been banned [bans] times, muted [mutes] times, kicked - [kicks] times and warned [warns] times ([warnPoints] Points), has [notes] - notes and been reported [reports] times' - ip: '&6This ip has been banned [bans] times, muted [mutes] times and range banned - [rangebans] times' - connection: '&6Their last connection was with [ip] on [lastSeen]' - geoip: 'Country: [country] City: [city]' + player: ' has been banned times, muted times, kicked times and warned + times ( Points), has notes and been reported times' + ip: 'This ip has been banned times, muted times and range banned times' + connection: 'Their last connection was with on ' + geoip: 'Country: City: ' ban: - permanent: '&6Currently banned for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently banned for &4[reason]&6 by [actor] at [created] which - expires in [expires]' - dateTimeFormat: dd-MM-yyyy HH:mm:ss + permanent: 'Currently banned for by at ' + temporary: 'Currently banned for by at which expires in ' + dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' ipban: - permanent: '&6Currently banned for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently banned for &4[reason]&6 by [actor] at [created] which - expires in [expires]' - dateTimeFormat: dd-MM-yyyy HH:mm:ss + permanent: 'Currently banned for by at ' + temporary: 'Currently banned for by at which expires in ' + dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' iprangeban: - permanent: '&6[from] - [to] banned for &4[reason]&6 by [actor] at [created]' - temporary: '&6[from] - [to] banned for &4[reason]&6 by [actor] at [created] - which expires in [expires]' - dateTimeFormat: dd-MM-yyyy HH:mm:ss + permanent: ' - banned for by at ' + temporary: ' - banned for by at which expires in ' + dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' ipmute: - permanent: '&6Currently muted for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently muted for &4[reason]&6 by [actor] at [created] which - expires in [expires]' - dateTimeFormat: dd-MM-yyyy HH:mm:ss + permanent: 'Currently muted for by at ' + temporary: 'Currently muted for by at which expires in ' + dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' mute: - permanent: '&6Currently muted for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently muted for &4[reason]&6 by [actor] at [created] which - expires in [expires]' - temporaryOnline: '&6Currently muted for &4[reason]&6 by [actor] at [created] which - expires in [expires] (online time)' - temporaryOnlinePaused: '&6Currently muted for &4[reason]&6 by [actor] at [created] - with [remaining] remaining (online time, paused)' - dateTimeFormat: dd-MM-yyyy HH:mm:ss + permanent: 'Currently muted for by at ' + temporary: 'Currently muted for by at which expires in ' + temporaryOnline: 'Currently muted for by at which expires in (online time)' + temporaryOnlinePaused: 'Currently muted for by at with remaining (online time, paused)' + dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' website: - player: https://yourdomain.com/player/[uuid] - ip: http://yourdomain.com/index.php?action=viewip&ip=[ip]&server=0 + player: 'https://yourdomain.com/player/' + ip: 'http://yourdomain.com/index.php?action=viewip&ip=&server=0' history: - row: '&7#[id] &a[&f[type]&a] &6[actor]&f [meta] [reason] - &e[created]' - dateTimeFormat: dd-MM-yyyy HH:mm:ss - noResults: '&cNo results found' + row: '# [] - ' + dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' + noResults: 'No results found' ips: - row: '&e[ip] - &6[join] - [leave]' - dateTimeFormat: dd-MM-yyyy HH:mm:ss + row: ' - - ' + dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' + kick: player: - noReason: '&6You have been kicked' - reason: '&6You have been kicked for &4[reason]' + noReason: 'You have been kicked' + reason: 'You have been kicked for ' notify: - noReason: '&6[player] has been kicked by [actor]' - reason: '&6[player] has been kicked by [actor] for &4[reason]' + noReason: ' has been kicked by ">View player info">[Info]' + reason: ' has been kicked by for ">View player info">[Info]' + kickall: player: - noReason: '&6You have been kicked' - reason: '&6You have been kicked for &4[reason]' + noReason: 'You have been kicked' + reason: 'You have been kicked for ' notify: - noReason: All players have been kicked by [actor] - reason: All players have been kicked by [actor] for &4[reason] + noReason: 'All players have been kicked by ' + reason: 'All players have been kicked by for ' + ban: player: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' - dateTimeFormat: yyyy-MM-dd HH:mm:ss - notify: '&6[player] has been permanently banned by [actor] for &4[reason]' + disallowed: 'You are banned from this server\n \nReason: \nBanned by: \nDate: \n \nAppeal at ' + kick: 'You have been banned\n \nReason: \nBanned by: ' + dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' + notify: ' has been permanently banned by for ">View player info">[Info] ">Unban player">[Unban]' error: - exists: '&c[player] is already banned' - cooldown: '&cThis player was banned too recently, try again later' + exists: ' is already banned' + cooldown: 'This player was banned too recently, try again later' + banall: - notify: '&6[player] will be permanently banned by [actor] for &4[reason]' + notify: ' will be permanently banned by for ' + tempban: player: - disallowed: '&6You have been temporarily banned from this server for &4[reason] - \n&6It expires in [expires]' - kick: '&6You have been temporarily banned for &4[reason]' - dateTimeFormat: yyyy-MM-dd HH:mm:ss - notify: '&6[player] has been temporarily banned for [expires] by [actor] for &4[reason]' + disallowed: 'You are temporarily banned from this server\n \nReason: \nBanned by: \nExpires: \nDate: \n \nAppeal at ' + kick: 'You have been temporarily banned\n \nReason: \nBanned by: \nExpires: ' + dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' + notify: ' has been temporarily banned for by for ">View player info">[Info] ">Unban player">[Unban]' + tempbanall: - notify: '&6[player] will be temporarily banned for [expires] by [actor] for &4[reason]' + notify: ' will be temporarily banned for by for ' + unban: - notify: '&6[player] has been unbanned by [actor]' + notify: ' has been unbanned by ' error: - noExists: '&c[player] is not banned' - notOwn: '&c[player] was not banned by you, unable to unban' + noExists: ' is not banned' + notOwn: ' was not banned by you, unable to unban' + unbanall: - notify: '&6[player] will be unbanned by [actor]' + notify: ' will be unbanned by ' + mute: player: - blocked: '&cYou may not use the [command] command whilst muted!' - disallowed: '&6You have been permanently muted for &4[reason] &6by [actor]' - broadcast: '&4[Muted] [player]&7 [message]' - notify: '&6[player] has been permanently muted by [actor] for &4[reason]' + blocked: 'You may not use the command whilst muted!' + disallowed: 'You have been permanently muted for by ' + broadcast: '[Muted] ' + notify: ' has been permanently muted by for ">View player info">[Info] ">Unmute player">[Unmute]' error: - exists: '&c[player] is already muted' - cooldown: '&cThis player was muted too recently, try again later' + exists: ' is already muted' + cooldown: 'This player was muted too recently, try again later' + muteip: ip: - disallowed: '&6You have been permanently muted for &4[reason] &6by [actor]' - broadcast: '&4[Muted] [player]&7 [message]' - notify: '&6[ip] ([players]) have been permanently muted by [actor] for &4[reason]' + disallowed: 'You have been permanently muted for by ' + broadcast: '[Muted] ' + notify: ' () have been permanently muted by for ' error: - exists: '&c[ip] is already muted' + exists: ' is already muted' + muteall: - notify: '&6[player] will be permanently muted by [actor] for &4[reason]' + notify: ' will be permanently muted by for ' + tempmute: player: - disallowed: '&6You have been temporarily muted for &4[reason] &6by [actor] which - expires in [expires]' - disallowedOnline: '&6You have been temporarily muted for &4[reason] &6by [actor] which - expires in [expires] (online time)' - notify: '&6[player] has been temporarily muted for [expires] by [actor] for &4[reason]' - notifyOnline: '&6[player] has been temporarily muted for [expires] (online time) by [actor] for &4[reason]' + disallowed: 'You have been temporarily muted for by which expires in ' + disallowedOnline: 'You have been temporarily muted for by which expires in (online time)' + notify: ' has been temporarily muted for by for ">View player info">[Info] ">Unmute player">[Unmute]' + notifyOnline: ' has been temporarily muted for (online time) by for ' error: - exists: '&c[player] is already muted' + exists: ' is already muted' + tempmuteip: ip: - disallowed: '&6You have been temporarily muted for &4[reason] &6by [actor] which - expires in [expires]' - notify: '&6[ip] ([players]) have been temporarily muted for [expires] by [actor] - for &4[reason]' + disallowed: 'You have been temporarily muted for by which expires in ' + notify: ' () have been temporarily muted for by for ' error: - exists: '&c[ip] is already muted' + exists: ' is already muted' + tempmuteall: - notify: '&6[player] will be temporarily muted for [expires] by [actor] for &4[reason]' + notify: ' will be temporarily muted for by for ' + unmute: - notify: '&6[player] has been unmuted by [actor]' - player: '&6You have been unmuted by [actor]' + notify: ' has been unmuted by ' + player: 'You have been unmuted by ' error: - noExists: '&c[player] is not muted' - notOwn: '&c[player] was not muted by you, unable to unmute' + noExists: ' is not muted' + notOwn: ' was not muted by you, unable to unmute' + unmuteip: - notify: '&6[ip] has been unmuted by [actor]' + notify: ' has been unmuted by ' error: - noExists: '&c[ip] is not muted' - notOwn: '&c[ip] was not muted by you, unable to unmute' + noExists: ' is not muted' + notOwn: ' was not muted by you, unable to unmute' + unmuteall: - notify: '&6[player] will be unmuted by [actor]' + notify: ' will be unmuted by ' + banname: name: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' - dateTimeFormat: yyyy-MM-dd HH:mm:ss - notify: '&6Name [name] has been permanently banned by [actor] for &4[reason]' + disallowed: 'You have been banned from this server for ' + kick: 'You have been banned permanently for ' + dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' + notify: 'Name has been permanently banned by for ' error: - exists: '&cName [name] is already banned' + exists: 'Name is already banned' + tempbanname: name: - disallowed: '&6You have been banned from this server for &4[reason] \n&6It expires - in [expires]' - kick: '&6You have been temporarily banned for &4[reason]' - dateTimeFormat: yyyy-MM-dd HH:mm:ss - notify: '&6Name [name] has been temporarily banned for [expires] by [actor] for - &4[reason]' + disallowed: 'You have been banned from this server for \nIt expires in ' + kick: 'You have been temporarily banned for ' + dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' + notify: 'Name has been temporarily banned for by for ' + unbanname: - notify: '&6Name [name] has been unbanned by [actor]' + notify: 'Name has been unbanned by ' error: - noExists: '&cName [name] is not banned' + noExists: 'Name is not banned' + banip: ip: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' - dateTimeFormat: yyyy-MM-dd HH:mm:ss - notify: '&6[ip] ([players]) has been permanently banned by [actor] for &4[reason]' + disallowed: 'You have been banned from this server for ' + kick: 'You have been banned permanently for ' + dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' + notify: ' () has been permanently banned by for ' error: - exists: '&c[ip] is already banned' - cooldown: '&cThis ip was banned too recently, try again later' + exists: ' is already banned' + cooldown: 'This ip was banned too recently, try again later' + baniprange: error: - invalid: '&cInvalid range, please use cidr notation 192.168.0.1/16 or wildcard - 192.168.*.*' - minMax: '&cRange must be lowest to highest' - exists: '&cA ban containing those ranges already exists' + invalid: 'Invalid range, please use cidr notation 192.168.0.1/16 or wildcard 192.168.*.*' + minMax: 'Range must be lowest to highest' + exists: 'A ban containing those ranges already exists' ip: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' - dateTimeFormat: yyyy-MM-dd HH:mm:ss - notify: '&6[from] - [to] have been banned by [actor]' + disallowed: 'You have been banned from this server for ' + kick: 'You have been banned permanently for ' + dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' + notify: ' - have been banned by ' + tempbaniprange: - notify: '&6[from] - [to] has been temporarily banned for [expires] by [actor]' + notify: ' - has been temporarily banned for by ' ip: - disallowed: '&6You have been banned from this server for &4[reason] \n&6It expires - in [expires]' - kick: '&6You have been temporarily banned for [expires] by [actor] for &4[reason]' - dateTimeFormat: yyyy-MM-dd HH:mm:ss + disallowed: 'You have been banned from this server for \nIt expires in ' + kick: 'You have been temporarily banned for by for ' + dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' + unbaniprange: - notify: '&6[from] - [to] has been unbanned by [actor]' + notify: ' - has been unbanned by ' + banipall: - notify: '&6[ip] will be permanently banned by [actor] for &4[reason]' + notify: ' will be permanently banned by for ' + tempbanip: ip: - disallowed: '&6You have been banned from this server for &4[reason] \n&6It expires - in [expires]' - kick: '&6You have been temporarily banned for &4[reason]' - dateTimeFormat: yyyy-MM-dd HH:mm:ss - notify: '&6[ip] ([players]) has been temporarily banned for [expires] by [actor] - for &4[reason]' + disallowed: 'You have been banned from this server for \nIt expires in ' + kick: 'You have been temporarily banned for ' + dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' + notify: ' () has been temporarily banned for by for ' + tempbanipall: - notify: '&6[ip] will be temporarily banned for [expires] by [actor] for &4[reason]' + notify: ' will be temporarily banned for by for ' + unbanip: - notify: '&6[ip] has been unbanned by [actor]' + notify: ' has been unbanned by ' error: - noExists: '&c[ip] is not banned' - notOwn: '&c[ip] was not banned by you, unable to unban' + noExists: ' is not banned' + notOwn: ' was not banned by you, unable to unban' + unbanipall: - notify: '&6[ip] will be unbanned by [actor]' + notify: ' will be unbanned by ' + warn: player: - warned: '&6You have been warned by [actor] for &4[reason]' + warned: 'You have been warned by for ' disallowed: - header: '&cYou may not speak until you have accepted your most recent warning. - Please type the following:' - reason: '&6[reason]' - removed: '&aThank you for your understanding, you may now speak again' - notify: '&6[player] has been warned by [actor] for &4[reason]' + header: 'You may not speak until you have accepted your most recent warning. Please type the following:' + reason: '' + removed: 'Thank you for your understanding, you may now speak again' + notify: ' has been warned by for ">View player info">[Info]' error: - cooldown: '&cThis player was warned too recently, try again later' + cooldown: 'This player was warned too recently, try again later' + tempwarn: player: - warned: '&6You have been warned for [expires] by [actor] for &4[reason]' - notify: '&6[player] has been warned for [expires] by [actor] for &4[reason]' + warned: 'You have been warned for by for ' + notify: ' has been warned for by for ">View player info">[Info]' + dwarn: player: - notify: '&6Your most recent warning has been deleted by &4[actor]' - notify: '&cThe most recent warning for [player] has been deleted' + notify: 'Your most recent warning has been deleted by ' + notify: 'The most recent warning for has been deleted' error: - noWarnings: '&c[player] has no warnings to delete' + noWarnings: ' has no warnings to delete' + bmclear: - notify: '&c[player] has had their [type] cleared' + notify: ' has had their cleared' error: - invalid: '&cInvalid type, please choose between banrecords, muterecords, kicks, - notes or warnings' + invalid: 'Invalid type, please choose between banrecords, muterecords, kicks, notes or warnings' + bmutils: missingplayers: - notify: '&c[amount] missing players added' - noneFound: '&a0 missing players found' - found: '&c[amount] missing player data found. Fixing...' + notify: ' missing players added' + noneFound: '0 missing players found' + found: ' missing player data found. Fixing...' error: - failedLookup: '&cFailed to lookup player [uuid], check server logs' - complete: '&a[amount] players resolved, please restart your server for failed - punishments to take affect' + failedLookup: 'Failed to lookup player , check server logs' + complete: ' players resolved, please restart your server for failed punishments to take affect' duplicates: lookup: - notFound: '&aNo duplicate player names found' + notFound: 'No duplicate player names found' error: - invalidName: '&cInvalid name, must be 16 characters or less and contain only - letters, numbers and an underscore' - nameExists: '&cA player with that name already exists' - success: '&aPlayer name set to [player] successfully' + invalidName: 'Invalid name, must be 16 characters or less and contain only letters, numbers and an underscore' + nameExists: 'A player with that name already exists' + success: 'Player name set to successfully' + bmrollback: - notify: '&c[player] has had their [type] actions undone' + notify: ' has had their actions undone' error: - invalid: '&cInvalid type [type], please choose between [types]' + invalid: 'Invalid type , please choose between ' + sync: player: - started: '&aStarting force [type] synchronisation' - finished: '&aForced [type] synchronisation complete' + started: 'Starting force synchronisation' + finished: 'Forced synchronisation complete' + update: - notify: '&6[BanManager] &aAn update is available' + notify: '[BanManager] An update is available' + notes: - header: '&6[player] has the following notes:' - joinAmount: '&6[player] has &e[amount] &6notes, click to view them' - note: '&6[[player]] &e[message] - &e[created]' - playerNote: '&a[[player]] &6[[actor]] &e[message] - &e[created]' - dateTimeFormat: dd-MM-yyyy - notify: '[player] has a new note attached by [actor]: [message]' + header: ' has the following notes:' + joinAmount: '"> has notes, click to view them' + note: '[] - ' + playerNote: '[] [] - ' + dateTimeFormat: 'dd-MM-yyyy' + notify: ' has a new note attached by : ' error: - noNotes: '&c[player] has no notes' - noOnlineNotes: '&cNo online players have notes' + noNotes: ' has no notes' + noOnlineNotes: 'No online players have notes' + report: - notify: '&6[player] has been reported by [actor] for &4[reason]' + notify: ' has been reported by for ' error: - cooldown: '&cThis player was reported too recently, try again later' + cooldown: 'This player was reported too recently, try again later' assign: - player: '&aReport [id] assigned to [player]' - notify: '&aYou have been assigned report [id] by [actor]' + player: 'Report assigned to ' + notify: 'You have been assigned report by ' unassign: - player: '&aReport [id] unassigned' + player: 'Report unassigned' close: notify: - closed: '&aReport [id] closed by [actor]' - command: '&aReport [id] closed by [actor] with [command]' - comment: '&aReport [id] closed by [actor] with [comment]' - dispatch: Executing command [command] + closed: 'Report closed by ' + command: 'Report closed by with ' + comment: 'Report closed by with ' + dispatch: 'Executing command ' list: - noResults: '&cNo reports found' + noResults: 'No reports found' error: - invalidState: '&cReport state [state] not found' + invalidState: 'Report state not found' row: - dateTimeFormat: yyyy-MM-dd HH:mm:ss - header: '&e-- Reports ([count]) -- Page ([page]/[maxPage])' - all: '&7#[id] &e[[state]] &6- [created] - [player]' + dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' + header: '-- Reports () -- Page (/)' + all: '">Click to view details"># [] - - ' tp: error: - notFound: '&cReport not found' - worldNotFound: '&cWorld [world] could not be found' - invalidId: '&c[id] is not a valid report id' - dateTimeFormat: yyyy-MM-dd HH:mm:ss + notFound: 'Report not found' + worldNotFound: 'World could not be found' + invalidId: ' is not a valid report id' + dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' notify: - report: '&7#[id] &6[actor] reported [player] for &4[reason]&6 at [created]' - location: '[world] - [x], [y], [z]' + report: '# reported for at ' + location: ' - , , ' info: error: - notFound: '&cReport not found' - invalidId: '&c[id] is not a valid report id' - dateTimeFormat: yyyy-MM-dd HH:mm:ss + notFound: 'Report not found' + invalidId: ' is not a valid report id' + dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' notify: - report: '&7#[id] &6[actor] reported [player] for &4[reason]&6 at [created]' - location: '[world] - [x], [y], [z]' + report: '# reported for at ' + location: ' - , , ' + actions: + assign: '">Assign to yourself">[Assign]' + close: '">Close this report">[Close]' + tp: '">Teleport to location">[TP]' + feedback: + assigned: 'Your report # has been assigned to ' + closed: 'Your report # has been closed by ' + addnoteall: - notify: '&c[player] will have a new attached by [actor]: [message]' + notify: ' will have a new attached by : ' + banlist: - header: '&6There are [bans] [type] bans:' + header: 'There are bans:' + row: + player: '">Click for info"> - ' + ip: ' - ' + iprange: ' - - ' + bmactivity: row: - all: '&a[&f[type]&a] &6[player]&f - &6[actor]&f - &e[created]' - player: '&a[&f[type]&a] &6[player]&f - &e[created]' - dateTimeFormat: dd-MM-yyyy HH:mm:ss - noResults: '&cNo results found' + all: '[] - - ' + player: '[] - ' + dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' + noResults: 'No results found' + bmdelete: - notify: '&a[rows] rows deleted' + notify: ' rows deleted' error: - invalid: '&cInvalid type, please choose between banrecords, muterecords, kicks, - notes or warnings' - invalidId: '&c[id] is not a valid number' + invalid: 'Invalid type, please choose between banrecords, muterecords, kicks, notes or warnings' + invalidId: ' is not a valid number' + denyalts: player: - disallowed: '&cThe IP address you are joining from is linked to a banned player' + disallowed: 'The IP address you are joining from is linked to a banned player' + reasons: - row: '[hashtag] = [reason]' + row: ' = ' + + dashboard: + header: ' Staff Dashboard ' + activeBans: 'Active Bans: ' + activeMutes: 'Active Mutes: ' + openReports: 'Open Reports: View reports">[View]' + recentActivity: 'Recent Activity (24h): ' + footer: ' ' diff --git a/e2e/platforms/sponge/configs/banmanager/messages/messages_en.yml b/e2e/platforms/sponge/configs/banmanager/messages/messages_en.yml index 205a94c13..494d65579 100644 --- a/e2e/platforms/sponge/configs/banmanager/messages/messages_en.yml +++ b/e2e/platforms/sponge/configs/banmanager/messages/messages_en.yml @@ -1,20 +1,22 @@ -# Variables -# [reason] = Ban/Mute reason -# [player] = The name of the player -# [ip] = The banned ip -# [actor] = Who banned/muted -# [expires] = How long until the ban/mute ends +# Message templates use MiniMessage formatting: https://docs.advntr.dev/minimessage/format.html +# Placeholders use angle brackets, e.g. , , , , + +tokens: + appeal_url: 'https://yourdomain.com/appeal' + server_name: 'My Server' + discord_url: 'https://discord.gg/example' + rules_url: 'https://yourdomain.com/rules' messages: - duplicateIP: '&cWarning: [player] has the same IP as the following banned players:\n&6[players]' - duplicateIPAlts: '&cWarning: [player] has the same IP as the following players:\n&6[players]' - configReloaded: '&aConfiguration reloaded successfully!' + duplicateIP: 'Warning: has the same IP as the following banned players:\n' + duplicateIPAlts: 'Warning: has the same IP as the following players:\n' + configReloaded: 'Configuration reloaded successfully!' deniedNotify: - player: '&cWarning: [player] attempted to join the server but was denied due to &4[reason]' - ip: '&cWarning: [ip] attempted to join the server but was denied due to &4[reason]' - deniedMaxIp: '&cToo many players with your ip address online' - deniedMultiaccounts: '&cToo many players with your ip address logged in recently' - deniedCountry: '&cYou may not connect from your region' + player: 'Warning: attempted to join the server but was denied due to ' + ip: 'Warning: attempted to join the server but was denied due to ' + deniedMaxIp: 'Too many players with your ip address online' + deniedMultiaccounts: 'Too many players with your ip address logged in recently' + deniedCountry: 'You may not connect from your region' time: now: 'now' @@ -34,415 +36,439 @@ messages: seconds: 'seconds' never: 'never' error: - invalid: '&cYour time length is invalid' - limit: '&cYou cannot perform this action for that length of time' + invalid: 'Your time length is invalid' + limit: 'You cannot perform this action for that length of time' none: 'none' # General command text sender: error: - notFound: '&c[player] not found, are you sure they exist?' - offline: '&c[player] is offline' - noSelf: '&cYou cannot perform that action on yourself!' - exception: '&cAn error occured whilst attempting to perform this command. Please check the console for further details.' - invalidIp: '&cInvalid IP address, expecting w.x.y.z format' - offlinePermission: '&cYou are not allowed to perform this action on an offline player' - ambiguousPlayer: '&cMultiple players match "[player]". Please use their full name.' - exempt: '&c[player] is exempt from that action' - noPermission: '&cYou do not have permission to perform that action' - invalidReason: '&c[reason] is no valid reason.' + notFound: ' not found, are you sure they exist?' + offline: ' is offline' + noSelf: 'You cannot perform that action on yourself!' + exception: 'An error occured whilst attempting to perform this command. Please check the console for further details.' + invalidIp: 'Invalid IP address, expecting w.x.y.z format' + offlinePermission: 'You are not allowed to perform this action on an offline player' + ambiguousPlayer: 'Multiple players match "". Please use their full name.' + exempt: ' is exempt from that action' + noPermission: 'You do not have permission to perform that action' + noConsole: 'This command cannot be used from console' + invalidReason: ' is no valid reason.' # Commands alts: header: 'Possible alts found:' + entry: '">' + separator: ', ' names: - header: 'Known names for [player]:' - row: '&e[name] &7(first: [firstSeen], last: [lastSeen])' + header: 'Known names for :' + row: ' (first: , last: )' + interactive: ' (first: , last: )">">' + separator: ', ' dateTimeFormat: 'dd-MM-yyyy' - none: '&7No name history found' + none: 'No name history found' export: error: - inProgress: '&cAn export is already in progress, please wait' + inProgress: 'An export is already in progress, please wait' player: - started: '&aPlayer ban export started' - finished: '&aPlayer ban export finished, file [file] created' + started: 'Player ban export started' + finished: 'Player ban export finished, file created' ip: - started: '&aIP ban export started' - finished: '&aIP ban export finished, file [file] created' + started: 'IP ban export started' + finished: 'IP ban export finished, file created' import: error: - inProgress: '&cAn import is already in progress, please wait' + inProgress: 'An import is already in progress, please wait' player: - started: '&aPlayer ban import started' - finished: '&aPlayer ban import finished' + started: 'Player ban import started' + finished: 'Player ban import finished' ip: - started: '&aIP ban import started' - finished: '&aIP ban import finished' + started: 'IP ban import started' + finished: 'IP ban import finished' advancedban: - started: '&aAdvancedBan import started' - finished: '&aAdvancedBan import finished' + started: 'AdvancedBan import started' + finished: 'AdvancedBan import finished' h2: - started: '&aH2 import started' - finished: '&aH2 import finished, please restart the server' + started: 'H2 import started' + finished: 'H2 import finished, please restart the server' litebans: - started: '&aLiteBans import started' - finished: '&aLiteBans import finished' + started: 'LiteBans import started' + finished: 'LiteBans import finished' info: error: - invalidIndex: '&cInvalid player option used' - indexRequired: '&cMultiple players named [name] found, please select a player by providing an index between 1 and [size], e.g. /bminfo [name] 1' - index: '&7#[index] - &6[name] - &4[uuid]' + invalidIndex: 'Invalid player option used' + indexRequired: 'Multiple players named found, please select a player by providing an index between 1 and , e.g. /bminfo 1' + index: '# - - ' stats: - player: '&6[player] has been banned [bans] times, muted [mutes] times, kicked [kicks] times and warned [warns] - times ([warnPoints] Points), has [notes] notes and been reported [reports] times' - ip: '&6This ip has been banned [bans] times, muted [mutes] times and range banned [rangebans] times' - connection: '&6Their last connection was with [ip] on [lastSeen]' - geoip: 'Country: [country] City: [city]' + player: ' has been banned times, muted times, kicked times and warned + times ( Points), has notes and been reported times' + ip: 'This ip has been banned times, muted times and range banned times' + connection: 'Their last connection was with on ' + geoip: 'Country: City: ' ban: - permanent: '&6Currently banned for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently banned for &4[reason]&6 by [actor] at [created] which expires in [expires]' + permanent: 'Currently banned for by at ' + temporary: 'Currently banned for by at which expires in ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' ipban: - permanent: '&6Currently banned for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently banned for &4[reason]&6 by [actor] at [created] which expires in [expires]' + permanent: 'Currently banned for by at ' + temporary: 'Currently banned for by at which expires in ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' iprangeban: - permanent: '&6[from] - [to] banned for &4[reason]&6 by [actor] at [created]' - temporary: '&6[from] - [to] banned for &4[reason]&6 by [actor] at [created] which expires in [expires]' + permanent: ' - banned for by at ' + temporary: ' - banned for by at which expires in ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' ipmute: - permanent: '&6Currently muted for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently muted for &4[reason]&6 by [actor] at [created] which expires in [expires]' + permanent: 'Currently muted for by at ' + temporary: 'Currently muted for by at which expires in ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' mute: - permanent: '&6Currently muted for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently muted for &4[reason]&6 by [actor] at [created] which expires in [expires]' - temporaryOnline: '&6Currently muted for &4[reason]&6 by [actor] at [created] which expires in [expires] (online time)' - temporaryOnlinePaused: '&6Currently muted for &4[reason]&6 by [actor] at [created] with [remaining] remaining (online time, paused)' + permanent: 'Currently muted for by at ' + temporary: 'Currently muted for by at which expires in ' + temporaryOnline: 'Currently muted for by at which expires in (online time)' + temporaryOnlinePaused: 'Currently muted for by at with remaining (online time, paused)' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' website: - player: 'https://yourdomain.com/player/[uuid]' - ip: 'http://yourdomain.com/index.php?action=viewip&ip=[ip]&server=0' + player: 'https://yourdomain.com/player/' + ip: 'http://yourdomain.com/index.php?action=viewip&ip=&server=0' history: - row: '&7#[id] &a[&f[type]&a] &6[actor]&f [meta] [reason] - &e[created]' + row: '# [] - ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' - noResults: '&cNo results found' + noResults: 'No results found' ips: - row: '&e[ip] - &6[join] - [leave]' + row: ' - - ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' kick: player: - noReason: '&6You have been kicked' - reason: '&6You have been kicked for &4[reason]' + noReason: 'You have been kicked' + reason: 'You have been kicked for ' notify: - noReason: '&6[player] has been kicked by [actor]' - reason: '&6[player] has been kicked by [actor] for &4[reason]' + noReason: ' has been kicked by ">View player info">[Info]' + reason: ' has been kicked by for ">View player info">[Info]' kickall: player: - noReason: '&6You have been kicked' - reason: '&6You have been kicked for &4[reason]' + noReason: 'You have been kicked' + reason: 'You have been kicked for ' notify: - noReason: 'All players have been kicked by [actor]' - reason: 'All players have been kicked by [actor] for &4[reason]' + noReason: 'All players have been kicked by ' + reason: 'All players have been kicked by for ' ban: player: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' + disallowed: 'You are banned from this server\n \nReason: \nBanned by: \nDate: \n \nAppeal at ' + kick: 'You have been banned\n \nReason: \nBanned by: ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[player] has been permanently banned by [actor] for &4[reason]' + notify: ' has been permanently banned by for ">View player info">[Info] ">Unban player">[Unban]' error: - exists: '&c[player] is already banned' - cooldown: '&cThis player was banned too recently, try again later' + exists: ' is already banned' + cooldown: 'This player was banned too recently, try again later' banall: - notify: '&6[player] will be permanently banned by [actor] for &4[reason]' + notify: ' will be permanently banned by for ' tempban: player: - disallowed: '&6You have been temporarily banned from this server for &4[reason] \n&6It expires in [expires]' - kick: '&6You have been temporarily banned for &4[reason]' + disallowed: 'You are temporarily banned from this server\n \nReason: \nBanned by: \nExpires: \nDate: \n \nAppeal at ' + kick: 'You have been temporarily banned\n \nReason: \nBanned by: \nExpires: ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[player] has been temporarily banned for [expires] by [actor] for &4[reason]' + notify: ' has been temporarily banned for by for ">View player info">[Info] ">Unban player">[Unban]' tempbanall: - notify: '&6[player] will be temporarily banned for [expires] by [actor] for &4[reason]' + notify: ' will be temporarily banned for by for ' unban: - notify: '&6[player] has been unbanned by [actor]' + notify: ' has been unbanned by ' error: - noExists: '&c[player] is not banned' - notOwn: '&c[player] was not banned by you, unable to unban' + noExists: ' is not banned' + notOwn: ' was not banned by you, unable to unban' unbanall: - notify: '&6[player] will be unbanned by [actor]' + notify: ' will be unbanned by ' mute: player: - blocked: '&cYou may not use the [command] command whilst muted!' - disallowed: '&6You have been permanently muted for &4[reason] &6by [actor]' - broadcast: '&4[Muted] [player]&7 [message]' - notify: '&6[player] has been permanently muted by [actor] for &4[reason]' + blocked: 'You may not use the command whilst muted!' + disallowed: 'You have been permanently muted for by ' + broadcast: '[Muted] ' + notify: ' has been permanently muted by for ">View player info">[Info] ">Unmute player">[Unmute]' error: - exists: '&c[player] is already muted' - cooldown: '&cThis player was muted too recently, try again later' + exists: ' is already muted' + cooldown: 'This player was muted too recently, try again later' muteip: ip: - disallowed: '&6You have been permanently muted for &4[reason] &6by [actor]' - broadcast: '&4[Muted] [player]&7 [message]' - notify: '&6[ip] ([players]) have been permanently muted by [actor] for &4[reason]' + disallowed: 'You have been permanently muted for by ' + broadcast: '[Muted] ' + notify: ' () have been permanently muted by for ' error: - exists: '&c[ip] is already muted' + exists: ' is already muted' muteall: - notify: '&6[player] will be permanently muted by [actor] for &4[reason]' + notify: ' will be permanently muted by for ' tempmute: player: - disallowed: '&6You have been temporarily muted for &4[reason] &6by [actor] which expires in [expires]' - disallowedOnline: '&6You have been temporarily muted for &4[reason] &6by [actor] which expires in [expires] (online time)' - notify: '&6[player] has been temporarily muted for [expires] by [actor] for &4[reason]' - notifyOnline: '&6[player] has been temporarily muted for [expires] (online time) by [actor] for &4[reason]' + disallowed: 'You have been temporarily muted for by which expires in ' + disallowedOnline: 'You have been temporarily muted for by which expires in (online time)' + notify: ' has been temporarily muted for by for ">View player info">[Info] ">Unmute player">[Unmute]' + notifyOnline: ' has been temporarily muted for (online time) by for ' error: - exists: '&c[player] is already muted' + exists: ' is already muted' tempmuteip: ip: - disallowed: '&6You have been temporarily muted for &4[reason] &6by [actor] which expires in [expires]' - notify: '&6[ip] ([players]) have been temporarily muted for [expires] by [actor] for &4[reason]' + disallowed: 'You have been temporarily muted for by which expires in ' + notify: ' () have been temporarily muted for by for ' error: - exists: '&c[ip] is already muted' + exists: ' is already muted' tempmuteall: - notify: '&6[player] will be temporarily muted for [expires] by [actor] for &4[reason]' + notify: ' will be temporarily muted for by for ' unmute: - notify: '&6[player] has been unmuted by [actor]' - player: '&6You have been unmuted by [actor]' + notify: ' has been unmuted by ' + player: 'You have been unmuted by ' error: - noExists: '&c[player] is not muted' - notOwn: '&c[player] was not muted by you, unable to unmute' + noExists: ' is not muted' + notOwn: ' was not muted by you, unable to unmute' unmuteip: - notify: '&6[ip] has been unmuted by [actor]' + notify: ' has been unmuted by ' error: - noExists: '&c[ip] is not muted' - notOwn: '&c[ip] was not muted by you, unable to unmute' + noExists: ' is not muted' + notOwn: ' was not muted by you, unable to unmute' unmuteall: - notify: '&6[player] will be unmuted by [actor]' + notify: ' will be unmuted by ' banname: name: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' + disallowed: 'You have been banned from this server for ' + kick: 'You have been banned permanently for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6Name [name] has been permanently banned by [actor] for &4[reason]' + notify: 'Name has been permanently banned by for ' error: - exists: '&cName [name] is already banned' + exists: 'Name is already banned' tempbanname: name: - disallowed: '&6You have been banned from this server for &4[reason] \n&6It expires in [expires]' - kick: '&6You have been temporarily banned for &4[reason]' + disallowed: 'You have been banned from this server for \nIt expires in ' + kick: 'You have been temporarily banned for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6Name [name] has been temporarily banned for [expires] by [actor] for &4[reason]' + notify: 'Name has been temporarily banned for by for ' unbanname: - notify: '&6Name [name] has been unbanned by [actor]' + notify: 'Name has been unbanned by ' error: - noExists: '&cName [name] is not banned' + noExists: 'Name is not banned' banip: ip: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' + disallowed: 'You have been banned from this server for ' + kick: 'You have been banned permanently for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[ip] ([players]) has been permanently banned by [actor] for &4[reason]' + notify: ' () has been permanently banned by for ' error: - exists: '&c[ip] is already banned' - cooldown: '&cThis ip was banned too recently, try again later' + exists: ' is already banned' + cooldown: 'This ip was banned too recently, try again later' baniprange: error: - invalid: '&cInvalid range, please use cidr notation 192.168.0.1/16 or wildcard 192.168.*.*' - minMax: '&cRange must be lowest to highest' - exists: '&cA ban containing those ranges already exists' + invalid: 'Invalid range, please use cidr notation 192.168.0.1/16 or wildcard 192.168.*.*' + minMax: 'Range must be lowest to highest' + exists: 'A ban containing those ranges already exists' ip: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' + disallowed: 'You have been banned from this server for ' + kick: 'You have been banned permanently for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[from] - [to] have been banned by [actor]' + notify: ' - have been banned by ' tempbaniprange: - notify: '&6[from] - [to] has been temporarily banned for [expires] by [actor]' + notify: ' - has been temporarily banned for by ' ip: - disallowed: '&6You have been banned from this server for &4[reason] \n&6It expires in [expires]' - kick: '&6You have been temporarily banned for [expires] by [actor] for &4[reason]' + disallowed: 'You have been banned from this server for \nIt expires in ' + kick: 'You have been temporarily banned for by for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' unbaniprange: - notify: '&6[from] - [to] has been unbanned by [actor]' + notify: ' - has been unbanned by ' banipall: - notify: '&6[ip] will be permanently banned by [actor] for &4[reason]' + notify: ' will be permanently banned by for ' tempbanip: ip: - disallowed: '&6You have been banned from this server for &4[reason] \n&6It expires in [expires]' - kick: '&6You have been temporarily banned for &4[reason]' + disallowed: 'You have been banned from this server for \nIt expires in ' + kick: 'You have been temporarily banned for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[ip] ([players]) has been temporarily banned for [expires] by [actor] for &4[reason]' + notify: ' () has been temporarily banned for by for ' tempbanipall: - notify: '&6[ip] will be temporarily banned for [expires] by [actor] for &4[reason]' + notify: ' will be temporarily banned for by for ' unbanip: - notify: '&6[ip] has been unbanned by [actor]' + notify: ' has been unbanned by ' error: - noExists: '&c[ip] is not banned' - notOwn: '&c[ip] was not banned by you, unable to unban' + noExists: ' is not banned' + notOwn: ' was not banned by you, unable to unban' unbanipall: - notify: '&6[ip] will be unbanned by [actor]' + notify: ' will be unbanned by ' warn: player: - warned: '&6You have been warned by [actor] for &4[reason]' + warned: 'You have been warned by for ' disallowed: - header: '&cYou may not speak until you have accepted your most recent warning. Please type the following:' - reason: '&6[reason]' - removed: '&aThank you for your understanding, you may now speak again' - notify: '&6[player] has been warned by [actor] for &4[reason]' + header: 'You may not speak until you have accepted your most recent warning. Please type the following:' + reason: '' + removed: 'Thank you for your understanding, you may now speak again' + notify: ' has been warned by for ">View player info">[Info]' error: - cooldown: '&cThis player was warned too recently, try again later' + cooldown: 'This player was warned too recently, try again later' tempwarn: player: - warned: '&6You have been warned for [expires] by [actor] for &4[reason]' - notify: '&6[player] has been warned for [expires] by [actor] for &4[reason]' + warned: 'You have been warned for by for ' + notify: ' has been warned for by for ">View player info">[Info]' dwarn: player: - notify: '&6Your most recent warning has been deleted by &4[actor]' - notify: '&cThe most recent warning for [player] has been deleted' + notify: 'Your most recent warning has been deleted by ' + notify: 'The most recent warning for has been deleted' error: - noWarnings: '&c[player] has no warnings to delete' + noWarnings: ' has no warnings to delete' bmclear: - notify: '&c[player] has had their [type] cleared' + notify: ' has had their cleared' error: - invalid: '&cInvalid type, please choose between banrecords, muterecords, kicks, notes or warnings' + invalid: 'Invalid type, please choose between banrecords, muterecords, kicks, notes or warnings' bmutils: missingplayers: - notify: '&c[amount] missing players added' - noneFound: '&a0 missing players found' - found: '&c[amount] missing player data found. Fixing...' + notify: ' missing players added' + noneFound: '0 missing players found' + found: ' missing player data found. Fixing...' error: - failedLookup: '&cFailed to lookup player [uuid], check server logs' - complete: '&a[amount] players resolved, please restart your server for failed punishments to take affect' + failedLookup: 'Failed to lookup player , check server logs' + complete: ' players resolved, please restart your server for failed punishments to take affect' duplicates: lookup: - notFound: '&aNo duplicate player names found' + notFound: 'No duplicate player names found' error: - invalidName: '&cInvalid name, must be 16 characters or less and contain only letters, numbers and an underscore' - nameExists: '&cA player with that name already exists' - success: '&aPlayer name set to [player] successfully' + invalidName: 'Invalid name, must be 16 characters or less and contain only letters, numbers and an underscore' + nameExists: 'A player with that name already exists' + success: 'Player name set to successfully' bmrollback: - notify: '&c[player] has had their [type] actions undone' + notify: ' has had their actions undone' error: - invalid: '&cInvalid type [type], please choose between [types]' + invalid: 'Invalid type , please choose between ' sync: player: - started: '&aStarting force [type] synchronisation' - finished: '&aForced [type] synchronisation complete' + started: 'Starting force synchronisation' + finished: 'Forced synchronisation complete' update: - notify: '&6[BanManager] &aAn update is available' + notify: '[BanManager] An update is available' notes: - header: '&6[player] has the following notes:' - joinAmount: '&6[player] has &e[amount] &6notes, click to view them' - note: '&6[[player]] &e[message] - &e[created]' - playerNote: '&a[[player]] &6[[actor]] &e[message] - &e[created]' + header: ' has the following notes:' + joinAmount: '"> has notes, click to view them' + note: '[] - ' + playerNote: '[] [] - ' dateTimeFormat: 'dd-MM-yyyy' - notify: '[player] has a new note attached by [actor]: [message]' + notify: ' has a new note attached by : ' error: - noNotes: '&c[player] has no notes' - noOnlineNotes: '&cNo online players have notes' + noNotes: ' has no notes' + noOnlineNotes: 'No online players have notes' report: - notify: '&6[player] has been reported by [actor] for &4[reason]' + notify: ' has been reported by for ' error: - cooldown: '&cThis player was reported too recently, try again later' + cooldown: 'This player was reported too recently, try again later' assign: - player: '&aReport [id] assigned to [player]' - notify: '&aYou have been assigned report [id] by [actor]' + player: 'Report assigned to ' + notify: 'You have been assigned report by ' unassign: - player: '&aReport [id] unassigned' + player: 'Report unassigned' close: notify: - closed: '&aReport [id] closed by [actor]' - command: '&aReport [id] closed by [actor] with [command]' - comment: '&aReport [id] closed by [actor] with [comment]' - dispatch: 'Executing command [command]' + closed: 'Report closed by ' + command: 'Report closed by with ' + comment: 'Report closed by with ' + dispatch: 'Executing command ' list: - noResults: '&cNo reports found' + noResults: 'No reports found' error: - invalidState: '&cReport state [state] not found' + invalidState: 'Report state not found' row: dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - header: '&e-- Reports ([count]) -- Page ([page]/[maxPage])' - all: '&7#[id] &e[[state]] &6- [created] - [player]' + header: '-- Reports () -- Page (/)' + all: '">Click to view details"># [] - - ' tp: error: - notFound: '&cReport not found' - worldNotFound: '&cWorld [world] could not be found' - invalidId: '&c[id] is not a valid report id' + notFound: 'Report not found' + worldNotFound: 'World could not be found' + invalidId: ' is not a valid report id' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' notify: - report: '&7#[id] &6[actor] reported [player] for &4[reason]&6 at [created]' - location: '[world] - [x], [y], [z]' + report: '# reported for at ' + location: ' - , , ' info: error: - notFound: '&cReport not found' - invalidId: '&c[id] is not a valid report id' + notFound: 'Report not found' + invalidId: ' is not a valid report id' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' notify: - report: '&7#[id] &6[actor] reported [player] for &4[reason]&6 at [created]' - location: '[world] - [x], [y], [z]' + report: '# reported for at ' + location: ' - , , ' + actions: + assign: '">Assign to yourself">[Assign]' + close: '">Close this report">[Close]' + tp: '">Teleport to location">[TP]' + feedback: + assigned: 'Your report # has been assigned to ' + closed: 'Your report # has been closed by ' addnoteall: - notify: '&c[player] will have a new attached by [actor]: [message]' + notify: ' will have a new attached by : ' banlist: - header: '&6There are [bans] [type] bans:' + header: 'There are bans:' + row: + player: '">Click for info"> - ' + ip: ' - ' + iprange: ' - - ' bmactivity: row: - all: '&a[&f[type]&a] &6[player]&f - &6[actor]&f - &e[created]' - player: '&a[&f[type]&a] &6[player]&f - &e[created]' + all: '[] - - ' + player: '[] - ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' - noResults: '&cNo results found' + noResults: 'No results found' bmdelete: - notify: '&a[rows] rows deleted' + notify: ' rows deleted' error: - invalid: '&cInvalid type, please choose between banrecords, muterecords, kicks, notes or warnings' - invalidId: '&c[id] is not a valid number' + invalid: 'Invalid type, please choose between banrecords, muterecords, kicks, notes or warnings' + invalidId: ' is not a valid number' denyalts: player: - disallowed: '&cThe IP address you are joining from is linked to a banned player' + disallowed: 'The IP address you are joining from is linked to a banned player' reasons: - row: '[hashtag] = [reason]' + row: ' = ' + + dashboard: + header: ' Staff Dashboard ' + activeBans: 'Active Bans: ' + activeMutes: 'Active Mutes: ' + openReports: 'Open Reports: View reports">[View]' + recentActivity: 'Recent Activity (24h): ' + footer: ' ' diff --git a/e2e/platforms/sponge/configs/banmanager/notifications.yml b/e2e/platforms/sponge/configs/banmanager/notifications.yml new file mode 100644 index 000000000..75b1fb646 --- /dev/null +++ b/e2e/platforms/sponge/configs/banmanager/notifications.yml @@ -0,0 +1,81 @@ +# Notifications Configuration +# Controls how punishment notifications are delivered to staff and players +# +# Each notification event can specify delivery channels: +# chat: true/false - Send via chat message (default: true) +# actionbar: true/false - Send via action bar (disappears after a few seconds) +# title: true/false - Send via title/subtitle overlay +# sound: '' - Sound to play (empty to disable). Use Minecraft sound names e.g. entity.experience_orb.pickup +# +# Title settings (only used when title: true): +# titleFadeIn: ticks for fade in (20 ticks = 1 second) +# titleStay: ticks to stay on screen +# titleFadeOut: ticks for fade out +# +# Sound settings: +# soundVolume: 0.0 - 1.0 +# soundPitch: 0.0 - 2.0 +# +# Platform notes: +# - BungeeCord: title, showTitle and playSound are not supported (ignored silently) +# - Sponge API7: playSound is not supported (ignored silently) +# - All other platforms (Bukkit/Paper, Velocity, Fabric, Sponge API8+) support all channels + +staff: + ban: + chat: true + actionbar: false + title: false + sound: 'entity.experience_orb.pickup' + soundVolume: 1.0 + soundPitch: 1.0 + tempban: + chat: true + actionbar: false + title: false + sound: 'entity.experience_orb.pickup' + soundVolume: 1.0 + soundPitch: 1.0 + mute: + chat: true + actionbar: false + title: false + sound: '' + soundVolume: 1.0 + soundPitch: 1.0 + tempmute: + chat: true + actionbar: false + title: false + sound: '' + soundVolume: 1.0 + soundPitch: 1.0 + warn: + chat: true + actionbar: false + title: false + sound: 'entity.experience_orb.pickup' + soundVolume: 1.0 + soundPitch: 1.0 + report: + chat: true + actionbar: false + title: false + sound: 'block.note_block.pling' + soundVolume: 1.0 + soundPitch: 1.0 + duplicateIp: + chat: true + actionbar: false + title: false + sound: '' + soundVolume: 1.0 + soundPitch: 1.0 + +player: + muted: + actionbar: true + warned: + sound: 'entity.villager.no' + soundVolume: 1.0 + soundPitch: 1.0 diff --git a/e2e/platforms/sponge7/configs/banmanager/messages.yml b/e2e/platforms/sponge7/configs/banmanager/messages.yml index cd7f4290c..494d65579 100644 --- a/e2e/platforms/sponge7/configs/banmanager/messages.yml +++ b/e2e/platforms/sponge7/configs/banmanager/messages.yml @@ -1,418 +1,474 @@ -# Variables -# [reason] = Ban/Mute reason -# [player] = The name of the player -# [ip] = The banned ip -# [actor] = Who banned/muted -# [expires] = How long until the ban/mute ends +# Message templates use MiniMessage formatting: https://docs.advntr.dev/minimessage/format.html +# Placeholders use angle brackets, e.g. , , , , + +tokens: + appeal_url: 'https://yourdomain.com/appeal' + server_name: 'My Server' + discord_url: 'https://discord.gg/example' + rules_url: 'https://yourdomain.com/rules' messages: - duplicateIP: '&cWarning: [player] has the same IP as the following banned players:\n&6[players]' - duplicateIPAlts: '&cWarning: [player] has the same IP as the following players:\n&6[players]' - configReloaded: '�ff00Configuration &#ff5733reloaded &asuccessfully!' + duplicateIP: 'Warning: has the same IP as the following banned players:\n' + duplicateIPAlts: 'Warning: has the same IP as the following players:\n' + configReloaded: 'Configuration reloaded successfully!' deniedNotify: - player: '&cWarning: [player] attempted to join the server but was denied due to - &4[reason]' - ip: '&cWarning: [ip] attempted to join the server but was denied due to &4[reason]' - deniedMaxIp: '&cToo many players with your ip address online' - deniedMultiaccounts: '&cToo many players with your ip address logged in recently' - deniedCountry: '&cYou may not connect from your region' + player: 'Warning: attempted to join the server but was denied due to ' + ip: 'Warning: attempted to join the server but was denied due to ' + deniedMaxIp: 'Too many players with your ip address online' + deniedMultiaccounts: 'Too many players with your ip address logged in recently' + deniedCountry: 'You may not connect from your region' + time: - now: now - year: year - years: years - month: month - months: months - week: week - weeks: weeks - day: day - days: days - hour: hour - hours: hours - minute: minute - minutes: minutes - second: second - seconds: seconds - never: never + now: 'now' + year: 'year' + years: 'years' + month: 'month' + months: 'months' + week: 'week' + weeks: 'weeks' + day: 'day' + days: 'days' + hour: 'hour' + hours: 'hours' + minute: 'minute' + minutes: 'minutes' + second: 'second' + seconds: 'seconds' + never: 'never' error: - invalid: '&cYour time length is invalid' - limit: '&cYou cannot perform this action for that length of time' - none: none + invalid: 'Your time length is invalid' + limit: 'You cannot perform this action for that length of time' + + none: 'none' + # General command text sender: error: - notFound: '&c[player] not found, are you sure they exist?' - offline: '&c[player] is offline' - noSelf: '&cYou cannot perform that action on yourself!' - exception: '&cAn error occured whilst attempting to perform this command. Please - check the console for further details.' - invalidIp: '&cInvalid IP address, expecting w.x.y.z format' - offlinePermission: '&cYou are not allowed to perform this action on an offline - player' - exempt: '&c[player] is exempt from that action' - noPermission: '&cYou do not have permission to perform that action' - invalidReason: '&c[reason] is no valid reason.' + notFound: ' not found, are you sure they exist?' + offline: ' is offline' + noSelf: 'You cannot perform that action on yourself!' + exception: 'An error occured whilst attempting to perform this command. Please check the console for further details.' + invalidIp: 'Invalid IP address, expecting w.x.y.z format' + offlinePermission: 'You are not allowed to perform this action on an offline player' + ambiguousPlayer: 'Multiple players match "". Please use their full name.' + exempt: ' is exempt from that action' + noPermission: 'You do not have permission to perform that action' + noConsole: 'This command cannot be used from console' + invalidReason: ' is no valid reason.' + # Commands alts: header: 'Possible alts found:' + entry: '">' + separator: ', ' + + names: + header: 'Known names for :' + row: ' (first: , last: )' + interactive: ' (first: , last: )">">' + separator: ', ' + dateTimeFormat: 'dd-MM-yyyy' + none: 'No name history found' + export: error: - inProgress: '&cAn export is already in progress, please wait' + inProgress: 'An export is already in progress, please wait' player: - started: '&aPlayer ban export started' - finished: '&aPlayer ban export finished, file [file] created' + started: 'Player ban export started' + finished: 'Player ban export finished, file created' ip: - started: '&aIP ban export started' - finished: '&aIP ban export finished, file [file] created' + started: 'IP ban export started' + finished: 'IP ban export finished, file created' + import: error: - inProgress: '&cAn import is already in progress, please wait' + inProgress: 'An import is already in progress, please wait' player: - started: '&aPlayer ban import started' - finished: '&aPlayer ban import finished' + started: 'Player ban import started' + finished: 'Player ban import finished' ip: - started: '&aIP ban import started' - finished: '&aIP ban import finished' + started: 'IP ban import started' + finished: 'IP ban import finished' advancedban: - started: '&aAdvancedBan import started' - finished: '&aAdvancedBan import finished' + started: 'AdvancedBan import started' + finished: 'AdvancedBan import finished' h2: - started: '&aH2 import started' - finished: '&aH2 import finished, please restart the server' + started: 'H2 import started' + finished: 'H2 import finished, please restart the server' litebans: - started: '&aLiteBans import started' - finished: '&aLiteBans import finished' + started: 'LiteBans import started' + finished: 'LiteBans import finished' + info: error: - invalidIndex: '&cInvalid player option used' - indexRequired: '&cMultiple players named [name] found, please select a player - by providing an index between 1 and [size], e.g. /bminfo [name] 1' - index: '&7#[index] - &6[name] - &4[uuid]' + invalidIndex: 'Invalid player option used' + indexRequired: 'Multiple players named found, please select a player by providing an index between 1 and , e.g. /bminfo 1' + index: '# - - ' stats: - player: '&6[player] has been banned [bans] times, muted [mutes] times, kicked - [kicks] times and warned [warns] times ([warnPoints] Points), has [notes] - notes and been reported [reports] times' - ip: '&6This ip has been banned [bans] times, muted [mutes] times and range banned - [rangebans] times' - connection: '&6Their last connection was with [ip] on [lastSeen]' - geoip: 'Country: [country] City: [city]' + player: ' has been banned times, muted times, kicked times and warned + times ( Points), has notes and been reported times' + ip: 'This ip has been banned times, muted times and range banned times' + connection: 'Their last connection was with on ' + geoip: 'Country: City: ' ban: - permanent: '&6Currently banned for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently banned for &4[reason]&6 by [actor] at [created] which - expires in [expires]' - dateTimeFormat: dd-MM-yyyy HH:mm:ss + permanent: 'Currently banned for by at ' + temporary: 'Currently banned for by at which expires in ' + dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' ipban: - permanent: '&6Currently banned for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently banned for &4[reason]&6 by [actor] at [created] which - expires in [expires]' - dateTimeFormat: dd-MM-yyyy HH:mm:ss + permanent: 'Currently banned for by at ' + temporary: 'Currently banned for by at which expires in ' + dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' iprangeban: - permanent: '&6[from] - [to] banned for &4[reason]&6 by [actor] at [created]' - temporary: '&6[from] - [to] banned for &4[reason]&6 by [actor] at [created] - which expires in [expires]' - dateTimeFormat: dd-MM-yyyy HH:mm:ss + permanent: ' - banned for by at ' + temporary: ' - banned for by at which expires in ' + dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' ipmute: - permanent: '&6Currently muted for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently muted for &4[reason]&6 by [actor] at [created] which - expires in [expires]' - dateTimeFormat: dd-MM-yyyy HH:mm:ss + permanent: 'Currently muted for by at ' + temporary: 'Currently muted for by at which expires in ' + dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' mute: - permanent: '&6Currently muted for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently muted for &4[reason]&6 by [actor] at [created] which - expires in [expires]' - temporaryOnline: '&6Currently muted for &4[reason]&6 by [actor] at [created] which - expires in [expires] (online time)' - temporaryOnlinePaused: '&6Currently muted for &4[reason]&6 by [actor] at [created] - with [remaining] remaining (online time, paused)' - dateTimeFormat: dd-MM-yyyy HH:mm:ss + permanent: 'Currently muted for by at ' + temporary: 'Currently muted for by at which expires in ' + temporaryOnline: 'Currently muted for by at which expires in (online time)' + temporaryOnlinePaused: 'Currently muted for by at with remaining (online time, paused)' + dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' website: - player: https://yourdomain.com/player/[uuid] - ip: http://yourdomain.com/index.php?action=viewip&ip=[ip]&server=0 + player: 'https://yourdomain.com/player/' + ip: 'http://yourdomain.com/index.php?action=viewip&ip=&server=0' history: - row: '&7#[id] &a[&f[type]&a] &6[actor]&f [meta] [reason] - &e[created]' - dateTimeFormat: dd-MM-yyyy HH:mm:ss - noResults: '&cNo results found' + row: '# [] - ' + dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' + noResults: 'No results found' ips: - row: '&e[ip] - &6[join] - [leave]' - dateTimeFormat: dd-MM-yyyy HH:mm:ss + row: ' - - ' + dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' + kick: player: - noReason: '&6You have been kicked' - reason: '&6You have been kicked for &4[reason]' + noReason: 'You have been kicked' + reason: 'You have been kicked for ' notify: - noReason: '&6[player] has been kicked by [actor]' - reason: '&6[player] has been kicked by [actor] for &4[reason]' + noReason: ' has been kicked by ">View player info">[Info]' + reason: ' has been kicked by for ">View player info">[Info]' + kickall: player: - noReason: '&6You have been kicked' - reason: '&6You have been kicked for &4[reason]' + noReason: 'You have been kicked' + reason: 'You have been kicked for ' notify: - noReason: All players have been kicked by [actor] - reason: All players have been kicked by [actor] for &4[reason] + noReason: 'All players have been kicked by ' + reason: 'All players have been kicked by for ' + ban: player: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' - dateTimeFormat: yyyy-MM-dd HH:mm:ss - notify: '&6[player] has been permanently banned by [actor] for &4[reason]' + disallowed: 'You are banned from this server\n \nReason: \nBanned by: \nDate: \n \nAppeal at ' + kick: 'You have been banned\n \nReason: \nBanned by: ' + dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' + notify: ' has been permanently banned by for ">View player info">[Info] ">Unban player">[Unban]' error: - exists: '&c[player] is already banned' - cooldown: '&cThis player was banned too recently, try again later' + exists: ' is already banned' + cooldown: 'This player was banned too recently, try again later' + banall: - notify: '&6[player] will be permanently banned by [actor] for &4[reason]' + notify: ' will be permanently banned by for ' + tempban: player: - disallowed: '&6You have been temporarily banned from this server for &4[reason] - \n&6It expires in [expires]' - kick: '&6You have been temporarily banned for &4[reason]' - dateTimeFormat: yyyy-MM-dd HH:mm:ss - notify: '&6[player] has been temporarily banned for [expires] by [actor] for &4[reason]' + disallowed: 'You are temporarily banned from this server\n \nReason: \nBanned by: \nExpires: \nDate: \n \nAppeal at ' + kick: 'You have been temporarily banned\n \nReason: \nBanned by: \nExpires: ' + dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' + notify: ' has been temporarily banned for by for ">View player info">[Info] ">Unban player">[Unban]' + tempbanall: - notify: '&6[player] will be temporarily banned for [expires] by [actor] for &4[reason]' + notify: ' will be temporarily banned for by for ' + unban: - notify: '&6[player] has been unbanned by [actor]' + notify: ' has been unbanned by ' error: - noExists: '&c[player] is not banned' - notOwn: '&c[player] was not banned by you, unable to unban' + noExists: ' is not banned' + notOwn: ' was not banned by you, unable to unban' + unbanall: - notify: '&6[player] will be unbanned by [actor]' + notify: ' will be unbanned by ' + mute: player: - blocked: '&cYou may not use the [command] command whilst muted!' - disallowed: '&6You have been permanently muted for &4[reason] &6by [actor]' - broadcast: '&4[Muted] [player]&7 [message]' - notify: '&6[player] has been permanently muted by [actor] for &4[reason]' + blocked: 'You may not use the command whilst muted!' + disallowed: 'You have been permanently muted for by ' + broadcast: '[Muted] ' + notify: ' has been permanently muted by for ">View player info">[Info] ">Unmute player">[Unmute]' error: - exists: '&c[player] is already muted' - cooldown: '&cThis player was muted too recently, try again later' + exists: ' is already muted' + cooldown: 'This player was muted too recently, try again later' + muteip: ip: - disallowed: '&6You have been permanently muted for &4[reason] &6by [actor]' - broadcast: '&4[Muted] [player]&7 [message]' - notify: '&6[ip] ([players]) have been permanently muted by [actor] for &4[reason]' + disallowed: 'You have been permanently muted for by ' + broadcast: '[Muted] ' + notify: ' () have been permanently muted by for ' error: - exists: '&c[ip] is already muted' + exists: ' is already muted' + muteall: - notify: '&6[player] will be permanently muted by [actor] for &4[reason]' + notify: ' will be permanently muted by for ' + tempmute: player: - disallowed: '&6You have been temporarily muted for &4[reason] &6by [actor] which - expires in [expires]' - disallowedOnline: '&6You have been temporarily muted for &4[reason] &6by [actor] which - expires in [expires] (online time)' - notify: '&6[player] has been temporarily muted for [expires] by [actor] for &4[reason]' - notifyOnline: '&6[player] has been temporarily muted for [expires] (online time) by [actor] for &4[reason]' + disallowed: 'You have been temporarily muted for by which expires in ' + disallowedOnline: 'You have been temporarily muted for by which expires in (online time)' + notify: ' has been temporarily muted for by for ">View player info">[Info] ">Unmute player">[Unmute]' + notifyOnline: ' has been temporarily muted for (online time) by for ' error: - exists: '&c[player] is already muted' + exists: ' is already muted' + tempmuteip: ip: - disallowed: '&6You have been temporarily muted for &4[reason] &6by [actor] which - expires in [expires]' - notify: '&6[ip] ([players]) have been temporarily muted for [expires] by [actor] - for &4[reason]' + disallowed: 'You have been temporarily muted for by which expires in ' + notify: ' () have been temporarily muted for by for ' error: - exists: '&c[ip] is already muted' + exists: ' is already muted' + tempmuteall: - notify: '&6[player] will be temporarily muted for [expires] by [actor] for &4[reason]' + notify: ' will be temporarily muted for by for ' + unmute: - notify: '&6[player] has been unmuted by [actor]' - player: '&6You have been unmuted by [actor]' + notify: ' has been unmuted by ' + player: 'You have been unmuted by ' error: - noExists: '&c[player] is not muted' - notOwn: '&c[player] was not muted by you, unable to unmute' + noExists: ' is not muted' + notOwn: ' was not muted by you, unable to unmute' + unmuteip: - notify: '&6[ip] has been unmuted by [actor]' + notify: ' has been unmuted by ' error: - noExists: '&c[ip] is not muted' - notOwn: '&c[ip] was not muted by you, unable to unmute' + noExists: ' is not muted' + notOwn: ' was not muted by you, unable to unmute' + unmuteall: - notify: '&6[player] will be unmuted by [actor]' + notify: ' will be unmuted by ' + banname: name: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' - dateTimeFormat: yyyy-MM-dd HH:mm:ss - notify: '&6Name [name] has been permanently banned by [actor] for &4[reason]' + disallowed: 'You have been banned from this server for ' + kick: 'You have been banned permanently for ' + dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' + notify: 'Name has been permanently banned by for ' error: - exists: '&cName [name] is already banned' + exists: 'Name is already banned' + tempbanname: name: - disallowed: '&6You have been banned from this server for &4[reason] \n&6It expires - in [expires]' - kick: '&6You have been temporarily banned for &4[reason]' - dateTimeFormat: yyyy-MM-dd HH:mm:ss - notify: '&6Name [name] has been temporarily banned for [expires] by [actor] for - &4[reason]' + disallowed: 'You have been banned from this server for \nIt expires in ' + kick: 'You have been temporarily banned for ' + dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' + notify: 'Name has been temporarily banned for by for ' + unbanname: - notify: '&6Name [name] has been unbanned by [actor]' + notify: 'Name has been unbanned by ' error: - noExists: '&cName [name] is not banned' + noExists: 'Name is not banned' + banip: ip: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' - dateTimeFormat: yyyy-MM-dd HH:mm:ss - notify: '&6[ip] ([players]) has been permanently banned by [actor] for &4[reason]' + disallowed: 'You have been banned from this server for ' + kick: 'You have been banned permanently for ' + dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' + notify: ' () has been permanently banned by for ' error: - exists: '&c[ip] is already banned' - cooldown: '&cThis ip was banned too recently, try again later' + exists: ' is already banned' + cooldown: 'This ip was banned too recently, try again later' + baniprange: error: - invalid: '&cInvalid range, please use cidr notation 192.168.0.1/16 or wildcard - 192.168.*.*' - minMax: '&cRange must be lowest to highest' - exists: '&cA ban containing those ranges already exists' + invalid: 'Invalid range, please use cidr notation 192.168.0.1/16 or wildcard 192.168.*.*' + minMax: 'Range must be lowest to highest' + exists: 'A ban containing those ranges already exists' ip: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' - dateTimeFormat: yyyy-MM-dd HH:mm:ss - notify: '&6[from] - [to] have been banned by [actor]' + disallowed: 'You have been banned from this server for ' + kick: 'You have been banned permanently for ' + dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' + notify: ' - have been banned by ' + tempbaniprange: - notify: '&6[from] - [to] has been temporarily banned for [expires] by [actor]' + notify: ' - has been temporarily banned for by ' ip: - disallowed: '&6You have been banned from this server for &4[reason] \n&6It expires - in [expires]' - kick: '&6You have been temporarily banned for [expires] by [actor] for &4[reason]' - dateTimeFormat: yyyy-MM-dd HH:mm:ss + disallowed: 'You have been banned from this server for \nIt expires in ' + kick: 'You have been temporarily banned for by for ' + dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' + unbaniprange: - notify: '&6[from] - [to] has been unbanned by [actor]' + notify: ' - has been unbanned by ' + banipall: - notify: '&6[ip] will be permanently banned by [actor] for &4[reason]' + notify: ' will be permanently banned by for ' + tempbanip: ip: - disallowed: '&6You have been banned from this server for &4[reason] \n&6It expires - in [expires]' - kick: '&6You have been temporarily banned for &4[reason]' - dateTimeFormat: yyyy-MM-dd HH:mm:ss - notify: '&6[ip] ([players]) has been temporarily banned for [expires] by [actor] - for &4[reason]' + disallowed: 'You have been banned from this server for \nIt expires in ' + kick: 'You have been temporarily banned for ' + dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' + notify: ' () has been temporarily banned for by for ' + tempbanipall: - notify: '&6[ip] will be temporarily banned for [expires] by [actor] for &4[reason]' + notify: ' will be temporarily banned for by for ' + unbanip: - notify: '&6[ip] has been unbanned by [actor]' + notify: ' has been unbanned by ' error: - noExists: '&c[ip] is not banned' - notOwn: '&c[ip] was not banned by you, unable to unban' + noExists: ' is not banned' + notOwn: ' was not banned by you, unable to unban' + unbanipall: - notify: '&6[ip] will be unbanned by [actor]' + notify: ' will be unbanned by ' + warn: player: - warned: '&6You have been warned by [actor] for &4[reason]' + warned: 'You have been warned by for ' disallowed: - header: '&cYou may not speak until you have accepted your most recent warning. - Please type the following:' - reason: '&6[reason]' - removed: '&aThank you for your understanding, you may now speak again' - notify: '&6[player] has been warned by [actor] for &4[reason]' + header: 'You may not speak until you have accepted your most recent warning. Please type the following:' + reason: '' + removed: 'Thank you for your understanding, you may now speak again' + notify: ' has been warned by for ">View player info">[Info]' error: - cooldown: '&cThis player was warned too recently, try again later' + cooldown: 'This player was warned too recently, try again later' + tempwarn: player: - warned: '&6You have been warned for [expires] by [actor] for &4[reason]' - notify: '&6[player] has been warned for [expires] by [actor] for &4[reason]' + warned: 'You have been warned for by for ' + notify: ' has been warned for by for ">View player info">[Info]' + dwarn: player: - notify: '&6Your most recent warning has been deleted by &4[actor]' - notify: '&cThe most recent warning for [player] has been deleted' + notify: 'Your most recent warning has been deleted by ' + notify: 'The most recent warning for has been deleted' error: - noWarnings: '&c[player] has no warnings to delete' + noWarnings: ' has no warnings to delete' + bmclear: - notify: '&c[player] has had their [type] cleared' + notify: ' has had their cleared' error: - invalid: '&cInvalid type, please choose between banrecords, muterecords, kicks, - notes or warnings' + invalid: 'Invalid type, please choose between banrecords, muterecords, kicks, notes or warnings' + bmutils: missingplayers: - notify: '&c[amount] missing players added' - noneFound: '&a0 missing players found' - found: '&c[amount] missing player data found. Fixing...' + notify: ' missing players added' + noneFound: '0 missing players found' + found: ' missing player data found. Fixing...' error: - failedLookup: '&cFailed to lookup player [uuid], check server logs' - complete: '&a[amount] players resolved, please restart your server for failed - punishments to take affect' + failedLookup: 'Failed to lookup player , check server logs' + complete: ' players resolved, please restart your server for failed punishments to take affect' duplicates: lookup: - notFound: '&aNo duplicate player names found' + notFound: 'No duplicate player names found' error: - invalidName: '&cInvalid name, must be 16 characters or less and contain only - letters, numbers and an underscore' - nameExists: '&cA player with that name already exists' - success: '&aPlayer name set to [player] successfully' + invalidName: 'Invalid name, must be 16 characters or less and contain only letters, numbers and an underscore' + nameExists: 'A player with that name already exists' + success: 'Player name set to successfully' + bmrollback: - notify: '&c[player] has had their [type] actions undone' + notify: ' has had their actions undone' error: - invalid: '&cInvalid type [type], please choose between [types]' + invalid: 'Invalid type , please choose between ' + sync: player: - started: '&aStarting force [type] synchronisation' - finished: '&aForced [type] synchronisation complete' + started: 'Starting force synchronisation' + finished: 'Forced synchronisation complete' + update: - notify: '&6[BanManager] &aAn update is available' + notify: '[BanManager] An update is available' + notes: - header: '&6[player] has the following notes:' - joinAmount: '&6[player] has &e[amount] &6notes, click to view them' - note: '&6[[player]] &e[message] - &e[created]' - playerNote: '&a[[player]] &6[[actor]] &e[message] - &e[created]' - dateTimeFormat: dd-MM-yyyy - notify: '[player] has a new note attached by [actor]: [message]' + header: ' has the following notes:' + joinAmount: '"> has notes, click to view them' + note: '[] - ' + playerNote: '[] [] - ' + dateTimeFormat: 'dd-MM-yyyy' + notify: ' has a new note attached by : ' error: - noNotes: '&c[player] has no notes' - noOnlineNotes: '&cNo online players have notes' + noNotes: ' has no notes' + noOnlineNotes: 'No online players have notes' + report: - notify: '&6[player] has been reported by [actor] for &4[reason]' + notify: ' has been reported by for ' error: - cooldown: '&cThis player was reported too recently, try again later' + cooldown: 'This player was reported too recently, try again later' assign: - player: '&aReport [id] assigned to [player]' - notify: '&aYou have been assigned report [id] by [actor]' + player: 'Report assigned to ' + notify: 'You have been assigned report by ' unassign: - player: '&aReport [id] unassigned' + player: 'Report unassigned' close: notify: - closed: '&aReport [id] closed by [actor]' - command: '&aReport [id] closed by [actor] with [command]' - comment: '&aReport [id] closed by [actor] with [comment]' - dispatch: Executing command [command] + closed: 'Report closed by ' + command: 'Report closed by with ' + comment: 'Report closed by with ' + dispatch: 'Executing command ' list: - noResults: '&cNo reports found' + noResults: 'No reports found' error: - invalidState: '&cReport state [state] not found' + invalidState: 'Report state not found' row: - dateTimeFormat: yyyy-MM-dd HH:mm:ss - header: '&e-- Reports ([count]) -- Page ([page]/[maxPage])' - all: '&7#[id] &e[[state]] &6- [created] - [player]' + dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' + header: '-- Reports () -- Page (/)' + all: '">Click to view details"># [] - - ' tp: error: - notFound: '&cReport not found' - worldNotFound: '&cWorld [world] could not be found' - invalidId: '&c[id] is not a valid report id' - dateTimeFormat: yyyy-MM-dd HH:mm:ss + notFound: 'Report not found' + worldNotFound: 'World could not be found' + invalidId: ' is not a valid report id' + dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' notify: - report: '&7#[id] &6[actor] reported [player] for &4[reason]&6 at [created]' - location: '[world] - [x], [y], [z]' + report: '# reported for at ' + location: ' - , , ' info: error: - notFound: '&cReport not found' - invalidId: '&c[id] is not a valid report id' - dateTimeFormat: yyyy-MM-dd HH:mm:ss + notFound: 'Report not found' + invalidId: ' is not a valid report id' + dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' notify: - report: '&7#[id] &6[actor] reported [player] for &4[reason]&6 at [created]' - location: '[world] - [x], [y], [z]' + report: '# reported for at ' + location: ' - , , ' + actions: + assign: '">Assign to yourself">[Assign]' + close: '">Close this report">[Close]' + tp: '">Teleport to location">[TP]' + feedback: + assigned: 'Your report # has been assigned to ' + closed: 'Your report # has been closed by ' + addnoteall: - notify: '&c[player] will have a new attached by [actor]: [message]' + notify: ' will have a new attached by : ' + banlist: - header: '&6There are [bans] [type] bans:' + header: 'There are bans:' + row: + player: '">Click for info"> - ' + ip: ' - ' + iprange: ' - - ' + bmactivity: row: - all: '&a[&f[type]&a] &6[player]&f - &6[actor]&f - &e[created]' - player: '&a[&f[type]&a] &6[player]&f - &e[created]' - dateTimeFormat: dd-MM-yyyy HH:mm:ss - noResults: '&cNo results found' + all: '[] - - ' + player: '[] - ' + dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' + noResults: 'No results found' + bmdelete: - notify: '&a[rows] rows deleted' + notify: ' rows deleted' error: - invalid: '&cInvalid type, please choose between banrecords, muterecords, kicks, - notes or warnings' - invalidId: '&c[id] is not a valid number' + invalid: 'Invalid type, please choose between banrecords, muterecords, kicks, notes or warnings' + invalidId: ' is not a valid number' + denyalts: player: - disallowed: '&cThe IP address you are joining from is linked to a banned player' + disallowed: 'The IP address you are joining from is linked to a banned player' + reasons: - row: '[hashtag] = [reason]' + row: ' = ' + + dashboard: + header: ' Staff Dashboard ' + activeBans: 'Active Bans: ' + activeMutes: 'Active Mutes: ' + openReports: 'Open Reports: View reports">[View]' + recentActivity: 'Recent Activity (24h): ' + footer: ' ' diff --git a/e2e/platforms/sponge7/configs/banmanager/messages/messages_en.yml b/e2e/platforms/sponge7/configs/banmanager/messages/messages_en.yml index 205a94c13..494d65579 100644 --- a/e2e/platforms/sponge7/configs/banmanager/messages/messages_en.yml +++ b/e2e/platforms/sponge7/configs/banmanager/messages/messages_en.yml @@ -1,20 +1,22 @@ -# Variables -# [reason] = Ban/Mute reason -# [player] = The name of the player -# [ip] = The banned ip -# [actor] = Who banned/muted -# [expires] = How long until the ban/mute ends +# Message templates use MiniMessage formatting: https://docs.advntr.dev/minimessage/format.html +# Placeholders use angle brackets, e.g. , , , , + +tokens: + appeal_url: 'https://yourdomain.com/appeal' + server_name: 'My Server' + discord_url: 'https://discord.gg/example' + rules_url: 'https://yourdomain.com/rules' messages: - duplicateIP: '&cWarning: [player] has the same IP as the following banned players:\n&6[players]' - duplicateIPAlts: '&cWarning: [player] has the same IP as the following players:\n&6[players]' - configReloaded: '&aConfiguration reloaded successfully!' + duplicateIP: 'Warning: has the same IP as the following banned players:\n' + duplicateIPAlts: 'Warning: has the same IP as the following players:\n' + configReloaded: 'Configuration reloaded successfully!' deniedNotify: - player: '&cWarning: [player] attempted to join the server but was denied due to &4[reason]' - ip: '&cWarning: [ip] attempted to join the server but was denied due to &4[reason]' - deniedMaxIp: '&cToo many players with your ip address online' - deniedMultiaccounts: '&cToo many players with your ip address logged in recently' - deniedCountry: '&cYou may not connect from your region' + player: 'Warning: attempted to join the server but was denied due to ' + ip: 'Warning: attempted to join the server but was denied due to ' + deniedMaxIp: 'Too many players with your ip address online' + deniedMultiaccounts: 'Too many players with your ip address logged in recently' + deniedCountry: 'You may not connect from your region' time: now: 'now' @@ -34,415 +36,439 @@ messages: seconds: 'seconds' never: 'never' error: - invalid: '&cYour time length is invalid' - limit: '&cYou cannot perform this action for that length of time' + invalid: 'Your time length is invalid' + limit: 'You cannot perform this action for that length of time' none: 'none' # General command text sender: error: - notFound: '&c[player] not found, are you sure they exist?' - offline: '&c[player] is offline' - noSelf: '&cYou cannot perform that action on yourself!' - exception: '&cAn error occured whilst attempting to perform this command. Please check the console for further details.' - invalidIp: '&cInvalid IP address, expecting w.x.y.z format' - offlinePermission: '&cYou are not allowed to perform this action on an offline player' - ambiguousPlayer: '&cMultiple players match "[player]". Please use their full name.' - exempt: '&c[player] is exempt from that action' - noPermission: '&cYou do not have permission to perform that action' - invalidReason: '&c[reason] is no valid reason.' + notFound: ' not found, are you sure they exist?' + offline: ' is offline' + noSelf: 'You cannot perform that action on yourself!' + exception: 'An error occured whilst attempting to perform this command. Please check the console for further details.' + invalidIp: 'Invalid IP address, expecting w.x.y.z format' + offlinePermission: 'You are not allowed to perform this action on an offline player' + ambiguousPlayer: 'Multiple players match "". Please use their full name.' + exempt: ' is exempt from that action' + noPermission: 'You do not have permission to perform that action' + noConsole: 'This command cannot be used from console' + invalidReason: ' is no valid reason.' # Commands alts: header: 'Possible alts found:' + entry: '">' + separator: ', ' names: - header: 'Known names for [player]:' - row: '&e[name] &7(first: [firstSeen], last: [lastSeen])' + header: 'Known names for :' + row: ' (first: , last: )' + interactive: ' (first: , last: )">">' + separator: ', ' dateTimeFormat: 'dd-MM-yyyy' - none: '&7No name history found' + none: 'No name history found' export: error: - inProgress: '&cAn export is already in progress, please wait' + inProgress: 'An export is already in progress, please wait' player: - started: '&aPlayer ban export started' - finished: '&aPlayer ban export finished, file [file] created' + started: 'Player ban export started' + finished: 'Player ban export finished, file created' ip: - started: '&aIP ban export started' - finished: '&aIP ban export finished, file [file] created' + started: 'IP ban export started' + finished: 'IP ban export finished, file created' import: error: - inProgress: '&cAn import is already in progress, please wait' + inProgress: 'An import is already in progress, please wait' player: - started: '&aPlayer ban import started' - finished: '&aPlayer ban import finished' + started: 'Player ban import started' + finished: 'Player ban import finished' ip: - started: '&aIP ban import started' - finished: '&aIP ban import finished' + started: 'IP ban import started' + finished: 'IP ban import finished' advancedban: - started: '&aAdvancedBan import started' - finished: '&aAdvancedBan import finished' + started: 'AdvancedBan import started' + finished: 'AdvancedBan import finished' h2: - started: '&aH2 import started' - finished: '&aH2 import finished, please restart the server' + started: 'H2 import started' + finished: 'H2 import finished, please restart the server' litebans: - started: '&aLiteBans import started' - finished: '&aLiteBans import finished' + started: 'LiteBans import started' + finished: 'LiteBans import finished' info: error: - invalidIndex: '&cInvalid player option used' - indexRequired: '&cMultiple players named [name] found, please select a player by providing an index between 1 and [size], e.g. /bminfo [name] 1' - index: '&7#[index] - &6[name] - &4[uuid]' + invalidIndex: 'Invalid player option used' + indexRequired: 'Multiple players named found, please select a player by providing an index between 1 and , e.g. /bminfo 1' + index: '# - - ' stats: - player: '&6[player] has been banned [bans] times, muted [mutes] times, kicked [kicks] times and warned [warns] - times ([warnPoints] Points), has [notes] notes and been reported [reports] times' - ip: '&6This ip has been banned [bans] times, muted [mutes] times and range banned [rangebans] times' - connection: '&6Their last connection was with [ip] on [lastSeen]' - geoip: 'Country: [country] City: [city]' + player: ' has been banned times, muted times, kicked times and warned + times ( Points), has notes and been reported times' + ip: 'This ip has been banned times, muted times and range banned times' + connection: 'Their last connection was with on ' + geoip: 'Country: City: ' ban: - permanent: '&6Currently banned for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently banned for &4[reason]&6 by [actor] at [created] which expires in [expires]' + permanent: 'Currently banned for by at ' + temporary: 'Currently banned for by at which expires in ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' ipban: - permanent: '&6Currently banned for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently banned for &4[reason]&6 by [actor] at [created] which expires in [expires]' + permanent: 'Currently banned for by at ' + temporary: 'Currently banned for by at which expires in ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' iprangeban: - permanent: '&6[from] - [to] banned for &4[reason]&6 by [actor] at [created]' - temporary: '&6[from] - [to] banned for &4[reason]&6 by [actor] at [created] which expires in [expires]' + permanent: ' - banned for by at ' + temporary: ' - banned for by at which expires in ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' ipmute: - permanent: '&6Currently muted for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently muted for &4[reason]&6 by [actor] at [created] which expires in [expires]' + permanent: 'Currently muted for by at ' + temporary: 'Currently muted for by at which expires in ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' mute: - permanent: '&6Currently muted for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently muted for &4[reason]&6 by [actor] at [created] which expires in [expires]' - temporaryOnline: '&6Currently muted for &4[reason]&6 by [actor] at [created] which expires in [expires] (online time)' - temporaryOnlinePaused: '&6Currently muted for &4[reason]&6 by [actor] at [created] with [remaining] remaining (online time, paused)' + permanent: 'Currently muted for by at ' + temporary: 'Currently muted for by at which expires in ' + temporaryOnline: 'Currently muted for by at which expires in (online time)' + temporaryOnlinePaused: 'Currently muted for by at with remaining (online time, paused)' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' website: - player: 'https://yourdomain.com/player/[uuid]' - ip: 'http://yourdomain.com/index.php?action=viewip&ip=[ip]&server=0' + player: 'https://yourdomain.com/player/' + ip: 'http://yourdomain.com/index.php?action=viewip&ip=&server=0' history: - row: '&7#[id] &a[&f[type]&a] &6[actor]&f [meta] [reason] - &e[created]' + row: '# [] - ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' - noResults: '&cNo results found' + noResults: 'No results found' ips: - row: '&e[ip] - &6[join] - [leave]' + row: ' - - ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' kick: player: - noReason: '&6You have been kicked' - reason: '&6You have been kicked for &4[reason]' + noReason: 'You have been kicked' + reason: 'You have been kicked for ' notify: - noReason: '&6[player] has been kicked by [actor]' - reason: '&6[player] has been kicked by [actor] for &4[reason]' + noReason: ' has been kicked by ">View player info">[Info]' + reason: ' has been kicked by for ">View player info">[Info]' kickall: player: - noReason: '&6You have been kicked' - reason: '&6You have been kicked for &4[reason]' + noReason: 'You have been kicked' + reason: 'You have been kicked for ' notify: - noReason: 'All players have been kicked by [actor]' - reason: 'All players have been kicked by [actor] for &4[reason]' + noReason: 'All players have been kicked by ' + reason: 'All players have been kicked by for ' ban: player: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' + disallowed: 'You are banned from this server\n \nReason: \nBanned by: \nDate: \n \nAppeal at ' + kick: 'You have been banned\n \nReason: \nBanned by: ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[player] has been permanently banned by [actor] for &4[reason]' + notify: ' has been permanently banned by for ">View player info">[Info] ">Unban player">[Unban]' error: - exists: '&c[player] is already banned' - cooldown: '&cThis player was banned too recently, try again later' + exists: ' is already banned' + cooldown: 'This player was banned too recently, try again later' banall: - notify: '&6[player] will be permanently banned by [actor] for &4[reason]' + notify: ' will be permanently banned by for ' tempban: player: - disallowed: '&6You have been temporarily banned from this server for &4[reason] \n&6It expires in [expires]' - kick: '&6You have been temporarily banned for &4[reason]' + disallowed: 'You are temporarily banned from this server\n \nReason: \nBanned by: \nExpires: \nDate: \n \nAppeal at ' + kick: 'You have been temporarily banned\n \nReason: \nBanned by: \nExpires: ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[player] has been temporarily banned for [expires] by [actor] for &4[reason]' + notify: ' has been temporarily banned for by for ">View player info">[Info] ">Unban player">[Unban]' tempbanall: - notify: '&6[player] will be temporarily banned for [expires] by [actor] for &4[reason]' + notify: ' will be temporarily banned for by for ' unban: - notify: '&6[player] has been unbanned by [actor]' + notify: ' has been unbanned by ' error: - noExists: '&c[player] is not banned' - notOwn: '&c[player] was not banned by you, unable to unban' + noExists: ' is not banned' + notOwn: ' was not banned by you, unable to unban' unbanall: - notify: '&6[player] will be unbanned by [actor]' + notify: ' will be unbanned by ' mute: player: - blocked: '&cYou may not use the [command] command whilst muted!' - disallowed: '&6You have been permanently muted for &4[reason] &6by [actor]' - broadcast: '&4[Muted] [player]&7 [message]' - notify: '&6[player] has been permanently muted by [actor] for &4[reason]' + blocked: 'You may not use the command whilst muted!' + disallowed: 'You have been permanently muted for by ' + broadcast: '[Muted] ' + notify: ' has been permanently muted by for ">View player info">[Info] ">Unmute player">[Unmute]' error: - exists: '&c[player] is already muted' - cooldown: '&cThis player was muted too recently, try again later' + exists: ' is already muted' + cooldown: 'This player was muted too recently, try again later' muteip: ip: - disallowed: '&6You have been permanently muted for &4[reason] &6by [actor]' - broadcast: '&4[Muted] [player]&7 [message]' - notify: '&6[ip] ([players]) have been permanently muted by [actor] for &4[reason]' + disallowed: 'You have been permanently muted for by ' + broadcast: '[Muted] ' + notify: ' () have been permanently muted by for ' error: - exists: '&c[ip] is already muted' + exists: ' is already muted' muteall: - notify: '&6[player] will be permanently muted by [actor] for &4[reason]' + notify: ' will be permanently muted by for ' tempmute: player: - disallowed: '&6You have been temporarily muted for &4[reason] &6by [actor] which expires in [expires]' - disallowedOnline: '&6You have been temporarily muted for &4[reason] &6by [actor] which expires in [expires] (online time)' - notify: '&6[player] has been temporarily muted for [expires] by [actor] for &4[reason]' - notifyOnline: '&6[player] has been temporarily muted for [expires] (online time) by [actor] for &4[reason]' + disallowed: 'You have been temporarily muted for by which expires in ' + disallowedOnline: 'You have been temporarily muted for by which expires in (online time)' + notify: ' has been temporarily muted for by for ">View player info">[Info] ">Unmute player">[Unmute]' + notifyOnline: ' has been temporarily muted for (online time) by for ' error: - exists: '&c[player] is already muted' + exists: ' is already muted' tempmuteip: ip: - disallowed: '&6You have been temporarily muted for &4[reason] &6by [actor] which expires in [expires]' - notify: '&6[ip] ([players]) have been temporarily muted for [expires] by [actor] for &4[reason]' + disallowed: 'You have been temporarily muted for by which expires in ' + notify: ' () have been temporarily muted for by for ' error: - exists: '&c[ip] is already muted' + exists: ' is already muted' tempmuteall: - notify: '&6[player] will be temporarily muted for [expires] by [actor] for &4[reason]' + notify: ' will be temporarily muted for by for ' unmute: - notify: '&6[player] has been unmuted by [actor]' - player: '&6You have been unmuted by [actor]' + notify: ' has been unmuted by ' + player: 'You have been unmuted by ' error: - noExists: '&c[player] is not muted' - notOwn: '&c[player] was not muted by you, unable to unmute' + noExists: ' is not muted' + notOwn: ' was not muted by you, unable to unmute' unmuteip: - notify: '&6[ip] has been unmuted by [actor]' + notify: ' has been unmuted by ' error: - noExists: '&c[ip] is not muted' - notOwn: '&c[ip] was not muted by you, unable to unmute' + noExists: ' is not muted' + notOwn: ' was not muted by you, unable to unmute' unmuteall: - notify: '&6[player] will be unmuted by [actor]' + notify: ' will be unmuted by ' banname: name: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' + disallowed: 'You have been banned from this server for ' + kick: 'You have been banned permanently for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6Name [name] has been permanently banned by [actor] for &4[reason]' + notify: 'Name has been permanently banned by for ' error: - exists: '&cName [name] is already banned' + exists: 'Name is already banned' tempbanname: name: - disallowed: '&6You have been banned from this server for &4[reason] \n&6It expires in [expires]' - kick: '&6You have been temporarily banned for &4[reason]' + disallowed: 'You have been banned from this server for \nIt expires in ' + kick: 'You have been temporarily banned for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6Name [name] has been temporarily banned for [expires] by [actor] for &4[reason]' + notify: 'Name has been temporarily banned for by for ' unbanname: - notify: '&6Name [name] has been unbanned by [actor]' + notify: 'Name has been unbanned by ' error: - noExists: '&cName [name] is not banned' + noExists: 'Name is not banned' banip: ip: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' + disallowed: 'You have been banned from this server for ' + kick: 'You have been banned permanently for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[ip] ([players]) has been permanently banned by [actor] for &4[reason]' + notify: ' () has been permanently banned by for ' error: - exists: '&c[ip] is already banned' - cooldown: '&cThis ip was banned too recently, try again later' + exists: ' is already banned' + cooldown: 'This ip was banned too recently, try again later' baniprange: error: - invalid: '&cInvalid range, please use cidr notation 192.168.0.1/16 or wildcard 192.168.*.*' - minMax: '&cRange must be lowest to highest' - exists: '&cA ban containing those ranges already exists' + invalid: 'Invalid range, please use cidr notation 192.168.0.1/16 or wildcard 192.168.*.*' + minMax: 'Range must be lowest to highest' + exists: 'A ban containing those ranges already exists' ip: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' + disallowed: 'You have been banned from this server for ' + kick: 'You have been banned permanently for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[from] - [to] have been banned by [actor]' + notify: ' - have been banned by ' tempbaniprange: - notify: '&6[from] - [to] has been temporarily banned for [expires] by [actor]' + notify: ' - has been temporarily banned for by ' ip: - disallowed: '&6You have been banned from this server for &4[reason] \n&6It expires in [expires]' - kick: '&6You have been temporarily banned for [expires] by [actor] for &4[reason]' + disallowed: 'You have been banned from this server for \nIt expires in ' + kick: 'You have been temporarily banned for by for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' unbaniprange: - notify: '&6[from] - [to] has been unbanned by [actor]' + notify: ' - has been unbanned by ' banipall: - notify: '&6[ip] will be permanently banned by [actor] for &4[reason]' + notify: ' will be permanently banned by for ' tempbanip: ip: - disallowed: '&6You have been banned from this server for &4[reason] \n&6It expires in [expires]' - kick: '&6You have been temporarily banned for &4[reason]' + disallowed: 'You have been banned from this server for \nIt expires in ' + kick: 'You have been temporarily banned for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[ip] ([players]) has been temporarily banned for [expires] by [actor] for &4[reason]' + notify: ' () has been temporarily banned for by for ' tempbanipall: - notify: '&6[ip] will be temporarily banned for [expires] by [actor] for &4[reason]' + notify: ' will be temporarily banned for by for ' unbanip: - notify: '&6[ip] has been unbanned by [actor]' + notify: ' has been unbanned by ' error: - noExists: '&c[ip] is not banned' - notOwn: '&c[ip] was not banned by you, unable to unban' + noExists: ' is not banned' + notOwn: ' was not banned by you, unable to unban' unbanipall: - notify: '&6[ip] will be unbanned by [actor]' + notify: ' will be unbanned by ' warn: player: - warned: '&6You have been warned by [actor] for &4[reason]' + warned: 'You have been warned by for ' disallowed: - header: '&cYou may not speak until you have accepted your most recent warning. Please type the following:' - reason: '&6[reason]' - removed: '&aThank you for your understanding, you may now speak again' - notify: '&6[player] has been warned by [actor] for &4[reason]' + header: 'You may not speak until you have accepted your most recent warning. Please type the following:' + reason: '' + removed: 'Thank you for your understanding, you may now speak again' + notify: ' has been warned by for ">View player info">[Info]' error: - cooldown: '&cThis player was warned too recently, try again later' + cooldown: 'This player was warned too recently, try again later' tempwarn: player: - warned: '&6You have been warned for [expires] by [actor] for &4[reason]' - notify: '&6[player] has been warned for [expires] by [actor] for &4[reason]' + warned: 'You have been warned for by for ' + notify: ' has been warned for by for ">View player info">[Info]' dwarn: player: - notify: '&6Your most recent warning has been deleted by &4[actor]' - notify: '&cThe most recent warning for [player] has been deleted' + notify: 'Your most recent warning has been deleted by ' + notify: 'The most recent warning for has been deleted' error: - noWarnings: '&c[player] has no warnings to delete' + noWarnings: ' has no warnings to delete' bmclear: - notify: '&c[player] has had their [type] cleared' + notify: ' has had their cleared' error: - invalid: '&cInvalid type, please choose between banrecords, muterecords, kicks, notes or warnings' + invalid: 'Invalid type, please choose between banrecords, muterecords, kicks, notes or warnings' bmutils: missingplayers: - notify: '&c[amount] missing players added' - noneFound: '&a0 missing players found' - found: '&c[amount] missing player data found. Fixing...' + notify: ' missing players added' + noneFound: '0 missing players found' + found: ' missing player data found. Fixing...' error: - failedLookup: '&cFailed to lookup player [uuid], check server logs' - complete: '&a[amount] players resolved, please restart your server for failed punishments to take affect' + failedLookup: 'Failed to lookup player , check server logs' + complete: ' players resolved, please restart your server for failed punishments to take affect' duplicates: lookup: - notFound: '&aNo duplicate player names found' + notFound: 'No duplicate player names found' error: - invalidName: '&cInvalid name, must be 16 characters or less and contain only letters, numbers and an underscore' - nameExists: '&cA player with that name already exists' - success: '&aPlayer name set to [player] successfully' + invalidName: 'Invalid name, must be 16 characters or less and contain only letters, numbers and an underscore' + nameExists: 'A player with that name already exists' + success: 'Player name set to successfully' bmrollback: - notify: '&c[player] has had their [type] actions undone' + notify: ' has had their actions undone' error: - invalid: '&cInvalid type [type], please choose between [types]' + invalid: 'Invalid type , please choose between ' sync: player: - started: '&aStarting force [type] synchronisation' - finished: '&aForced [type] synchronisation complete' + started: 'Starting force synchronisation' + finished: 'Forced synchronisation complete' update: - notify: '&6[BanManager] &aAn update is available' + notify: '[BanManager] An update is available' notes: - header: '&6[player] has the following notes:' - joinAmount: '&6[player] has &e[amount] &6notes, click to view them' - note: '&6[[player]] &e[message] - &e[created]' - playerNote: '&a[[player]] &6[[actor]] &e[message] - &e[created]' + header: ' has the following notes:' + joinAmount: '"> has notes, click to view them' + note: '[] - ' + playerNote: '[] [] - ' dateTimeFormat: 'dd-MM-yyyy' - notify: '[player] has a new note attached by [actor]: [message]' + notify: ' has a new note attached by : ' error: - noNotes: '&c[player] has no notes' - noOnlineNotes: '&cNo online players have notes' + noNotes: ' has no notes' + noOnlineNotes: 'No online players have notes' report: - notify: '&6[player] has been reported by [actor] for &4[reason]' + notify: ' has been reported by for ' error: - cooldown: '&cThis player was reported too recently, try again later' + cooldown: 'This player was reported too recently, try again later' assign: - player: '&aReport [id] assigned to [player]' - notify: '&aYou have been assigned report [id] by [actor]' + player: 'Report assigned to ' + notify: 'You have been assigned report by ' unassign: - player: '&aReport [id] unassigned' + player: 'Report unassigned' close: notify: - closed: '&aReport [id] closed by [actor]' - command: '&aReport [id] closed by [actor] with [command]' - comment: '&aReport [id] closed by [actor] with [comment]' - dispatch: 'Executing command [command]' + closed: 'Report closed by ' + command: 'Report closed by with ' + comment: 'Report closed by with ' + dispatch: 'Executing command ' list: - noResults: '&cNo reports found' + noResults: 'No reports found' error: - invalidState: '&cReport state [state] not found' + invalidState: 'Report state not found' row: dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - header: '&e-- Reports ([count]) -- Page ([page]/[maxPage])' - all: '&7#[id] &e[[state]] &6- [created] - [player]' + header: '-- Reports () -- Page (/)' + all: '">Click to view details"># [] - - ' tp: error: - notFound: '&cReport not found' - worldNotFound: '&cWorld [world] could not be found' - invalidId: '&c[id] is not a valid report id' + notFound: 'Report not found' + worldNotFound: 'World could not be found' + invalidId: ' is not a valid report id' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' notify: - report: '&7#[id] &6[actor] reported [player] for &4[reason]&6 at [created]' - location: '[world] - [x], [y], [z]' + report: '# reported for at ' + location: ' - , , ' info: error: - notFound: '&cReport not found' - invalidId: '&c[id] is not a valid report id' + notFound: 'Report not found' + invalidId: ' is not a valid report id' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' notify: - report: '&7#[id] &6[actor] reported [player] for &4[reason]&6 at [created]' - location: '[world] - [x], [y], [z]' + report: '# reported for at ' + location: ' - , , ' + actions: + assign: '">Assign to yourself">[Assign]' + close: '">Close this report">[Close]' + tp: '">Teleport to location">[TP]' + feedback: + assigned: 'Your report # has been assigned to ' + closed: 'Your report # has been closed by ' addnoteall: - notify: '&c[player] will have a new attached by [actor]: [message]' + notify: ' will have a new attached by : ' banlist: - header: '&6There are [bans] [type] bans:' + header: 'There are bans:' + row: + player: '">Click for info"> - ' + ip: ' - ' + iprange: ' - - ' bmactivity: row: - all: '&a[&f[type]&a] &6[player]&f - &6[actor]&f - &e[created]' - player: '&a[&f[type]&a] &6[player]&f - &e[created]' + all: '[] - - ' + player: '[] - ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' - noResults: '&cNo results found' + noResults: 'No results found' bmdelete: - notify: '&a[rows] rows deleted' + notify: ' rows deleted' error: - invalid: '&cInvalid type, please choose between banrecords, muterecords, kicks, notes or warnings' - invalidId: '&c[id] is not a valid number' + invalid: 'Invalid type, please choose between banrecords, muterecords, kicks, notes or warnings' + invalidId: ' is not a valid number' denyalts: player: - disallowed: '&cThe IP address you are joining from is linked to a banned player' + disallowed: 'The IP address you are joining from is linked to a banned player' reasons: - row: '[hashtag] = [reason]' + row: ' = ' + + dashboard: + header: ' Staff Dashboard ' + activeBans: 'Active Bans: ' + activeMutes: 'Active Mutes: ' + openReports: 'Open Reports: View reports">[View]' + recentActivity: 'Recent Activity (24h): ' + footer: ' ' diff --git a/e2e/platforms/sponge7/configs/banmanager/notifications.yml b/e2e/platforms/sponge7/configs/banmanager/notifications.yml new file mode 100644 index 000000000..75b1fb646 --- /dev/null +++ b/e2e/platforms/sponge7/configs/banmanager/notifications.yml @@ -0,0 +1,81 @@ +# Notifications Configuration +# Controls how punishment notifications are delivered to staff and players +# +# Each notification event can specify delivery channels: +# chat: true/false - Send via chat message (default: true) +# actionbar: true/false - Send via action bar (disappears after a few seconds) +# title: true/false - Send via title/subtitle overlay +# sound: '' - Sound to play (empty to disable). Use Minecraft sound names e.g. entity.experience_orb.pickup +# +# Title settings (only used when title: true): +# titleFadeIn: ticks for fade in (20 ticks = 1 second) +# titleStay: ticks to stay on screen +# titleFadeOut: ticks for fade out +# +# Sound settings: +# soundVolume: 0.0 - 1.0 +# soundPitch: 0.0 - 2.0 +# +# Platform notes: +# - BungeeCord: title, showTitle and playSound are not supported (ignored silently) +# - Sponge API7: playSound is not supported (ignored silently) +# - All other platforms (Bukkit/Paper, Velocity, Fabric, Sponge API8+) support all channels + +staff: + ban: + chat: true + actionbar: false + title: false + sound: 'entity.experience_orb.pickup' + soundVolume: 1.0 + soundPitch: 1.0 + tempban: + chat: true + actionbar: false + title: false + sound: 'entity.experience_orb.pickup' + soundVolume: 1.0 + soundPitch: 1.0 + mute: + chat: true + actionbar: false + title: false + sound: '' + soundVolume: 1.0 + soundPitch: 1.0 + tempmute: + chat: true + actionbar: false + title: false + sound: '' + soundVolume: 1.0 + soundPitch: 1.0 + warn: + chat: true + actionbar: false + title: false + sound: 'entity.experience_orb.pickup' + soundVolume: 1.0 + soundPitch: 1.0 + report: + chat: true + actionbar: false + title: false + sound: 'block.note_block.pling' + soundVolume: 1.0 + soundPitch: 1.0 + duplicateIp: + chat: true + actionbar: false + title: false + sound: '' + soundVolume: 1.0 + soundPitch: 1.0 + +player: + muted: + actionbar: true + warned: + sound: 'entity.villager.no' + soundVolume: 1.0 + soundPitch: 1.0 diff --git a/e2e/platforms/velocity/configs/banmanager/messages.yml b/e2e/platforms/velocity/configs/banmanager/messages.yml index 689b5c8c8..494d65579 100644 --- a/e2e/platforms/velocity/configs/banmanager/messages.yml +++ b/e2e/platforms/velocity/configs/banmanager/messages.yml @@ -1,424 +1,474 @@ -# Variables -# [reason] = Ban/Mute reason -# [player] = The name of the player -# [ip] = The banned ip -# [actor] = Who banned/muted -# [expires] = How long until the ban/mute ends +# Message templates use MiniMessage formatting: https://docs.advntr.dev/minimessage/format.html +# Placeholders use angle brackets, e.g. , , , , + +tokens: + appeal_url: 'https://yourdomain.com/appeal' + server_name: 'My Server' + discord_url: 'https://discord.gg/example' + rules_url: 'https://yourdomain.com/rules' messages: - duplicateIP: '&cWarning: [player] has the same IP as the following banned players:\n&6[players]' - duplicateIPAlts: '&cWarning: [player] has the same IP as the following players:\n&6[players]' - configReloaded: '�ff00Configuration &#ff5733reloaded &asuccessfully!' + duplicateIP: 'Warning: has the same IP as the following banned players:\n' + duplicateIPAlts: 'Warning: has the same IP as the following players:\n' + configReloaded: 'Configuration reloaded successfully!' deniedNotify: - player: '&cWarning: [player] attempted to join the server but was denied due to - &4[reason]' - ip: '&cWarning: [ip] attempted to join the server but was denied due to &4[reason]' - deniedMaxIp: '&cToo many players with your ip address online' - deniedMultiaccounts: '&cToo many players with your ip address logged in recently' - deniedCountry: '&cYou may not connect from your region' + player: 'Warning: attempted to join the server but was denied due to ' + ip: 'Warning: attempted to join the server but was denied due to ' + deniedMaxIp: 'Too many players with your ip address online' + deniedMultiaccounts: 'Too many players with your ip address logged in recently' + deniedCountry: 'You may not connect from your region' + time: - now: now - year: year - years: years - month: month - months: months - week: week - weeks: weeks - day: day - days: days - hour: hour - hours: hours - minute: minute - minutes: minutes - second: second - seconds: seconds - never: never + now: 'now' + year: 'year' + years: 'years' + month: 'month' + months: 'months' + week: 'week' + weeks: 'weeks' + day: 'day' + days: 'days' + hour: 'hour' + hours: 'hours' + minute: 'minute' + minutes: 'minutes' + second: 'second' + seconds: 'seconds' + never: 'never' error: - invalid: '&cYour time length is invalid' - limit: '&cYou cannot perform this action for that length of time' - none: none + invalid: 'Your time length is invalid' + limit: 'You cannot perform this action for that length of time' + + none: 'none' + # General command text sender: error: - notFound: '&c[player] not found, are you sure they exist?' - offline: '&c[player] is offline' - noSelf: '&cYou cannot perform that action on yourself!' - exception: '&cAn error occured whilst attempting to perform this command. Please - check the console for further details.' - invalidIp: '&cInvalid IP address, expecting w.x.y.z format' - offlinePermission: '&cYou are not allowed to perform this action on an offline - player' - exempt: '&c[player] is exempt from that action' - noPermission: '&cYou do not have permission to perform that action' - invalidReason: '&c[reason] is no valid reason.' + notFound: ' not found, are you sure they exist?' + offline: ' is offline' + noSelf: 'You cannot perform that action on yourself!' + exception: 'An error occured whilst attempting to perform this command. Please check the console for further details.' + invalidIp: 'Invalid IP address, expecting w.x.y.z format' + offlinePermission: 'You are not allowed to perform this action on an offline player' + ambiguousPlayer: 'Multiple players match "". Please use their full name.' + exempt: ' is exempt from that action' + noPermission: 'You do not have permission to perform that action' + noConsole: 'This command cannot be used from console' + invalidReason: ' is no valid reason.' + # Commands alts: header: 'Possible alts found:' + entry: '">' + separator: ', ' + names: - header: 'Known names for [player]:' - row: '&e[name] &7(first: [firstSeen], last: [lastSeen])' - dateTimeFormat: dd-MM-yyyy - none: '&7No name history found' + header: 'Known names for :' + row: ' (first: , last: )' + interactive: ' (first: , last: )">">' + separator: ', ' + dateTimeFormat: 'dd-MM-yyyy' + none: 'No name history found' + export: error: - inProgress: '&cAn export is already in progress, please wait' + inProgress: 'An export is already in progress, please wait' player: - started: '&aPlayer ban export started' - finished: '&aPlayer ban export finished, file [file] created' + started: 'Player ban export started' + finished: 'Player ban export finished, file created' ip: - started: '&aIP ban export started' - finished: '&aIP ban export finished, file [file] created' + started: 'IP ban export started' + finished: 'IP ban export finished, file created' + import: error: - inProgress: '&cAn import is already in progress, please wait' + inProgress: 'An import is already in progress, please wait' player: - started: '&aPlayer ban import started' - finished: '&aPlayer ban import finished' + started: 'Player ban import started' + finished: 'Player ban import finished' ip: - started: '&aIP ban import started' - finished: '&aIP ban import finished' + started: 'IP ban import started' + finished: 'IP ban import finished' advancedban: - started: '&aAdvancedBan import started' - finished: '&aAdvancedBan import finished' + started: 'AdvancedBan import started' + finished: 'AdvancedBan import finished' h2: - started: '&aH2 import started' - finished: '&aH2 import finished, please restart the server' + started: 'H2 import started' + finished: 'H2 import finished, please restart the server' litebans: - started: '&aLiteBans import started' - finished: '&aLiteBans import finished' + started: 'LiteBans import started' + finished: 'LiteBans import finished' + info: error: - invalidIndex: '&cInvalid player option used' - indexRequired: '&cMultiple players named [name] found, please select a player - by providing an index between 1 and [size], e.g. /bminfo [name] 1' - index: '&7#[index] - &6[name] - &4[uuid]' + invalidIndex: 'Invalid player option used' + indexRequired: 'Multiple players named found, please select a player by providing an index between 1 and , e.g. /bminfo 1' + index: '# - - ' stats: - player: '&6[player] has been banned [bans] times, muted [mutes] times, kicked - [kicks] times and warned [warns] times ([warnPoints] Points), has [notes] - notes and been reported [reports] times' - ip: '&6This ip has been banned [bans] times, muted [mutes] times and range banned - [rangebans] times' - connection: '&6Their last connection was with [ip] on [lastSeen]' - geoip: 'Country: [country] City: [city]' + player: ' has been banned times, muted times, kicked times and warned + times ( Points), has notes and been reported times' + ip: 'This ip has been banned times, muted times and range banned times' + connection: 'Their last connection was with on ' + geoip: 'Country: City: ' ban: - permanent: '&6Currently banned for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently banned for &4[reason]&6 by [actor] at [created] which - expires in [expires]' - dateTimeFormat: dd-MM-yyyy HH:mm:ss + permanent: 'Currently banned for by at ' + temporary: 'Currently banned for by at which expires in ' + dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' ipban: - permanent: '&6Currently banned for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently banned for &4[reason]&6 by [actor] at [created] which - expires in [expires]' - dateTimeFormat: dd-MM-yyyy HH:mm:ss + permanent: 'Currently banned for by at ' + temporary: 'Currently banned for by at which expires in ' + dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' iprangeban: - permanent: '&6[from] - [to] banned for &4[reason]&6 by [actor] at [created]' - temporary: '&6[from] - [to] banned for &4[reason]&6 by [actor] at [created] - which expires in [expires]' - dateTimeFormat: dd-MM-yyyy HH:mm:ss + permanent: ' - banned for by at ' + temporary: ' - banned for by at which expires in ' + dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' ipmute: - permanent: '&6Currently muted for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently muted for &4[reason]&6 by [actor] at [created] which - expires in [expires]' - dateTimeFormat: dd-MM-yyyy HH:mm:ss + permanent: 'Currently muted for by at ' + temporary: 'Currently muted for by at which expires in ' + dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' mute: - permanent: '&6Currently muted for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently muted for &4[reason]&6 by [actor] at [created] which - expires in [expires]' - temporaryOnline: '&6Currently muted for &4[reason]&6 by [actor] at [created] - which expires in [expires] (online time)' - temporaryOnlinePaused: '&6Currently muted for &4[reason]&6 by [actor] at [created] - with [remaining] remaining (online time, paused)' - dateTimeFormat: dd-MM-yyyy HH:mm:ss + permanent: 'Currently muted for by at ' + temporary: 'Currently muted for by at which expires in ' + temporaryOnline: 'Currently muted for by at which expires in (online time)' + temporaryOnlinePaused: 'Currently muted for by at with remaining (online time, paused)' + dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' website: - player: https://yourdomain.com/player/[uuid] - ip: http://yourdomain.com/index.php?action=viewip&ip=[ip]&server=0 + player: 'https://yourdomain.com/player/' + ip: 'http://yourdomain.com/index.php?action=viewip&ip=&server=0' history: - row: '&7#[id] &a[&f[type]&a] &6[actor]&f [meta] [reason] - &e[created]' - dateTimeFormat: dd-MM-yyyy HH:mm:ss - noResults: '&cNo results found' + row: '# [] - ' + dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' + noResults: 'No results found' ips: - row: '&e[ip] - &6[join] - [leave]' - dateTimeFormat: dd-MM-yyyy HH:mm:ss + row: ' - - ' + dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' + kick: player: - noReason: '&6You have been kicked' - reason: '&6You have been kicked for &4[reason]' + noReason: 'You have been kicked' + reason: 'You have been kicked for ' notify: - noReason: '&6[player] has been kicked by [actor]' - reason: '&6[player] has been kicked by [actor] for &4[reason]' + noReason: ' has been kicked by ">View player info">[Info]' + reason: ' has been kicked by for ">View player info">[Info]' + kickall: player: - noReason: '&6You have been kicked' - reason: '&6You have been kicked for &4[reason]' + noReason: 'You have been kicked' + reason: 'You have been kicked for ' notify: - noReason: All players have been kicked by [actor] - reason: All players have been kicked by [actor] for &4[reason] + noReason: 'All players have been kicked by ' + reason: 'All players have been kicked by for ' + ban: player: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' - dateTimeFormat: yyyy-MM-dd HH:mm:ss - notify: '&6[player] has been permanently banned by [actor] for &4[reason]' + disallowed: 'You are banned from this server\n \nReason: \nBanned by: \nDate: \n \nAppeal at ' + kick: 'You have been banned\n \nReason: \nBanned by: ' + dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' + notify: ' has been permanently banned by for ">View player info">[Info] ">Unban player">[Unban]' error: - exists: '&c[player] is already banned' - cooldown: '&cThis player was banned too recently, try again later' + exists: ' is already banned' + cooldown: 'This player was banned too recently, try again later' + banall: - notify: '&6[player] will be permanently banned by [actor] for &4[reason]' + notify: ' will be permanently banned by for ' + tempban: player: - disallowed: '&6You have been temporarily banned from this server for &4[reason] - \n&6It expires in [expires]' - kick: '&6You have been temporarily banned for &4[reason]' - dateTimeFormat: yyyy-MM-dd HH:mm:ss - notify: '&6[player] has been temporarily banned for [expires] by [actor] for &4[reason]' + disallowed: 'You are temporarily banned from this server\n \nReason: \nBanned by: \nExpires: \nDate: \n \nAppeal at ' + kick: 'You have been temporarily banned\n \nReason: \nBanned by: \nExpires: ' + dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' + notify: ' has been temporarily banned for by for ">View player info">[Info] ">Unban player">[Unban]' + tempbanall: - notify: '&6[player] will be temporarily banned for [expires] by [actor] for &4[reason]' + notify: ' will be temporarily banned for by for ' + unban: - notify: '&6[player] has been unbanned by [actor]' + notify: ' has been unbanned by ' error: - noExists: '&c[player] is not banned' - notOwn: '&c[player] was not banned by you, unable to unban' + noExists: ' is not banned' + notOwn: ' was not banned by you, unable to unban' + unbanall: - notify: '&6[player] will be unbanned by [actor]' + notify: ' will be unbanned by ' + mute: player: - blocked: '&cYou may not use the [command] command whilst muted!' - disallowed: '&6You have been permanently muted for &4[reason] &6by [actor]' - broadcast: '&4[Muted] [player]&7 [message]' - notify: '&6[player] has been permanently muted by [actor] for &4[reason]' + blocked: 'You may not use the command whilst muted!' + disallowed: 'You have been permanently muted for by ' + broadcast: '[Muted] ' + notify: ' has been permanently muted by for ">View player info">[Info] ">Unmute player">[Unmute]' error: - exists: '&c[player] is already muted' - cooldown: '&cThis player was muted too recently, try again later' + exists: ' is already muted' + cooldown: 'This player was muted too recently, try again later' + muteip: ip: - disallowed: '&6You have been permanently muted for &4[reason] &6by [actor]' - broadcast: '&4[Muted] [player]&7 [message]' - notify: '&6[ip] ([players]) have been permanently muted by [actor] for &4[reason]' + disallowed: 'You have been permanently muted for by ' + broadcast: '[Muted] ' + notify: ' () have been permanently muted by for ' error: - exists: '&c[ip] is already muted' + exists: ' is already muted' + muteall: - notify: '&6[player] will be permanently muted by [actor] for &4[reason]' + notify: ' will be permanently muted by for ' + tempmute: player: - disallowed: '&6You have been temporarily muted for &4[reason] &6by [actor] which - expires in [expires]' - disallowedOnline: '&6You have been temporarily muted for &4[reason] &6by [actor] - which expires in [expires] (online time)' - notify: '&6[player] has been temporarily muted for [expires] by [actor] for &4[reason]' - notifyOnline: '&6[player] has been temporarily muted for [expires] (online time) - by [actor] for &4[reason]' + disallowed: 'You have been temporarily muted for by which expires in ' + disallowedOnline: 'You have been temporarily muted for by which expires in (online time)' + notify: ' has been temporarily muted for by for ">View player info">[Info] ">Unmute player">[Unmute]' + notifyOnline: ' has been temporarily muted for (online time) by for ' error: - exists: '&c[player] is already muted' + exists: ' is already muted' + tempmuteip: ip: - disallowed: '&6You have been temporarily muted for &4[reason] &6by [actor] which - expires in [expires]' - notify: '&6[ip] ([players]) have been temporarily muted for [expires] by [actor] - for &4[reason]' + disallowed: 'You have been temporarily muted for by which expires in ' + notify: ' () have been temporarily muted for by for ' error: - exists: '&c[ip] is already muted' + exists: ' is already muted' + tempmuteall: - notify: '&6[player] will be temporarily muted for [expires] by [actor] for &4[reason]' + notify: ' will be temporarily muted for by for ' + unmute: - notify: '&6[player] has been unmuted by [actor]' - player: '&6You have been unmuted by [actor]' + notify: ' has been unmuted by ' + player: 'You have been unmuted by ' error: - noExists: '&c[player] is not muted' - notOwn: '&c[player] was not muted by you, unable to unmute' + noExists: ' is not muted' + notOwn: ' was not muted by you, unable to unmute' + unmuteip: - notify: '&6[ip] has been unmuted by [actor]' + notify: ' has been unmuted by ' error: - noExists: '&c[ip] is not muted' - notOwn: '&c[ip] was not muted by you, unable to unmute' + noExists: ' is not muted' + notOwn: ' was not muted by you, unable to unmute' + unmuteall: - notify: '&6[player] will be unmuted by [actor]' + notify: ' will be unmuted by ' + banname: name: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' - dateTimeFormat: yyyy-MM-dd HH:mm:ss - notify: '&6Name [name] has been permanently banned by [actor] for &4[reason]' + disallowed: 'You have been banned from this server for ' + kick: 'You have been banned permanently for ' + dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' + notify: 'Name has been permanently banned by for ' error: - exists: '&cName [name] is already banned' + exists: 'Name is already banned' + tempbanname: name: - disallowed: '&6You have been banned from this server for &4[reason] \n&6It expires - in [expires]' - kick: '&6You have been temporarily banned for &4[reason]' - dateTimeFormat: yyyy-MM-dd HH:mm:ss - notify: '&6Name [name] has been temporarily banned for [expires] by [actor] for - &4[reason]' + disallowed: 'You have been banned from this server for \nIt expires in ' + kick: 'You have been temporarily banned for ' + dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' + notify: 'Name has been temporarily banned for by for ' + unbanname: - notify: '&6Name [name] has been unbanned by [actor]' + notify: 'Name has been unbanned by ' error: - noExists: '&cName [name] is not banned' + noExists: 'Name is not banned' + banip: ip: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' - dateTimeFormat: yyyy-MM-dd HH:mm:ss - notify: '&6[ip] ([players]) has been permanently banned by [actor] for &4[reason]' + disallowed: 'You have been banned from this server for ' + kick: 'You have been banned permanently for ' + dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' + notify: ' () has been permanently banned by for ' error: - exists: '&c[ip] is already banned' - cooldown: '&cThis ip was banned too recently, try again later' + exists: ' is already banned' + cooldown: 'This ip was banned too recently, try again later' + baniprange: error: - invalid: '&cInvalid range, please use cidr notation 192.168.0.1/16 or wildcard - 192.168.*.*' - minMax: '&cRange must be lowest to highest' - exists: '&cA ban containing those ranges already exists' + invalid: 'Invalid range, please use cidr notation 192.168.0.1/16 or wildcard 192.168.*.*' + minMax: 'Range must be lowest to highest' + exists: 'A ban containing those ranges already exists' ip: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' - dateTimeFormat: yyyy-MM-dd HH:mm:ss - notify: '&6[from] - [to] have been banned by [actor]' + disallowed: 'You have been banned from this server for ' + kick: 'You have been banned permanently for ' + dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' + notify: ' - have been banned by ' + tempbaniprange: - notify: '&6[from] - [to] has been temporarily banned for [expires] by [actor]' + notify: ' - has been temporarily banned for by ' ip: - disallowed: '&6You have been banned from this server for &4[reason] \n&6It expires - in [expires]' - kick: '&6You have been temporarily banned for [expires] by [actor] for &4[reason]' - dateTimeFormat: yyyy-MM-dd HH:mm:ss + disallowed: 'You have been banned from this server for \nIt expires in ' + kick: 'You have been temporarily banned for by for ' + dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' + unbaniprange: - notify: '&6[from] - [to] has been unbanned by [actor]' + notify: ' - has been unbanned by ' + banipall: - notify: '&6[ip] will be permanently banned by [actor] for &4[reason]' + notify: ' will be permanently banned by for ' + tempbanip: ip: - disallowed: '&6You have been banned from this server for &4[reason] \n&6It expires - in [expires]' - kick: '&6You have been temporarily banned for &4[reason]' - dateTimeFormat: yyyy-MM-dd HH:mm:ss - notify: '&6[ip] ([players]) has been temporarily banned for [expires] by [actor] - for &4[reason]' + disallowed: 'You have been banned from this server for \nIt expires in ' + kick: 'You have been temporarily banned for ' + dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' + notify: ' () has been temporarily banned for by for ' + tempbanipall: - notify: '&6[ip] will be temporarily banned for [expires] by [actor] for &4[reason]' + notify: ' will be temporarily banned for by for ' + unbanip: - notify: '&6[ip] has been unbanned by [actor]' + notify: ' has been unbanned by ' error: - noExists: '&c[ip] is not banned' - notOwn: '&c[ip] was not banned by you, unable to unban' + noExists: ' is not banned' + notOwn: ' was not banned by you, unable to unban' + unbanipall: - notify: '&6[ip] will be unbanned by [actor]' + notify: ' will be unbanned by ' + warn: player: - warned: '&6You have been warned by [actor] for &4[reason]' + warned: 'You have been warned by for ' disallowed: - header: '&cYou may not speak until you have accepted your most recent warning. - Please type the following:' - reason: '&6[reason]' - removed: '&aThank you for your understanding, you may now speak again' - notify: '&6[player] has been warned by [actor] for &4[reason]' + header: 'You may not speak until you have accepted your most recent warning. Please type the following:' + reason: '' + removed: 'Thank you for your understanding, you may now speak again' + notify: ' has been warned by for ">View player info">[Info]' error: - cooldown: '&cThis player was warned too recently, try again later' + cooldown: 'This player was warned too recently, try again later' + tempwarn: player: - warned: '&6You have been warned for [expires] by [actor] for &4[reason]' - notify: '&6[player] has been warned for [expires] by [actor] for &4[reason]' + warned: 'You have been warned for by for ' + notify: ' has been warned for by for ">View player info">[Info]' + dwarn: player: - notify: '&6Your most recent warning has been deleted by &4[actor]' - notify: '&cThe most recent warning for [player] has been deleted' + notify: 'Your most recent warning has been deleted by ' + notify: 'The most recent warning for has been deleted' error: - noWarnings: '&c[player] has no warnings to delete' + noWarnings: ' has no warnings to delete' + bmclear: - notify: '&c[player] has had their [type] cleared' + notify: ' has had their cleared' error: - invalid: '&cInvalid type, please choose between banrecords, muterecords, kicks, - notes or warnings' + invalid: 'Invalid type, please choose between banrecords, muterecords, kicks, notes or warnings' + bmutils: missingplayers: - notify: '&c[amount] missing players added' - noneFound: '&a0 missing players found' - found: '&c[amount] missing player data found. Fixing...' + notify: ' missing players added' + noneFound: '0 missing players found' + found: ' missing player data found. Fixing...' error: - failedLookup: '&cFailed to lookup player [uuid], check server logs' - complete: '&a[amount] players resolved, please restart your server for failed - punishments to take affect' + failedLookup: 'Failed to lookup player , check server logs' + complete: ' players resolved, please restart your server for failed punishments to take affect' duplicates: lookup: - notFound: '&aNo duplicate player names found' + notFound: 'No duplicate player names found' error: - invalidName: '&cInvalid name, must be 16 characters or less and contain only - letters, numbers and an underscore' - nameExists: '&cA player with that name already exists' - success: '&aPlayer name set to [player] successfully' + invalidName: 'Invalid name, must be 16 characters or less and contain only letters, numbers and an underscore' + nameExists: 'A player with that name already exists' + success: 'Player name set to successfully' + bmrollback: - notify: '&c[player] has had their [type] actions undone' + notify: ' has had their actions undone' error: - invalid: '&cInvalid type [type], please choose between [types]' + invalid: 'Invalid type , please choose between ' + sync: player: - started: '&aStarting force [type] synchronisation' - finished: '&aForced [type] synchronisation complete' + started: 'Starting force synchronisation' + finished: 'Forced synchronisation complete' + update: - notify: '&6[BanManager] &aAn update is available' + notify: '[BanManager] An update is available' + notes: - header: '&6[player] has the following notes:' - joinAmount: '&6[player] has &e[amount] &6notes, click to view them' - note: '&6[[player]] &e[message] - &e[created]' - playerNote: '&a[[player]] &6[[actor]] &e[message] - &e[created]' - dateTimeFormat: dd-MM-yyyy - notify: '[player] has a new note attached by [actor]: [message]' + header: ' has the following notes:' + joinAmount: '"> has notes, click to view them' + note: '[] - ' + playerNote: '[] [] - ' + dateTimeFormat: 'dd-MM-yyyy' + notify: ' has a new note attached by : ' error: - noNotes: '&c[player] has no notes' - noOnlineNotes: '&cNo online players have notes' + noNotes: ' has no notes' + noOnlineNotes: 'No online players have notes' + report: - notify: '&6[player] has been reported by [actor] for &4[reason]' + notify: ' has been reported by for ' error: - cooldown: '&cThis player was reported too recently, try again later' + cooldown: 'This player was reported too recently, try again later' assign: - player: '&aReport [id] assigned to [player]' - notify: '&aYou have been assigned report [id] by [actor]' + player: 'Report assigned to ' + notify: 'You have been assigned report by ' unassign: - player: '&aReport [id] unassigned' + player: 'Report unassigned' close: notify: - closed: '&aReport [id] closed by [actor]' - command: '&aReport [id] closed by [actor] with [command]' - comment: '&aReport [id] closed by [actor] with [comment]' - dispatch: Executing command [command] + closed: 'Report closed by ' + command: 'Report closed by with ' + comment: 'Report closed by with ' + dispatch: 'Executing command ' list: - noResults: '&cNo reports found' + noResults: 'No reports found' error: - invalidState: '&cReport state [state] not found' + invalidState: 'Report state not found' row: - dateTimeFormat: yyyy-MM-dd HH:mm:ss - header: '&e-- Reports ([count]) -- Page ([page]/[maxPage])' - all: '&7#[id] &e[[state]] &6- [created] - [player]' + dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' + header: '-- Reports () -- Page (/)' + all: '">Click to view details"># [] - - ' tp: error: - notFound: '&cReport not found' - worldNotFound: '&cWorld [world] could not be found' - invalidId: '&c[id] is not a valid report id' - dateTimeFormat: yyyy-MM-dd HH:mm:ss + notFound: 'Report not found' + worldNotFound: 'World could not be found' + invalidId: ' is not a valid report id' + dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' notify: - report: '&7#[id] &6[actor] reported [player] for &4[reason]&6 at [created]' - location: '[world] - [x], [y], [z]' + report: '# reported for at ' + location: ' - , , ' info: error: - notFound: '&cReport not found' - invalidId: '&c[id] is not a valid report id' - dateTimeFormat: yyyy-MM-dd HH:mm:ss + notFound: 'Report not found' + invalidId: ' is not a valid report id' + dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' notify: - report: '&7#[id] &6[actor] reported [player] for &4[reason]&6 at [created]' - location: '[world] - [x], [y], [z]' + report: '# reported for at ' + location: ' - , , ' + actions: + assign: '">Assign to yourself">[Assign]' + close: '">Close this report">[Close]' + tp: '">Teleport to location">[TP]' + feedback: + assigned: 'Your report # has been assigned to ' + closed: 'Your report # has been closed by ' + addnoteall: - notify: '&c[player] will have a new attached by [actor]: [message]' + notify: ' will have a new attached by : ' + banlist: - header: '&6There are [bans] [type] bans:' + header: 'There are bans:' + row: + player: '">Click for info"> - ' + ip: ' - ' + iprange: ' - - ' + bmactivity: row: - all: '&a[&f[type]&a] &6[player]&f - &6[actor]&f - &e[created]' - player: '&a[&f[type]&a] &6[player]&f - &e[created]' - dateTimeFormat: dd-MM-yyyy HH:mm:ss - noResults: '&cNo results found' + all: '[] - - ' + player: '[] - ' + dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' + noResults: 'No results found' + bmdelete: - notify: '&a[rows] rows deleted' + notify: ' rows deleted' error: - invalid: '&cInvalid type, please choose between banrecords, muterecords, kicks, - notes or warnings' - invalidId: '&c[id] is not a valid number' + invalid: 'Invalid type, please choose between banrecords, muterecords, kicks, notes or warnings' + invalidId: ' is not a valid number' + denyalts: player: - disallowed: '&cThe IP address you are joining from is linked to a banned player' + disallowed: 'The IP address you are joining from is linked to a banned player' + reasons: - row: '[hashtag] = [reason]' + row: ' = ' + + dashboard: + header: ' Staff Dashboard ' + activeBans: 'Active Bans: ' + activeMutes: 'Active Mutes: ' + openReports: 'Open Reports: View reports">[View]' + recentActivity: 'Recent Activity (24h): ' + footer: ' ' diff --git a/e2e/platforms/velocity/configs/banmanager/messages/messages_en.yml b/e2e/platforms/velocity/configs/banmanager/messages/messages_en.yml index 205a94c13..494d65579 100644 --- a/e2e/platforms/velocity/configs/banmanager/messages/messages_en.yml +++ b/e2e/platforms/velocity/configs/banmanager/messages/messages_en.yml @@ -1,20 +1,22 @@ -# Variables -# [reason] = Ban/Mute reason -# [player] = The name of the player -# [ip] = The banned ip -# [actor] = Who banned/muted -# [expires] = How long until the ban/mute ends +# Message templates use MiniMessage formatting: https://docs.advntr.dev/minimessage/format.html +# Placeholders use angle brackets, e.g. , , , , + +tokens: + appeal_url: 'https://yourdomain.com/appeal' + server_name: 'My Server' + discord_url: 'https://discord.gg/example' + rules_url: 'https://yourdomain.com/rules' messages: - duplicateIP: '&cWarning: [player] has the same IP as the following banned players:\n&6[players]' - duplicateIPAlts: '&cWarning: [player] has the same IP as the following players:\n&6[players]' - configReloaded: '&aConfiguration reloaded successfully!' + duplicateIP: 'Warning: has the same IP as the following banned players:\n' + duplicateIPAlts: 'Warning: has the same IP as the following players:\n' + configReloaded: 'Configuration reloaded successfully!' deniedNotify: - player: '&cWarning: [player] attempted to join the server but was denied due to &4[reason]' - ip: '&cWarning: [ip] attempted to join the server but was denied due to &4[reason]' - deniedMaxIp: '&cToo many players with your ip address online' - deniedMultiaccounts: '&cToo many players with your ip address logged in recently' - deniedCountry: '&cYou may not connect from your region' + player: 'Warning: attempted to join the server but was denied due to ' + ip: 'Warning: attempted to join the server but was denied due to ' + deniedMaxIp: 'Too many players with your ip address online' + deniedMultiaccounts: 'Too many players with your ip address logged in recently' + deniedCountry: 'You may not connect from your region' time: now: 'now' @@ -34,415 +36,439 @@ messages: seconds: 'seconds' never: 'never' error: - invalid: '&cYour time length is invalid' - limit: '&cYou cannot perform this action for that length of time' + invalid: 'Your time length is invalid' + limit: 'You cannot perform this action for that length of time' none: 'none' # General command text sender: error: - notFound: '&c[player] not found, are you sure they exist?' - offline: '&c[player] is offline' - noSelf: '&cYou cannot perform that action on yourself!' - exception: '&cAn error occured whilst attempting to perform this command. Please check the console for further details.' - invalidIp: '&cInvalid IP address, expecting w.x.y.z format' - offlinePermission: '&cYou are not allowed to perform this action on an offline player' - ambiguousPlayer: '&cMultiple players match "[player]". Please use their full name.' - exempt: '&c[player] is exempt from that action' - noPermission: '&cYou do not have permission to perform that action' - invalidReason: '&c[reason] is no valid reason.' + notFound: ' not found, are you sure they exist?' + offline: ' is offline' + noSelf: 'You cannot perform that action on yourself!' + exception: 'An error occured whilst attempting to perform this command. Please check the console for further details.' + invalidIp: 'Invalid IP address, expecting w.x.y.z format' + offlinePermission: 'You are not allowed to perform this action on an offline player' + ambiguousPlayer: 'Multiple players match "". Please use their full name.' + exempt: ' is exempt from that action' + noPermission: 'You do not have permission to perform that action' + noConsole: 'This command cannot be used from console' + invalidReason: ' is no valid reason.' # Commands alts: header: 'Possible alts found:' + entry: '">' + separator: ', ' names: - header: 'Known names for [player]:' - row: '&e[name] &7(first: [firstSeen], last: [lastSeen])' + header: 'Known names for :' + row: ' (first: , last: )' + interactive: ' (first: , last: )">">' + separator: ', ' dateTimeFormat: 'dd-MM-yyyy' - none: '&7No name history found' + none: 'No name history found' export: error: - inProgress: '&cAn export is already in progress, please wait' + inProgress: 'An export is already in progress, please wait' player: - started: '&aPlayer ban export started' - finished: '&aPlayer ban export finished, file [file] created' + started: 'Player ban export started' + finished: 'Player ban export finished, file created' ip: - started: '&aIP ban export started' - finished: '&aIP ban export finished, file [file] created' + started: 'IP ban export started' + finished: 'IP ban export finished, file created' import: error: - inProgress: '&cAn import is already in progress, please wait' + inProgress: 'An import is already in progress, please wait' player: - started: '&aPlayer ban import started' - finished: '&aPlayer ban import finished' + started: 'Player ban import started' + finished: 'Player ban import finished' ip: - started: '&aIP ban import started' - finished: '&aIP ban import finished' + started: 'IP ban import started' + finished: 'IP ban import finished' advancedban: - started: '&aAdvancedBan import started' - finished: '&aAdvancedBan import finished' + started: 'AdvancedBan import started' + finished: 'AdvancedBan import finished' h2: - started: '&aH2 import started' - finished: '&aH2 import finished, please restart the server' + started: 'H2 import started' + finished: 'H2 import finished, please restart the server' litebans: - started: '&aLiteBans import started' - finished: '&aLiteBans import finished' + started: 'LiteBans import started' + finished: 'LiteBans import finished' info: error: - invalidIndex: '&cInvalid player option used' - indexRequired: '&cMultiple players named [name] found, please select a player by providing an index between 1 and [size], e.g. /bminfo [name] 1' - index: '&7#[index] - &6[name] - &4[uuid]' + invalidIndex: 'Invalid player option used' + indexRequired: 'Multiple players named found, please select a player by providing an index between 1 and , e.g. /bminfo 1' + index: '# - - ' stats: - player: '&6[player] has been banned [bans] times, muted [mutes] times, kicked [kicks] times and warned [warns] - times ([warnPoints] Points), has [notes] notes and been reported [reports] times' - ip: '&6This ip has been banned [bans] times, muted [mutes] times and range banned [rangebans] times' - connection: '&6Their last connection was with [ip] on [lastSeen]' - geoip: 'Country: [country] City: [city]' + player: ' has been banned times, muted times, kicked times and warned + times ( Points), has notes and been reported times' + ip: 'This ip has been banned times, muted times and range banned times' + connection: 'Their last connection was with on ' + geoip: 'Country: City: ' ban: - permanent: '&6Currently banned for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently banned for &4[reason]&6 by [actor] at [created] which expires in [expires]' + permanent: 'Currently banned for by at ' + temporary: 'Currently banned for by at which expires in ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' ipban: - permanent: '&6Currently banned for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently banned for &4[reason]&6 by [actor] at [created] which expires in [expires]' + permanent: 'Currently banned for by at ' + temporary: 'Currently banned for by at which expires in ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' iprangeban: - permanent: '&6[from] - [to] banned for &4[reason]&6 by [actor] at [created]' - temporary: '&6[from] - [to] banned for &4[reason]&6 by [actor] at [created] which expires in [expires]' + permanent: ' - banned for by at ' + temporary: ' - banned for by at which expires in ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' ipmute: - permanent: '&6Currently muted for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently muted for &4[reason]&6 by [actor] at [created] which expires in [expires]' + permanent: 'Currently muted for by at ' + temporary: 'Currently muted for by at which expires in ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' mute: - permanent: '&6Currently muted for &4[reason]&6 by [actor] at [created]' - temporary: '&6Currently muted for &4[reason]&6 by [actor] at [created] which expires in [expires]' - temporaryOnline: '&6Currently muted for &4[reason]&6 by [actor] at [created] which expires in [expires] (online time)' - temporaryOnlinePaused: '&6Currently muted for &4[reason]&6 by [actor] at [created] with [remaining] remaining (online time, paused)' + permanent: 'Currently muted for by at ' + temporary: 'Currently muted for by at which expires in ' + temporaryOnline: 'Currently muted for by at which expires in (online time)' + temporaryOnlinePaused: 'Currently muted for by at with remaining (online time, paused)' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' website: - player: 'https://yourdomain.com/player/[uuid]' - ip: 'http://yourdomain.com/index.php?action=viewip&ip=[ip]&server=0' + player: 'https://yourdomain.com/player/' + ip: 'http://yourdomain.com/index.php?action=viewip&ip=&server=0' history: - row: '&7#[id] &a[&f[type]&a] &6[actor]&f [meta] [reason] - &e[created]' + row: '# [] - ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' - noResults: '&cNo results found' + noResults: 'No results found' ips: - row: '&e[ip] - &6[join] - [leave]' + row: ' - - ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' kick: player: - noReason: '&6You have been kicked' - reason: '&6You have been kicked for &4[reason]' + noReason: 'You have been kicked' + reason: 'You have been kicked for ' notify: - noReason: '&6[player] has been kicked by [actor]' - reason: '&6[player] has been kicked by [actor] for &4[reason]' + noReason: ' has been kicked by ">View player info">[Info]' + reason: ' has been kicked by for ">View player info">[Info]' kickall: player: - noReason: '&6You have been kicked' - reason: '&6You have been kicked for &4[reason]' + noReason: 'You have been kicked' + reason: 'You have been kicked for ' notify: - noReason: 'All players have been kicked by [actor]' - reason: 'All players have been kicked by [actor] for &4[reason]' + noReason: 'All players have been kicked by ' + reason: 'All players have been kicked by for ' ban: player: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' + disallowed: 'You are banned from this server\n \nReason: \nBanned by: \nDate: \n \nAppeal at ' + kick: 'You have been banned\n \nReason: \nBanned by: ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[player] has been permanently banned by [actor] for &4[reason]' + notify: ' has been permanently banned by for ">View player info">[Info] ">Unban player">[Unban]' error: - exists: '&c[player] is already banned' - cooldown: '&cThis player was banned too recently, try again later' + exists: ' is already banned' + cooldown: 'This player was banned too recently, try again later' banall: - notify: '&6[player] will be permanently banned by [actor] for &4[reason]' + notify: ' will be permanently banned by for ' tempban: player: - disallowed: '&6You have been temporarily banned from this server for &4[reason] \n&6It expires in [expires]' - kick: '&6You have been temporarily banned for &4[reason]' + disallowed: 'You are temporarily banned from this server\n \nReason: \nBanned by: \nExpires: \nDate: \n \nAppeal at ' + kick: 'You have been temporarily banned\n \nReason: \nBanned by: \nExpires: ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[player] has been temporarily banned for [expires] by [actor] for &4[reason]' + notify: ' has been temporarily banned for by for ">View player info">[Info] ">Unban player">[Unban]' tempbanall: - notify: '&6[player] will be temporarily banned for [expires] by [actor] for &4[reason]' + notify: ' will be temporarily banned for by for ' unban: - notify: '&6[player] has been unbanned by [actor]' + notify: ' has been unbanned by ' error: - noExists: '&c[player] is not banned' - notOwn: '&c[player] was not banned by you, unable to unban' + noExists: ' is not banned' + notOwn: ' was not banned by you, unable to unban' unbanall: - notify: '&6[player] will be unbanned by [actor]' + notify: ' will be unbanned by ' mute: player: - blocked: '&cYou may not use the [command] command whilst muted!' - disallowed: '&6You have been permanently muted for &4[reason] &6by [actor]' - broadcast: '&4[Muted] [player]&7 [message]' - notify: '&6[player] has been permanently muted by [actor] for &4[reason]' + blocked: 'You may not use the command whilst muted!' + disallowed: 'You have been permanently muted for by ' + broadcast: '[Muted] ' + notify: ' has been permanently muted by for ">View player info">[Info] ">Unmute player">[Unmute]' error: - exists: '&c[player] is already muted' - cooldown: '&cThis player was muted too recently, try again later' + exists: ' is already muted' + cooldown: 'This player was muted too recently, try again later' muteip: ip: - disallowed: '&6You have been permanently muted for &4[reason] &6by [actor]' - broadcast: '&4[Muted] [player]&7 [message]' - notify: '&6[ip] ([players]) have been permanently muted by [actor] for &4[reason]' + disallowed: 'You have been permanently muted for by ' + broadcast: '[Muted] ' + notify: ' () have been permanently muted by for ' error: - exists: '&c[ip] is already muted' + exists: ' is already muted' muteall: - notify: '&6[player] will be permanently muted by [actor] for &4[reason]' + notify: ' will be permanently muted by for ' tempmute: player: - disallowed: '&6You have been temporarily muted for &4[reason] &6by [actor] which expires in [expires]' - disallowedOnline: '&6You have been temporarily muted for &4[reason] &6by [actor] which expires in [expires] (online time)' - notify: '&6[player] has been temporarily muted for [expires] by [actor] for &4[reason]' - notifyOnline: '&6[player] has been temporarily muted for [expires] (online time) by [actor] for &4[reason]' + disallowed: 'You have been temporarily muted for by which expires in ' + disallowedOnline: 'You have been temporarily muted for by which expires in (online time)' + notify: ' has been temporarily muted for by for ">View player info">[Info] ">Unmute player">[Unmute]' + notifyOnline: ' has been temporarily muted for (online time) by for ' error: - exists: '&c[player] is already muted' + exists: ' is already muted' tempmuteip: ip: - disallowed: '&6You have been temporarily muted for &4[reason] &6by [actor] which expires in [expires]' - notify: '&6[ip] ([players]) have been temporarily muted for [expires] by [actor] for &4[reason]' + disallowed: 'You have been temporarily muted for by which expires in ' + notify: ' () have been temporarily muted for by for ' error: - exists: '&c[ip] is already muted' + exists: ' is already muted' tempmuteall: - notify: '&6[player] will be temporarily muted for [expires] by [actor] for &4[reason]' + notify: ' will be temporarily muted for by for ' unmute: - notify: '&6[player] has been unmuted by [actor]' - player: '&6You have been unmuted by [actor]' + notify: ' has been unmuted by ' + player: 'You have been unmuted by ' error: - noExists: '&c[player] is not muted' - notOwn: '&c[player] was not muted by you, unable to unmute' + noExists: ' is not muted' + notOwn: ' was not muted by you, unable to unmute' unmuteip: - notify: '&6[ip] has been unmuted by [actor]' + notify: ' has been unmuted by ' error: - noExists: '&c[ip] is not muted' - notOwn: '&c[ip] was not muted by you, unable to unmute' + noExists: ' is not muted' + notOwn: ' was not muted by you, unable to unmute' unmuteall: - notify: '&6[player] will be unmuted by [actor]' + notify: ' will be unmuted by ' banname: name: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' + disallowed: 'You have been banned from this server for ' + kick: 'You have been banned permanently for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6Name [name] has been permanently banned by [actor] for &4[reason]' + notify: 'Name has been permanently banned by for ' error: - exists: '&cName [name] is already banned' + exists: 'Name is already banned' tempbanname: name: - disallowed: '&6You have been banned from this server for &4[reason] \n&6It expires in [expires]' - kick: '&6You have been temporarily banned for &4[reason]' + disallowed: 'You have been banned from this server for \nIt expires in ' + kick: 'You have been temporarily banned for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6Name [name] has been temporarily banned for [expires] by [actor] for &4[reason]' + notify: 'Name has been temporarily banned for by for ' unbanname: - notify: '&6Name [name] has been unbanned by [actor]' + notify: 'Name has been unbanned by ' error: - noExists: '&cName [name] is not banned' + noExists: 'Name is not banned' banip: ip: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' + disallowed: 'You have been banned from this server for ' + kick: 'You have been banned permanently for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[ip] ([players]) has been permanently banned by [actor] for &4[reason]' + notify: ' () has been permanently banned by for ' error: - exists: '&c[ip] is already banned' - cooldown: '&cThis ip was banned too recently, try again later' + exists: ' is already banned' + cooldown: 'This ip was banned too recently, try again later' baniprange: error: - invalid: '&cInvalid range, please use cidr notation 192.168.0.1/16 or wildcard 192.168.*.*' - minMax: '&cRange must be lowest to highest' - exists: '&cA ban containing those ranges already exists' + invalid: 'Invalid range, please use cidr notation 192.168.0.1/16 or wildcard 192.168.*.*' + minMax: 'Range must be lowest to highest' + exists: 'A ban containing those ranges already exists' ip: - disallowed: '&6You have been banned from this server for &4[reason]' - kick: '&6You have been banned permanently for &4[reason]' + disallowed: 'You have been banned from this server for ' + kick: 'You have been banned permanently for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[from] - [to] have been banned by [actor]' + notify: ' - have been banned by ' tempbaniprange: - notify: '&6[from] - [to] has been temporarily banned for [expires] by [actor]' + notify: ' - has been temporarily banned for by ' ip: - disallowed: '&6You have been banned from this server for &4[reason] \n&6It expires in [expires]' - kick: '&6You have been temporarily banned for [expires] by [actor] for &4[reason]' + disallowed: 'You have been banned from this server for \nIt expires in ' + kick: 'You have been temporarily banned for by for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' unbaniprange: - notify: '&6[from] - [to] has been unbanned by [actor]' + notify: ' - has been unbanned by ' banipall: - notify: '&6[ip] will be permanently banned by [actor] for &4[reason]' + notify: ' will be permanently banned by for ' tempbanip: ip: - disallowed: '&6You have been banned from this server for &4[reason] \n&6It expires in [expires]' - kick: '&6You have been temporarily banned for &4[reason]' + disallowed: 'You have been banned from this server for \nIt expires in ' + kick: 'You have been temporarily banned for ' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - notify: '&6[ip] ([players]) has been temporarily banned for [expires] by [actor] for &4[reason]' + notify: ' () has been temporarily banned for by for ' tempbanipall: - notify: '&6[ip] will be temporarily banned for [expires] by [actor] for &4[reason]' + notify: ' will be temporarily banned for by for ' unbanip: - notify: '&6[ip] has been unbanned by [actor]' + notify: ' has been unbanned by ' error: - noExists: '&c[ip] is not banned' - notOwn: '&c[ip] was not banned by you, unable to unban' + noExists: ' is not banned' + notOwn: ' was not banned by you, unable to unban' unbanipall: - notify: '&6[ip] will be unbanned by [actor]' + notify: ' will be unbanned by ' warn: player: - warned: '&6You have been warned by [actor] for &4[reason]' + warned: 'You have been warned by for ' disallowed: - header: '&cYou may not speak until you have accepted your most recent warning. Please type the following:' - reason: '&6[reason]' - removed: '&aThank you for your understanding, you may now speak again' - notify: '&6[player] has been warned by [actor] for &4[reason]' + header: 'You may not speak until you have accepted your most recent warning. Please type the following:' + reason: '' + removed: 'Thank you for your understanding, you may now speak again' + notify: ' has been warned by for ">View player info">[Info]' error: - cooldown: '&cThis player was warned too recently, try again later' + cooldown: 'This player was warned too recently, try again later' tempwarn: player: - warned: '&6You have been warned for [expires] by [actor] for &4[reason]' - notify: '&6[player] has been warned for [expires] by [actor] for &4[reason]' + warned: 'You have been warned for by for ' + notify: ' has been warned for by for ">View player info">[Info]' dwarn: player: - notify: '&6Your most recent warning has been deleted by &4[actor]' - notify: '&cThe most recent warning for [player] has been deleted' + notify: 'Your most recent warning has been deleted by ' + notify: 'The most recent warning for has been deleted' error: - noWarnings: '&c[player] has no warnings to delete' + noWarnings: ' has no warnings to delete' bmclear: - notify: '&c[player] has had their [type] cleared' + notify: ' has had their cleared' error: - invalid: '&cInvalid type, please choose between banrecords, muterecords, kicks, notes or warnings' + invalid: 'Invalid type, please choose between banrecords, muterecords, kicks, notes or warnings' bmutils: missingplayers: - notify: '&c[amount] missing players added' - noneFound: '&a0 missing players found' - found: '&c[amount] missing player data found. Fixing...' + notify: ' missing players added' + noneFound: '0 missing players found' + found: ' missing player data found. Fixing...' error: - failedLookup: '&cFailed to lookup player [uuid], check server logs' - complete: '&a[amount] players resolved, please restart your server for failed punishments to take affect' + failedLookup: 'Failed to lookup player , check server logs' + complete: ' players resolved, please restart your server for failed punishments to take affect' duplicates: lookup: - notFound: '&aNo duplicate player names found' + notFound: 'No duplicate player names found' error: - invalidName: '&cInvalid name, must be 16 characters or less and contain only letters, numbers and an underscore' - nameExists: '&cA player with that name already exists' - success: '&aPlayer name set to [player] successfully' + invalidName: 'Invalid name, must be 16 characters or less and contain only letters, numbers and an underscore' + nameExists: 'A player with that name already exists' + success: 'Player name set to successfully' bmrollback: - notify: '&c[player] has had their [type] actions undone' + notify: ' has had their actions undone' error: - invalid: '&cInvalid type [type], please choose between [types]' + invalid: 'Invalid type , please choose between ' sync: player: - started: '&aStarting force [type] synchronisation' - finished: '&aForced [type] synchronisation complete' + started: 'Starting force synchronisation' + finished: 'Forced synchronisation complete' update: - notify: '&6[BanManager] &aAn update is available' + notify: '[BanManager] An update is available' notes: - header: '&6[player] has the following notes:' - joinAmount: '&6[player] has &e[amount] &6notes, click to view them' - note: '&6[[player]] &e[message] - &e[created]' - playerNote: '&a[[player]] &6[[actor]] &e[message] - &e[created]' + header: ' has the following notes:' + joinAmount: '"> has notes, click to view them' + note: '[] - ' + playerNote: '[] [] - ' dateTimeFormat: 'dd-MM-yyyy' - notify: '[player] has a new note attached by [actor]: [message]' + notify: ' has a new note attached by : ' error: - noNotes: '&c[player] has no notes' - noOnlineNotes: '&cNo online players have notes' + noNotes: ' has no notes' + noOnlineNotes: 'No online players have notes' report: - notify: '&6[player] has been reported by [actor] for &4[reason]' + notify: ' has been reported by for ' error: - cooldown: '&cThis player was reported too recently, try again later' + cooldown: 'This player was reported too recently, try again later' assign: - player: '&aReport [id] assigned to [player]' - notify: '&aYou have been assigned report [id] by [actor]' + player: 'Report assigned to ' + notify: 'You have been assigned report by ' unassign: - player: '&aReport [id] unassigned' + player: 'Report unassigned' close: notify: - closed: '&aReport [id] closed by [actor]' - command: '&aReport [id] closed by [actor] with [command]' - comment: '&aReport [id] closed by [actor] with [comment]' - dispatch: 'Executing command [command]' + closed: 'Report closed by ' + command: 'Report closed by with ' + comment: 'Report closed by with ' + dispatch: 'Executing command ' list: - noResults: '&cNo reports found' + noResults: 'No reports found' error: - invalidState: '&cReport state [state] not found' + invalidState: 'Report state not found' row: dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' - header: '&e-- Reports ([count]) -- Page ([page]/[maxPage])' - all: '&7#[id] &e[[state]] &6- [created] - [player]' + header: '-- Reports () -- Page (/)' + all: '">Click to view details"># [] - - ' tp: error: - notFound: '&cReport not found' - worldNotFound: '&cWorld [world] could not be found' - invalidId: '&c[id] is not a valid report id' + notFound: 'Report not found' + worldNotFound: 'World could not be found' + invalidId: ' is not a valid report id' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' notify: - report: '&7#[id] &6[actor] reported [player] for &4[reason]&6 at [created]' - location: '[world] - [x], [y], [z]' + report: '# reported for at ' + location: ' - , , ' info: error: - notFound: '&cReport not found' - invalidId: '&c[id] is not a valid report id' + notFound: 'Report not found' + invalidId: ' is not a valid report id' dateTimeFormat: 'yyyy-MM-dd HH:mm:ss' notify: - report: '&7#[id] &6[actor] reported [player] for &4[reason]&6 at [created]' - location: '[world] - [x], [y], [z]' + report: '# reported for at ' + location: ' - , , ' + actions: + assign: '">Assign to yourself">[Assign]' + close: '">Close this report">[Close]' + tp: '">Teleport to location">[TP]' + feedback: + assigned: 'Your report # has been assigned to ' + closed: 'Your report # has been closed by ' addnoteall: - notify: '&c[player] will have a new attached by [actor]: [message]' + notify: ' will have a new attached by : ' banlist: - header: '&6There are [bans] [type] bans:' + header: 'There are bans:' + row: + player: '">Click for info"> - ' + ip: ' - ' + iprange: ' - - ' bmactivity: row: - all: '&a[&f[type]&a] &6[player]&f - &6[actor]&f - &e[created]' - player: '&a[&f[type]&a] &6[player]&f - &e[created]' + all: '[] - - ' + player: '[] - ' dateTimeFormat: 'dd-MM-yyyy HH:mm:ss' - noResults: '&cNo results found' + noResults: 'No results found' bmdelete: - notify: '&a[rows] rows deleted' + notify: ' rows deleted' error: - invalid: '&cInvalid type, please choose between banrecords, muterecords, kicks, notes or warnings' - invalidId: '&c[id] is not a valid number' + invalid: 'Invalid type, please choose between banrecords, muterecords, kicks, notes or warnings' + invalidId: ' is not a valid number' denyalts: player: - disallowed: '&cThe IP address you are joining from is linked to a banned player' + disallowed: 'The IP address you are joining from is linked to a banned player' reasons: - row: '[hashtag] = [reason]' + row: ' = ' + + dashboard: + header: ' Staff Dashboard ' + activeBans: 'Active Bans: ' + activeMutes: 'Active Mutes: ' + openReports: 'Open Reports: View reports">[View]' + recentActivity: 'Recent Activity (24h): ' + footer: ' ' diff --git a/e2e/platforms/velocity/configs/banmanager/notifications.yml b/e2e/platforms/velocity/configs/banmanager/notifications.yml new file mode 100644 index 000000000..75b1fb646 --- /dev/null +++ b/e2e/platforms/velocity/configs/banmanager/notifications.yml @@ -0,0 +1,81 @@ +# Notifications Configuration +# Controls how punishment notifications are delivered to staff and players +# +# Each notification event can specify delivery channels: +# chat: true/false - Send via chat message (default: true) +# actionbar: true/false - Send via action bar (disappears after a few seconds) +# title: true/false - Send via title/subtitle overlay +# sound: '' - Sound to play (empty to disable). Use Minecraft sound names e.g. entity.experience_orb.pickup +# +# Title settings (only used when title: true): +# titleFadeIn: ticks for fade in (20 ticks = 1 second) +# titleStay: ticks to stay on screen +# titleFadeOut: ticks for fade out +# +# Sound settings: +# soundVolume: 0.0 - 1.0 +# soundPitch: 0.0 - 2.0 +# +# Platform notes: +# - BungeeCord: title, showTitle and playSound are not supported (ignored silently) +# - Sponge API7: playSound is not supported (ignored silently) +# - All other platforms (Bukkit/Paper, Velocity, Fabric, Sponge API8+) support all channels + +staff: + ban: + chat: true + actionbar: false + title: false + sound: 'entity.experience_orb.pickup' + soundVolume: 1.0 + soundPitch: 1.0 + tempban: + chat: true + actionbar: false + title: false + sound: 'entity.experience_orb.pickup' + soundVolume: 1.0 + soundPitch: 1.0 + mute: + chat: true + actionbar: false + title: false + sound: '' + soundVolume: 1.0 + soundPitch: 1.0 + tempmute: + chat: true + actionbar: false + title: false + sound: '' + soundVolume: 1.0 + soundPitch: 1.0 + warn: + chat: true + actionbar: false + title: false + sound: 'entity.experience_orb.pickup' + soundVolume: 1.0 + soundPitch: 1.0 + report: + chat: true + actionbar: false + title: false + sound: 'block.note_block.pling' + soundVolume: 1.0 + soundPitch: 1.0 + duplicateIp: + chat: true + actionbar: false + title: false + sound: '' + soundVolume: 1.0 + soundPitch: 1.0 + +player: + muted: + actionbar: true + warned: + sound: 'entity.villager.no' + soundVolume: 1.0 + soundPitch: 1.0 diff --git a/e2e/tests/src/hex-colors.test.ts b/e2e/tests/src/hex-colors.test.ts index 817f197c7..6d1b8d72e 100644 --- a/e2e/tests/src/hex-colors.test.ts +++ b/e2e/tests/src/hex-colors.test.ts @@ -37,7 +37,7 @@ describe('Hex Color Support E2E Tests', () => { }) test('hex color message is received correctly', async () => { - // configReloaded in messages.yml uses &#rrggbb hex colors + // configReloaded in messages.yml uses MiniMessage hex colors (<#rrggbb>) await bot.sendChat('/bmreload') await waitFor( @@ -65,8 +65,8 @@ describe('Hex Color Support E2E Tests', () => { }, 30000) test('hex colors are processed correctly', async () => { - // configReloaded: '�ff00Configuration &#ff5733reloaded &asuccessfully!' - // - Bukkit/Bungee/Sponge: hex downsampled to legacy codes (&2, &c) + // configReloaded: '<#00ff00>Configuration <#ff5733>reloaded successfully!' + // - Bukkit/Bungee/Sponge: colors may downsample when sent to legacy clients // - Velocity/Fabric: full hex preserved in JSON await bot.sendChat('/bmreload') diff --git a/fabric/src/main/java/me/confuser/banmanager/fabric/BMFabricPlugin.java b/fabric/src/main/java/me/confuser/banmanager/fabric/BMFabricPlugin.java index 21fbc1762..f57eaa93b 100644 --- a/fabric/src/main/java/me/confuser/banmanager/fabric/BMFabricPlugin.java +++ b/fabric/src/main/java/me/confuser/banmanager/fabric/BMFabricPlugin.java @@ -49,7 +49,7 @@ public class BMFabricPlugin implements DedicatedServerModInitializer { "webhooks.yml", "exemptions.yml", "geoip.yml", - "messages.yml", + "notifications.yml", "reasons.yml", "schedules.yml" }; diff --git a/fabric/src/main/java/me/confuser/banmanager/fabric/FabricPlayer.java b/fabric/src/main/java/me/confuser/banmanager/fabric/FabricPlayer.java index 56a0508ee..fd25707e9 100644 --- a/fabric/src/main/java/me/confuser/banmanager/fabric/FabricPlayer.java +++ b/fabric/src/main/java/me/confuser/banmanager/fabric/FabricPlayer.java @@ -11,10 +11,12 @@ import me.confuser.banmanager.common.BanManagerPlugin; import me.confuser.banmanager.common.CommonPlayer; import me.confuser.banmanager.common.CommonWorld; +import me.confuser.banmanager.common.kyori.text.Component; import me.confuser.banmanager.common.kyori.text.TextComponent; import me.confuser.banmanager.common.kyori.text.serializer.gson.GsonComponentSerializer; import me.confuser.banmanager.common.data.PlayerData; import me.confuser.banmanager.common.util.Message; +import me.confuser.banmanager.common.util.MessageRenderer; import me.confuser.banmanager.common.util.MessageRegistry; import me.confuser.banmanager.common.util.UUIDUtils; //? if >=1.21.1 @@ -41,6 +43,11 @@ public void kick(String message) { this.player.networkHandler.disconnect(FabricServer.formatMessage(message)); } + @Override + public void kick(Component component) { + this.player.networkHandler.disconnect(FabricServer.formatJsonMessage(MessageRenderer.getInstance().toJson(component))); + } + public void sendMessage(String message) { if(message.isEmpty()) return; @@ -51,8 +58,51 @@ public void sendMessage(String message) { } } - public void sendMessage(Message message) { - sendMessage(message.toString()); + @Override + public void sendMessage(Component component) { + getPlayer().sendMessage(FabricServer.formatJsonMessage(MessageRenderer.getInstance().toJson(component))); + } + + @Override + public void sendActionBar(Component component) { + getPlayer().sendMessage(FabricServer.formatJsonMessage(MessageRenderer.getInstance().toJson(component)), true); + } + + @Override + public void showTitle(Component title, Component subtitle, int fadeIn, int stay, int fadeOut) { + ServerPlayerEntity p = getPlayer(); + if (p == null) return; + MessageRenderer renderer = MessageRenderer.getInstance(); + if (title != null) { + net.minecraft.text.Text titleText = FabricServer.formatJsonMessage(renderer.toJson(title)); + p.networkHandler.sendPacket(new net.minecraft.network.packet.s2c.play.TitleS2CPacket(titleText)); + } + if (subtitle != null) { + net.minecraft.text.Text subtitleText = FabricServer.formatJsonMessage(renderer.toJson(subtitle)); + p.networkHandler.sendPacket(new net.minecraft.network.packet.s2c.play.SubtitleS2CPacket(subtitleText)); + } + p.networkHandler.sendPacket(new net.minecraft.network.packet.s2c.play.TitleFadeS2CPacket(fadeIn, stay, fadeOut)); + } + + @Override + public void playSound(String sound, float volume, float pitch) { + ServerPlayerEntity p = getPlayer(); + if (p == null) return; + try { + //? if >=1.21 { + net.minecraft.util.Identifier id = net.minecraft.util.Identifier.of(sound); + //?} else { + /*net.minecraft.util.Identifier id = new net.minecraft.util.Identifier(sound); + *///?} + net.minecraft.sound.SoundEvent event = net.minecraft.sound.SoundEvent.of(id); + //? if >=1.21.11 { + p.getEntityWorld().playSound(null, p.getBlockPos(), event, net.minecraft.sound.SoundCategory.MASTER, volume, pitch); + //?} else { + /*p.getWorld().playSound(null, p.getBlockPos(), event, net.minecraft.sound.SoundCategory.MASTER, volume, pitch); + *///?} + } catch (IllegalArgumentException ignored) { + // Invalid sound key or identifier -- silently ignore + } } @Override diff --git a/fabric/src/main/java/me/confuser/banmanager/fabric/FabricSender.java b/fabric/src/main/java/me/confuser/banmanager/fabric/FabricSender.java index 187f670d8..308884b69 100644 --- a/fabric/src/main/java/me/confuser/banmanager/fabric/FabricSender.java +++ b/fabric/src/main/java/me/confuser/banmanager/fabric/FabricSender.java @@ -35,11 +35,6 @@ public void sendMessage(String message) { sender.sendMessage(FabricServer.formatMessage(message)); } - @Override - public void sendMessage(Message message) { - sendMessage(message.toString()); - } - @Override public boolean isConsole() { return !sender.isExecutedByPlayer(); diff --git a/fabric/src/main/java/me/confuser/banmanager/fabric/FabricServer.java b/fabric/src/main/java/me/confuser/banmanager/fabric/FabricServer.java index b5d474e99..4ddef55f8 100644 --- a/fabric/src/main/java/me/confuser/banmanager/fabric/FabricServer.java +++ b/fabric/src/main/java/me/confuser/banmanager/fabric/FabricServer.java @@ -31,7 +31,7 @@ import me.confuser.banmanager.common.data.PlayerNoteData; import me.confuser.banmanager.common.data.PlayerReportData; import me.confuser.banmanager.common.data.PlayerWarnData; -import me.confuser.banmanager.common.kyori.text.TextComponent; +import me.confuser.banmanager.common.kyori.text.Component; import me.confuser.banmanager.common.kyori.text.serializer.gson.GsonComponentSerializer; import me.confuser.banmanager.common.kyori.text.serializer.legacy.LegacyComponentSerializer; import com.google.gson.JsonElement; @@ -96,12 +96,6 @@ public void broadcast(String message, String permission) { getConsoleSender().sendMessage(message); } - public void broadcastJSON(TextComponent message, String permission) { - Arrays.stream(getOnlinePlayers()) - .filter(player -> player.hasPermission(permission)) - .forEach(player -> player.sendJSONMessage(message)); - } - public void broadcast(String message, String permission, CommonSender sender) { broadcast(message, permission); @@ -350,10 +344,10 @@ public static Text formatMessage(String message) { } public static Text formatMessage(Message message) { - return formatMessage(message.toString()); + return formatMessage(message.resolveComponent()); } - public static Text formatMessage(TextComponent message) { + public static Text formatMessage(Component message) { //? if >=1.21 { return TextCodecs.CODEC .decode(JsonOps.INSTANCE, JsonParser.parseString(GsonComponentSerializer.gson().serialize(message))) diff --git a/fabric/src/main/java/me/confuser/banmanager/fabric/listeners/JoinListener.java b/fabric/src/main/java/me/confuser/banmanager/fabric/listeners/JoinListener.java index eb6ac779c..8d5d38d0e 100644 --- a/fabric/src/main/java/me/confuser/banmanager/fabric/listeners/JoinListener.java +++ b/fabric/src/main/java/me/confuser/banmanager/fabric/listeners/JoinListener.java @@ -61,7 +61,7 @@ public void handlePlayerDeny(PlayerData player, Message message) { plugin.getServer().callEvent("PlayerDeniedEvent", player, message); String locale = player.getLocale() != null ? player.getLocale() : "en"; isDenied = true; - handler.disconnect(FabricServer.formatMessage(message.resolve(locale))); + handler.disconnect(FabricServer.formatMessage(message.resolveComponent(locale))); } @Override diff --git a/gradle.properties b/gradle.properties index 33c58b8bf..79a0ef2cb 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ group=me.confuser.banmanager -version=7.11.0-SNAPSHOT +version=8.0.0-SNAPSHOT org.gradle.parallel=true description="The defacto plugin for Minecraft to manage punishments and moderate more effectively" diff --git a/libs/build.gradle.kts b/libs/build.gradle.kts index bdffcc3f9..47058d1e5 100644 --- a/libs/build.gradle.kts +++ b/libs/build.gradle.kts @@ -5,8 +5,14 @@ applyLibrariesConfiguration() dependencies { "shade"("net.kyori:adventure-text-serializer-legacy:${Versions.ADVENTURE}") "shade"("net.kyori:adventure-text-serializer-gson:${Versions.ADVENTURE}") + "shade"("net.kyori:adventure-text-serializer-json:${Versions.ADVENTURE}") + "shade"("net.kyori:adventure-text-serializer-plain:${Versions.ADVENTURE}") + "shade"("net.kyori:adventure-text-minimessage:${Versions.ADVENTURE}") "shade"("net.kyori:adventure-api:${Versions.ADVENTURE}") + "shade"("net.kyori:adventure-text-serializer-commons:${Versions.ADVENTURE}") "shade"("net.kyori:examination-api:1.3.0") + "shade"("net.kyori:examination-string:1.3.0") + "shade"("net.kyori:option:1.1.0") "shade"("com.j256.ormlite:ormlite-core:5.1") "shade"("com.j256.ormlite:ormlite-jdbc:5.1") @@ -38,12 +44,21 @@ tasks.named("jar") { relocate("net.kyori.adventure", "me.confuser.banmanager.common.kyori") { include(dependency("net.kyori:adventure-text-serializer-legacy")) include(dependency("net.kyori:adventure-text-serializer-gson")) + include(dependency("net.kyori:adventure-text-serializer-json")) + include(dependency("net.kyori:adventure-text-serializer-plain")) + include(dependency("net.kyori:adventure-text-serializer-commons")) + include(dependency("net.kyori:adventure-text-minimessage")) include(dependency("net.kyori:adventure-api")) include(dependency("net.kyori:adventure-key")) } relocate("net.kyori.examination", "me.confuser.banmanager.common.kyori.examination") { include(dependency("net.kyori:examination-api")) + include(dependency("net.kyori:examination-string")) + } + + relocate("net.kyori.option", "me.confuser.banmanager.common.kyori.option") { + include(dependency("net.kyori:option")) } relocate("org.yaml.snakeyaml", "me.confuser.banmanager.common.snakeyaml") { diff --git a/sponge-api7/build.gradle.kts b/sponge-api7/build.gradle.kts index eea753630..aab072552 100644 --- a/sponge-api7/build.gradle.kts +++ b/sponge-api7/build.gradle.kts @@ -120,7 +120,7 @@ dependencies { "shadeOnly"("org.bstats:bstats-sponge:2.2.1") } -val javaTarget = 8 // Sponge targets a minimum of Java 8 +val javaTarget = 17 java { sourceCompatibility = JavaVersion.toVersion(javaTarget) targetCompatibility = JavaVersion.toVersion(javaTarget) diff --git a/sponge-api7/src/main/java/me/confuser/banmanager/sponge/BMSpongePlugin.java b/sponge-api7/src/main/java/me/confuser/banmanager/sponge/BMSpongePlugin.java index efb180955..a2de6e6e4 100644 --- a/sponge-api7/src/main/java/me/confuser/banmanager/sponge/BMSpongePlugin.java +++ b/sponge-api7/src/main/java/me/confuser/banmanager/sponge/BMSpongePlugin.java @@ -63,7 +63,7 @@ public class BMSpongePlugin { "webhooks.yml", "exemptions.yml", "geoip.yml", - "messages.yml", + "notifications.yml", "reasons.yml", "schedules.yml" }; diff --git a/sponge-api7/src/main/java/me/confuser/banmanager/sponge/SpongePlayer.java b/sponge-api7/src/main/java/me/confuser/banmanager/sponge/SpongePlayer.java index d986cca7e..ff6be1316 100644 --- a/sponge-api7/src/main/java/me/confuser/banmanager/sponge/SpongePlayer.java +++ b/sponge-api7/src/main/java/me/confuser/banmanager/sponge/SpongePlayer.java @@ -4,15 +4,20 @@ import me.confuser.banmanager.common.CommonPlayer; import me.confuser.banmanager.common.CommonWorld; import me.confuser.banmanager.common.data.PlayerData; +import me.confuser.banmanager.common.kyori.text.Component; import me.confuser.banmanager.common.kyori.text.TextComponent; import me.confuser.banmanager.common.kyori.text.serializer.gson.GsonComponentSerializer; import me.confuser.banmanager.common.util.Message; +import me.confuser.banmanager.common.util.MessageRenderer; import me.confuser.banmanager.common.util.MessageRegistry; import me.confuser.banmanager.common.util.UUIDUtils; import org.spongepowered.api.Sponge; import org.spongepowered.api.entity.living.player.Player; import org.spongepowered.api.entity.living.player.User; +import org.spongepowered.api.text.Text; +import org.spongepowered.api.text.chat.ChatTypes; import org.spongepowered.api.text.serializer.TextSerializers; +import org.spongepowered.api.text.title.Title; import org.spongepowered.api.world.Location; import org.spongepowered.api.world.World; @@ -48,6 +53,12 @@ public void kick(String message) { getPlayer().kick(SpongeServer.formatMessage(message)); } + @Override + public void kick(Component component) { + String json = MessageRenderer.getInstance().toJson(component); + getPlayer().kick(TextSerializers.JSON.deserialize(json)); + } + @Override public void sendMessage(String message) { if(message.isEmpty()) return; @@ -60,8 +71,31 @@ public void sendMessage(String message) { } @Override - public void sendMessage(Message message) { - sendMessage(message.toString()); + public void sendMessage(Component component) { + String json = MessageRenderer.getInstance().toJson(component); + getPlayer().sendMessage(TextSerializers.JSON.deserialize(json)); + } + + @Override + public void sendActionBar(Component component) { + String json = MessageRenderer.getInstance().toJson(component); + getPlayer().sendMessage(ChatTypes.ACTION_BAR, TextSerializers.JSON.deserialize(json)); + } + + @Override + public void showTitle(Component title, Component subtitle, int fadeIn, int stay, int fadeOut) { + MessageRenderer renderer = MessageRenderer.getInstance(); + Text spongeTitle = title != null + ? TextSerializers.JSON.deserialize(renderer.toJson(title)) : Text.EMPTY; + Text spongeSubtitle = subtitle != null + ? TextSerializers.JSON.deserialize(renderer.toJson(subtitle)) : Text.EMPTY; + getPlayer().sendTitle(Title.builder() + .title(spongeTitle) + .subtitle(spongeSubtitle) + .fadeIn(fadeIn) + .stay(stay) + .fadeOut(fadeOut) + .build()); } @Override diff --git a/sponge-api7/src/main/java/me/confuser/banmanager/sponge/SpongeSender.java b/sponge-api7/src/main/java/me/confuser/banmanager/sponge/SpongeSender.java index 577889f8a..9b5cfabd0 100644 --- a/sponge-api7/src/main/java/me/confuser/banmanager/sponge/SpongeSender.java +++ b/sponge-api7/src/main/java/me/confuser/banmanager/sponge/SpongeSender.java @@ -35,11 +35,6 @@ public void sendMessage(String message) { sender.sendMessage(SpongeServer.formatMessage(message)); } - @Override - public void sendMessage(Message message) { - sendMessage(message.toString()); - } - @Override public boolean isConsole() { return !(sender instanceof Player); diff --git a/sponge-api7/src/main/java/me/confuser/banmanager/sponge/SpongeServer.java b/sponge-api7/src/main/java/me/confuser/banmanager/sponge/SpongeServer.java index a3ceafd3d..6e9e73c7a 100644 --- a/sponge-api7/src/main/java/me/confuser/banmanager/sponge/SpongeServer.java +++ b/sponge-api7/src/main/java/me/confuser/banmanager/sponge/SpongeServer.java @@ -5,7 +5,7 @@ import me.confuser.banmanager.common.commands.CommonSender; import me.confuser.banmanager.common.data.*; import me.confuser.banmanager.common.kyori.text.serializer.gson.GsonComponentSerializer; -import me.confuser.banmanager.common.kyori.text.TextComponent; +import me.confuser.banmanager.common.kyori.text.Component; import me.confuser.banmanager.common.util.ColorUtils; import me.confuser.banmanager.common.util.Message; import me.confuser.banmanager.sponge.api.events.*; @@ -67,13 +67,6 @@ public void broadcast(String message, String permission) { Sponge.getServer().getConsole().sendMessage(Text.of(message)); } - @Override - public void broadcastJSON(TextComponent message, String permission) { - Arrays.stream(getOnlinePlayers()).forEach(player -> { - if (player.hasPermission(permission)) player.sendJSONMessage(message); - }); - } - public void broadcast(String message, String permission, CommonSender sender) { broadcast(message, permission); @@ -85,8 +78,8 @@ public static Text formatMessage(String message) { return TextSerializers.JSON.deserialize(json); } - public static Text formatMessage(TextComponent message) { - String json = GsonComponentSerializer.colorDownsamplingGson().serialize(message); + public static Text formatMessage(Component message) { + String json = GsonComponentSerializer.builder().downsampleColors().build().serialize(message); return TextSerializers.JSON.deserialize(json); } diff --git a/sponge-api7/src/main/java/me/confuser/banmanager/sponge/listeners/JoinListener.java b/sponge-api7/src/main/java/me/confuser/banmanager/sponge/listeners/JoinListener.java index 1e8ed1573..b934f0649 100644 --- a/sponge-api7/src/main/java/me/confuser/banmanager/sponge/listeners/JoinListener.java +++ b/sponge-api7/src/main/java/me/confuser/banmanager/sponge/listeners/JoinListener.java @@ -60,13 +60,13 @@ public void handlePlayerDeny(PlayerData player, Message message) { plugin.getServer().callEvent("PlayerDeniedEvent", player, message); String locale = player.getLocale() != null ? player.getLocale() : "en"; event.setCancelled(true); - event.setMessage(SpongeServer.formatMessage(message.resolve(locale))); + event.setMessage(SpongeServer.formatMessage(message.resolveComponent(locale))); } @Override public void handleDeny(Message message) { event.setCancelled(true); - event.setMessage(SpongeServer.formatMessage(message.toString())); + event.setMessage(SpongeServer.formatMessage(message.resolveComponent())); } } @@ -81,7 +81,7 @@ public void handlePlayerDeny(PlayerData player, Message message) { @Override public void handleDeny(Message message) { - event.setMessage(SpongeServer.formatMessage(message.toString())); + event.setMessage(SpongeServer.formatMessage(message.resolveComponent())); event.setCancelled(true); } } diff --git a/sponge/src/main/java/me/confuser/banmanager/sponge/BMSpongePlugin.java b/sponge/src/main/java/me/confuser/banmanager/sponge/BMSpongePlugin.java index 4b4f8d737..95c124cfc 100644 --- a/sponge/src/main/java/me/confuser/banmanager/sponge/BMSpongePlugin.java +++ b/sponge/src/main/java/me/confuser/banmanager/sponge/BMSpongePlugin.java @@ -55,7 +55,7 @@ public class BMSpongePlugin { "webhooks.yml", "exemptions.yml", "geoip.yml", - "messages.yml", + "notifications.yml", "reasons.yml", "schedules.yml" }; diff --git a/sponge/src/main/java/me/confuser/banmanager/sponge/SpongePlayer.java b/sponge/src/main/java/me/confuser/banmanager/sponge/SpongePlayer.java index 187d928e7..e2e8fd7a8 100644 --- a/sponge/src/main/java/me/confuser/banmanager/sponge/SpongePlayer.java +++ b/sponge/src/main/java/me/confuser/banmanager/sponge/SpongePlayer.java @@ -6,15 +6,19 @@ import me.confuser.banmanager.common.data.PlayerData; import me.confuser.banmanager.common.kyori.text.TextComponent; import me.confuser.banmanager.common.util.Message; +import me.confuser.banmanager.common.util.MessageRenderer; import me.confuser.banmanager.common.util.MessageRegistry; import me.confuser.banmanager.common.util.UUIDUtils; +import net.kyori.adventure.key.Key; +import net.kyori.adventure.sound.Sound; import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; +import net.kyori.adventure.title.Title; import org.spongepowered.api.Sponge; import org.spongepowered.api.entity.living.player.server.ServerPlayer; import org.spongepowered.api.world.server.ServerLocation; import org.spongepowered.api.world.server.ServerWorld; -import org.spongepowered.math.vector.Vector3d; import java.net.InetAddress; import java.sql.SQLException; @@ -47,6 +51,11 @@ public void kick(String message) { getPlayer().kick(SpongeServer.formatMessage(message)); } + @Override + public void kick(me.confuser.banmanager.common.kyori.text.Component component) { + getPlayer().kick(convertToNative(component)); + } + @Override public void sendMessage(String message) { if (message.isEmpty()) return; @@ -59,8 +68,38 @@ public void sendMessage(String message) { } @Override - public void sendMessage(Message message) { - sendMessage(message.toString()); + public void sendMessage(me.confuser.banmanager.common.kyori.text.Component component) { + getPlayer().sendMessage(convertToNative(component)); + } + + @Override + public void sendActionBar(me.confuser.banmanager.common.kyori.text.Component component) { + getPlayer().sendActionBar(convertToNative(component)); + } + + @Override + public void showTitle(me.confuser.banmanager.common.kyori.text.Component title, + me.confuser.banmanager.common.kyori.text.Component subtitle, + int fadeIn, int stay, int fadeOut) { + Component nativeTitle = title != null ? convertToNative(title) : Component.empty(); + Component nativeSubtitle = subtitle != null ? convertToNative(subtitle) : Component.empty(); + Title.Times times = Title.Times.times( + java.time.Duration.ofMillis(fadeIn * 50L), + java.time.Duration.ofMillis(stay * 50L), + java.time.Duration.ofMillis(fadeOut * 50L) + ); + getPlayer().showTitle(Title.title(nativeTitle, nativeSubtitle, times)); + } + + @Override + public void playSound(String sound, float volume, float pitch) { + ServerPlayer p = getPlayer(); + if (p == null) return; + try { + p.playSound(Sound.sound(Key.key(sound), Sound.Source.MASTER, volume, pitch)); + } catch (IllegalArgumentException ignored) { + // Invalid sound key -- silently ignore + } } @Override @@ -73,6 +112,11 @@ public void sendJSONMessage(String jsonString) { getPlayer().sendMessage(SpongeServer.formatJsonMessage(jsonString)); } + private Component convertToNative(me.confuser.banmanager.common.kyori.text.Component component) { + String json = MessageRenderer.getInstance().toJson(component); + return GsonComponentSerializer.gson().deserialize(json); + } + @Override public boolean isConsole() { return false; diff --git a/sponge/src/main/java/me/confuser/banmanager/sponge/SpongeSender.java b/sponge/src/main/java/me/confuser/banmanager/sponge/SpongeSender.java index ff1db3334..cbb681024 100644 --- a/sponge/src/main/java/me/confuser/banmanager/sponge/SpongeSender.java +++ b/sponge/src/main/java/me/confuser/banmanager/sponge/SpongeSender.java @@ -61,11 +61,6 @@ public void sendMessage(String message) { audience.sendMessage(SpongeServer.formatMessage(message)); } - @Override - public void sendMessage(Message message) { - sendMessage(message.toString()); - } - @Override public boolean isConsole() { if (audience instanceof ServerPlayer) { diff --git a/sponge/src/main/java/me/confuser/banmanager/sponge/SpongeServer.java b/sponge/src/main/java/me/confuser/banmanager/sponge/SpongeServer.java index d7031da51..b10f3bc6d 100644 --- a/sponge/src/main/java/me/confuser/banmanager/sponge/SpongeServer.java +++ b/sponge/src/main/java/me/confuser/banmanager/sponge/SpongeServer.java @@ -4,7 +4,6 @@ import me.confuser.banmanager.common.api.events.CommonEvent; import me.confuser.banmanager.common.commands.CommonSender; import me.confuser.banmanager.common.data.*; -import me.confuser.banmanager.common.kyori.text.TextComponent; import me.confuser.banmanager.common.kyori.text.serializer.gson.GsonComponentSerializer; import me.confuser.banmanager.common.util.ColorUtils; import me.confuser.banmanager.common.util.Message; @@ -66,13 +65,6 @@ public void broadcast(String message, String permission) { Sponge.systemSubject().sendMessage(formatMessage(message)); } - @Override - public void broadcastJSON(TextComponent message, String permission) { - Arrays.stream(getOnlinePlayers()).forEach(player -> { - if (player.hasPermission(permission)) player.sendJSONMessage(message); - }); - } - public void broadcast(String message, String permission, CommonSender sender) { broadcast(message, permission); @@ -88,10 +80,10 @@ public static Component formatMessage(String message) { } public static Component formatMessage(Message message) { - return formatMessage(message.toString()); + return formatMessage(message.resolveComponent()); } - public static Component formatMessage(TextComponent message) { + public static Component formatMessage(me.confuser.banmanager.common.kyori.text.Component message) { String json = GsonComponentSerializer.gson().serialize(message); return net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().deserialize(json); } diff --git a/sponge/src/main/java/me/confuser/banmanager/sponge/listeners/JoinListener.java b/sponge/src/main/java/me/confuser/banmanager/sponge/listeners/JoinListener.java index 8efc90a43..ea4749f44 100644 --- a/sponge/src/main/java/me/confuser/banmanager/sponge/listeners/JoinListener.java +++ b/sponge/src/main/java/me/confuser/banmanager/sponge/listeners/JoinListener.java @@ -82,14 +82,14 @@ public void handlePlayerDeny(PlayerData player, Message message) { String locale = player.getLocale() != null ? player.getLocale() : "en"; isDenied = true; event.setCancelled(true); - event.setMessage(SpongeServer.formatMessage(message.resolve(locale))); + event.setMessage(SpongeServer.formatMessage(message.resolveComponent(locale))); } @Override public void handleDeny(Message message) { isDenied = true; event.setCancelled(true); - event.setMessage(SpongeServer.formatMessage(message.toString())); + event.setMessage(SpongeServer.formatMessage(message.resolveComponent())); } } diff --git a/velocity/src/main/java/me/confuser/banmanager/velocity/BMVelocityPlugin.java b/velocity/src/main/java/me/confuser/banmanager/velocity/BMVelocityPlugin.java index ffc4ae78b..e9e49511d 100644 --- a/velocity/src/main/java/me/confuser/banmanager/velocity/BMVelocityPlugin.java +++ b/velocity/src/main/java/me/confuser/banmanager/velocity/BMVelocityPlugin.java @@ -59,7 +59,7 @@ public class BMVelocityPlugin { "webhooks.yml", "exemptions.yml", "geoip.yml", - "messages.yml", + "notifications.yml", "reasons.yml", "schedules.yml" }; diff --git a/velocity/src/main/java/me/confuser/banmanager/velocity/VelocityPlayer.java b/velocity/src/main/java/me/confuser/banmanager/velocity/VelocityPlayer.java index 00158c854..e2977477f 100644 --- a/velocity/src/main/java/me/confuser/banmanager/velocity/VelocityPlayer.java +++ b/velocity/src/main/java/me/confuser/banmanager/velocity/VelocityPlayer.java @@ -5,17 +5,25 @@ import me.confuser.banmanager.common.CommonWorld; import me.confuser.banmanager.common.commands.CommonCommand; import me.confuser.banmanager.common.data.PlayerData; +import me.confuser.banmanager.common.kyori.text.Component; +import me.confuser.banmanager.common.kyori.text.TextComponent; import me.confuser.banmanager.common.util.Message; +import me.confuser.banmanager.common.util.MessageRenderer; import me.confuser.banmanager.common.util.MessageRegistry; -import me.confuser.banmanager.common.kyori.text.TextComponent; +import net.kyori.adventure.key.Key; +import net.kyori.adventure.sound.Sound; import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; - +import net.kyori.adventure.title.Title; import java.net.InetAddress; -import java.util.Optional; +import java.time.Duration; import java.util.UUID; public class VelocityPlayer implements CommonPlayer { + // Only used for legacy sendJSONMessage(String) path; Component methods use full-color gson + private static final GsonComponentSerializer DOWNSAMPLING_GSON = + GsonComponentSerializer.builder().downsampleColors().build(); + private final UUID uuid; private final boolean onlineMode; private final Player player; @@ -31,6 +39,11 @@ public void kick(String message) { player.disconnect(VelocityServer.formatMessage(message)); } + @Override + public void kick(Component component) { + player.disconnect(convertToNative(component)); + } + @Override public void sendMessage(String message) { if(message.isEmpty()) return; @@ -43,8 +56,37 @@ public void sendMessage(String message) { } @Override - public void sendMessage(Message message) { - sendMessage(message.toString()); + public void sendMessage(Component component) { + player.sendMessage(convertToNative(component)); + } + + @Override + public void sendActionBar(Component component) { + player.sendActionBar(convertToNative(component)); + } + + @Override + public void showTitle(Component title, Component subtitle, int fadeIn, int stay, int fadeOut) { + net.kyori.adventure.text.Component nativeTitle = title != null + ? convertToNative(title) : net.kyori.adventure.text.Component.empty(); + net.kyori.adventure.text.Component nativeSubtitle = subtitle != null + ? convertToNative(subtitle) : net.kyori.adventure.text.Component.empty(); + + Title.Times times = Title.Times.of( + Duration.ofMillis(fadeIn * 50L), + Duration.ofMillis(stay * 50L), + Duration.ofMillis(fadeOut * 50L) + ); + player.showTitle(Title.title(nativeTitle, nativeSubtitle, times)); + } + + @Override + public void playSound(String sound, float volume, float pitch) { + try { + player.playSound(Sound.sound(Key.key(sound), Sound.Source.MASTER, volume, pitch)); + } catch (IllegalArgumentException ignored) { + // Invalid sound key -- silently ignore + } } @Override @@ -54,7 +96,12 @@ public void sendJSONMessage(TextComponent jsonString) { @Override public void sendJSONMessage(String jsonString) { - player.sendMessage(GsonComponentSerializer.colorDownsamplingGson().deserialize(jsonString)); + player.sendMessage(DOWNSAMPLING_GSON.deserialize(jsonString)); + } + + private net.kyori.adventure.text.Component convertToNative(Component component) { + String json = MessageRenderer.getInstance().toJson(component); + return GsonComponentSerializer.gson().deserialize(json); } @Override @@ -99,7 +146,7 @@ public InetAddress getAddress() { @Override public UUID getUniqueId() { - return this.player.getUniqueId(); + return this.uuid; } @Override diff --git a/velocity/src/main/java/me/confuser/banmanager/velocity/VelocitySender.java b/velocity/src/main/java/me/confuser/banmanager/velocity/VelocitySender.java index af783e818..e7270df8e 100644 --- a/velocity/src/main/java/me/confuser/banmanager/velocity/VelocitySender.java +++ b/velocity/src/main/java/me/confuser/banmanager/velocity/VelocitySender.java @@ -6,7 +6,6 @@ import me.confuser.banmanager.common.commands.CommonCommand; import me.confuser.banmanager.common.commands.CommonSender; import me.confuser.banmanager.common.data.PlayerData; -import me.confuser.banmanager.common.util.Message; public class VelocitySender implements CommonSender { @@ -31,11 +30,6 @@ public void sendMessage(String message) { commandSource.sendMessage(VelocityServer.formatMessage(message)); } - @Override - public void sendMessage(Message message) { - sendMessage(message.toString()); - } - @Override public boolean isConsole() { return !(commandSource instanceof Player); diff --git a/velocity/src/main/java/me/confuser/banmanager/velocity/VelocityServer.java b/velocity/src/main/java/me/confuser/banmanager/velocity/VelocityServer.java index 129f723d1..f4357eacc 100644 --- a/velocity/src/main/java/me/confuser/banmanager/velocity/VelocityServer.java +++ b/velocity/src/main/java/me/confuser/banmanager/velocity/VelocityServer.java @@ -9,7 +9,6 @@ import me.confuser.banmanager.common.api.events.CommonEvent; import me.confuser.banmanager.common.commands.CommonSender; import me.confuser.banmanager.common.data.*; -import me.confuser.banmanager.common.kyori.text.TextComponent; import me.confuser.banmanager.common.util.ColorUtils; import me.confuser.banmanager.common.util.Message; import me.confuser.banmanager.velocity.api.events.*; @@ -70,16 +69,6 @@ public void broadcast(String message, String permission) { } } - @Override - public void broadcastJSON(TextComponent message, String permission) { - Component converted = convert(message); - for (Player player : server.getAllPlayers()) { - if (player.hasPermission(permission)) { - player.sendMessage(converted); - } - } - } - @Override public void broadcast(String message, String permission, CommonSender sender) { broadcast(message, permission); diff --git a/velocity/src/main/java/me/confuser/banmanager/velocity/listeners/JoinListener.java b/velocity/src/main/java/me/confuser/banmanager/velocity/listeners/JoinListener.java index 7b3b9c842..c806feb0c 100644 --- a/velocity/src/main/java/me/confuser/banmanager/velocity/listeners/JoinListener.java +++ b/velocity/src/main/java/me/confuser/banmanager/velocity/listeners/JoinListener.java @@ -56,13 +56,14 @@ public static class BanJoinHandler implements CommonJoinHandler { @Override public void handleDeny(Message message) { - event.setResult(ResultedEvent.ComponentResult.denied(VelocityServer.formatMessage(message.toString()))); + event.setResult(ResultedEvent.ComponentResult.denied(VelocityServer.convert(message.resolveComponent()))); } @Override public void handlePlayerDeny(PlayerData player, Message message) { plugin.getServer().callEvent("PlayerDeniedEvent", player, message); - event.setResult(ResultedEvent.ComponentResult.denied(VelocityServer.formatMessage(message.resolve(player.getLocale() != null ? player.getLocale() : "en")))); + event.setResult(ResultedEvent.ComponentResult.denied( + VelocityServer.convert(message.resolveComponent(player.getLocale() != null ? player.getLocale() : "en")))); } } @@ -72,7 +73,7 @@ public class LoginHandler implements CommonJoinHandler { @Override public void handleDeny(Message message) { - event.getPlayer().disconnect(VelocityServer.formatMessage(message.toString())); + event.getPlayer().disconnect(VelocityServer.convert(message.resolveComponent())); } @Override