From 6b657da3f19b894cd08421c201a84ba9694d0b63 Mon Sep 17 00:00:00 2001 From: cl3i550n Date: Mon, 23 Mar 2026 11:17:57 -0300 Subject: [PATCH 1/6] Update dependencies and improve command messaging - Bumped Spigot version to 1.21.11-R0.1-SNAPSHOT for compatibility with Paper API. - Added Paper API repository and dependency for AsyncPlayerSpawnLocationEvent. - Refactored command responses to use a centralized messaging service for consistency and clarity. - Enhanced various command implementations to provide better feedback to users, including error messages and success confirmations. --- pom.xml | 18 +- src/main/java/fr/xephi/authme/AuthMe.java | 7 +- .../xephi/authme/command/CommandHandler.java | 19 +- .../xephi/authme/command/PlayerCommand.java | 10 +- .../command/executable/HelpCommand.java | 20 +- .../executable/authme/AccountsCommand.java | 16 +- .../executable/authme/AuthMeCommand.java | 19 +- .../executable/authme/ConverterCommand.java | 5 +- .../executable/authme/FirstSpawnCommand.java | 3 +- .../executable/authme/ForceLoginCommand.java | 11 +- .../executable/authme/GetEmailCommand.java | 2 +- .../executable/authme/GetIpCommand.java | 15 +- .../executable/authme/LastLoginCommand.java | 24 +- .../executable/authme/PurgeCommand.java | 11 +- .../authme/PurgeLastPositionCommand.java | 4 +- .../executable/authme/PurgePlayerCommand.java | 10 +- .../authme/RecentPlayersCommand.java | 25 +- .../executable/authme/ReloadCommand.java | 5 +- .../authme/SetFirstSpawnCommand.java | 5 +- .../executable/authme/SetSpawnCommand.java | 5 +- .../executable/authme/SpawnCommand.java | 3 +- .../authme/SwitchAntiBotCommand.java | 17 +- .../authme/TotpDisableAdminCommand.java | 9 +- .../authme/TotpViewStatusCommand.java | 5 +- .../authme/UpdateHelpMessagesCommand.java | 9 +- .../executable/authme/VersionCommand.java | 51 +- .../authme/debug/CountryLookup.java | 28 +- .../authme/debug/DataStatistics.java | 36 +- .../executable/authme/debug/DebugCommand.java | 16 +- .../authme/debug/HasPermissionChecker.java | 31 +- .../authme/debug/InputValidator.java | 28 +- .../authme/debug/LimboPlayerViewer.java | 64 +- .../authme/debug/MySqlDefaultChanger.java | 60 +- .../authme/debug/PermissionGroups.java | 15 +- .../authme/debug/PlayerAuthViewer.java | 43 +- .../authme/debug/SpawnLocationViewer.java | 33 +- .../authme/debug/TestEmailSender.java | 31 +- .../authme/command/help/HelpMessage.java | 14 +- .../authme/command/help/HelpProvider.java | 5 +- .../AbstractDataSourceConverter.java | 23 +- .../converter/CrazyLoginConverter.java | 8 +- .../datasource/converter/H2ToSqlite.java | 5 +- .../converter/LoginSecurityConverter.java | 23 +- .../datasource/converter/MySqlToSqlite.java | 6 +- .../datasource/converter/SqliteToH2.java | 5 +- .../datasource/converter/SqliteToSql.java | 5 +- .../datasource/converter/XAuthConverter.java | 17 +- .../listener/PlayerListener19Spigot.java | 10 +- .../PlayerListenerPaperAsyncSpawn.java | 38 ++ .../fr/xephi/authme/message/MessageKey.java | 639 +++++++++++++++++- .../message/updater/MessageUpdater.java | 3 + .../xephi/authme/service/BackupService.java | 16 +- .../xephi/authme/service/CommonService.java | 12 + .../authme/service/TeleportationService.java | 37 +- .../fr/xephi/authme/settings/SpawnLoader.java | 32 +- .../xephi/authme/task/purge/PurgeService.java | 18 +- .../fr/xephi/authme/task/purge/PurgeTask.java | 24 +- src/main/resources/messages/help_br.yml | 76 ++- src/main/resources/messages/help_en.yml | 4 + src/main/resources/messages/messages_br.yml | 477 +++++++++---- src/main/resources/messages/messages_en.yml | 220 ++++++ 61 files changed, 1891 insertions(+), 539 deletions(-) create mode 100644 src/main/java/fr/xephi/authme/listener/PlayerListenerPaperAsyncSpawn.java diff --git a/pom.xml b/pom.xml index c4565feb56..00fa11d221 100644 --- a/pom.xml +++ b/pom.xml @@ -95,8 +95,8 @@ 0.10.2 1.5.0 1.3.1 - - 1.21.1-R0.1-SNAPSHOT + + 1.21.11-R0.1-SNAPSHOT 2.20.0 3.0.2 @@ -451,6 +451,12 @@ + + + papermc + https://repo.papermc.io/repository/maven-public/ + + codemc-repo @@ -737,6 +743,14 @@ + + + + io.papermc.paper + paper-api + ${dependencies.spigot.version} + provided + org.apache.logging.log4j log4j-core diff --git a/src/main/java/fr/xephi/authme/AuthMe.java b/src/main/java/fr/xephi/authme/AuthMe.java index 78a19279e4..c8247ca626 100644 --- a/src/main/java/fr/xephi/authme/AuthMe.java +++ b/src/main/java/fr/xephi/authme/AuthMe.java @@ -25,6 +25,7 @@ import fr.xephi.authme.listener.PlayerListener111; import fr.xephi.authme.listener.PlayerListener19; import fr.xephi.authme.listener.PlayerListener19Spigot; +import fr.xephi.authme.listener.PlayerListenerPaperAsyncSpawn; import fr.xephi.authme.listener.PlayerListenerHigherThan18; import fr.xephi.authme.listener.PurgeListener; import fr.xephi.authme.listener.ServerListener; @@ -335,8 +336,10 @@ void registerEventListeners(Injector injector) { // pluginManager.registerEvents(injector.getSingleton(PlayerListener19.class), this); // } - // Try to register 1.9 spigot player listeners - if (isClassLoaded("org.spigotmc.event.player.PlayerSpawnLocationEvent")) { + // Join spawn: Paper 1.21.9+ uses AsyncPlayerSpawnLocationEvent; Spigot event is deprecated there + if (isClassLoaded("io.papermc.paper.event.player.AsyncPlayerSpawnLocationEvent")) { + pluginManager.registerEvents(injector.getSingleton(PlayerListenerPaperAsyncSpawn.class), this); + } else if (isClassLoaded("org.spigotmc.event.player.PlayerSpawnLocationEvent")) { pluginManager.registerEvents(injector.getSingleton(PlayerListener19Spigot.class), this); } diff --git a/src/main/java/fr/xephi/authme/command/CommandHandler.java b/src/main/java/fr/xephi/authme/command/CommandHandler.java index 08629c6f5c..acfa0d824b 100644 --- a/src/main/java/fr/xephi/authme/command/CommandHandler.java +++ b/src/main/java/fr/xephi/authme/command/CommandHandler.java @@ -7,7 +7,6 @@ import fr.xephi.authme.message.Messages; import fr.xephi.authme.permission.PermissionsManager; import fr.xephi.authme.util.StringUtils; -import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import javax.inject.Inject; @@ -81,7 +80,7 @@ private void handleCommandResult(CommandSender sender, FoundCommandResult result executeCommand(sender, result); break; case MISSING_BASE_COMMAND: - sender.sendMessage(ChatColor.DARK_RED + "Failed to parse " + AuthMe.getPluginName() + " command!"); + messages.send(sender, MessageKey.COMMAND_PARSE_FAILED, AuthMe.getPluginName()); break; case INCORRECT_ARGUMENTS: sendImproperArgumentsMessage(sender, result); @@ -145,17 +144,16 @@ private static List skipEmptyArguments(String[] args) { * @param sender The command sender * @param result The command that was found during the mapping process */ - private static void sendUnknownCommandMessage(CommandSender sender, FoundCommandResult result) { - sender.sendMessage(ChatColor.DARK_RED + "Unknown command!"); + private void sendUnknownCommandMessage(CommandSender sender, FoundCommandResult result) { + messages.send(sender, MessageKey.UNKNOWN_AUTHME_COMMAND); // Show a command suggestion if available and the difference isn't too big if (result.getDifference() <= SUGGEST_COMMAND_THRESHOLD && result.getCommandDescription() != null) { - sender.sendMessage(ChatColor.YELLOW + "Did you mean " + ChatColor.GOLD - + CommandUtils.constructCommandPath(result.getCommandDescription()) + ChatColor.YELLOW + "?"); + messages.send(sender, MessageKey.COMMAND_SUGGEST_SIMILAR, + CommandUtils.constructCommandPath(result.getCommandDescription())); } - sender.sendMessage(ChatColor.YELLOW + "Use the command " + ChatColor.GOLD + "/" + result.getLabels().get(0) - + " help" + ChatColor.YELLOW + " to view help."); + messages.send(sender, MessageKey.COMMAND_USE_HELP, result.getLabels().get(0)); } private void sendImproperArgumentsMessage(CommandSender sender, FoundCommandResult result) { @@ -175,12 +173,11 @@ private void sendImproperArgumentsMessage(CommandSender sender, FoundCommandResu } private void showHelpForCommand(CommandSender sender, FoundCommandResult result) { - sender.sendMessage(ChatColor.DARK_RED + "Incorrect command arguments!"); + messages.send(sender, MessageKey.INCORRECT_COMMAND_ARGUMENTS_GENERIC); helpProvider.outputHelp(sender, result, HelpProvider.SHOW_ARGUMENTS); List labels = result.getLabels(); String childLabel = labels.size() >= 2 ? labels.get(1) : ""; - sender.sendMessage(ChatColor.GOLD + "Detailed help: " + ChatColor.WHITE - + "/" + labels.get(0) + " help " + childLabel); + messages.send(sender, MessageKey.COMMAND_DETAILED_HELP_SYNTAX, labels.get(0), childLabel); } } diff --git a/src/main/java/fr/xephi/authme/command/PlayerCommand.java b/src/main/java/fr/xephi/authme/command/PlayerCommand.java index 8ce6e05fcb..f439a4155f 100644 --- a/src/main/java/fr/xephi/authme/command/PlayerCommand.java +++ b/src/main/java/fr/xephi/authme/command/PlayerCommand.java @@ -1,8 +1,11 @@ package fr.xephi.authme.command; +import fr.xephi.authme.message.MessageKey; +import fr.xephi.authme.service.CommonService; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import javax.inject.Inject; import java.util.List; /** @@ -10,6 +13,9 @@ */ public abstract class PlayerCommand implements ExecutableCommand { + @Inject + protected CommonService commonService; + @Override public void executeCommand(CommandSender sender, List arguments) { if (sender instanceof Player) { @@ -17,9 +23,9 @@ public void executeCommand(CommandSender sender, List arguments) { } else { String alternative = getAlternativeCommand(); if (alternative != null) { - sender.sendMessage("Player only! Please use " + alternative + " instead."); + commonService.send(sender, MessageKey.PLAYER_ONLY_ALTERNATIVE, alternative); } else { - sender.sendMessage("This command is only for players."); + commonService.send(sender, MessageKey.PLAYER_ONLY); } } } diff --git a/src/main/java/fr/xephi/authme/command/executable/HelpCommand.java b/src/main/java/fr/xephi/authme/command/executable/HelpCommand.java index 118994f072..9bd2479946 100644 --- a/src/main/java/fr/xephi/authme/command/executable/HelpCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/HelpCommand.java @@ -5,13 +5,16 @@ import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.command.FoundCommandResult; import fr.xephi.authme.command.FoundResultStatus; +import fr.xephi.authme.command.help.HelpMessage; +import fr.xephi.authme.command.help.HelpMessagesService; import fr.xephi.authme.command.help.HelpProvider; -import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import javax.inject.Inject; import java.util.List; +import static org.bukkit.ChatColor.translateAlternateColorCodes; + import static fr.xephi.authme.command.FoundResultStatus.MISSING_BASE_COMMAND; import static fr.xephi.authme.command.FoundResultStatus.UNKNOWN_LABEL; import static fr.xephi.authme.command.help.HelpProvider.ALL_OPTIONS; @@ -31,6 +34,9 @@ public class HelpCommand implements ExecutableCommand { @Inject private HelpProvider helpProvider; + @Inject + private HelpMessagesService helpMessagesService; + // Convention: arguments is not the actual invoked arguments but the command that was invoked, // e.g. "/authme help register" would typically be arguments = [register], but here we pass [authme, register] @@ -40,15 +46,19 @@ public void executeCommand(CommandSender sender, List arguments) { FoundResultStatus resultStatus = result.getResultStatus(); if (MISSING_BASE_COMMAND.equals(resultStatus)) { - sender.sendMessage(ChatColor.DARK_RED + "Could not get base command"); + sender.sendMessage(translateAlternateColorCodes('&', + helpMessagesService.getMessage(HelpMessage.HELP_MISSING_BASE_COMMAND))); return; } else if (UNKNOWN_LABEL.equals(resultStatus)) { if (result.getCommandDescription() == null) { - sender.sendMessage(ChatColor.DARK_RED + "Unknown command"); + sender.sendMessage(translateAlternateColorCodes('&', + helpMessagesService.getMessage(HelpMessage.HELP_UNKNOWN_COMMAND))); return; } else { - sender.sendMessage(ChatColor.GOLD + "Assuming " + ChatColor.WHITE - + CommandUtils.constructCommandPath(result.getCommandDescription())); + String path = CommandUtils.constructCommandPath(result.getCommandDescription()); + String message = helpMessagesService.getMessage(HelpMessage.HELP_ASSUMING_COMMAND) + .replace("%command%", path); + sender.sendMessage(translateAlternateColorCodes('&', message)); } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/AccountsCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/AccountsCommand.java index 20f6bff8ab..b64641bd0d 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/AccountsCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/AccountsCommand.java @@ -36,9 +36,9 @@ public void executeCommand(final CommandSender sender, List arguments) { bukkitService.runTaskAsynchronously(() -> { List accountList = dataSource.getAllAuthsByIp(playerName); if (accountList.isEmpty()) { - sender.sendMessage("[AuthMe] This IP does not exist in the database."); + commonService.send(sender, MessageKey.ADMIN_ACCOUNTS_IP_UNKNOWN); } else if (accountList.size() == 1) { - sender.sendMessage("[AuthMe] " + playerName + " is a single account player"); + commonService.send(sender, MessageKey.ADMIN_ACCOUNTS_SINGLE, playerName); } else { outputAccountsList(sender, playerName, accountList); } @@ -50,7 +50,7 @@ public void executeCommand(final CommandSender sender, List arguments) { commonService.send(sender, MessageKey.UNKNOWN_USER); return; } else if (auth.getLastIp() == null) { - sender.sendMessage("No known last IP address for player"); + commonService.send(sender, MessageKey.ADMIN_ACCOUNTS_NO_LAST_IP); return; } @@ -58,7 +58,7 @@ public void executeCommand(final CommandSender sender, List arguments) { if (accountList.isEmpty()) { commonService.send(sender, MessageKey.UNKNOWN_USER); } else if (accountList.size() == 1) { - sender.sendMessage("[AuthMe] " + playerName + " is a single account player"); + commonService.send(sender, MessageKey.ADMIN_ACCOUNTS_SINGLE, playerName); } else { outputAccountsList(sender, playerName, accountList); } @@ -66,9 +66,9 @@ public void executeCommand(final CommandSender sender, List arguments) { } } - private static void outputAccountsList(CommandSender sender, String playerName, List accountList) { - sender.sendMessage("[AuthMe] " + playerName + " has " + accountList.size() + " accounts."); - String message = "[AuthMe] " + String.join(", ", accountList) + "."; - sender.sendMessage(message); + private void outputAccountsList(CommandSender sender, String playerName, List accountList) { + commonService.send(sender, MessageKey.ADMIN_ACCOUNTS_MULTIPLE, playerName, + String.valueOf(accountList.size())); + commonService.send(sender, MessageKey.ADMIN_ACCOUNTS_LIST, String.join(", ", accountList)); } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/AuthMeCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/AuthMeCommand.java index 2648177eb5..0a4efcf9d2 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/AuthMeCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/AuthMeCommand.java @@ -2,9 +2,11 @@ import fr.xephi.authme.AuthMe; import fr.xephi.authme.command.ExecutableCommand; -import org.bukkit.ChatColor; +import fr.xephi.authme.message.MessageKey; +import fr.xephi.authme.message.Messages; import org.bukkit.command.CommandSender; +import javax.inject.Inject; import java.util.List; /** @@ -12,13 +14,16 @@ */ public class AuthMeCommand implements ExecutableCommand { + @Inject + private Messages messages; + @Override public void executeCommand(CommandSender sender, List arguments) { - sender.sendMessage(ChatColor.GREEN + "This server is running " + AuthMe.getPluginName() + " v" - + AuthMe.getPluginVersion() + " b" + AuthMe.getPluginBuildNumber()+ "! " + ChatColor.RED + "<3"); - sender.sendMessage(ChatColor.YELLOW + "Use the command " + ChatColor.GOLD + "/authme help" + ChatColor.YELLOW - + " to view help."); - sender.sendMessage(ChatColor.YELLOW + "Use the command " + ChatColor.GOLD + "/authme about" + ChatColor.YELLOW - + " to view about."); + messages.send(sender, MessageKey.AUTHME_INFO_RUNNING, + AuthMe.getPluginName(), + AuthMe.getPluginVersion(), + String.valueOf(AuthMe.getPluginBuildNumber())); + messages.send(sender, MessageKey.AUTHME_INFO_HELP); + messages.send(sender, MessageKey.AUTHME_INFO_ABOUT); } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/ConverterCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/ConverterCommand.java index 15875ac9b3..0ca34ed3f7 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/ConverterCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/ConverterCommand.java @@ -48,7 +48,8 @@ public class ConverterCommand implements ExecutableCommand { public void executeCommand(CommandSender sender, List arguments) { Class converterClass = getConverterClassFromArgs(arguments); if (converterClass == null) { - sender.sendMessage("Converters: " + String.join(", ", CONVERTERS.keySet())); + commonService.send(sender, MessageKey.ADMIN_CONVERTER_LIST, + String.join(", ", CONVERTERS.keySet())); return; } @@ -66,7 +67,7 @@ public void executeCommand(CommandSender sender, List arguments) { }); // Show a status message - sender.sendMessage("[AuthMe] Successfully started " + arguments.get(0)); + commonService.send(sender, MessageKey.ADMIN_CONVERTER_STARTED, arguments.get(0)); } private static Class getConverterClassFromArgs(List arguments) { diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/FirstSpawnCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/FirstSpawnCommand.java index 9eba3d1510..ba7422f816 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/FirstSpawnCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/FirstSpawnCommand.java @@ -1,6 +1,7 @@ package fr.xephi.authme.command.executable.authme; import fr.xephi.authme.command.PlayerCommand; +import fr.xephi.authme.message.MessageKey; import fr.xephi.authme.service.BukkitService; import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.SpawnLoader; @@ -23,7 +24,7 @@ public class FirstSpawnCommand extends PlayerCommand { @Override public void runCommand(Player player, List arguments) { if (spawnLoader.getFirstSpawn() == null) { - player.sendMessage("[AuthMe] First spawn has failed, please try to define the first spawn"); + commonService.send(player, MessageKey.ADMIN_FIRST_SPAWN_FAILED); } else { //String name= player.getName(); bukkitService.runTaskIfFolia(player, () -> { diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/ForceLoginCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/ForceLoginCommand.java index 3adcad45e1..9e971f63dc 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/ForceLoginCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/ForceLoginCommand.java @@ -2,8 +2,10 @@ import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.permission.PermissionsManager; +import fr.xephi.authme.message.MessageKey; import fr.xephi.authme.process.Management; import fr.xephi.authme.service.BukkitService; +import fr.xephi.authme.service.CommonService; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -26,6 +28,9 @@ public class ForceLoginCommand implements ExecutableCommand { @Inject private BukkitService bukkitService; + @Inject + private CommonService commonService; + @Override public void executeCommand(CommandSender sender, List arguments) { // Get the player query @@ -33,12 +38,12 @@ public void executeCommand(CommandSender sender, List arguments) { Player player = bukkitService.getPlayerExact(playerName); if (player == null || !player.isOnline()) { - sender.sendMessage("Player needs to be online!"); + commonService.send(sender, MessageKey.ADMIN_FORCE_LOGIN_OFFLINE); } else if (!permissionsManager.hasPermission(player, CAN_LOGIN_BE_FORCED)) { - sender.sendMessage("You cannot force login the player " + playerName + "!"); + commonService.send(sender, MessageKey.ADMIN_FORCE_LOGIN_DENIED, playerName); } else { management.forceLogin(player); - sender.sendMessage("Force login for " + playerName + " performed!"); + commonService.send(sender, MessageKey.ADMIN_FORCE_LOGIN_SUCCESS, playerName); } } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/GetEmailCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/GetEmailCommand.java index b669143877..41996455dc 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/GetEmailCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/GetEmailCommand.java @@ -27,7 +27,7 @@ public void executeCommand(CommandSender sender, List arguments) { DataSourceValue email = dataSource.getEmail(playerName); if (email.rowExists()) { - sender.sendMessage("[AuthMe] " + playerName + "'s email: " + email.getValue()); + commonService.send(sender, MessageKey.ADMIN_GET_EMAIL, playerName, email.getValue()); } else { commonService.send(sender, MessageKey.UNKNOWN_USER); } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/GetIpCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/GetIpCommand.java index 2e00c65e99..007484a7af 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/GetIpCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/GetIpCommand.java @@ -3,7 +3,9 @@ import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.data.auth.PlayerAuth; import fr.xephi.authme.datasource.DataSource; +import fr.xephi.authme.message.MessageKey; import fr.xephi.authme.service.BukkitService; +import fr.xephi.authme.service.CommonService; import fr.xephi.authme.util.PlayerUtils; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -19,6 +21,9 @@ public class GetIpCommand implements ExecutableCommand { @Inject private DataSource dataSource; + @Inject + private CommonService commonService; + @Override public void executeCommand(CommandSender sender, List arguments) { String playerName = arguments.get(0); @@ -26,16 +31,16 @@ public void executeCommand(CommandSender sender, List arguments) { PlayerAuth auth = dataSource.getAuth(playerName); if (player != null) { - sender.sendMessage("Current IP of " + player.getName() + " is " + PlayerUtils.getPlayerIp(player) - + ":" + player.getAddress().getPort()); + commonService.send(sender, MessageKey.ADMIN_GET_IP_CURRENT, player.getName(), + PlayerUtils.getPlayerIp(player), String.valueOf(player.getAddress().getPort())); } if (auth == null) { String displayName = player == null ? playerName : player.getName(); - sender.sendMessage(displayName + " is not registered in the database"); + commonService.send(sender, MessageKey.ADMIN_GET_IP_NOT_REGISTERED, displayName); } else { - sender.sendMessage("Database: last IP: " + auth.getLastIp() + ", registration IP: " - + auth.getRegistrationIp()); + commonService.send(sender, MessageKey.ADMIN_GET_IP_DATABASE, + String.valueOf(auth.getLastIp()), String.valueOf(auth.getRegistrationIp())); } } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/LastLoginCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/LastLoginCommand.java index f522e80fb5..4a47ba69e8 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/LastLoginCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/LastLoginCommand.java @@ -35,22 +35,26 @@ public void executeCommand(CommandSender sender, List arguments) { // Get the last login date final Long lastLogin = auth.getLastLogin(); - final String lastLoginDate = lastLogin == null ? "never" : new Date(lastLogin).toString(); + final String lastLoginDate = lastLogin == null + ? commonService.retrieveSingleMessage(sender, MessageKey.ADMIN_LAST_LOGIN_NEVER) + : new Date(lastLogin).toString(); // Show the player status - sender.sendMessage("[AuthMe] " + playerName + " last login: " + lastLoginDate); + commonService.send(sender, MessageKey.ADMIN_LAST_LOGIN, playerName, lastLoginDate); if (lastLogin != null) { - sender.sendMessage("[AuthMe] The player " + playerName + " last logged in " - + createLastLoginIntervalMessage(lastLogin) + " ago"); + String interval = createLastLoginIntervalMessage(sender, lastLogin); + commonService.send(sender, MessageKey.ADMIN_LAST_LOGIN_INTERVAL, playerName, interval); } - sender.sendMessage("[AuthMe] Last player's IP: " + auth.getLastIp()); + commonService.send(sender, MessageKey.ADMIN_LAST_LOGIN_IP, String.valueOf(auth.getLastIp())); } - private static String createLastLoginIntervalMessage(long lastLogin) { + private String createLastLoginIntervalMessage(CommandSender sender, long lastLogin) { final long diff = System.currentTimeMillis() - lastLogin; - return (int) (diff / 86400000) + " days " - + (int) (diff / 3600000 % 24) + " hours " - + (int) (diff / 60000 % 60) + " mins " - + (int) (diff / 1000 % 60) + " secs"; + int days = (int) (diff / 86400000); + int hours = (int) (diff / 3600000 % 24); + int mins = (int) (diff / 60000 % 60); + int secs = (int) (diff / 1000 % 60); + return commonService.retrieveSingleMessage(sender, MessageKey.ADMIN_LAST_LOGIN_INTERVAL_PARTS, + String.valueOf(days), String.valueOf(hours), String.valueOf(mins), String.valueOf(secs)); } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/PurgeCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/PurgeCommand.java index 1538061e90..aef00aed79 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/PurgeCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/PurgeCommand.java @@ -2,8 +2,9 @@ import com.google.common.primitives.Ints; import fr.xephi.authme.command.ExecutableCommand; +import fr.xephi.authme.message.MessageKey; +import fr.xephi.authme.service.CommonService; import fr.xephi.authme.task.purge.PurgeService; -import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import javax.inject.Inject; @@ -21,6 +22,9 @@ public class PurgeCommand implements ExecutableCommand { @Inject private PurgeService purgeService; + @Inject + private CommonService commonService; + @Override public void executeCommand(CommandSender sender, List arguments) { // Get the days parameter @@ -29,14 +33,13 @@ public void executeCommand(CommandSender sender, List arguments) { // Convert the days string to an integer value, and make sure it's valid Integer days = Ints.tryParse(daysStr); if (days == null) { - sender.sendMessage(ChatColor.RED + "The value you've entered is invalid!"); + commonService.send(sender, MessageKey.PURGE_INVALID_VALUE); return; } // Validate the value if (days < MINIMUM_LAST_SEEN_DAYS) { - sender.sendMessage(ChatColor.RED + "You can only purge data older than " - + MINIMUM_LAST_SEEN_DAYS + " days"); + commonService.send(sender, MessageKey.PURGE_MINIMUM_DAYS, String.valueOf(MINIMUM_LAST_SEEN_DAYS)); return; } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/PurgeLastPositionCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/PurgeLastPositionCommand.java index 4e20b0313e..0895b6494f 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/PurgeLastPositionCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/PurgeLastPositionCommand.java @@ -31,7 +31,7 @@ public void executeCommand(CommandSender sender, List arguments) { dataSource.updateQuitLoc(auth); // TODO: send an update when a messaging service will be implemented (QUITLOC) } - sender.sendMessage("All players last position locations are now reset"); + commonService.send(sender, MessageKey.ADMIN_PURGE_LASTPOS_ALL); } else { // Get the user auth and make sure the user exists PlayerAuth auth = dataSource.getAuth(playerName); @@ -43,7 +43,7 @@ public void executeCommand(CommandSender sender, List arguments) { resetLastPosition(auth); dataSource.updateQuitLoc(auth); // TODO: send an update when a messaging service will be implemented (QUITLOC) - sender.sendMessage(playerName + "'s last position location is now reset"); + commonService.send(sender, MessageKey.ADMIN_PURGE_LASTPOS_ONE, playerName); } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/PurgePlayerCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/PurgePlayerCommand.java index e0bf9040fe..e4a0fdb927 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/PurgePlayerCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/PurgePlayerCommand.java @@ -2,7 +2,9 @@ import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.datasource.DataSource; +import fr.xephi.authme.message.MessageKey; import fr.xephi.authme.service.BukkitService; +import fr.xephi.authme.service.CommonService; import fr.xephi.authme.task.purge.PurgeExecutor; import org.bukkit.OfflinePlayer; import org.bukkit.command.CommandSender; @@ -27,6 +29,9 @@ public class PurgePlayerCommand implements ExecutableCommand { @Inject private DataSource dataSource; + @Inject + private CommonService commonService; + @Override public void executeCommand(CommandSender sender, List arguments) { String option = arguments.size() > 1 ? arguments.get(1) : null; @@ -38,10 +43,9 @@ private void executeCommand(CommandSender sender, String name, String option) { if ("force".equals(option) || !dataSource.isAuthAvailable(name)) { OfflinePlayer offlinePlayer = bukkitService.getOfflinePlayer(name); purgeExecutor.executePurge(singletonList(offlinePlayer), singletonList(name.toLowerCase(Locale.ROOT))); - sender.sendMessage("Purged data for player " + name); + commonService.send(sender, MessageKey.ADMIN_PURGE_PLAYER_SUCCESS, name); } else { - sender.sendMessage("This player is still registered! Are you sure you want to proceed? " - + "Use '/authme purgeplayer " + name + " force' to run the command anyway"); + commonService.send(sender, MessageKey.ADMIN_PURGE_PLAYER_CONFIRM, name); } } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/RecentPlayersCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/RecentPlayersCommand.java index 3ae185e3e1..b814bd3842 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/RecentPlayersCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/RecentPlayersCommand.java @@ -4,7 +4,8 @@ import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.data.auth.PlayerAuth; import fr.xephi.authme.datasource.DataSource; -import org.bukkit.ChatColor; +import fr.xephi.authme.message.MessageKey; +import fr.xephi.authme.service.CommonService; import org.bukkit.command.CommandSender; import javax.inject.Inject; @@ -26,13 +27,19 @@ public class RecentPlayersCommand implements ExecutableCommand { @Inject private DataSource dataSource; + @Inject + private CommonService commonService; + @Override public void executeCommand(CommandSender sender, List arguments) { List recentPlayers = dataSource.getRecentlyLoggedInPlayers(); - sender.sendMessage(ChatColor.BLUE + "[AuthMe] Recently logged in players"); + commonService.send(sender, MessageKey.RECENT_PLAYERS_HEADER); for (PlayerAuth auth : recentPlayers) { - sender.sendMessage(formatPlayerMessage(auth)); + commonService.send(sender, MessageKey.RECENT_PLAYER_LINE, + auth.getRealName(), + formatLastLoginText(sender, auth), + String.valueOf(auth.getLastIp())); } } @@ -41,15 +48,11 @@ ZoneId getZoneId() { return ZoneId.systemDefault(); } - private String formatPlayerMessage(PlayerAuth auth) { - String lastLoginText; + private String formatLastLoginText(CommandSender sender, PlayerAuth auth) { if (auth.getLastLogin() == null) { - lastLoginText = "never"; - } else { - LocalDateTime lastLogin = LocalDateTime.ofInstant(ofEpochMilli(auth.getLastLogin()), getZoneId()); - lastLoginText = DATE_FORMAT.format(lastLogin); + return commonService.retrieveSingleMessage(sender, MessageKey.ADMIN_LAST_LOGIN_NEVER); } - - return "- " + auth.getRealName() + " (" + lastLoginText + " with IP " + auth.getLastIp() + ")"; + LocalDateTime lastLogin = LocalDateTime.ofInstant(ofEpochMilli(auth.getLastLogin()), getZoneId()); + return DATE_FORMAT.format(lastLogin); } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/ReloadCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/ReloadCommand.java index 2956a39f64..02646c34a3 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/ReloadCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/ReloadCommand.java @@ -56,12 +56,13 @@ public void executeCommand(CommandSender sender, List arguments) { // We do not change database type for consistency issues, but we'll output a note in the logs if (!settings.getProperty(DatabaseSettings.BACKEND).equals(dataSource.getType())) { - Utils.logAndSendMessage(sender, "Note: cannot change database type during /authme reload"); + Utils.logAndSendMessage(sender, + commonService.retrieveSingleMessage(sender, MessageKey.RELOAD_DATABASE_TYPE_NOTE)); } performReloadOnServices(); commonService.send(sender, MessageKey.CONFIG_RELOAD_SUCCESS); } catch (Exception e) { - sender.sendMessage("Error occurred during reload of AuthMe: aborting"); + commonService.send(sender, MessageKey.RELOAD_ABORT_ERROR); logger.logException("Aborting! Encountered exception during reload of AuthMe:", e); plugin.stopOrUnload(); } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/SetFirstSpawnCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/SetFirstSpawnCommand.java index 899a1103fe..5435060dc2 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/SetFirstSpawnCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/SetFirstSpawnCommand.java @@ -1,6 +1,7 @@ package fr.xephi.authme.command.executable.authme; import fr.xephi.authme.command.PlayerCommand; +import fr.xephi.authme.message.MessageKey; import fr.xephi.authme.settings.SpawnLoader; import org.bukkit.entity.Player; @@ -15,9 +16,9 @@ public class SetFirstSpawnCommand extends PlayerCommand { @Override public void runCommand(Player player, List arguments) { if (spawnLoader.setFirstSpawn(player.getLocation())) { - player.sendMessage("[AuthMe] Correctly defined new first spawn point"); + commonService.send(player, MessageKey.ADMIN_SET_FIRST_SPAWN_SUCCESS); } else { - player.sendMessage("[AuthMe] SetFirstSpawn has failed, please retry"); + commonService.send(player, MessageKey.ADMIN_SET_FIRST_SPAWN_FAILED); } } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/SetSpawnCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/SetSpawnCommand.java index fc9a67b9eb..555444e88d 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/SetSpawnCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/SetSpawnCommand.java @@ -1,6 +1,7 @@ package fr.xephi.authme.command.executable.authme; import fr.xephi.authme.command.PlayerCommand; +import fr.xephi.authme.message.MessageKey; import fr.xephi.authme.settings.SpawnLoader; import org.bukkit.entity.Player; @@ -15,9 +16,9 @@ public class SetSpawnCommand extends PlayerCommand { @Override public void runCommand(Player player, List arguments) { if (spawnLoader.setSpawn(player.getLocation())) { - player.sendMessage("[AuthMe] Correctly defined new spawn point"); + commonService.send(player, MessageKey.ADMIN_SET_SPAWN_SUCCESS); } else { - player.sendMessage("[AuthMe] SetSpawn has failed, please retry"); + commonService.send(player, MessageKey.ADMIN_SET_SPAWN_FAILED); } } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/SpawnCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/SpawnCommand.java index 92ad0a3041..a0f4a3986d 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/SpawnCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/SpawnCommand.java @@ -1,6 +1,7 @@ package fr.xephi.authme.command.executable.authme; import fr.xephi.authme.command.PlayerCommand; +import fr.xephi.authme.message.MessageKey; import fr.xephi.authme.service.BukkitService; import fr.xephi.authme.settings.SpawnLoader; import fr.xephi.authme.util.TeleportUtils; @@ -19,7 +20,7 @@ public class SpawnCommand extends PlayerCommand { @Override public void runCommand(Player player, List arguments) { if (spawnLoader.getSpawn() == null) { - player.sendMessage("[AuthMe] Spawn has failed, please try to define the spawn"); + commonService.send(player, MessageKey.ADMIN_SPAWN_FAILED); } else { bukkitService.runTaskIfFolia(player, () -> TeleportUtils.teleport(player, spawnLoader.getSpawn())); } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/SwitchAntiBotCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/SwitchAntiBotCommand.java index 1e72c0587f..6db20359a1 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/SwitchAntiBotCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/SwitchAntiBotCommand.java @@ -4,8 +4,9 @@ import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.command.FoundCommandResult; import fr.xephi.authme.command.help.HelpProvider; +import fr.xephi.authme.message.MessageKey; import fr.xephi.authme.service.AntiBotService; -import org.bukkit.ChatColor; +import fr.xephi.authme.service.CommonService; import org.bukkit.command.CommandSender; import javax.inject.Inject; @@ -26,10 +27,14 @@ public class SwitchAntiBotCommand implements ExecutableCommand { @Inject private HelpProvider helpProvider; + @Inject + private CommonService commonService; + @Override public void executeCommand(final CommandSender sender, List arguments) { if (arguments.isEmpty()) { - sender.sendMessage("[AuthMe] AntiBot status: " + antiBotService.getAntiBotStatus().name()); + commonService.send(sender, MessageKey.ADMIN_ANTIBOT_STATUS, + antiBotService.getAntiBotStatus().name()); return; } @@ -38,15 +43,15 @@ public void executeCommand(final CommandSender sender, List arguments) { // Enable or disable the mod if ("ON".equalsIgnoreCase(newState)) { antiBotService.overrideAntiBotStatus(true); - sender.sendMessage("[AuthMe] AntiBot Manual Override: enabled!"); + commonService.send(sender, MessageKey.ADMIN_ANTIBOT_MANUAL_ENABLED); } else if ("OFF".equalsIgnoreCase(newState)) { antiBotService.overrideAntiBotStatus(false); - sender.sendMessage("[AuthMe] AntiBot Manual Override: disabled!"); + commonService.send(sender, MessageKey.ADMIN_ANTIBOT_MANUAL_DISABLED); } else { - sender.sendMessage(ChatColor.DARK_RED + "Invalid AntiBot mode!"); + commonService.send(sender, MessageKey.ADMIN_ANTIBOT_INVALID_MODE); FoundCommandResult result = commandMapper.mapPartsToCommand(sender, Arrays.asList("authme", "antibot")); helpProvider.outputHelp(sender, result, HelpProvider.SHOW_ARGUMENTS); - sender.sendMessage(ChatColor.GOLD + "Detailed help: " + ChatColor.WHITE + "/authme help antibot"); + commonService.send(sender, MessageKey.ADMIN_ANTIBOT_DETAILED_HELP, "/authme help antibot"); } } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/TotpDisableAdminCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/TotpDisableAdminCommand.java index 4789e0439f..b087530977 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/TotpDisableAdminCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/TotpDisableAdminCommand.java @@ -8,7 +8,7 @@ import fr.xephi.authme.message.Messages; import fr.xephi.authme.output.ConsoleLoggerFactory; import fr.xephi.authme.service.BukkitService; -import org.bukkit.ChatColor; +import fr.xephi.authme.service.CommonService; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -31,6 +31,9 @@ public class TotpDisableAdminCommand implements ExecutableCommand { @Inject private BukkitService bukkitService; + @Inject + private CommonService commonService; + @Override public void executeCommand(CommandSender sender, List arguments) { String player = arguments.get(0); @@ -39,7 +42,7 @@ public void executeCommand(CommandSender sender, List arguments) { if (auth == null) { messages.send(sender, MessageKey.UNKNOWN_USER); } else if (auth.getTotpKey() == null) { - sender.sendMessage(ChatColor.RED + "Player '" + player + "' does not have two-factor auth enabled"); + commonService.send(sender, MessageKey.ADMIN_TOTP_NOT_ENABLED, player); } else { removeTotpKey(sender, player); } @@ -47,7 +50,7 @@ public void executeCommand(CommandSender sender, List arguments) { private void removeTotpKey(CommandSender sender, String player) { if (dataSource.removeTotpKey(player)) { - sender.sendMessage("Disabled two-factor authentication successfully for '" + player + "'"); + commonService.send(sender, MessageKey.ADMIN_TOTP_DISABLED_SUCCESS, player); logger.info(sender.getName() + " disable two-factor authentication for '" + player + "'"); Player onlinePlayer = bukkitService.getPlayerExact(player); diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/TotpViewStatusCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/TotpViewStatusCommand.java index d9b2c92c90..de4aed8ba2 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/TotpViewStatusCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/TotpViewStatusCommand.java @@ -5,7 +5,6 @@ import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.message.MessageKey; import fr.xephi.authme.message.Messages; -import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import javax.inject.Inject; @@ -30,9 +29,9 @@ public void executeCommand(CommandSender sender, List arguments) { if (auth == null) { messages.send(sender, MessageKey.UNKNOWN_USER); } else if (auth.getTotpKey() == null) { - sender.sendMessage(ChatColor.RED + "Player '" + player + "' does NOT have two-factor auth enabled"); + messages.send(sender, MessageKey.ADMIN_TOTP_VIEW_DISABLED, player); } else { - sender.sendMessage(ChatColor.DARK_GREEN + "Player '" + player + "' has enabled two-factor authentication"); + messages.send(sender, MessageKey.ADMIN_TOTP_VIEW_ENABLED, player); } } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/UpdateHelpMessagesCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/UpdateHelpMessagesCommand.java index 7f61afd0f7..1d2c7c5bca 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/UpdateHelpMessagesCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/UpdateHelpMessagesCommand.java @@ -4,6 +4,8 @@ import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.command.help.HelpMessagesService; import fr.xephi.authme.output.ConsoleLoggerFactory; +import fr.xephi.authme.message.MessageKey; +import fr.xephi.authme.service.CommonService; import fr.xephi.authme.service.HelpTranslationGenerator; import org.bukkit.command.CommandSender; @@ -25,14 +27,17 @@ public class UpdateHelpMessagesCommand implements ExecutableCommand { @Inject private HelpMessagesService helpMessagesService; + @Inject + private CommonService commonService; + @Override public void executeCommand(CommandSender sender, List arguments) { try { File updatedFile = helpTranslationGenerator.updateHelpFile(); - sender.sendMessage("Successfully updated the help file '" + updatedFile.getName() + "'"); + commonService.send(sender, MessageKey.ADMIN_HELP_FILE_UPDATED, updatedFile.getName()); helpMessagesService.reloadMessagesFile(); } catch (IOException e) { - sender.sendMessage("Could not update help file: " + e.getMessage()); + commonService.send(sender, MessageKey.ADMIN_HELP_FILE_UPDATE_FAILED, e.getMessage()); logger.logException("Could not update help file:", e); } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/VersionCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/VersionCommand.java index 2f7e8a7c68..ad087749a9 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/VersionCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/VersionCommand.java @@ -2,10 +2,11 @@ import fr.xephi.authme.AuthMe; import fr.xephi.authme.command.ExecutableCommand; +import fr.xephi.authme.message.MessageKey; +import fr.xephi.authme.message.Messages; import fr.xephi.authme.service.BukkitService; import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.properties.DatabaseSettings; -import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -21,33 +22,31 @@ public class VersionCommand implements ExecutableCommand { private BukkitService bukkitService; @Inject private Settings settings; + @Inject + private Messages messages; @Override public void executeCommand(CommandSender sender, List arguments) { - // Show some version info - sender.sendMessage(ChatColor.GOLD + "==========[ " + AuthMe.getPluginName() + " ABOUT ]=========="); - sender.sendMessage(ChatColor.GOLD + "Version: " + ChatColor.WHITE + AuthMe.getPluginName() - + " v" + AuthMe.getPluginVersion() + ChatColor.GRAY + " (build: " + AuthMe.getPluginBuildNumber() + ")"); - sender.sendMessage(ChatColor.GOLD + "Database Implementation: " + ChatColor.WHITE + settings.getProperty(DatabaseSettings.BACKEND).toString()); - sender.sendMessage(ChatColor.GOLD + "Authors:"); + String year = new SimpleDateFormat("yyyy").format(new Date()); + messages.send(sender, MessageKey.ABOUT_HEADER, AuthMe.getPluginName()); + messages.send(sender, MessageKey.ABOUT_VERSION, AuthMe.getPluginName(), AuthMe.getPluginVersion(), + AuthMe.getPluginBuildNumber()); + messages.send(sender, MessageKey.ABOUT_DATABASE, settings.getProperty(DatabaseSettings.BACKEND).toString()); + messages.send(sender, MessageKey.ABOUT_AUTHORS_HEADER); Collection onlinePlayers = bukkitService.getOnlinePlayers(); printDeveloper(sender, "Gabriele C.", "sgdc3", "Project manager, Contributor", onlinePlayers); printDeveloper(sender, "Lucas J.", "ljacqu", "Main Developer", onlinePlayers); printDeveloper(sender, "games647", "games647", "Developer", onlinePlayers); printDeveloper(sender, "Hex3l", "Hex3l", "Developer", onlinePlayers); printDeveloper(sender, "krusic22", "krusic22", "Support", onlinePlayers); - sender.sendMessage(ChatColor.GOLD + "Retired authors:"); + messages.send(sender, MessageKey.ABOUT_RETIRED_HEADER); printDeveloper(sender, "Alexandre Vanhecke", "xephi59", "Original Author", onlinePlayers); printDeveloper(sender, "Gnat008", "gnat008", "Developer, Retired", onlinePlayers); printDeveloper(sender, "DNx5", "DNx5", "Developer, Retired", onlinePlayers); printDeveloper(sender, "Tim Visee", "timvisee", "Developer, Retired", onlinePlayers); - sender.sendMessage(ChatColor.GOLD + "Website: " + ChatColor.WHITE - + "https://github.com/AuthMe/AuthMeReloaded"); - sender.sendMessage(ChatColor.GOLD + "License: " + ChatColor.WHITE + "GNU GPL v3.0" - + ChatColor.GRAY + ChatColor.ITALIC + " (See LICENSE file)"); - sender.sendMessage(ChatColor.GOLD + "Copyright: " + ChatColor.WHITE - + "Copyright (c) AuthMe-Team " + new SimpleDateFormat("yyyy").format(new Date()) - + ". Released under GPL v3 License."); + messages.send(sender, MessageKey.ABOUT_WEBSITE, "https://github.com/AuthMe/AuthMeReloaded"); + messages.send(sender, MessageKey.ABOUT_LICENSE); + messages.send(sender, MessageKey.ABOUT_COPYRIGHT, year); } /** @@ -59,25 +58,13 @@ public void executeCommand(CommandSender sender, List arguments) { * @param function The function of the developer * @param onlinePlayers The list of online players */ - private static void printDeveloper(CommandSender sender, String name, String minecraftName, String function, - Collection onlinePlayers) { - // Print the name - StringBuilder msg = new StringBuilder(); - msg.append(" ") - .append(ChatColor.WHITE) - .append(name); - - // Append the Minecraft name - msg.append(ChatColor.GRAY).append(" // ").append(ChatColor.WHITE).append(minecraftName); - msg.append(ChatColor.GRAY).append(ChatColor.ITALIC).append(" (").append(function).append(")"); - - // Show the online status + private void printDeveloper(CommandSender sender, String name, String minecraftName, String function, + Collection onlinePlayers) { + String line = messages.retrieveSingle(sender, MessageKey.ABOUT_DEVELOPER_LINE, name, minecraftName, function); if (isPlayerOnline(minecraftName, onlinePlayers)) { - msg.append(ChatColor.GREEN).append(ChatColor.ITALIC).append(" (In-Game)"); + line += messages.retrieveSingle(sender, MessageKey.ABOUT_DEVELOPER_INGAME); } - - // Print the message - sender.sendMessage(msg.toString()); + sender.sendMessage(line); } /** diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/debug/CountryLookup.java b/src/main/java/fr/xephi/authme/command/executable/authme/debug/CountryLookup.java index 78cee4622e..febc54bccb 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/debug/CountryLookup.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/debug/CountryLookup.java @@ -2,12 +2,13 @@ import fr.xephi.authme.data.auth.PlayerAuth; import fr.xephi.authme.datasource.DataSource; +import fr.xephi.authme.message.MessageKey; +import fr.xephi.authme.message.Messages; import fr.xephi.authme.permission.DebugSectionPermissions; import fr.xephi.authme.permission.PermissionNode; import fr.xephi.authme.service.GeoIpService; import fr.xephi.authme.service.ValidationService; import fr.xephi.authme.settings.properties.ProtectionSettings; -import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import javax.inject.Inject; @@ -30,6 +31,9 @@ class CountryLookup implements DebugSection { @Inject private ValidationService validationService; + @Inject + private Messages messages; + @Override public String getName() { return "cty"; @@ -42,10 +46,10 @@ public String getDescription() { @Override public void execute(CommandSender sender, List arguments) { - sender.sendMessage(ChatColor.BLUE + "AuthMe country lookup"); + messages.send(sender, MessageKey.DEBUG_CTY_TITLE); if (arguments.isEmpty()) { - sender.sendMessage("Check player: /authme debug cty Bobby"); - sender.sendMessage("Check IP address: /authme debug cty 127.123.45.67"); + messages.send(sender, MessageKey.DEBUG_CTY_USAGE_PLAYER); + messages.send(sender, MessageKey.DEBUG_CTY_USAGE_IP); return; } @@ -63,25 +67,25 @@ public PermissionNode getRequiredPermission() { } private void outputInfoForIpAddr(CommandSender sender, String ipAddr) { - sender.sendMessage("IP '" + ipAddr + "' maps to country '" + geoIpService.getCountryCode(ipAddr) - + "' (" + geoIpService.getCountryName(ipAddr) + ")"); + messages.send(sender, MessageKey.DEBUG_CTY_IP_INFO, ipAddr, + geoIpService.getCountryCode(ipAddr), geoIpService.getCountryName(ipAddr)); if (validationService.isCountryAdmitted(ipAddr)) { - sender.sendMessage(ChatColor.DARK_GREEN + "This IP address' country is not blocked"); + messages.send(sender, MessageKey.DEBUG_CTY_NOT_BLOCKED); } else { - sender.sendMessage(ChatColor.DARK_RED + "This IP address' country is blocked from the server"); + messages.send(sender, MessageKey.DEBUG_CTY_BLOCKED); } - sender.sendMessage("Note: if " + ProtectionSettings.ENABLE_PROTECTION + " is false no country is blocked"); + messages.send(sender, MessageKey.DEBUG_CTY_NOTE, ProtectionSettings.ENABLE_PROTECTION.getPath()); } // TODO #1366: Extend with registration IP? private void outputInfoForPlayer(CommandSender sender, String name) { PlayerAuth auth = dataSource.getAuth(name); if (auth == null) { - sender.sendMessage("No player with name '" + name + "'"); + messages.send(sender, MessageKey.DEBUG_CTY_NO_PLAYER, name); } else if (auth.getLastIp() == null) { - sender.sendMessage("No last IP address known for '" + name + "'"); + messages.send(sender, MessageKey.DEBUG_CTY_NO_IP, name); } else { - sender.sendMessage("Player '" + name + "' has IP address " + auth.getLastIp()); + messages.send(sender, MessageKey.DEBUG_CTY_PLAYER_IP, name, auth.getLastIp()); outputInfoForIpAddr(sender, auth.getLastIp()); } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/debug/DataStatistics.java b/src/main/java/fr/xephi/authme/command/executable/authme/debug/DataStatistics.java index 406ee17deb..901b19f6e1 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/debug/DataStatistics.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/debug/DataStatistics.java @@ -8,17 +8,15 @@ import fr.xephi.authme.initialization.HasCleanup; import fr.xephi.authme.initialization.Reloadable; import fr.xephi.authme.initialization.SettingsDependent; +import fr.xephi.authme.message.MessageKey; +import fr.xephi.authme.message.Messages; import fr.xephi.authme.output.ConsoleLoggerFactory; import fr.xephi.authme.permission.DebugSectionPermissions; import fr.xephi.authme.permission.PermissionNode; -import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import javax.inject.Inject; import java.util.List; -import java.util.Map; - -import static fr.xephi.authme.command.executable.authme.debug.DebugSectionUtils.applyToLimboPlayersMap; /** * Fetches various statistics, particularly regarding in-memory data that is stored. @@ -37,6 +35,9 @@ class DataStatistics implements DebugSection { @Inject private SingletonStore singletonStore; + @Inject + private Messages messages; + @Override public String getName() { return "stats"; @@ -49,13 +50,16 @@ public String getDescription() { @Override public void execute(CommandSender sender, List arguments) { - sender.sendMessage(ChatColor.BLUE + "AuthMe statistics"); - sender.sendMessage("LimboPlayers in memory: " + applyToLimboPlayersMap(limboService, Map::size)); - sender.sendMessage("PlayerCache size: " + playerCache.getLogged() + " (= logged in players)"); + messages.send(sender, MessageKey.DEBUG_STATS_TITLE); + Integer limboCount = DebugSectionUtils.applyToLimboPlayersMap(limboService, + map -> map == null ? 0 : map.size()); + messages.send(sender, MessageKey.DEBUG_STATS_LIMBO, String.valueOf(limboCount != null ? limboCount : 0)); + messages.send(sender, MessageKey.DEBUG_STATS_CACHE, String.valueOf(playerCache.getLogged())); outputDatabaseStats(sender); outputInjectorStats(sender); - sender.sendMessage("Total logger instances: " + ConsoleLoggerFactory.getTotalLoggers()); + messages.send(sender, MessageKey.DEBUG_STATS_LOGGERS, + String.valueOf(ConsoleLoggerFactory.getTotalLoggers())); } @Override @@ -64,18 +68,20 @@ public PermissionNode getRequiredPermission() { } private void outputDatabaseStats(CommandSender sender) { - sender.sendMessage("Total players in DB: " + dataSource.getAccountsRegistered()); + messages.send(sender, MessageKey.DEBUG_STATS_DB_TOTAL, String.valueOf(dataSource.getAccountsRegistered())); if (dataSource instanceof CacheDataSource) { CacheDataSource cacheDataSource = (CacheDataSource) this.dataSource; - sender.sendMessage("Cached PlayerAuth objects: " + cacheDataSource.getCachedAuths().size()); + messages.send(sender, MessageKey.DEBUG_STATS_CACHE_OBJS, + String.valueOf(cacheDataSource.getCachedAuths().size())); } } private void outputInjectorStats(CommandSender sender) { - sender.sendMessage("Singleton Java classes: " + singletonStore.retrieveAllOfType().size()); - sender.sendMessage(String.format("(Reloadable: %d / SettingsDependent: %d / HasCleanup: %d)", - singletonStore.retrieveAllOfType(Reloadable.class).size(), - singletonStore.retrieveAllOfType(SettingsDependent.class).size(), - singletonStore.retrieveAllOfType(HasCleanup.class).size())); + messages.send(sender, MessageKey.DEBUG_STATS_SINGLETONS, + String.valueOf(singletonStore.retrieveAllOfType().size())); + messages.send(sender, MessageKey.DEBUG_STATS_INJECTOR_BREAKDOWN, + String.valueOf(singletonStore.retrieveAllOfType(Reloadable.class).size()), + String.valueOf(singletonStore.retrieveAllOfType(SettingsDependent.class).size()), + String.valueOf(singletonStore.retrieveAllOfType(HasCleanup.class).size())); } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/debug/DebugCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/debug/DebugCommand.java index 4198a19ebb..f9037c4032 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/debug/DebugCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/debug/DebugCommand.java @@ -3,8 +3,9 @@ import ch.jalu.injector.factory.Factory; import com.google.common.collect.ImmutableSet; import fr.xephi.authme.command.ExecutableCommand; +import fr.xephi.authme.message.MessageKey; +import fr.xephi.authme.message.Messages; import fr.xephi.authme.permission.PermissionsManager; -import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import javax.inject.Inject; @@ -30,6 +31,9 @@ public class DebugCommand implements ExecutableCommand { @Inject private PermissionsManager permissionsManager; + @Inject + private Messages messages; + private Map sections; @Override @@ -50,15 +54,15 @@ private DebugSection findDebugSection(List arguments) { } private void sendAvailableSections(CommandSender sender) { - sender.sendMessage(ChatColor.BLUE + "AuthMe debug utils"); - sender.sendMessage("Sections available to you:"); + messages.send(sender, MessageKey.DEBUG_COMMAND_TITLE); + messages.send(sender, MessageKey.DEBUG_COMMAND_SECTIONS_AVAILABLE); long availableSections = getSections().values().stream() .filter(section -> permissionsManager.hasPermission(sender, section.getRequiredPermission())) - .peek(e -> sender.sendMessage("- " + e.getName() + ": " + e.getDescription())) + .peek(e -> messages.send(sender, MessageKey.DEBUG_COMMAND_SECTION_LINE, e.getName(), e.getDescription())) .count(); if (availableSections == 0) { - sender.sendMessage(ChatColor.RED + "You don't have permission to view any debug section"); + messages.send(sender, MessageKey.DEBUG_COMMAND_NO_PERM_ANY); } } @@ -66,7 +70,7 @@ private void executeSection(DebugSection section, CommandSender sender, List arguments) { - sender.sendMessage(ChatColor.BLUE + "AuthMe permission check"); + messages.send(sender, MessageKey.DEBUG_PERM_TITLE); if (arguments.size() < 2) { - sender.sendMessage("Check if a player has permission:"); - sender.sendMessage("Example: /authme debug perm bobby my.perm.node"); - sender.sendMessage("Permission system type used: " + permissionsManager.getPermissionSystem()); + messages.send(sender, MessageKey.DEBUG_PERM_USAGE_LINE1); + messages.send(sender, MessageKey.DEBUG_PERM_USAGE_EXAMPLE); + messages.send(sender, MessageKey.DEBUG_PERM_SYSTEM, + String.valueOf(permissionsManager.getPermissionSystem())); return; } @@ -62,9 +67,9 @@ public void execute(CommandSender sender, List arguments) { if (player == null) { OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(playerName); if (offlinePlayer == null) { - sender.sendMessage(ChatColor.DARK_RED + "Player '" + playerName + "' does not exist"); + messages.send(sender, MessageKey.DEBUG_PERM_PLAYER_NOT_EXIST, playerName); } else { - sender.sendMessage("Player '" + playerName + "' not online; checking with offline player"); + messages.send(sender, MessageKey.DEBUG_PERM_OFFLINE_CHECK, playerName); performPermissionCheck(offlinePlayer, permissionNode, permissionsManager::hasPermissionOffline, sender); } } else { @@ -87,16 +92,14 @@ public PermissionNode getRequiredPermission() { * @param sender the sender to inform of the result * @param

the player type */ - private static

void performPermissionCheck( + private

void performPermissionCheck( P player, String node, BiFunction permissionChecker, CommandSender sender) { PermissionNode permNode = getPermissionNode(sender, node); if (permissionChecker.apply(player, permNode)) { - sender.sendMessage(ChatColor.DARK_GREEN + "Success: player '" + player.getName() - + "' has permission '" + node + "'"); + messages.send(sender, MessageKey.DEBUG_PERM_SUCCESS, player.getName(), node); } else { - sender.sendMessage(ChatColor.DARK_RED + "Check failed: player '" + player.getName() - + "' does NOT have permission '" + node + "'"); + messages.send(sender, MessageKey.DEBUG_PERM_FAIL, player.getName(), node); } } @@ -108,7 +111,7 @@ private static

void performPermissionCheck( * @param node the node to search for * @return the node as {@link PermissionNode} object */ - private static PermissionNode getPermissionNode(CommandSender sender, String node) { + private PermissionNode getPermissionNode(CommandSender sender, String node) { Optional permNode = PERMISSION_NODE_CLASSES.stream() .map(Class::getEnumConstants) .flatMap(Arrays::stream) @@ -117,7 +120,7 @@ private static PermissionNode getPermissionNode(CommandSender sender, String nod if (permNode.isPresent()) { return permNode.get(); } else { - sender.sendMessage("Did not detect AuthMe permission; using default permission = DENIED"); + messages.send(sender, MessageKey.DEBUG_PERM_DEFAULT_DENIED); return createPermNode(node); } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/debug/InputValidator.java b/src/main/java/fr/xephi/authme/command/executable/authme/debug/InputValidator.java index 2e82c3c823..d398c27c40 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/debug/InputValidator.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/debug/InputValidator.java @@ -2,12 +2,12 @@ import fr.xephi.authme.listener.FailedVerificationException; import fr.xephi.authme.listener.OnJoinVerifier; +import fr.xephi.authme.message.MessageKey; import fr.xephi.authme.message.Messages; import fr.xephi.authme.permission.DebugSectionPermissions; import fr.xephi.authme.permission.PermissionNode; import fr.xephi.authme.service.ValidationService; import fr.xephi.authme.service.ValidationService.ValidationResult; -import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import javax.inject.Inject; @@ -68,40 +68,38 @@ public PermissionNode getRequiredPermission() { } private void displayUsageHint(CommandSender sender) { - sender.sendMessage(ChatColor.BLUE + "Validation tests"); - sender.sendMessage("You can define forbidden emails and passwords in your config.yml." - + " You can test your settings with this command."); - final String command = ChatColor.GOLD + "/authme debug valid"; - sender.sendMessage(" Use " + command + " pass " + ChatColor.RESET + " to check a password"); - sender.sendMessage(" Use " + command + " mail " + ChatColor.RESET + " to check an email"); - sender.sendMessage(" Use " + command + " name " + ChatColor.RESET + " to check a username"); + messages.send(sender, MessageKey.DEBUG_VALID_TITLE); + messages.send(sender, MessageKey.DEBUG_VALID_INTRO); + messages.send(sender, MessageKey.DEBUG_VALID_PASS_USAGE); + messages.send(sender, MessageKey.DEBUG_VALID_MAIL_USAGE); + messages.send(sender, MessageKey.DEBUG_VALID_NAME_USAGE); } private void validatePassword(CommandSender sender, String password) { ValidationResult validationResult = validationService.validatePassword(password, ""); - sender.sendMessage(ChatColor.BLUE + "Validation of password '" + password + "'"); + messages.send(sender, MessageKey.DEBUG_VALID_VALIDATE_PASSWORD, password); if (validationResult.hasError()) { messages.send(sender, validationResult.getMessageKey(), validationResult.getArgs()); } else { - sender.sendMessage(ChatColor.DARK_GREEN + "Valid password!"); + messages.send(sender, MessageKey.DEBUG_VALID_VALID_PASSWORD); } } private void validateEmail(CommandSender sender, String email) { boolean isValidEmail = validationService.validateEmail(email); - sender.sendMessage(ChatColor.BLUE + "Validation of email '" + email + "'"); + messages.send(sender, MessageKey.DEBUG_VALID_VALIDATE_EMAIL, email); if (isValidEmail) { - sender.sendMessage(ChatColor.DARK_GREEN + "Valid email!"); + messages.send(sender, MessageKey.DEBUG_VALID_VALID_EMAIL); } else { - sender.sendMessage(ChatColor.DARK_RED + "Email is not valid!"); + messages.send(sender, MessageKey.DEBUG_VALID_INVALID_EMAIL); } } private void validateUsername(CommandSender sender, String username) { - sender.sendMessage(ChatColor.BLUE + "Validation of username '" + username + "'"); + messages.send(sender, MessageKey.DEBUG_VALID_VALIDATE_NAME, username); try { onJoinVerifier.checkIsValidName(username); - sender.sendMessage("Valid username!"); + messages.send(sender, MessageKey.DEBUG_VALID_VALID_NAME); } catch (FailedVerificationException failedVerificationEx) { messages.send(sender, failedVerificationEx.getReason(), failedVerificationEx.getArgs()); } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/debug/LimboPlayerViewer.java b/src/main/java/fr/xephi/authme/command/executable/authme/debug/LimboPlayerViewer.java index 7338c86862..74688a1ab6 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/debug/LimboPlayerViewer.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/debug/LimboPlayerViewer.java @@ -3,21 +3,20 @@ import fr.xephi.authme.data.limbo.LimboPlayer; import fr.xephi.authme.data.limbo.LimboService; import fr.xephi.authme.data.limbo.persistence.LimboPersistence; +import fr.xephi.authme.message.MessageKey; +import fr.xephi.authme.message.Messages; import fr.xephi.authme.permission.DebugSectionPermissions; import fr.xephi.authme.permission.PermissionNode; import fr.xephi.authme.permission.PermissionsManager; import fr.xephi.authme.service.BukkitService; -import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import javax.inject.Inject; import java.util.List; -import java.util.Map; import java.util.Optional; import java.util.function.Function; -import static fr.xephi.authme.command.executable.authme.debug.DebugSectionUtils.applyToLimboPlayersMap; import static fr.xephi.authme.command.executable.authme.debug.DebugSectionUtils.formatLocation; /** @@ -37,6 +36,9 @@ class LimboPlayerViewer implements DebugSection { @Inject private PermissionsManager permissionsManager; + @Inject + private Messages messages; + @Override public String getName() { return "limbo"; @@ -50,9 +52,11 @@ public String getDescription() { @Override public void execute(CommandSender sender, List arguments) { if (arguments.isEmpty()) { - sender.sendMessage(ChatColor.BLUE + "AuthMe limbo viewer"); - sender.sendMessage("/authme debug limbo : show a player's limbo info"); - sender.sendMessage("Available limbo records: " + applyToLimboPlayersMap(limboService, Map::keySet)); + messages.send(sender, MessageKey.DEBUG_LIMBO_TITLE); + messages.send(sender, MessageKey.DEBUG_LIMBO_USAGE); + String limboKeys = DebugSectionUtils.applyToLimboPlayersMap(limboService, + map -> map == null ? "" : map.keySet().toString()); + messages.send(sender, MessageKey.DEBUG_LIMBO_AVAILABLE, limboKeys != null ? limboKeys : ""); return; } @@ -60,19 +64,20 @@ public void execute(CommandSender sender, List arguments) { Player player = bukkitService.getPlayerExact(arguments.get(0)); LimboPlayer diskLimbo = player != null ? limboPersistence.getLimboPlayer(player) : null; if (memoryLimbo == null && player == null) { - sender.sendMessage(ChatColor.BLUE + "No AuthMe limbo data"); - sender.sendMessage("No limbo data and no player online with name '" + arguments.get(0) + "'"); + messages.send(sender, MessageKey.DEBUG_LIMBO_NO_DATA_TITLE); + messages.send(sender, MessageKey.DEBUG_LIMBO_NO_DATA_DETAIL, arguments.get(0)); return; } - sender.sendMessage(ChatColor.BLUE + "Player / limbo / disk limbo info for '" + arguments.get(0) + "'"); - new InfoDisplayer(sender, player, memoryLimbo, diskLimbo) - .sendEntry("Is op", Player::isOp, LimboPlayer::isOperator) - .sendEntry("Walk speed", Player::getWalkSpeed, LimboPlayer::getWalkSpeed) - .sendEntry("Can fly", Player::getAllowFlight, LimboPlayer::isCanFly) - .sendEntry("Fly speed", Player::getFlySpeed, LimboPlayer::getFlySpeed) - .sendEntry("Location", p -> formatLocation(p.getLocation()), l -> formatLocation(l.getLocation())) - .sendEntry("Prim. group", + messages.send(sender, MessageKey.DEBUG_LIMBO_INFO_HEADER, arguments.get(0)); + InfoDisplayer displayer = new InfoDisplayer(sender, player, memoryLimbo, diskLimbo, messages); + displayer.sendEntry(MessageKey.DEBUG_LIMBO_FIELD_IS_OP, Player::isOp, LimboPlayer::isOperator) + .sendEntry(MessageKey.DEBUG_LIMBO_FIELD_WALK_SPEED, Player::getWalkSpeed, LimboPlayer::getWalkSpeed) + .sendEntry(MessageKey.DEBUG_LIMBO_FIELD_CAN_FLY, Player::getAllowFlight, LimboPlayer::isCanFly) + .sendEntry(MessageKey.DEBUG_LIMBO_FIELD_FLY_SPEED, Player::getFlySpeed, LimboPlayer::getFlySpeed) + .sendEntry(MessageKey.DEBUG_LIMBO_FIELD_LOCATION, + p -> formatLocation(p.getLocation()), l -> formatLocation(l.getLocation())) + .sendEntry(MessageKey.DEBUG_LIMBO_FIELD_PRIMARY_GROUP, p -> permissionsManager.hasGroupSupport() ? permissionsManager.getPrimaryGroup(p) : "N/A", LimboPlayer::getGroups); } @@ -90,6 +95,7 @@ private static final class InfoDisplayer { private final Optional player; private final Optional memoryLimbo; private final Optional diskLimbo; + private final Messages messages; /** * Constructor. @@ -98,41 +104,41 @@ private static final class InfoDisplayer { * @param player the player to get data from * @param memoryLimbo the limbo player to get data from */ - InfoDisplayer(CommandSender sender, Player player, LimboPlayer memoryLimbo, LimboPlayer diskLimbo) { + InfoDisplayer(CommandSender sender, Player player, LimboPlayer memoryLimbo, LimboPlayer diskLimbo, + Messages messages) { this.sender = sender; this.player = Optional.ofNullable(player); this.memoryLimbo = Optional.ofNullable(memoryLimbo); this.diskLimbo = Optional.ofNullable(diskLimbo); + this.messages = messages; if (memoryLimbo == null) { - sender.sendMessage("Note: no Limbo information available"); + messages.send(sender, MessageKey.DEBUG_LIMBO_NOTE_MEMORY); } if (player == null) { - sender.sendMessage("Note: player is not online"); + messages.send(sender, MessageKey.DEBUG_LIMBO_NOTE_OFFLINE); } else if (diskLimbo == null) { - sender.sendMessage("Note: no Limbo on disk available"); + messages.send(sender, MessageKey.DEBUG_LIMBO_NOTE_DISK); } } /** * Displays a piece of information to the command sender. * - * @param title the designation of the piece of information + * @param titleKey the designation of the piece of information * @param playerGetter getter for data retrieval on Player * @param limboGetter getter for data retrieval on the LimboPlayer * @param the data type * @return this instance (for chaining) */ - InfoDisplayer sendEntry(String title, + InfoDisplayer sendEntry(MessageKey titleKey, Function playerGetter, Function limboGetter) { - sender.sendMessage( - title + ": " - + getData(player, playerGetter) - + " / " - + getData(memoryLimbo, limboGetter) - + " / " - + getData(diskLimbo, limboGetter)); + String title = messages.retrieveSingle(sender, titleKey); + sender.sendMessage(messages.retrieveSingle(sender, MessageKey.DEBUG_LIMBO_ROW, title, + getData(player, playerGetter), + getData(memoryLimbo, limboGetter), + getData(diskLimbo, limboGetter))); return this; } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/debug/MySqlDefaultChanger.java b/src/main/java/fr/xephi/authme/command/executable/authme/debug/MySqlDefaultChanger.java index d4eb1d3c1e..3f19cd1eb0 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/debug/MySqlDefaultChanger.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/debug/MySqlDefaultChanger.java @@ -5,6 +5,8 @@ import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.datasource.MySQL; +import fr.xephi.authme.message.MessageKey; +import fr.xephi.authme.message.Messages; import fr.xephi.authme.output.ConsoleLoggerFactory; import fr.xephi.authme.permission.DebugSectionPermissions; import fr.xephi.authme.permission.PermissionNode; @@ -52,6 +54,9 @@ class MySqlDefaultChanger implements DebugSection { @Inject private DataSource dataSource; + @Inject + private Messages messages; + private MySQL mySql; @PostConstruct @@ -77,7 +82,7 @@ public PermissionNode getRequiredPermission() { @Override public void execute(CommandSender sender, List arguments) { if (mySql == null) { - sender.sendMessage("Defaults can be changed for the MySQL data source only."); + messages.send(sender, MessageKey.DEBUG_MYSQL_NON_MYSQL); return; } @@ -88,7 +93,7 @@ public void execute(CommandSender sender, List arguments) { } else if (operation == null || column == null) { displayUsageHints(sender); } else { - sender.sendMessage(ChatColor.BLUE + "[AuthMe] MySQL change '" + column + "'"); + messages.send(sender, MessageKey.DEBUG_MYSQL_CHANGE_HEADER, column.name()); try (Connection con = getConnection(mySql)) { switch (operation) { case ADD: @@ -127,13 +132,13 @@ private void changeColumnToNotNullWithDefault(CommandSender sender, Columns colu pst.setObject(1, column.getDefaultValue()); updatedRows = pst.executeUpdate(); } - sender.sendMessage("Replaced NULLs with default value ('" + column.getDefaultValue() - + "'), modifying " + updatedRows + " entries"); + messages.send(sender, MessageKey.DEBUG_MYSQL_REPLACED_NULLS, + String.valueOf(column.getDefaultValue()), String.valueOf(updatedRows)); // Change column definition to NOT NULL version try (Statement st = con.createStatement()) { st.execute(format("ALTER TABLE %s MODIFY %s %s", tableName, columnName, column.getNotNullDefinition())); - sender.sendMessage("Changed column '" + columnName + "' to have NOT NULL constraint"); + messages.send(sender, MessageKey.DEBUG_MYSQL_NOT_NULL_SET, columnName); } // Log success message @@ -157,7 +162,7 @@ private void removeNotNullAndDefault(CommandSender sender, Columns column, Conne // Change column definition to nullable version try (Statement st = con.createStatement()) { st.execute(format("ALTER TABLE %s MODIFY %s %s", tableName, columnName, column.getNullableDefinition())); - sender.sendMessage("Changed column '" + columnName + "' to allow nulls"); + messages.send(sender, MessageKey.DEBUG_MYSQL_ALLOW_NULLS, columnName); } // Replace old default value with NULL @@ -167,8 +172,8 @@ private void removeNotNullAndDefault(CommandSender sender, Columns column, Conne pst.setObject(1, column.getDefaultValue()); updatedRows = pst.executeUpdate(); } - sender.sendMessage("Replaced default value ('" + column.getDefaultValue() - + "') to be NULL, modifying " + updatedRows + " entries"); + messages.send(sender, MessageKey.DEBUG_MYSQL_REPLACED_DEFAULT_NULL, + String.valueOf(column.getDefaultValue()), String.valueOf(updatedRows)); // Log success message logger.info("Changed MySQL column '" + columnName + "' to allow NULL, as initiated by '" @@ -181,21 +186,27 @@ private void removeNotNullAndDefault(CommandSender sender, Columns column, Conne * @param sender command sender to output the data to */ private void showColumnDetails(CommandSender sender) { - sender.sendMessage(ChatColor.BLUE + "MySQL column details"); + messages.send(sender, MessageKey.DEBUG_MYSQL_DETAILS_TITLE); final String tableName = settings.getProperty(DatabaseSettings.MYSQL_TABLE); try (Connection con = getConnection(mySql)) { final DatabaseMetaData metaData = con.getMetaData(); for (Columns col : Columns.values()) { String columnName = settings.getProperty(col.getColumnNameProperty()); - String isNullText = isNotNullColumn(metaData, tableName, columnName) ? "NOT NULL" : "nullable"; + boolean notNull = isNotNullColumn(metaData, tableName, columnName); + String isNullText = notNull + ? messages.retrieveSingle(sender, MessageKey.DEBUG_MYSQL_COL_STATE_NOT_NULL) + : messages.retrieveSingle(sender, MessageKey.DEBUG_MYSQL_COL_STATE_NULLABLE); Object defaultValue = getColumnDefaultValue(metaData, tableName, columnName); - String defaultText = defaultValue == null ? "no default" : "default: '" + defaultValue + "'"; - sender.sendMessage(formatColumnWithMetadata(col, metaData, tableName) - + " (" + columnName + "): " + isNullText + ", " + defaultText); + String defaultClause = defaultValue == null + ? messages.retrieveSingle(sender, MessageKey.DEBUG_MYSQL_COL_NO_DEFAULT) + : messages.retrieveSingle(sender, MessageKey.DEBUG_MYSQL_COL_DEFAULT, String.valueOf(defaultValue)); + String prefix = formatColumnWithMetadata(col, metaData, tableName); + sender.sendMessage(messages.retrieveSingle(sender, MessageKey.DEBUG_MYSQL_COL_ROW, + prefix, columnName, isNullText, defaultClause)); } } catch (SQLException e) { logger.logException("Failed while showing column details:", e); - sender.sendMessage("Failed while showing column details. See log for info"); + messages.send(sender, MessageKey.DEBUG_MYSQL_DETAILS_FAILED); } } @@ -206,21 +217,20 @@ private void showColumnDetails(CommandSender sender) { * @param sender the sender issuing the command */ private void displayUsageHints(CommandSender sender) { - sender.sendMessage(ChatColor.BLUE + "MySQL column changer"); - sender.sendMessage("Adds or removes a NOT NULL constraint for a column."); - sender.sendMessage("Examples: add a NOT NULL constraint with"); - sender.sendMessage(" /authme debug mysqldef add "); - sender.sendMessage("Remove one with /authme debug mysqldef remove "); - - sender.sendMessage("Available columns: " + constructColumnListWithMetadata()); - sender.sendMessage(" " + NOT_NULL_SUFFIX + ": not-null, " + DEFAULT_VALUE_SUFFIX - + ": has default. See /authme debug mysqldef details"); + messages.send(sender, MessageKey.DEBUG_MYSQL_USAGE_TITLE); + messages.send(sender, MessageKey.DEBUG_MYSQL_USAGE_INTRO); + messages.send(sender, MessageKey.DEBUG_MYSQL_USAGE_EXAMPLE_ADD); + messages.send(sender, MessageKey.DEBUG_MYSQL_USAGE_EXAMPLE_ADD_CMD); + messages.send(sender, MessageKey.DEBUG_MYSQL_USAGE_EXAMPLE_REMOVE); + + messages.send(sender, MessageKey.DEBUG_MYSQL_AVAILABLE_COLS, constructColumnListWithMetadata(sender)); + messages.send(sender, MessageKey.DEBUG_MYSQL_LEGEND); } /** * @return list of {@link Columns} we can toggle with suffixes indicating their NOT NULL and default value status */ - private String constructColumnListWithMetadata() { + private String constructColumnListWithMetadata(CommandSender sender) { try (Connection con = getConnection(mySql)) { final DatabaseMetaData metaData = con.getMetaData(); final String tableName = settings.getProperty(DatabaseSettings.MYSQL_TABLE); @@ -232,7 +242,7 @@ private String constructColumnListWithMetadata() { return String.join(ChatColor.RESET + ", ", formattedColumns); } catch (SQLException e) { logger.logException("Failed to construct column list:", e); - return ChatColor.RED + "An error occurred! Please see the console for details."; + return messages.retrieveSingle(sender, MessageKey.DEBUG_MYSQL_COL_LIST_ERROR); } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/debug/PermissionGroups.java b/src/main/java/fr/xephi/authme/command/executable/authme/debug/PermissionGroups.java index 4515ca0bd0..b98b30f69a 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/debug/PermissionGroups.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/debug/PermissionGroups.java @@ -1,11 +1,12 @@ package fr.xephi.authme.command.executable.authme.debug; import fr.xephi.authme.data.limbo.UserGroup; +import fr.xephi.authme.message.MessageKey; +import fr.xephi.authme.message.Messages; import fr.xephi.authme.permission.DebugSectionPermissions; import fr.xephi.authme.permission.PermissionNode; import fr.xephi.authme.permission.PermissionsManager; import org.bukkit.Bukkit; -import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -22,6 +23,9 @@ class PermissionGroups implements DebugSection { @Inject private PermissionsManager permissionsManager; + @Inject + private Messages messages; + @Override public String getName() { return "groups"; @@ -34,18 +38,19 @@ public String getDescription() { @Override public void execute(CommandSender sender, List arguments) { - sender.sendMessage(ChatColor.BLUE + "AuthMe permission groups"); + messages.send(sender, MessageKey.DEBUG_GROUPS_TITLE); String name = arguments.isEmpty() ? sender.getName() : arguments.get(0); Player player = Bukkit.getPlayer(name); if (player == null) { - sender.sendMessage("Player " + name + " could not be found"); + messages.send(sender, MessageKey.DEBUG_GROUPS_PLAYER_NOT_FOUND, name); } else { List groupNames = permissionsManager.getGroups(player).stream() .map(UserGroup::getGroupName) .collect(toList()); - sender.sendMessage("Player " + name + " has permission groups: " + String.join(", ", groupNames)); - sender.sendMessage("Primary group is: " + permissionsManager.getGroups(player)); + messages.send(sender, MessageKey.DEBUG_GROUPS_LIST, name, String.join(", ", groupNames)); + messages.send(sender, MessageKey.DEBUG_GROUPS_PRIMARY, + String.valueOf(permissionsManager.getGroups(player))); } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/debug/PlayerAuthViewer.java b/src/main/java/fr/xephi/authme/command/executable/authme/debug/PlayerAuthViewer.java index 99115cfe21..fe4371a8d6 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/debug/PlayerAuthViewer.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/debug/PlayerAuthViewer.java @@ -2,11 +2,12 @@ import fr.xephi.authme.data.auth.PlayerAuth; import fr.xephi.authme.datasource.DataSource; +import fr.xephi.authme.message.MessageKey; +import fr.xephi.authme.message.Messages; import fr.xephi.authme.permission.DebugSectionPermissions; import fr.xephi.authme.permission.PermissionNode; import fr.xephi.authme.security.crypts.HashedPassword; import fr.xephi.authme.util.StringUtils; -import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import javax.inject.Inject; @@ -26,6 +27,9 @@ class PlayerAuthViewer implements DebugSection { @Inject private DataSource dataSource; + @Inject + private Messages messages; + @Override public String getName() { return "db"; @@ -39,16 +43,16 @@ public String getDescription() { @Override public void execute(CommandSender sender, List arguments) { if (arguments.isEmpty()) { - sender.sendMessage(ChatColor.BLUE + "AuthMe database viewer"); - sender.sendMessage("Enter player name to view his data in the database."); - sender.sendMessage("Example: /authme debug db Bobby"); + messages.send(sender, MessageKey.DEBUG_DB_TITLE); + messages.send(sender, MessageKey.DEBUG_DB_ENTER_NAME); + messages.send(sender, MessageKey.DEBUG_DB_EXAMPLE); return; } PlayerAuth auth = dataSource.getAuth(arguments.get(0)); if (auth == null) { - sender.sendMessage(ChatColor.BLUE + "AuthMe database viewer"); - sender.sendMessage("No record exists for '" + arguments.get(0) + "'"); + messages.send(sender, MessageKey.DEBUG_DB_TITLE); + messages.send(sender, MessageKey.DEBUG_DB_NO_RECORD, arguments.get(0)); } else { displayAuthToSender(auth, sender); } @@ -66,18 +70,19 @@ public PermissionNode getRequiredPermission() { * @param sender the sender to send the messages to */ private void displayAuthToSender(PlayerAuth auth, CommandSender sender) { - sender.sendMessage(ChatColor.BLUE + "[AuthMe] Player " + auth.getNickname() + " / " + auth.getRealName()); - sender.sendMessage("Email: " + auth.getEmail() + ". IP: " + auth.getLastIp() + ". Group: " + auth.getGroupId()); - sender.sendMessage("Quit location: " - + formatLocation(auth.getQuitLocX(), auth.getQuitLocY(), auth.getQuitLocZ(), auth.getWorld())); - sender.sendMessage("Last login: " + formatDate(auth.getLastLogin())); - sender.sendMessage("Registration: " + formatDate(auth.getRegistrationDate()) - + " with IP " + auth.getRegistrationIp()); + messages.send(sender, MessageKey.DEBUG_DB_PLAYER_HEADER, auth.getNickname(), auth.getRealName()); + messages.send(sender, MessageKey.DEBUG_DB_SUMMARY, auth.getEmail(), auth.getLastIp(), + String.valueOf(auth.getGroupId())); + messages.send(sender, MessageKey.DEBUG_DB_QUIT_LOC, + formatLocation(auth.getQuitLocX(), auth.getQuitLocY(), auth.getQuitLocZ(), auth.getWorld())); + messages.send(sender, MessageKey.DEBUG_DB_LAST_LOGIN, formatDate(sender, auth.getLastLogin())); + messages.send(sender, MessageKey.DEBUG_DB_REGISTRATION, + formatDate(sender, auth.getRegistrationDate()), auth.getRegistrationIp()); HashedPassword hashedPass = auth.getPassword(); - sender.sendMessage("Hash / salt (partial): '" + safeSubstring(hashedPass.getHash(), 6) - + "' / '" + safeSubstring(hashedPass.getSalt(), 4) + "'"); - sender.sendMessage("TOTP code (partial): '" + safeSubstring(auth.getTotpKey(), 3) + "'"); + messages.send(sender, MessageKey.DEBUG_DB_HASH, + safeSubstring(hashedPass.getHash(), 6), safeSubstring(hashedPass.getSalt(), 4)); + messages.send(sender, MessageKey.DEBUG_DB_TOTP, safeSubstring(auth.getTotpKey(), 3)); } /** @@ -104,11 +109,11 @@ private static String safeSubstring(String str, int length) { * @param timestamp the timestamp to format (nullable) * @return the formatted timestamp */ - private static String formatDate(Long timestamp) { + private String formatDate(CommandSender sender, Long timestamp) { if (timestamp == null) { - return "Not available (null)"; + return messages.retrieveSingle(sender, MessageKey.DEBUG_DB_DATE_NULL); } else if (timestamp == 0) { - return "Not available (0)"; + return messages.retrieveSingle(sender, MessageKey.DEBUG_DB_DATE_ZERO); } else { LocalDateTime date = LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZoneId.systemDefault()); return DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(date); diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/debug/SpawnLocationViewer.java b/src/main/java/fr/xephi/authme/command/executable/authme/debug/SpawnLocationViewer.java index 30f756c321..1a92a95e85 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/debug/SpawnLocationViewer.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/debug/SpawnLocationViewer.java @@ -1,12 +1,13 @@ package fr.xephi.authme.command.executable.authme.debug; +import fr.xephi.authme.message.MessageKey; +import fr.xephi.authme.message.Messages; import fr.xephi.authme.permission.DebugSectionPermissions; import fr.xephi.authme.permission.PermissionNode; import fr.xephi.authme.service.BukkitService; import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.SpawnLoader; import fr.xephi.authme.settings.properties.RestrictionSettings; -import org.bukkit.ChatColor; import org.bukkit.Location; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -30,6 +31,8 @@ class SpawnLocationViewer implements DebugSection { @Inject private BukkitService bukkitService; + @Inject + private Messages messages; @Override public String getName() { @@ -43,7 +46,7 @@ public String getDescription() { @Override public void execute(CommandSender sender, List arguments) { - sender.sendMessage(ChatColor.BLUE + "AuthMe spawn location viewer"); + messages.send(sender, MessageKey.DEBUG_SPAWN_TITLE); if (arguments.isEmpty()) { showGeneralInfo(sender); } else if ("?".equals(arguments.get(0))) { @@ -59,29 +62,29 @@ public PermissionNode getRequiredPermission() { } private void showGeneralInfo(CommandSender sender) { - sender.sendMessage("Spawn priority: " - + String.join(", ", settings.getProperty(RestrictionSettings.SPAWN_PRIORITY))); - sender.sendMessage("AuthMe spawn location: " + formatLocation(spawnLoader.getSpawn())); - sender.sendMessage("AuthMe first spawn location: " + formatLocation(spawnLoader.getFirstSpawn())); - sender.sendMessage("AuthMe (first)spawn are only used depending on the configured priority!"); - sender.sendMessage("Use '/authme debug spawn ?' for further help"); + messages.send(sender, MessageKey.DEBUG_SPAWN_PRIORITY, + String.join(", ", settings.getProperty(RestrictionSettings.SPAWN_PRIORITY))); + messages.send(sender, MessageKey.DEBUG_SPAWN_LOCATION, formatLocation(spawnLoader.getSpawn())); + messages.send(sender, MessageKey.DEBUG_SPAWN_FIRST_LOCATION, formatLocation(spawnLoader.getFirstSpawn())); + messages.send(sender, MessageKey.DEBUG_SPAWN_PRIORITY_NOTE); + messages.send(sender, MessageKey.DEBUG_SPAWN_HELP_HINT); } private void showHelp(CommandSender sender) { - sender.sendMessage("Use /authme spawn and /authme firstspawn to teleport to the spawns."); - sender.sendMessage("/authme set(first)spawn sets the (first) spawn to your current location."); - sender.sendMessage("Use /authme debug spawn to view where a player would be teleported to."); - sender.sendMessage("Read more at https://github.com/AuthMe/AuthMeReloaded/wiki/Spawn-Handling"); + messages.send(sender, MessageKey.DEBUG_SPAWN_HELP_TELEPORT); + messages.send(sender, MessageKey.DEBUG_SPAWN_HELP_SET); + messages.send(sender, MessageKey.DEBUG_SPAWN_HELP_PLAYER); + messages.send(sender, MessageKey.DEBUG_SPAWN_HELP_WIKI); } private void showPlayerSpawn(CommandSender sender, String playerName) { Player player = bukkitService.getPlayerExact(playerName); if (player == null) { - sender.sendMessage("Player '" + playerName + "' is not online!"); + messages.send(sender, MessageKey.DEBUG_SPAWN_PLAYER_OFFLINE, playerName); } else { Location spawn = spawnLoader.getSpawnLocation(player); - sender.sendMessage("Player '" + playerName + "' has spawn location: " + formatLocation(spawn)); - sender.sendMessage("Note: this check excludes the AuthMe firstspawn."); + messages.send(sender, MessageKey.DEBUG_SPAWN_PLAYER_LOCATION, playerName, formatLocation(spawn)); + messages.send(sender, MessageKey.DEBUG_SPAWN_PLAYER_NOTE); } } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/debug/TestEmailSender.java b/src/main/java/fr/xephi/authme/command/executable/authme/debug/TestEmailSender.java index 388a18af15..235ae2ef14 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/debug/TestEmailSender.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/debug/TestEmailSender.java @@ -5,13 +5,14 @@ import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.mail.SendMailSsl; import fr.xephi.authme.output.ConsoleLoggerFactory; +import fr.xephi.authme.message.MessageKey; +import fr.xephi.authme.message.Messages; import fr.xephi.authme.permission.DebugSectionPermissions; import fr.xephi.authme.permission.PermissionNode; import fr.xephi.authme.util.StringUtils; import fr.xephi.authme.util.Utils; import org.apache.commons.mail.EmailException; import org.apache.commons.mail.HtmlEmail; -import org.bukkit.ChatColor; import org.bukkit.Server; import org.bukkit.command.CommandSender; @@ -34,6 +35,8 @@ class TestEmailSender implements DebugSection { @Inject private Server server; + @Inject + private Messages messages; @Override public String getName() { @@ -47,10 +50,9 @@ public String getDescription() { @Override public void execute(CommandSender sender, List arguments) { - sender.sendMessage(ChatColor.BLUE + "AuthMe test email sender"); + messages.send(sender, MessageKey.DEBUG_MAIL_TITLE); if (!sendMailSsl.hasAllInformation()) { - sender.sendMessage(ChatColor.RED + "You haven't set all required configurations in config.yml " - + "for sending emails. Please check your config.yml"); + messages.send(sender, MessageKey.DEBUG_MAIL_CONFIG_INCOMPLETE); return; } @@ -58,11 +60,11 @@ public void execute(CommandSender sender, List arguments) { // getEmail() takes care of informing the sender of the error if email == null if (email != null) { - boolean sendMail = sendTestEmail(email); + boolean sendMail = sendTestEmail(sender, email); if (sendMail) { - sender.sendMessage("Test email sent to " + email + " with success"); + messages.send(sender, MessageKey.DEBUG_MAIL_SENT, email); } else { - sender.sendMessage(ChatColor.RED + "Failed to send test mail to " + email + "; please check your logs"); + messages.send(sender, MessageKey.DEBUG_MAIL_FAILED, email); } } } @@ -87,14 +89,12 @@ private String getEmail(CommandSender sender, List arguments) { if (arguments.isEmpty()) { DataSourceValue emailResult = dataSource.getEmail(sender.getName()); if (!emailResult.rowExists()) { - sender.sendMessage(ChatColor.RED + "Please provide an email address, " - + "e.g. /authme debug mail test@example.com"); + messages.send(sender, MessageKey.DEBUG_MAIL_PROVIDE_ADDRESS); return null; } final String email = emailResult.getValue(); if (Utils.isEmailEmpty(email)) { - sender.sendMessage(ChatColor.RED + "No email set for your account!" - + " Please use /authme debug mail "); + messages.send(sender, MessageKey.DEBUG_MAIL_NO_ACCOUNT_EMAIL); return null; } return email; @@ -103,12 +103,12 @@ private String getEmail(CommandSender sender, List arguments) { if (StringUtils.isInsideString('@', email)) { return email; } - sender.sendMessage(ChatColor.RED + "Invalid email! Usage: /authme debug mail test@example.com"); + messages.send(sender, MessageKey.DEBUG_MAIL_INVALID); return null; } } - private boolean sendTestEmail(String email) { + private boolean sendTestEmail(CommandSender sender, String email) { HtmlEmail htmlEmail; try { htmlEmail = sendMailSsl.initializeMail(email); @@ -117,9 +117,8 @@ private boolean sendTestEmail(String email) { return false; } - htmlEmail.setSubject("AuthMe test email"); - String message = "Hello there!
This is a sample email sent to you from a Minecraft server (" - + server.getName() + ") via /authme debug mail. If you're seeing this, sending emails should be fine."; + htmlEmail.setSubject(messages.retrieveSingle(sender, MessageKey.DEBUG_MAIL_SUBJECT)); + String message = messages.retrieveSingle(sender, MessageKey.DEBUG_MAIL_BODY, server.getName()); return sendMailSsl.sendEmail(message, htmlEmail); } } diff --git a/src/main/java/fr/xephi/authme/command/help/HelpMessage.java b/src/main/java/fr/xephi/authme/command/help/HelpMessage.java index ae306a4033..5d4156ca50 100644 --- a/src/main/java/fr/xephi/authme/command/help/HelpMessage.java +++ b/src/main/java/fr/xephi/authme/command/help/HelpMessage.java @@ -16,7 +16,19 @@ public enum HelpMessage { DEFAULT("default"), - RESULT("result"); + RESULT("result"), + + /** Shown when help output cannot be built because the command description is missing */ + HELP_FAILED_RETRIEVE_INFO("helpFailedRetrieveInfo"), + + /** Shown when the help command cannot resolve the base command */ + HELP_MISSING_BASE_COMMAND("helpMissingBaseCommand"), + + /** Shown when the user requests help for an unknown command label */ + HELP_UNKNOWN_COMMAND("helpUnknownCommand"), + + /** Shown when the command mapper corrects a typo; %command% is the resolved command path */ + HELP_ASSUMING_COMMAND("helpAssumingCommand"); private static final String PREFIX = "common."; private final String key; diff --git a/src/main/java/fr/xephi/authme/command/help/HelpProvider.java b/src/main/java/fr/xephi/authme/command/help/HelpProvider.java index 4327b827f1..d697c96fc8 100644 --- a/src/main/java/fr/xephi/authme/command/help/HelpProvider.java +++ b/src/main/java/fr/xephi/authme/command/help/HelpProvider.java @@ -19,6 +19,8 @@ import java.util.List; import java.util.function.Function; +import static org.bukkit.ChatColor.translateAlternateColorCodes; + import static fr.xephi.authme.command.help.HelpSection.DETAILED_DESCRIPTION; import static fr.xephi.authme.command.help.HelpSection.SHORT_DESCRIPTION; import static java.util.Collections.singletonList; @@ -68,7 +70,8 @@ public class HelpProvider implements Reloadable { */ private List buildHelpOutput(CommandSender sender, FoundCommandResult result, int options) { if (result.getCommandDescription() == null) { - return singletonList(ChatColor.DARK_RED + "Failed to retrieve any help information!"); + return singletonList(translateAlternateColorCodes('&', + helpMessagesService.getMessage(HelpMessage.HELP_FAILED_RETRIEVE_INFO))); } List lines = new ArrayList<>(); diff --git a/src/main/java/fr/xephi/authme/datasource/converter/AbstractDataSourceConverter.java b/src/main/java/fr/xephi/authme/datasource/converter/AbstractDataSourceConverter.java index fdced2fa4d..301c6c6927 100644 --- a/src/main/java/fr/xephi/authme/datasource/converter/AbstractDataSourceConverter.java +++ b/src/main/java/fr/xephi/authme/datasource/converter/AbstractDataSourceConverter.java @@ -4,7 +4,10 @@ import fr.xephi.authme.data.auth.PlayerAuth; import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.datasource.DataSourceType; +import fr.xephi.authme.message.MessageKey; +import fr.xephi.authme.message.Messages; import fr.xephi.authme.output.ConsoleLoggerFactory; +import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import java.util.ArrayList; @@ -23,6 +26,7 @@ public abstract class AbstractDataSourceConverter implemen private final DataSource destination; private final DataSourceType destinationType; + private final Messages messages; /** * Constructor. @@ -31,20 +35,22 @@ public abstract class AbstractDataSourceConverter implemen * @param destinationType the data source type of the destination. The given data source is checked that its * type corresponds to this type before the conversion is started, enabling us to just pass * the current data source and letting this class check that the types correspond. + * @param messages message service for user-facing output */ - public AbstractDataSourceConverter(DataSource destination, DataSourceType destinationType) { + public AbstractDataSourceConverter(DataSource destination, DataSourceType destinationType, Messages messages) { this.destination = destination; this.destinationType = destinationType; + this.messages = messages; } // Implementation note: Because of ForceFlatToSqlite it is possible that the CommandSender is null, // which is never the case when a converter is launched from the /authme converter command. @Override public void execute(CommandSender sender) { + CommandSender audience = sender != null ? sender : Bukkit.getConsoleSender(); if (destinationType != destination.getType()) { if (sender != null) { - sender.sendMessage("Please configure your connection to " - + destinationType + " and re-run this command"); + messages.send(sender, MessageKey.CONVERTER_CONFIGURE_DESTINATION, destinationType.name()); } return; } @@ -53,7 +59,8 @@ public void execute(CommandSender sender) { try { source = getSource(); } catch (Exception e) { - logAndSendMessage(sender, "The data source to convert from could not be initialized"); + logAndSendMessage(sender, + messages.retrieveSingle(audience, MessageKey.CONVERTER_SOURCE_INIT_FAILED)); logger.logException("Could not initialize source:", e); return; } @@ -70,11 +77,11 @@ public void execute(CommandSender sender) { } if (!skippedPlayers.isEmpty()) { - logAndSendMessage(sender, "Skipped conversion for players which were already in " - + destinationType + ": " + String.join(", ", skippedPlayers)); + logAndSendMessage(sender, messages.retrieveSingle(audience, MessageKey.CONVERTER_SKIPPED_EXISTING, + destinationType.name(), String.join(", ", skippedPlayers))); } - logAndSendMessage(sender, "Database successfully converted from " + source.getType() - + " to " + destinationType); + logAndSendMessage(sender, messages.retrieveSingle(audience, MessageKey.CONVERTER_FINISHED, + source.getType().name(), destinationType.name())); } /** diff --git a/src/main/java/fr/xephi/authme/datasource/converter/CrazyLoginConverter.java b/src/main/java/fr/xephi/authme/datasource/converter/CrazyLoginConverter.java index a91972239d..8780bcf65b 100644 --- a/src/main/java/fr/xephi/authme/datasource/converter/CrazyLoginConverter.java +++ b/src/main/java/fr/xephi/authme/datasource/converter/CrazyLoginConverter.java @@ -4,6 +4,8 @@ import fr.xephi.authme.data.auth.PlayerAuth; import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.initialization.DataFolder; +import fr.xephi.authme.message.MessageKey; +import fr.xephi.authme.message.Messages; import fr.xephi.authme.output.ConsoleLoggerFactory; import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.properties.ConverterSettings; @@ -26,12 +28,14 @@ public class CrazyLoginConverter implements Converter { private final DataSource database; private final Settings settings; private final File dataFolder; + private final Messages messages; @Inject - CrazyLoginConverter(@DataFolder File dataFolder, DataSource dataSource, Settings settings) { + CrazyLoginConverter(@DataFolder File dataFolder, DataSource dataSource, Settings settings, Messages messages) { this.dataFolder = dataFolder; this.database = dataSource; this.settings = settings; + this.messages = messages; } @Override @@ -39,7 +43,7 @@ public void execute(CommandSender sender) { String fileName = settings.getProperty(ConverterSettings.CRAZYLOGIN_FILE_NAME); File source = new File(dataFolder, fileName); if (!source.exists()) { - sender.sendMessage("CrazyLogin file not found, please put " + fileName + " in AuthMe folder!"); + messages.send(sender, MessageKey.CONVERTER_CRAZYLOGIN_FILE_NOT_FOUND, fileName); return; } diff --git a/src/main/java/fr/xephi/authme/datasource/converter/H2ToSqlite.java b/src/main/java/fr/xephi/authme/datasource/converter/H2ToSqlite.java index 03520b80f9..8a86c9af02 100644 --- a/src/main/java/fr/xephi/authme/datasource/converter/H2ToSqlite.java +++ b/src/main/java/fr/xephi/authme/datasource/converter/H2ToSqlite.java @@ -4,6 +4,7 @@ import fr.xephi.authme.datasource.DataSourceType; import fr.xephi.authme.datasource.H2; import fr.xephi.authme.initialization.DataFolder; +import fr.xephi.authme.message.Messages; import fr.xephi.authme.settings.Settings; import javax.inject.Inject; @@ -20,8 +21,8 @@ public class H2ToSqlite extends AbstractDataSourceConverter

{ private final File dataFolder; @Inject - H2ToSqlite(Settings settings, DataSource dataSource, @DataFolder File dataFolder) { - super(dataSource, DataSourceType.SQLITE); + H2ToSqlite(Settings settings, DataSource dataSource, @DataFolder File dataFolder, Messages messages) { + super(dataSource, DataSourceType.SQLITE, messages); this.settings = settings; this.dataFolder = dataFolder; } diff --git a/src/main/java/fr/xephi/authme/datasource/converter/LoginSecurityConverter.java b/src/main/java/fr/xephi/authme/datasource/converter/LoginSecurityConverter.java index dbdce5dfd6..d69bd2cfbb 100644 --- a/src/main/java/fr/xephi/authme/datasource/converter/LoginSecurityConverter.java +++ b/src/main/java/fr/xephi/authme/datasource/converter/LoginSecurityConverter.java @@ -5,6 +5,8 @@ import fr.xephi.authme.data.auth.PlayerAuth; import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.initialization.DataFolder; +import fr.xephi.authme.message.MessageKey; +import fr.xephi.authme.message.Messages; import fr.xephi.authme.output.ConsoleLoggerFactory; import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.properties.ConverterSettings; @@ -41,11 +43,13 @@ public class LoginSecurityConverter implements Converter { private final String mySqlDatabase; private final String mySqlUser; private final String mySqlPassword; + private final Messages messages; @Inject - LoginSecurityConverter(@DataFolder File dataFolder, DataSource dataSource, Settings settings) { + LoginSecurityConverter(@DataFolder File dataFolder, DataSource dataSource, Settings settings, Messages messages) { this.dataFolder = dataFolder; this.dataSource = dataSource; + this.messages = messages; useSqlite = settings.getProperty(ConverterSettings.LOGINSECURITY_USE_SQLITE); mySqlHost = settings.getProperty(ConverterSettings.LOGINSECURITY_MYSQL_HOST); @@ -63,7 +67,7 @@ public void execute(CommandSender sender) { + "in your configuration file!"); } } catch (SQLException e) { - sender.sendMessage("Failed to convert from SQLite. Please see the log for more info"); + messages.send(sender, MessageKey.CONVERTER_LOGINSECURITY_FAILED); logger.logException("Could not fetch or migrate data:", e); } } @@ -106,10 +110,12 @@ private void migrateData(CommandSender sender, ResultSet resultSet) throws SQLEx } } - logAndSendMessage(sender, "Migrated " + successfulSaves + " accounts successfully from LoginSecurity"); + logAndSendMessage(sender, + messages.retrieveSingle(sender, MessageKey.CONVERTER_LOGINSECURITY_MIGRATED, String.valueOf(successfulSaves))); if (!skippedPlayers.isEmpty()) { - logAndSendMessage(sender, "Skipped conversion for players which were already in AuthMe: " - + String.join(", ", skippedPlayers)); + logAndSendMessage(sender, + messages.retrieveSingle(sender, MessageKey.CONVERTER_LOGINSECURITY_SKIPPED, + String.join(", ", skippedPlayers))); } } @@ -155,21 +161,20 @@ private Connection createConnectionOrInformSender(CommandSender sender) { if (useSqlite) { File sqliteDatabase = new File(dataFolder.getParentFile(), "LoginSecurity/LoginSecurity.db"); if (!sqliteDatabase.exists()) { - sender.sendMessage("The file '" + sqliteDatabase.getPath() + "' does not exist"); + messages.send(sender, MessageKey.CONVERTER_LOGINSECURITY_FILE_MISSING, sqliteDatabase.getPath()); return null; } connection = createSqliteConnection("plugins/LoginSecurity/LoginSecurity.db"); } else { if (mySqlDatabase.isEmpty() || mySqlUser.isEmpty()) { - sender.sendMessage("The LoginSecurity database or username is not configured in AuthMe's config.yml"); + messages.send(sender, MessageKey.CONVERTER_LOGINSECURITY_MYSQL_UNCONFIGURED); return null; } connection = createMySqlConnection(); } if (connection == null) { - sender.sendMessage("Could not connect to LoginSecurity using Sqlite = " - + useSqlite + ", see log for more info"); + messages.send(sender, MessageKey.CONVERTER_LOGINSECURITY_CONNECT_FAILED, String.valueOf(useSqlite)); return null; } return connection; diff --git a/src/main/java/fr/xephi/authme/datasource/converter/MySqlToSqlite.java b/src/main/java/fr/xephi/authme/datasource/converter/MySqlToSqlite.java index b1a485b979..54fddfe4d5 100644 --- a/src/main/java/fr/xephi/authme/datasource/converter/MySqlToSqlite.java +++ b/src/main/java/fr/xephi/authme/datasource/converter/MySqlToSqlite.java @@ -4,6 +4,7 @@ import fr.xephi.authme.datasource.DataSourceType; import fr.xephi.authme.datasource.MySQL; import fr.xephi.authme.datasource.mysqlextensions.MySqlExtensionsFactory; +import fr.xephi.authme.message.Messages; import fr.xephi.authme.settings.Settings; import javax.inject.Inject; @@ -18,8 +19,9 @@ public class MySqlToSqlite extends AbstractDataSourceConverter { private final MySqlExtensionsFactory mySqlExtensionsFactory; @Inject - MySqlToSqlite(DataSource dataSource, Settings settings, MySqlExtensionsFactory mySqlExtensionsFactory) { - super(dataSource, DataSourceType.SQLITE); + MySqlToSqlite(DataSource dataSource, Settings settings, MySqlExtensionsFactory mySqlExtensionsFactory, + Messages messages) { + super(dataSource, DataSourceType.SQLITE, messages); this.settings = settings; this.mySqlExtensionsFactory = mySqlExtensionsFactory; } diff --git a/src/main/java/fr/xephi/authme/datasource/converter/SqliteToH2.java b/src/main/java/fr/xephi/authme/datasource/converter/SqliteToH2.java index eea2bfcab6..dbda4b9597 100644 --- a/src/main/java/fr/xephi/authme/datasource/converter/SqliteToH2.java +++ b/src/main/java/fr/xephi/authme/datasource/converter/SqliteToH2.java @@ -4,6 +4,7 @@ import fr.xephi.authme.datasource.DataSourceType; import fr.xephi.authme.datasource.SQLite; import fr.xephi.authme.initialization.DataFolder; +import fr.xephi.authme.message.Messages; import fr.xephi.authme.settings.Settings; import javax.inject.Inject; @@ -20,8 +21,8 @@ public class SqliteToH2 extends AbstractDataSourceConverter{ private final File dataFolder; @Inject - SqliteToH2(Settings settings, DataSource dataSource, @DataFolder File dataFolder) { - super(dataSource, DataSourceType.H2); + SqliteToH2(Settings settings, DataSource dataSource, @DataFolder File dataFolder, Messages messages) { + super(dataSource, DataSourceType.H2, messages); this.settings = settings; this.dataFolder = dataFolder; } diff --git a/src/main/java/fr/xephi/authme/datasource/converter/SqliteToSql.java b/src/main/java/fr/xephi/authme/datasource/converter/SqliteToSql.java index cc472da28a..a34e88c762 100644 --- a/src/main/java/fr/xephi/authme/datasource/converter/SqliteToSql.java +++ b/src/main/java/fr/xephi/authme/datasource/converter/SqliteToSql.java @@ -4,6 +4,7 @@ import fr.xephi.authme.datasource.DataSourceType; import fr.xephi.authme.datasource.SQLite; import fr.xephi.authme.initialization.DataFolder; +import fr.xephi.authme.message.Messages; import fr.xephi.authme.settings.Settings; import javax.inject.Inject; @@ -19,8 +20,8 @@ public class SqliteToSql extends AbstractDataSourceConverter { private final File dataFolder; @Inject - SqliteToSql(Settings settings, DataSource dataSource, @DataFolder File dataFolder) { - super(dataSource, DataSourceType.MYSQL); + SqliteToSql(Settings settings, DataSource dataSource, @DataFolder File dataFolder, Messages messages) { + super(dataSource, DataSourceType.MYSQL, messages); this.settings = settings; this.dataFolder = dataFolder; } diff --git a/src/main/java/fr/xephi/authme/datasource/converter/XAuthConverter.java b/src/main/java/fr/xephi/authme/datasource/converter/XAuthConverter.java index 0f04310cb8..7b60115890 100644 --- a/src/main/java/fr/xephi/authme/datasource/converter/XAuthConverter.java +++ b/src/main/java/fr/xephi/authme/datasource/converter/XAuthConverter.java @@ -6,6 +6,8 @@ import fr.xephi.authme.data.auth.PlayerAuth; import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.initialization.DataFolder; +import fr.xephi.authme.message.MessageKey; +import fr.xephi.authme.message.Messages; import fr.xephi.authme.util.Utils; import org.bukkit.command.CommandSender; import org.bukkit.plugin.PluginManager; @@ -32,6 +34,9 @@ public class XAuthConverter implements Converter { @Inject private PluginManager pluginManager; + @Inject + private Messages messages; + XAuthConverter() { } @@ -41,26 +46,26 @@ public void execute(CommandSender sender) { Class.forName("de.luricos.bukkit.xAuth.xAuth"); convert(sender); } catch (ClassNotFoundException ce) { - sender.sendMessage("xAuth has not been found, please put xAuth.jar in your plugin folder and restart!"); + messages.send(sender, MessageKey.CONVERTER_XAUTH_CLASS_NOT_FOUND); } } private void convert(CommandSender sender) { if (pluginManager.getPlugin("xAuth") == null) { - sender.sendMessage("[AuthMe] xAuth plugin not found"); + messages.send(sender, MessageKey.CONVERTER_XAUTH_PLUGIN_NOT_FOUND); return; } //TODO ljacqu 20160702: xAuthDb is not used except for the existence check -- is this intended? File xAuthDb = new File(dataFolder.getParent(), makePath("xAuth", "xAuth.h2.db")); if (!xAuthDb.exists()) { - sender.sendMessage("[AuthMe] xAuth H2 database not found, checking for MySQL or SQLite data..."); + messages.send(sender, MessageKey.CONVERTER_XAUTH_H2_MISSING); } List players = getXAuthPlayers(); if (Utils.isCollectionEmpty(players)) { - sender.sendMessage("[AuthMe] Error while importing xAuthPlayers: did not find any players"); + messages.send(sender, MessageKey.CONVERTER_XAUTH_NO_PLAYERS); return; } - sender.sendMessage("[AuthMe] Starting import..."); + messages.send(sender, MessageKey.CONVERTER_XAUTH_STARTING); for (int id : players) { String pl = getIdPlayer(id); @@ -73,7 +78,7 @@ private void convert(CommandSender sender) { database.saveAuth(auth); } } - sender.sendMessage("[AuthMe] Successfully converted from xAuth database"); + messages.send(sender, MessageKey.CONVERTER_XAUTH_SUCCESS); } private String getIdPlayer(int id) { diff --git a/src/main/java/fr/xephi/authme/listener/PlayerListener19Spigot.java b/src/main/java/fr/xephi/authme/listener/PlayerListener19Spigot.java index a068f27d27..2823f9f518 100644 --- a/src/main/java/fr/xephi/authme/listener/PlayerListener19Spigot.java +++ b/src/main/java/fr/xephi/authme/listener/PlayerListener19Spigot.java @@ -22,13 +22,21 @@ public static boolean isPlayerSpawnLocationEventCalled() { return isPlayerSpawnLocationEventCalled; } + /** + * Marks that the join spawn location was already handled (Paper async hook calls this). + */ + public static void setJoinSpawnLocationHookRan() { + isPlayerSpawnLocationEventCalled = true; + } + // Note: the following event is called since MC1.9, in older versions we have to fallback on the PlayerJoinEvent @EventHandler(priority = EventPriority.HIGH) public void onPlayerSpawn(PlayerSpawnLocationEvent event) { isPlayerSpawnLocationEventCalled = true; final Player player = event.getPlayer(); - Location customSpawnLocation = teleportationService.prepareOnJoinSpawnLocation(player); + Location customSpawnLocation = teleportationService.prepareOnJoinSpawnLocation( + player.getName(), event.getSpawnLocation()); if (customSpawnLocation != null) { event.setSpawnLocation(customSpawnLocation); } diff --git a/src/main/java/fr/xephi/authme/listener/PlayerListenerPaperAsyncSpawn.java b/src/main/java/fr/xephi/authme/listener/PlayerListenerPaperAsyncSpawn.java new file mode 100644 index 0000000000..b730767d4d --- /dev/null +++ b/src/main/java/fr/xephi/authme/listener/PlayerListenerPaperAsyncSpawn.java @@ -0,0 +1,38 @@ +package fr.xephi.authme.listener; + +import fr.xephi.authme.service.TeleportationService; +import io.papermc.paper.event.player.AsyncPlayerSpawnLocationEvent; +import org.bukkit.Location; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; + +import javax.inject.Inject; + +/** + * Paper 1.21.9+: handles join spawn before the player entity is fully available. + *

+ * Replaces {@link org.spigotmc.event.player.PlayerSpawnLocationEvent} for Paper servers — that event is + * deprecated for removal; using {@link org.bukkit.event.player.PlayerEvent#getPlayer()} for entity-related + * logic is unsafe during the configuration phase (see Paper Javadoc). + * + * @see AsyncPlayerSpawnLocationEvent + */ +public class PlayerListenerPaperAsyncSpawn implements Listener { + + @Inject + private TeleportationService teleportationService; + + @EventHandler(priority = EventPriority.HIGH) + public void onAsyncPlayerSpawn(AsyncPlayerSpawnLocationEvent event) { + PlayerListener19Spigot.setJoinSpawnLocationHookRan(); + String name = event.getConnection().getProfile().getName(); + if (name == null) { + return; + } + Location customSpawn = teleportationService.prepareOnJoinSpawnLocation(name, event.getSpawnLocation()); + if (customSpawn != null) { + event.setSpawnLocation(customSpawn); + } + } +} diff --git a/src/main/java/fr/xephi/authme/message/MessageKey.java b/src/main/java/fr/xephi/authme/message/MessageKey.java index ab05738dfc..6e8fca630d 100644 --- a/src/main/java/fr/xephi/authme/message/MessageKey.java +++ b/src/main/java/fr/xephi/authme/message/MessageKey.java @@ -341,6 +341,24 @@ public enum MessageKey { /** You used a command too fast! Please, join the server again and wait more before using any command. */ QUICK_COMMAND_PROTECTION_KICK("on_join_validation.quick_command"), + /** Failed to parse %plugin% command! */ + COMMAND_PARSE_FAILED("error.command_parse_failed", "%plugin%"), + + /** Unknown command! (AuthMe command router) */ + UNKNOWN_AUTHME_COMMAND("error.unknown_authme_command"), + + /** Did you mean %command%? */ + COMMAND_SUGGEST_SIMILAR("error.command_suggest_similar", "%command%"), + + /** Use the command /%label% help to view help. */ + COMMAND_USE_HELP("error.command_use_help", "%label%"), + + /** Incorrect command arguments! */ + INCORRECT_COMMAND_ARGUMENTS_GENERIC("error.incorrect_command_arguments"), + + /** Detailed help: /%label% help %child% */ + COMMAND_DETAILED_HELP_SYNTAX("error.command_detailed_help_syntax", "%label%", "%child%"), + /** second */ SECOND("time.second"), @@ -363,7 +381,626 @@ public enum MessageKey { DAY("time.day"), /** days */ - DAYS("time.days"); + DAYS("time.days"), + + // Staff command feedback (/authme and related) + /** Error occurred during reload of AuthMe: aborting */ + RELOAD_ABORT_ERROR("admin.reload_abort_error"), + + /** Note: cannot change database type during /authme reload */ + RELOAD_DATABASE_TYPE_NOTE("admin.reload_database_type_note"), + + /** [AuthMe] Spawn has failed, please try to define the spawn */ + ADMIN_SPAWN_FAILED("admin.spawn_failed"), + + /** [AuthMe] First spawn has failed, please try to define the first spawn */ + ADMIN_FIRST_SPAWN_FAILED("admin.first_spawn_failed"), + + /** [AuthMe] Correctly defined new spawn point */ + ADMIN_SET_SPAWN_SUCCESS("admin.set_spawn_success"), + + /** [AuthMe] SetSpawn has failed, please retry */ + ADMIN_SET_SPAWN_FAILED("admin.set_spawn_failed"), + + /** [AuthMe] Correctly defined new first spawn point */ + ADMIN_SET_FIRST_SPAWN_SUCCESS("admin.set_first_spawn_success"), + + /** [AuthMe] SetFirstSpawn has failed, please retry */ + ADMIN_SET_FIRST_SPAWN_FAILED("admin.set_first_spawn_failed"), + + /** [AuthMe] AntiBot status: %status% */ + ADMIN_ANTIBOT_STATUS("admin.antibot_status", "%status%"), + + /** [AuthMe] AntiBot Manual Override: enabled! */ + ADMIN_ANTIBOT_MANUAL_ENABLED("admin.antibot_manual_enabled"), + + /** [AuthMe] AntiBot Manual Override: disabled! */ + ADMIN_ANTIBOT_MANUAL_DISABLED("admin.antibot_manual_disabled"), + + /** Invalid AntiBot mode! */ + ADMIN_ANTIBOT_INVALID_MODE("admin.antibot_invalid_mode"), + + /** Detailed help: %command% */ + ADMIN_ANTIBOT_DETAILED_HELP("admin.antibot_detailed_help", "%command%"), + + /** Purged data for player %player% */ + ADMIN_PURGE_PLAYER_SUCCESS("admin.purge_player_success", "%player%"), + + /** + * This player is still registered! Are you sure you want to proceed? + * Use '/authme purgeplayer %player% force' to run the command anyway + */ + ADMIN_PURGE_PLAYER_CONFIRM("admin.purge_player_confirm", "%player%"), + + /** All players last position locations are now reset */ + ADMIN_PURGE_LASTPOS_ALL("admin.purge_lastpos_all"), + + /** %player%'s last position location is now reset */ + ADMIN_PURGE_LASTPOS_ONE("admin.purge_lastpos_one", "%player%"), + + /** Player needs to be online! */ + ADMIN_FORCE_LOGIN_OFFLINE("admin.force_login_offline"), + + /** You cannot force login the player %player%! */ + ADMIN_FORCE_LOGIN_DENIED("admin.force_login_denied", "%player%"), + + /** Force login for %player% performed! */ + ADMIN_FORCE_LOGIN_SUCCESS("admin.force_login_success", "%player%"), + + /** [AuthMe] This IP does not exist in the database. */ + ADMIN_ACCOUNTS_IP_UNKNOWN("admin.accounts_ip_unknown"), + + /** [AuthMe] %player% is a single account player */ + ADMIN_ACCOUNTS_SINGLE("admin.accounts_single", "%player%"), + + /** No known last IP address for player */ + ADMIN_ACCOUNTS_NO_LAST_IP("admin.accounts_no_last_ip"), + + /** [AuthMe] %player% has %count% accounts. */ + ADMIN_ACCOUNTS_MULTIPLE("admin.accounts_multiple", "%player%", "%count%"), + + /** [AuthMe] %list%. */ + ADMIN_ACCOUNTS_LIST("admin.accounts_list", "%list%"), + + /** Current IP of %name% is %ip%:%port% */ + ADMIN_GET_IP_CURRENT("admin.get_ip_current", "%name%", "%ip%", "%port%"), + + /** %name% is not registered in the database */ + ADMIN_GET_IP_NOT_REGISTERED("admin.get_ip_not_registered", "%name%"), + + /** Database: last IP: %lastIp%, registration IP: %regIp% */ + ADMIN_GET_IP_DATABASE("admin.get_ip_database", "%lastIp%", "%regIp%"), + + /** [AuthMe] %player%'s email: %email% */ + ADMIN_GET_EMAIL("admin.get_email", "%player%", "%email%"), + + /** [AuthMe] %player% last login: %date% */ + ADMIN_LAST_LOGIN("admin.last_login", "%player%", "%date%"), + + /** [AuthMe] The player %player% last logged in %interval% ago */ + ADMIN_LAST_LOGIN_INTERVAL("admin.last_login_interval", "%player%", "%interval%"), + + /** [AuthMe] Last player's IP: %ip% */ + ADMIN_LAST_LOGIN_IP("admin.last_login_ip", "%ip%"), + + /** never */ + ADMIN_LAST_LOGIN_NEVER("admin.last_login_never"), + + /** %days% days %hours% hours %mins% mins %secs% secs */ + ADMIN_LAST_LOGIN_INTERVAL_PARTS("admin.last_login_interval_parts", "%days%", "%hours%", "%mins%", "%secs%"), + + /** Converters: %list% */ + ADMIN_CONVERTER_LIST("admin.converter_list", "%list%"), + + /** [AuthMe] Successfully started %name% */ + ADMIN_CONVERTER_STARTED("admin.converter_started", "%name%"), + + /** Player '%player%' does not have two-factor auth enabled */ + ADMIN_TOTP_NOT_ENABLED("admin.totp_not_enabled", "%player%"), + + /** Disabled two-factor authentication successfully for '%player%' */ + ADMIN_TOTP_DISABLED_SUCCESS("admin.totp_disabled_success", "%player%"), + + /** Successfully updated the help file '%file%' */ + ADMIN_HELP_FILE_UPDATED("admin.help_file_updated", "%file%"), + + /** Could not update help file: %error% */ + ADMIN_HELP_FILE_UPDATE_FAILED("admin.help_file_update_failed", "%error%"), + + /** Player '%player%' does NOT have two-factor auth enabled */ + ADMIN_TOTP_VIEW_DISABLED("admin.totp_view_disabled", "%player%"), + + /** Player '%player%' has enabled two-factor authentication */ + ADMIN_TOTP_VIEW_ENABLED("admin.totp_view_enabled", "%player%"), + + /** This server is running %plugin% v%version% b%build%! <3 */ + AUTHME_INFO_RUNNING("admin.authme_info_running", "%plugin%", "%version%", "%build%"), + + /** Use the command /authme help to view help. */ + AUTHME_INFO_HELP("admin.authme_info_help"), + + /** Use the command /authme about to view about. */ + AUTHME_INFO_ABOUT("admin.authme_info_about"), + + /** The value you've entered is invalid! */ + PURGE_INVALID_VALUE("admin.purge_invalid_value"), + + /** You can only purge data older than %days% days */ + PURGE_MINIMUM_DAYS("admin.purge_minimum_days", "%days%"), + + /** No players to purge */ + PURGE_NO_PLAYERS("admin.purge_no_players"), + + /** Purge is already in progress! Aborting purge request */ + PURGE_ALREADY_RUNNING("admin.purge_already_running"), + + /** [AuthMe] Purge progress %current%/%total% */ + PURGE_PROGRESS("admin.purge_progress", "%current%", "%total%"), + + /** [AuthMe] Database has been purged successfully */ + PURGE_DATABASE_SUCCESS("admin.purge_database_success"), + + /** [AuthMe] Recently logged in players */ + RECENT_PLAYERS_HEADER("admin.recent_players_header"), + + /** - %player% (%lastlogin% with IP %ip%) */ + RECENT_PLAYER_LINE("admin.recent_player_line", "%player%", "%lastlogin%", "%ip%"), + + /** Can't perform a backup: disabled in configuration. Cause of the backup: %cause% */ + BACKUP_DISABLED("admin.backup_disabled", "%cause%"), + + /** A backup has been performed successfully. Cause of the backup: %cause% */ + BACKUP_SUCCESS("admin.backup_success", "%cause%"), + + /** Error while performing a backup! Cause of the backup: %cause% */ + BACKUP_FAILED("admin.backup_failed", "%cause%"), + + /** Please configure your connection to %type% and re-run this command */ + CONVERTER_CONFIGURE_DESTINATION("admin.converter_configure_destination", "%type%"), + + /** The data source to convert from could not be initialized */ + CONVERTER_SOURCE_INIT_FAILED("admin.converter_source_init_failed"), + + /** Skipped conversion for players which were already in %type%: %players% */ + CONVERTER_SKIPPED_EXISTING("admin.converter_skipped_existing", "%type%", "%players%"), + + /** Database successfully converted from %source% to %target% */ + CONVERTER_FINISHED("admin.converter_finished", "%source%", "%target%"), + + /** xAuth has not been found, please put xAuth.jar in your plugin folder and restart! */ + CONVERTER_XAUTH_CLASS_NOT_FOUND("admin.converter_xauth_class_not_found"), + + /** [AuthMe] xAuth plugin not found */ + CONVERTER_XAUTH_PLUGIN_NOT_FOUND("admin.converter_xauth_plugin_not_found"), + + /** [AuthMe] xAuth H2 database not found, checking for MySQL or SQLite data... */ + CONVERTER_XAUTH_H2_MISSING("admin.converter_xauth_h2_missing"), + + /** [AuthMe] Error while importing xAuthPlayers: did not find any players */ + CONVERTER_XAUTH_NO_PLAYERS("admin.converter_xauth_no_players"), + + /** [AuthMe] Starting import... */ + CONVERTER_XAUTH_STARTING("admin.converter_xauth_starting"), + + /** [AuthMe] Successfully converted from xAuth database */ + CONVERTER_XAUTH_SUCCESS("admin.converter_xauth_success"), + + /** CrazyLogin file not found, please put %file% in AuthMe folder! */ + CONVERTER_CRAZYLOGIN_FILE_NOT_FOUND("admin.converter_crazylogin_file_not_found", "%file%"), + + /** Failed to convert from SQLite. Please see the log for more info */ + CONVERTER_LOGINSECURITY_FAILED("admin.converter_loginsecurity_failed"), + + /** Migrated %count% accounts successfully from LoginSecurity */ + CONVERTER_LOGINSECURITY_MIGRATED("admin.converter_loginsecurity_migrated", "%count%"), + + /** Skipped conversion for players which were already in AuthMe: %players% */ + CONVERTER_LOGINSECURITY_SKIPPED("admin.converter_loginsecurity_skipped", "%players%"), + + /** The file '%path%' does not exist */ + CONVERTER_LOGINSECURITY_FILE_MISSING("admin.converter_loginsecurity_file_missing", "%path%"), + + /** The LoginSecurity database or username is not configured in AuthMe's config.yml */ + CONVERTER_LOGINSECURITY_MYSQL_UNCONFIGURED("admin.converter_loginsecurity_mysql_unconfigured"), + + /** Could not connect to LoginSecurity using Sqlite = %sqlite%, see log for more info */ + CONVERTER_LOGINSECURITY_CONNECT_FAILED("admin.converter_loginsecurity_connect_failed", "%sqlite%"), + + /** ==========[ %plugin% ABOUT ]========== */ + ABOUT_HEADER("about.header", "%plugin%"), + + /** Version: %plugin% v%version% (build: %build%) */ + ABOUT_VERSION("about.version", "%plugin%", "%version%", "%build%"), + + /** Database Implementation: %backend% */ + ABOUT_DATABASE("about.database", "%backend%"), + + /** Authors: */ + ABOUT_AUTHORS_HEADER("about.authors_header"), + + /** Retired authors: */ + ABOUT_RETIRED_HEADER("about.retired_header"), + + /** Developer line (name // mcname (role)) */ + ABOUT_DEVELOPER_LINE("about.developer_line", "%name%", "%mcname%", "%function%"), + + /** (In-Game) suffix when developer is online */ + ABOUT_DEVELOPER_INGAME("about.developer_ingame"), + + /** Website: %url% */ + ABOUT_WEBSITE("about.website", "%url%"), + + /** License: GNU GPL v3.0 */ + ABOUT_LICENSE("about.license"), + + /** Copyright line */ + ABOUT_COPYRIGHT("about.copyright", "%year%"), + + /** AuthMe debug utils */ + DEBUG_COMMAND_TITLE("debug.command_title"), + + /** Sections available to you: */ + DEBUG_COMMAND_SECTIONS_AVAILABLE("debug.command_sections_available"), + + /** - %name%: %description% */ + DEBUG_COMMAND_SECTION_LINE("debug.command_section_line", "%name%", "%description%"), + + /** You don't have permission to view any debug section */ + DEBUG_COMMAND_NO_PERM_ANY("debug.command_no_perm_any"), + + /** You don't have permission for this section. See /authme debug */ + DEBUG_COMMAND_NO_PERM_SECTION("debug.command_no_perm_section"), + + /** AuthMe spawn location viewer */ + DEBUG_SPAWN_TITLE("debug.spawn_title"), + + /** Spawn priority: %list% */ + DEBUG_SPAWN_PRIORITY("debug.spawn_priority", "%list%"), + + /** AuthMe spawn location: %location% */ + DEBUG_SPAWN_LOCATION("debug.spawn_location", "%location%"), + + /** AuthMe first spawn location: %location% */ + DEBUG_SPAWN_FIRST_LOCATION("debug.spawn_first_location", "%location%"), + + /** AuthMe (first)spawn are only used depending on the configured priority! */ + DEBUG_SPAWN_PRIORITY_NOTE("debug.spawn_priority_note"), + + /** Use '/authme debug spawn ?' for further help */ + DEBUG_SPAWN_HELP_HINT("debug.spawn_help_hint"), + + /** Use /authme spawn and /authme firstspawn to teleport to the spawns. */ + DEBUG_SPAWN_HELP_TELEPORT("debug.spawn_help_teleport"), + + /** /authme set(first)spawn sets the (first) spawn to your current location. */ + DEBUG_SPAWN_HELP_SET("debug.spawn_help_set"), + + /** Use /authme debug spawn to view where a player would be teleported to. */ + DEBUG_SPAWN_HELP_PLAYER("debug.spawn_help_player"), + + /** Read more at wiki URL */ + DEBUG_SPAWN_HELP_WIKI("debug.spawn_help_wiki"), + + /** Player '%player%' is not online! */ + DEBUG_SPAWN_PLAYER_OFFLINE("debug.spawn_player_offline", "%player%"), + + /** Player '%player%' has spawn location: %location% */ + DEBUG_SPAWN_PLAYER_LOCATION("debug.spawn_player_location", "%player%", "%location%"), + + /** Note: this check excludes the AuthMe firstspawn. */ + DEBUG_SPAWN_PLAYER_NOTE("debug.spawn_player_note"), + + /** AuthMe test email sender */ + DEBUG_MAIL_TITLE("debug.mail_title"), + + /** Email config incomplete */ + DEBUG_MAIL_CONFIG_INCOMPLETE("debug.mail_config_incomplete"), + + /** Test email sent to %email% with success */ + DEBUG_MAIL_SENT("debug.mail_sent", "%email%"), + + /** Failed to send test mail to %email% */ + DEBUG_MAIL_FAILED("debug.mail_failed", "%email%"), + + /** Please provide an email address */ + DEBUG_MAIL_PROVIDE_ADDRESS("debug.mail_provide_address"), + + /** No email set for your account */ + DEBUG_MAIL_NO_ACCOUNT_EMAIL("debug.mail_no_account_email"), + + /** Invalid email usage */ + DEBUG_MAIL_INVALID("debug.mail_invalid"), + + /** AuthMe test email (subject) */ + DEBUG_MAIL_SUBJECT("debug.mail_subject"), + + /** Sample HTML email body */ + DEBUG_MAIL_BODY("debug.mail_body", "%server%"), + + /** AuthMe database viewer */ + DEBUG_DB_TITLE("debug.db_title"), + + /** Enter player name to view his data in the database. */ + DEBUG_DB_ENTER_NAME("debug.db_enter_name"), + + /** Example: /authme debug db Bobby */ + DEBUG_DB_EXAMPLE("debug.db_example"), + + /** No record exists for '%name%' */ + DEBUG_DB_NO_RECORD("debug.db_no_record", "%name%"), + + /** [AuthMe] Player %nick% / %realname% */ + DEBUG_DB_PLAYER_HEADER("debug.db_player_header", "%nick%", "%realname%"), + + /** Email / IP / Group summary line */ + DEBUG_DB_SUMMARY("debug.db_summary", "%email%", "%ip%", "%group%"), + + /** Quit location: %location% */ + DEBUG_DB_QUIT_LOC("debug.db_quit_location", "%location%"), + + /** Last login: %date% */ + DEBUG_DB_LAST_LOGIN("debug.db_last_login", "%date%"), + + /** Registration: %date% with IP %regip% */ + DEBUG_DB_REGISTRATION("debug.db_registration", "%date%", "%regip%"), + + /** Hash / salt (partial) */ + DEBUG_DB_HASH("debug.db_hash", "%hash%", "%salt%"), + + /** TOTP code (partial) */ + DEBUG_DB_TOTP("debug.db_totp", "%totp%"), + + /** Not available (null) */ + DEBUG_DB_DATE_NULL("debug.db_date_null"), + + /** Not available (0) */ + DEBUG_DB_DATE_ZERO("debug.db_date_zero"), + + /** AuthMe permission groups */ + DEBUG_GROUPS_TITLE("debug.groups_title"), + + /** Player %name% could not be found */ + DEBUG_GROUPS_PLAYER_NOT_FOUND("debug.groups_player_not_found", "%name%"), + + /** Player %name% has permission groups: %groups% */ + DEBUG_GROUPS_LIST("debug.groups_list", "%name%", "%groups%"), + + /** Primary group is: %primary% */ + DEBUG_GROUPS_PRIMARY("debug.groups_primary", "%primary%"), + + /** Defaults can be changed for the MySQL data source only. */ + DEBUG_MYSQL_NON_MYSQL("debug.mysql_non_mysql"), + + /** [AuthMe] MySQL change '%column%' */ + DEBUG_MYSQL_CHANGE_HEADER("debug.mysql_change_header", "%column%"), + + /** Replaced NULLs with default value */ + DEBUG_MYSQL_REPLACED_NULLS("debug.mysql_replaced_nulls", "%value%", "%rows%"), + + /** Changed column NOT NULL */ + DEBUG_MYSQL_NOT_NULL_SET("debug.mysql_not_null_set", "%column%"), + + /** Changed column to allow nulls */ + DEBUG_MYSQL_ALLOW_NULLS("debug.mysql_allow_nulls", "%column%"), + + /** Replaced default value to NULL */ + DEBUG_MYSQL_REPLACED_DEFAULT_NULL("debug.mysql_replaced_default_null", "%value%", "%rows%"), + + /** MySQL column details */ + DEBUG_MYSQL_DETAILS_TITLE("debug.mysql_details_title"), + + /** Failed while showing column details */ + DEBUG_MYSQL_DETAILS_FAILED("debug.mysql_details_failed"), + + /** MySQL column changer title */ + DEBUG_MYSQL_USAGE_TITLE("debug.mysql_usage_title"), + + /** Adds or removes a NOT NULL constraint for a column. */ + DEBUG_MYSQL_USAGE_INTRO("debug.mysql_usage_intro"), + + /** Example add line */ + DEBUG_MYSQL_USAGE_EXAMPLE_ADD("debug.mysql_usage_example_add"), + + /** Example add command */ + DEBUG_MYSQL_USAGE_EXAMPLE_ADD_CMD("debug.mysql_usage_example_add_cmd"), + + /** Example remove line */ + DEBUG_MYSQL_USAGE_EXAMPLE_REMOVE("debug.mysql_usage_example_remove"), + + /** Available columns: %columns% */ + DEBUG_MYSQL_AVAILABLE_COLS("debug.mysql_available_columns", "%columns%"), + + /** Legend for @ and # suffixes */ + DEBUG_MYSQL_LEGEND("debug.mysql_legend"), + + /** Column list error */ + DEBUG_MYSQL_COL_LIST_ERROR("debug.mysql_column_list_error"), + + /** NOT NULL state text */ + DEBUG_MYSQL_COL_STATE_NOT_NULL("debug.mysql_col_state_not_null"), + + /** nullable state text */ + DEBUG_MYSQL_COL_STATE_NULLABLE("debug.mysql_col_state_nullable"), + + /** no default */ + DEBUG_MYSQL_COL_NO_DEFAULT("debug.mysql_col_no_default"), + + /** default: '%value%' */ + DEBUG_MYSQL_COL_DEFAULT("debug.mysql_col_default", "%value%"), + + /** Full detail row: %prefix% (%columnName%): %nullState%, %defaultClause% */ + DEBUG_MYSQL_COL_ROW("debug.mysql_col_row", "%prefix%", "%columnName%", "%nullState%", "%defaultClause%"), + + /** AuthMe limbo viewer */ + DEBUG_LIMBO_TITLE("debug.limbo_title"), + + /** /authme debug limbo usage */ + DEBUG_LIMBO_USAGE("debug.limbo_usage"), + + /** Available limbo records: %records% */ + DEBUG_LIMBO_AVAILABLE("debug.limbo_available", "%records%"), + + /** No AuthMe limbo data */ + DEBUG_LIMBO_NO_DATA_TITLE("debug.limbo_no_data_title"), + + /** No limbo data and no player online */ + DEBUG_LIMBO_NO_DATA_DETAIL("debug.limbo_no_data_detail", "%name%"), + + /** Player / limbo / disk header */ + DEBUG_LIMBO_INFO_HEADER("debug.limbo_info_header", "%name%"), + + /** Note: no Limbo information available */ + DEBUG_LIMBO_NOTE_MEMORY("debug.limbo_note_memory"), + + /** Note: player is not online */ + DEBUG_LIMBO_NOTE_OFFLINE("debug.limbo_note_offline"), + + /** Note: no Limbo on disk available */ + DEBUG_LIMBO_NOTE_DISK("debug.limbo_note_disk"), + + /** %title%: %player% / %memory% / %disk% */ + DEBUG_LIMBO_ROW("debug.limbo_row", "%title%", "%player%", "%memory%", "%disk%"), + + /** Is op */ + DEBUG_LIMBO_FIELD_IS_OP("debug.limbo_field_is_op"), + + /** Walk speed */ + DEBUG_LIMBO_FIELD_WALK_SPEED("debug.limbo_field_walk_speed"), + + /** Can fly */ + DEBUG_LIMBO_FIELD_CAN_FLY("debug.limbo_field_can_fly"), + + /** Fly speed */ + DEBUG_LIMBO_FIELD_FLY_SPEED("debug.limbo_field_fly_speed"), + + /** Location */ + DEBUG_LIMBO_FIELD_LOCATION("debug.limbo_field_location"), + + /** Prim. group */ + DEBUG_LIMBO_FIELD_PRIMARY_GROUP("debug.limbo_field_primary_group"), + + /** Validation tests */ + DEBUG_VALID_TITLE("debug.valid_title"), + + /** Intro for validation command */ + DEBUG_VALID_INTRO("debug.valid_intro"), + + /** Use ... pass */ + DEBUG_VALID_PASS_USAGE("debug.valid_pass_usage"), + + /** Use ... mail */ + DEBUG_VALID_MAIL_USAGE("debug.valid_mail_usage"), + + /** Use ... name */ + DEBUG_VALID_NAME_USAGE("debug.valid_name_usage"), + + /** Validation of password '%password%' */ + DEBUG_VALID_VALIDATE_PASSWORD("debug.valid_validate_password", "%password%"), + + /** Valid password! */ + DEBUG_VALID_VALID_PASSWORD("debug.valid_valid_password"), + + /** Validation of email '%email%' */ + DEBUG_VALID_VALIDATE_EMAIL("debug.valid_validate_email", "%email%"), + + /** Valid email! */ + DEBUG_VALID_VALID_EMAIL("debug.valid_valid_email"), + + /** Email is not valid! */ + DEBUG_VALID_INVALID_EMAIL("debug.valid_invalid_email"), + + /** Validation of username '%name%' */ + DEBUG_VALID_VALIDATE_NAME("debug.valid_validate_name", "%name%"), + + /** Valid username! */ + DEBUG_VALID_VALID_NAME("debug.valid_valid_name"), + + /** AuthMe permission check */ + DEBUG_PERM_TITLE("debug.perm_title"), + + /** Check if a player has permission: */ + DEBUG_PERM_USAGE_LINE1("debug.perm_usage_line1"), + + /** Example: /authme debug perm bobby my.perm.node */ + DEBUG_PERM_USAGE_EXAMPLE("debug.perm_usage_example"), + + /** Permission system type used: %system% */ + DEBUG_PERM_SYSTEM("debug.perm_system", "%system%"), + + /** Player does not exist */ + DEBUG_PERM_PLAYER_NOT_EXIST("debug.perm_player_not_exist", "%player%"), + + /** Player not online; checking offline */ + DEBUG_PERM_OFFLINE_CHECK("debug.perm_offline_check", "%player%"), + + /** Success: player has permission */ + DEBUG_PERM_SUCCESS("debug.perm_success", "%player%", "%node%"), + + /** Check failed: player does NOT have permission */ + DEBUG_PERM_FAIL("debug.perm_fail", "%player%", "%node%"), + + /** Did not detect AuthMe permission; using default permission = DENIED */ + DEBUG_PERM_DEFAULT_DENIED("debug.perm_default_denied"), + + /** AuthMe country lookup */ + DEBUG_CTY_TITLE("debug.cty_title"), + + /** Check player usage */ + DEBUG_CTY_USAGE_PLAYER("debug.cty_usage_player"), + + /** Check IP usage */ + DEBUG_CTY_USAGE_IP("debug.cty_usage_ip"), + + /** IP maps to country */ + DEBUG_CTY_IP_INFO("debug.cty_ip_info", "%ip%", "%code%", "%country%"), + + /** Country is not blocked */ + DEBUG_CTY_NOT_BLOCKED("debug.cty_not_blocked"), + + /** Country is blocked */ + DEBUG_CTY_BLOCKED("debug.cty_blocked"), + + /** Note about enableProtection */ + DEBUG_CTY_NOTE("debug.cty_note", "%setting%"), + + /** No player with name */ + DEBUG_CTY_NO_PLAYER("debug.cty_no_player", "%name%"), + + /** No last IP known */ + DEBUG_CTY_NO_IP("debug.cty_no_ip", "%name%"), + + /** Player has IP address */ + DEBUG_CTY_PLAYER_IP("debug.cty_player_ip", "%name%", "%ip%"), + + /** AuthMe statistics */ + DEBUG_STATS_TITLE("debug.stats_title"), + + /** LimboPlayers in memory */ + DEBUG_STATS_LIMBO("debug.stats_limbo", "%count%"), + + /** PlayerCache size */ + DEBUG_STATS_CACHE("debug.stats_cache", "%count%"), + + /** Total players in DB */ + DEBUG_STATS_DB_TOTAL("debug.stats_db_total", "%count%"), + + /** Cached PlayerAuth objects */ + DEBUG_STATS_CACHE_OBJS("debug.stats_cache_objs", "%count%"), + + /** Total logger instances */ + DEBUG_STATS_LOGGERS("debug.stats_loggers", "%count%"), + + /** Singleton Java classes */ + DEBUG_STATS_SINGLETONS("debug.stats_singletons", "%count%"), + + /** Reloadable / SettingsDependent / HasCleanup */ + DEBUG_STATS_INJECTOR_BREAKDOWN("debug.stats_injector_breakdown", "%reloadable%", "%settingsDep%", "%cleanup%"), + + /** Player only! Please use %command% instead. */ + PLAYER_ONLY_ALTERNATIVE("admin.player_only_alternative", "%command%"), + + /** This command is only for players. */ + PLAYER_ONLY("admin.player_only"); private String key; diff --git a/src/main/java/fr/xephi/authme/message/updater/MessageUpdater.java b/src/main/java/fr/xephi/authme/message/updater/MessageUpdater.java index f3f718c889..d09830935e 100644 --- a/src/main/java/fr/xephi/authme/message/updater/MessageUpdater.java +++ b/src/main/java/fr/xephi/authme/message/updater/MessageUpdater.java @@ -152,6 +152,9 @@ public static MessageKeyConfigurationData createConfigurationData() { .put("bedrock_auto_login", "3rd party features: Bedrock Auto Login") .put("login_location_fix", "3rd party features: Login Location Fix") .put("double_login_fix", "3rd party features: Double Login Fix") + .put("about", "/authme about") + .put("debug", "/authme debug") + .put("admin", "Staff command feedback (/authme, console)") .build(); Set addedKeys = new HashSet<>(); diff --git a/src/main/java/fr/xephi/authme/service/BackupService.java b/src/main/java/fr/xephi/authme/service/BackupService.java index 3e570c3d5f..da87467f58 100644 --- a/src/main/java/fr/xephi/authme/service/BackupService.java +++ b/src/main/java/fr/xephi/authme/service/BackupService.java @@ -4,11 +4,14 @@ import fr.xephi.authme.datasource.DataSourceType; import fr.xephi.authme.initialization.DataFolder; import fr.xephi.authme.mail.EmailService; +import fr.xephi.authme.message.MessageKey; +import fr.xephi.authme.message.Messages; import fr.xephi.authme.output.ConsoleLoggerFactory; import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.properties.BackupSettings; import fr.xephi.authme.settings.properties.DatabaseSettings; import fr.xephi.authme.util.FileUtils; +import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import javax.inject.Inject; @@ -33,6 +36,7 @@ public class BackupService { private final File dataFolder; private final File backupFolder; private final Settings settings; + private final Messages messages; /** @@ -42,10 +46,11 @@ public class BackupService { * @param settings the plugin settings */ @Inject - public BackupService(@DataFolder File dataFolder, Settings settings) { + public BackupService(@DataFolder File dataFolder, Settings settings, Messages messages) { this.dataFolder = dataFolder; this.backupFolder = new File(dataFolder, "backups"); this.settings = settings; + this.messages = messages; } /** @@ -67,8 +72,9 @@ public void doBackup(BackupCause cause, CommandSender sender) { if (!settings.getProperty(BackupSettings.ENABLED)) { // Print a warning if the backup was requested via command or by another plugin if (cause == BackupCause.COMMAND || cause == BackupCause.OTHER) { + CommandSender audience = sender != null ? sender : Bukkit.getConsoleSender(); logAndSendWarning(sender, - "Can't perform a backup: disabled in configuration. Cause of the backup: " + cause.name()); + messages.retrieveSingle(audience, MessageKey.BACKUP_DISABLED, cause.name())); } return; } else if (BackupCause.START == cause && !settings.getProperty(BackupSettings.ON_SERVER_START) @@ -78,11 +84,13 @@ public void doBackup(BackupCause cause, CommandSender sender) { } // Do backup and check return value! + CommandSender audience = sender != null ? sender : Bukkit.getConsoleSender(); if (doBackup()) { logAndSendMessage(sender, - "A backup has been performed successfully. Cause of the backup: " + cause.name()); + messages.retrieveSingle(audience, MessageKey.BACKUP_SUCCESS, cause.name())); } else { - logAndSendWarning(sender, "Error while performing a backup! Cause of the backup: " + cause.name()); + logAndSendWarning(sender, + messages.retrieveSingle(audience, MessageKey.BACKUP_FAILED, cause.name())); } } diff --git a/src/main/java/fr/xephi/authme/service/CommonService.java b/src/main/java/fr/xephi/authme/service/CommonService.java index 92a49267b1..843a87f104 100644 --- a/src/main/java/fr/xephi/authme/service/CommonService.java +++ b/src/main/java/fr/xephi/authme/service/CommonService.java @@ -71,6 +71,18 @@ public String retrieveSingleMessage(CommandSender sender, MessageKey key) { return messages.retrieveSingle(sender, key); } + /** + * Retrieves a message in one piece with tag replacements. + * + * @param sender the command sender (for locale-aware messages) + * @param key the message key + * @param replacements replacements for the message tags + * @return the message + */ + public String retrieveSingleMessage(CommandSender sender, MessageKey key, String... replacements) { + return messages.retrieveSingle(sender, key, replacements); + } + /** * Checks whether the player has the given permission. * diff --git a/src/main/java/fr/xephi/authme/service/TeleportationService.java b/src/main/java/fr/xephi/authme/service/TeleportationService.java index 4693d1fd6b..9aab0a0152 100644 --- a/src/main/java/fr/xephi/authme/service/TeleportationService.java +++ b/src/main/java/fr/xephi/authme/service/TeleportationService.java @@ -74,25 +74,38 @@ public void teleportOnJoin(final Player player) { } /** - * Returns the player's custom on join location. + * Returns the player's custom on-join spawn location during the join configuration phase. + *

+ * Prefer this overload when the {@link Player} entity must not be used (Paper + * {@code AsyncPlayerSpawnLocationEvent}): use the connection profile name and the vanilla spawn + * from the event as world context. * - * @param player the player to process - * - * @return the custom spawn location, null if the player should spawn at the original location + * @param playerName case-sensitive name from profile / safe join APIs + * @param vanillaSpawnLocation server default spawn for this join (world context); not null + * @return custom spawn, or null to keep vanilla spawn */ - public Location prepareOnJoinSpawnLocation(final Player player) { + public Location prepareOnJoinSpawnLocation(String playerName, Location vanillaSpawnLocation) { if (!settings.getProperty(RestrictionSettings.NO_TELEPORT) && settings.getProperty(TELEPORT_UNAUTHED_TO_SPAWN)) { - final Location location = spawnLoader.getSpawnLocation(player); - - SpawnTeleportEvent event = new SpawnTeleportEvent(player, location, - playerCache.isAuthenticated(player.getName())); - bukkitService.callEvent(event); - if (!isEventValid(event)) { + if (playerName == null || vanillaSpawnLocation == null || vanillaSpawnLocation.getWorld() == null) { return null; } + final Location location = spawnLoader.getSpawnLocationForWorld(vanillaSpawnLocation.getWorld()); + if (location == null) { + return null; + } + + Player player = bukkitService.getPlayerExact(playerName); + if (player != null) { + SpawnTeleportEvent event = new SpawnTeleportEvent(player, location, + playerCache.isAuthenticated(playerName)); + bukkitService.callEvent(event); + if (!isEventValid(event)) { + return null; + } + } - logger.debug("Returning custom location for >1.9 join event for player `{0}`", player.getName()); + logger.debug("Returning custom location for join spawn event for player `{0}`", playerName); return location; } return null; diff --git a/src/main/java/fr/xephi/authme/settings/SpawnLoader.java b/src/main/java/fr/xephi/authme/settings/SpawnLoader.java index 47e9711de2..959c37d6b3 100644 --- a/src/main/java/fr/xephi/authme/settings/SpawnLoader.java +++ b/src/main/java/fr/xephi/authme/settings/SpawnLoader.java @@ -174,29 +174,43 @@ public Location getSpawnLocation(Player player) { if (player == null || player.getWorld() == null) { return null; } + return getSpawnLocationForWorld(player.getWorld()); + } + + /** + * Resolves the configured spawn location for the given world (same rules as {@link #getSpawnLocation(Player)}). + * Used when no fully valid {@link Player} entity is available (e.g. Paper {@code AsyncPlayerSpawnLocationEvent}). + * + * @param world the world context (typically from the join / vanilla spawn location) + * @return spawn location, or null if world is null + */ + public Location getSpawnLocationForWorld(World world) { + if (world == null) { + return null; + } - World world = player.getWorld(); + World mutableWorld = world; Location spawnLoc = null; for (String priority : spawnPriority) { switch (priority.toLowerCase(Locale.ROOT).trim()) { case "default": - if (world.getSpawnLocation() != null) { - if (!isValidSpawnPoint(world.getSpawnLocation())) { + if (mutableWorld.getSpawnLocation() != null) { + if (!isValidSpawnPoint(mutableWorld.getSpawnLocation())) { for (World spawnWorld : Bukkit.getWorlds()) { if (isValidSpawnPoint(spawnWorld.getSpawnLocation())) { - world = spawnWorld; + mutableWorld = spawnWorld; break; } } logger.warning("Seems like AuthMe is unable to find a proper spawn location. " + "Set a location with the command '/authme setspawn'"); } - spawnLoc = world.getSpawnLocation(); + spawnLoc = mutableWorld.getSpawnLocation(); } break; case "multiverse": if (settings.getProperty(HooksSettings.MULTIVERSE)) { - spawnLoc = pluginHookService.getMultiverseSpawn(world); + spawnLoc = pluginHookService.getMultiverseSpawn(mutableWorld); } break; case "essentials": @@ -212,13 +226,13 @@ public Location getSpawnLocation(Player player) { // ignore } if (spawnLoc != null) { - logger.debug("Spawn location determined as `{0}` for world `{1}`", spawnLoc, world.getName()); + logger.debug("Spawn location determined as `{0}` for world `{1}`", spawnLoc, mutableWorld.getName()); return spawnLoc; } } - logger.debug("Fall back to default world spawn location. World: `{0}`", world.getName()); + logger.debug("Fall back to default world spawn location. World: `{0}`", mutableWorld.getName()); - return world.getSpawnLocation(); // return default location + return mutableWorld.getSpawnLocation(); // return default location } /** diff --git a/src/main/java/fr/xephi/authme/task/purge/PurgeService.java b/src/main/java/fr/xephi/authme/task/purge/PurgeService.java index 880d51185a..52e836a04e 100644 --- a/src/main/java/fr/xephi/authme/task/purge/PurgeService.java +++ b/src/main/java/fr/xephi/authme/task/purge/PurgeService.java @@ -2,12 +2,15 @@ import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.datasource.DataSource; +import fr.xephi.authme.message.MessageKey; +import fr.xephi.authme.message.Messages; import fr.xephi.authme.output.ConsoleLoggerFactory; import fr.xephi.authme.permission.PermissionsManager; import fr.xephi.authme.service.BukkitService; import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.properties.PurgeSettings; import fr.xephi.authme.util.Utils; +import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; import org.bukkit.command.CommandSender; @@ -40,6 +43,9 @@ public class PurgeService { @Inject private PurgeExecutor purgeExecutor; + @Inject + private Messages messages; + /** Keeps track of whether a purge task is currently running. */ private boolean isPurging = false; @@ -77,7 +83,8 @@ public void runPurge(CommandSender sender, long until) { //todo: note this should may run async because it may executes a SQL-Query Set toPurge = dataSource.getRecordsToPurge(until); if (Utils.isCollectionEmpty(toPurge)) { - logAndSendMessage(sender, "No players to purge"); + logAndSendMessage(sender, + messages.retrieveSingle(resolveSender(sender), MessageKey.PURGE_NO_PLAYERS)); return; } @@ -93,12 +100,13 @@ public void runPurge(CommandSender sender, long until) { */ public void purgePlayers(CommandSender sender, Set names, OfflinePlayer[] players) { if (isPurging) { - logAndSendMessage(sender, "Purge is already in progress! Aborting purge request"); + logAndSendMessage(sender, + messages.retrieveSingle(resolveSender(sender), MessageKey.PURGE_ALREADY_RUNNING)); return; } isPurging = true; - PurgeTask purgeTask = new PurgeTask(this, permissionsManager, sender, names, players); + PurgeTask purgeTask = new PurgeTask(this, permissionsManager, sender, names, players, messages); bukkitService.runTaskTimerAsynchronously(purgeTask, 0, 1); } @@ -107,6 +115,10 @@ public void purgePlayers(CommandSender sender, Set names, OfflinePlayer[ * * @param purging True if purging. */ + private static CommandSender resolveSender(CommandSender sender) { + return sender != null ? sender : Bukkit.getConsoleSender(); + } + void setPurging(boolean purging) { this.isPurging = purging; } diff --git a/src/main/java/fr/xephi/authme/task/purge/PurgeTask.java b/src/main/java/fr/xephi/authme/task/purge/PurgeTask.java index 15ab6552cf..5997975f93 100644 --- a/src/main/java/fr/xephi/authme/task/purge/PurgeTask.java +++ b/src/main/java/fr/xephi/authme/task/purge/PurgeTask.java @@ -2,11 +2,12 @@ import com.github.Anon8281.universalScheduler.UniversalRunnable; import fr.xephi.authme.ConsoleLogger; +import fr.xephi.authme.message.MessageKey; +import fr.xephi.authme.message.Messages; import fr.xephi.authme.output.ConsoleLoggerFactory; import fr.xephi.authme.permission.PermissionsManager; import fr.xephi.authme.permission.PlayerStatePermission; import org.bukkit.Bukkit; -import org.bukkit.ChatColor; import org.bukkit.OfflinePlayer; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -29,6 +30,7 @@ class PurgeTask extends UniversalRunnable { private final OfflinePlayer[] offlinePlayers; private final int totalPurgeCount; + private final Messages messages; private int currentPage = 0; @@ -42,9 +44,10 @@ class PurgeTask extends UniversalRunnable { * @param offlinePlayers offline players to map to the names */ PurgeTask(PurgeService service, PermissionsManager permissionsManager, CommandSender sender, - Set toPurge, OfflinePlayer[] offlinePlayers) { + Set toPurge, OfflinePlayer[] offlinePlayers, Messages messages) { this.purgeService = service; this.permissionsManager = permissionsManager; + this.messages = messages; if (sender instanceof Player) { this.sender = ((Player) sender).getUniqueId(); @@ -103,7 +106,8 @@ public void run() { purgeService.executePurge(playerPortion, namePortion); if (currentPage % 20 == 0) { int completed = totalPurgeCount - toPurge.size(); - sendMessage("[AuthMe] Purge progress " + completed + '/' + totalPurgeCount); + sendMessage(messages.retrieveSingle(resolveSender(), MessageKey.PURGE_PROGRESS, + String.valueOf(completed), String.valueOf(totalPurgeCount))); } } @@ -111,17 +115,25 @@ private void finish() { cancel(); // Show a status message - sendMessage(ChatColor.GREEN + "[AuthMe] Database has been purged successfully"); + sendMessage(messages.retrieveSingle(resolveSender(), MessageKey.PURGE_DATABASE_SUCCESS)); logger.info("Purge finished!"); purgeService.setPurging(false); } - private void sendMessage(String message) { + private CommandSender resolveSender() { if (sender == null) { + return Bukkit.getConsoleSender(); + } + Player player = Bukkit.getPlayer(sender); + return player != null ? player : Bukkit.getConsoleSender(); + } + + private void sendMessage(String message) { + if (this.sender == null) { Bukkit.getConsoleSender().sendMessage(message); } else { - Player player = Bukkit.getPlayer(sender); + Player player = Bukkit.getPlayer(this.sender); if (player != null) { player.sendMessage(message); } diff --git a/src/main/resources/messages/help_br.yml b/src/main/resources/messages/help_br.yml index 818daf57ad..dcad29d48e 100644 --- a/src/main/resources/messages/help_br.yml +++ b/src/main/resources/messages/help_br.yml @@ -1,46 +1,48 @@ -# Arquivo de tradução da ajuda do AuthMe (comando /authme help) -# Tradução por Frani (PotterCraft_) e RenanYudi +# Tradução da ajuda do AuthMe (/authme help, /authme help ) +# Baseado em help_en.yml — revisão e chaves novas alinhadas ao EN +# Créditos anteriores: Frani (PotterCraft_), RenanYudi # ------------------------------------------------------- -# Lista de textos usados na seção de ajuda: +# Textos comuns da ajuda common: - header: '==========[ Ajuda AuthMeReloaded ]==========' - optional: 'Opcional' - hasPermission: 'Você tem permissão' - noPermission: 'Sem permissão' - default: 'Padrão' - result: 'Resultado' - defaultPermissions: - notAllowed: 'Sem permissão' - opOnly: 'Apenas jogadores com OP' - allowed: 'Todos tem permissão' + header: '==========[ Ajuda AuthMeReloaded ]==========' + optional: 'Opcional' + hasPermission: 'Você tem permissão' + noPermission: 'Sem permissão' + default: 'Padrão' + result: 'Resultado' + defaultPermissions: + notAllowed: 'Sem permissão' + opOnly: 'Apenas OP' + allowed: 'Todos podem usar' + helpFailedRetrieveInfo: '&4Não foi possível obter informações de ajuda!' + helpMissingBaseCommand: '&4Não foi possível obter o comando base' + helpUnknownCommand: '&4Comando desconhecido' + helpAssumingCommand: '&6Assumindo &f%command%' # ------------------------------------------------------- -# Títulos das seções individuais de ajuda -# Deixe o texto traduzido vazio para desativá-lo/esconde-lo -# alternatives: '' +# Títulos das seções de ajuda +# Texto vazio desativa a seção (ex.: alternatives: '') section: - command: 'Comando' - description: 'Descrição breve' - detailedDescription: 'Descrição detalhada' - arguments: 'Argumentos' - permissions: 'Permissões' - alternatives: 'Alternativas' - children: 'Comandos' + command: 'Comando' + description: 'Descrição breve' + detailedDescription: 'Descrição detalhada' + arguments: 'Argumentos' + permissions: 'Permissões' + alternatives: 'Alternativas' + children: 'Comandos' # ------------------------------------------------------- -# Você pode traduzir o help de qualquer comando usando o padrão abaixo -# Por exemplo, para traduzir /authme reload, crie uma seção "authme.reload", ou "login" para /login -# Se o comando usa argumentos, você pode usar arg1 para traduzir o primeiro argumento e assim em diante, como exemplificado abaixo -# As traduções não precisam ser completas, qualquer parte faltante será obtida da configuração padrão. -# OBS: Coloque os comandos principais, como "authme" antes de seus subcomandos (como "authme.reload") +# Tradução por comando: ex. authme.reload para /authme reload, login para /login +# Use arg1, arg2... para argumentos. Chaves em falta usam o idioma padrão. +# Coloque comandos pai (ex.: authme) antes dos filhos (ex.: authme.reload). commands: - authme.register: - description: 'Registra um jogador' - detailedDescription: 'Registra um jogador específico com uma senha específica.' - arg1: - label: 'player' - description: 'Nome do jogador' - arg2: - label: 'password' - description: 'Senha' + authme.register: + description: 'Registrar um jogador' + detailedDescription: 'Registra o jogador indicado com a senha indicada.' + arg1: + label: 'jogador' + description: 'Nome do jogador' + arg2: + label: 'senha' + description: 'Senha' diff --git a/src/main/resources/messages/help_en.yml b/src/main/resources/messages/help_en.yml index bcc501b7f9..318a612f61 100644 --- a/src/main/resources/messages/help_en.yml +++ b/src/main/resources/messages/help_en.yml @@ -13,6 +13,10 @@ common: notAllowed: 'No permission' opOnly: 'OP''s only' allowed: 'Everyone allowed' + helpFailedRetrieveInfo: '&4Failed to retrieve any help information!' + helpMissingBaseCommand: '&4Could not get base command' + helpUnknownCommand: '&4Unknown command' + helpAssumingCommand: '&6Assuming &f%command%' # ------------------------------------------------------- # Titles of the individual help sections diff --git a/src/main/resources/messages/messages_br.yml b/src/main/resources/messages/messages_br.yml index 396008bce8..4d2b43f88b 100644 --- a/src/main/resources/messages/messages_br.yml +++ b/src/main/resources/messages/messages_br.yml @@ -1,143 +1,150 @@ -# AuthMe Reloaded | Tradução pt-br -# Por Eufranio, GabrielDev (DeathRush) e RenanYudi +# AuthMe ReReloaded — Português (Brasil) +# Baseado em messages_en.yml — mesmas chaves; respeite as tags exatas de cada mensagem no MessageKey.java +# Contribuições anteriores: Eufranio, GabrielDev (DeathRush), RenanYudi # -# Lista de tags globais: -# %nl% - Pula uma linha -# %username% - Substitui pelo nome do jogador que está recebendo a mensagem -# %displayname% - Substitui pelo nickname (e cores) do jogador que está recebendo a mensagem +# Tags globais: +# %nl% — nova linha +# %username% — nome de quem recebe a mensagem +# %displayname% — apelido (com cores) de quem recebe # Registro registration: - disabled: '&cRegistrar-se está desativado neste servidor!' - name_taken: '&cVocê já registrou este nome de usuário!' - register_request: '&3Por favor, registre-se com o comando "/register "' - command_usage: '&cUse: /register ' - reg_only: '&4Somente usuários registrados podem entrar no servidor! Por favor visite www.seusite.com para se registrar!' - success: '&2Registrado com sucesso!' - kicked_admin_registered: 'Um administrador registrou você. Por favor, faça login novamente' - -# Erros de senha ao registrar-se + disabled: '&cO registro no jogo está desativado!' + name_taken: '&cVocê já registrou este nome de usuário!' + register_request: '&3Registre-se no servidor com: /register ' + command_usage: '&cUso: /register ' + reg_only: '&4Apenas usuários registrados podem entrar! Visite https://example.com para se registrar!' + success: '&2Registro concluído com sucesso!' + kicked_admin_registered: 'Um administrador acabou de registrar você; faça login novamente.' + +# Erros de senha no registro password: - match_error: '&cAs senhas não coincidem, tente novamente!' - name_in_password: '&Você não pode usar o seu nome como senha. Por favor, escolha outra senha...' - unsafe_password: '&cA senha escolhida não é segura. Por favor, escolha outra senha...' - forbidden_characters: '&Sua senha contém caracteres inválidos. Caracteres permitidos: %valid_chars' - wrong_length: '&cSua senha é muito curta ou muito longa! Por favor, escolha outra senha...' - pwned_password: '&cSua senha escolhida não é segura. Ela foi usada %pwned_count vezes já! Por favor, use uma senha forte...' + match_error: '&cAs senhas não coincidem, verifique e tente de novo!' + name_in_password: '&cVocê não pode usar seu nome como senha; escolha outra...' + unsafe_password: '&cA senha escolhida não é segura; escolha outra...' + forbidden_characters: '&4Sua senha contém caracteres não permitidos. Permitidos: %valid_chars' + wrong_length: '&cSua senha é curta ou longa demais! Tente outra!' + pwned_password: '&cSua senha não é segura. Ela já apareceu %pwned_count vezes em vazamentos! Use uma senha forte...' # Login login: - command_usage: '&cUse: /login ' - wrong_password: '&cSenha incorreta!' - success: '&2Login realizado com sucesso!' - login_request: '&cPor favor, faça login com o comando "/login "' - timeout_error: '&4Tempo limite excedido.' + command_usage: '&cUso: /login ' + wrong_password: '&cSenha incorreta!' + success: '&2Login realizado com sucesso!' + login_request: '&cFaça login com: /login ' + timeout_error: '&4Tempo de login esgotado; você foi expulso do servidor. Tente novamente!' # Erros error: - denied_command: '&cPara utilizar este comando é necessário estar logado!' - denied_chat: '&cPara utilizar o chat é necessário estar logado!' - unregistered_user: '&cEste usuário não está registrado!' - not_logged_in: '&cVocê não está logado!' - no_permission: '&4Você não tem permissão para executar esta ação!' - unexpected_error: '&4Ocorreu um erro inesperado. Por favor contate um administrador!' - max_registration: '&cVocê excedeu o número máximo de registros (%reg_count/%max_acc %reg_names) para o seu IP!' - logged_in: '&cVocê já está logado!' - kick_for_vip: '&3Um jogador VIP juntou-se ao servidor enquanto ele estava cheio!' - kick_unresolved_hostname: '&cErro: hostname do jogador não resolvido!' - tempban_max_logins: '&cVocê foi temporariamente banido por tentar fazer login muitas vezes.' + denied_command: '&cVocê precisa estar autenticado para usar este comando!' + denied_chat: '&cVocê precisa estar autenticado para conversar no chat!' + unregistered_user: '&cEste usuário não está registrado!' + not_logged_in: '&cVocê não está logado!' + no_permission: '&4Você não tem permissão para esta ação!' + unexpected_error: '&4Ocorreu um erro inesperado; contate um administrador!' + max_registration: '&cVocê excedeu o máximo de registros (%reg_count/%max_acc %reg_names) para sua conexão!' + logged_in: '&cVocê já está logado!' + kick_for_vip: '&3Um jogador VIP entrou quando o servidor estava cheio!' + kick_unresolved_hostname: '&cErro: não foi possível resolver o hostname do jogador!' + tempban_max_logins: '&cVocê foi banido temporariamente por falhar o login muitas vezes.' + command_parse_failed: '&4Falha ao interpretar o comando do %plugin%!' + unknown_authme_command: '&4Comando desconhecido!' + command_suggest_similar: '&eQuis dizer &6%command%&e?' + command_use_help: '&eUse &6/%label% help&e para ver a ajuda.' + incorrect_command_arguments: '&4Argumentos do comando incorretos!' + command_detailed_help_syntax: '&6Ajuda detalhada: &f/%label% help %child%' # AntiBot antibot: - kick_antibot: 'O modo de proteção AntiBot está ativo, espere alguns minutos antes de entrar no servidor!' - auto_enabled: '&4O AntiBot foi ativado devido ao grande número de conexões!' - auto_disabled: '&2AntiBot desativado após %m minutos!' + kick_antibot: 'Modo AntiBot ativo! Aguarde alguns minutos antes de entrar no servidor.' + auto_enabled: '&4[AntiBotService] AntiBot ativado devido ao grande número de conexões!' + auto_disabled: '&2[AntiBotService] AntiBot desativado após %m minutos!' -# Deletar conta +# Cancelar registro unregister: - success: '&cConta deletada!' - command_usage: '&cUse: /unregister ' + success: '&cConta removida com sucesso!' + command_usage: '&cUso: /unregister ' # Outras mensagens misc: - account_not_activated: '&cA sua conta ainda não está ativada. Por favor, verifique seus e-mails!' - not_activated: '&cConta não ativada, por favor registre e ative antes de tentar novamente.' - password_changed: '&2Senha alterada com sucesso!' - logout: '&2Desconectado com sucesso!' - reload: '&2A configuração e o banco de dados foram recarregados corretamente!' - usage_change_password: '&cUse: /changepassword ' - accounts_owned_self: 'Você tem %count contas:' - accounts_owned_other: 'O jogador %name tem %count contas:' - -# Mensagens de sessão + account_not_activated: '&cSua conta ainda não está ativada; verifique seu e-mail!' + not_activated: '&cConta não ativada; registre-se e ative antes de tentar de novo.' + password_changed: '&2Senha alterada com sucesso!' + logout: '&2Logout realizado com sucesso!' + reload: '&2Configuração e banco de dados recarregados com sucesso!' + usage_change_password: '&cUso: /changepassword ' + accounts_owned_self: 'Você possui %count contas:' + accounts_owned_other: 'O jogador %name possui %count contas:' + +# Sessão session: - valid_session: '&2Você deslogou recentemente, então sua sessão foi retomada!' - invalid_session: '&fO seu IP foi alterado e sua sessão expirou!' + invalid_session: '&cSeu IP mudou e os dados da sessão expiraram!' + valid_session: '&2Logado novamente por reconexão de sessão.' -# Mensagens de erro ao entrar +# Validação ao entrar on_join_validation: - same_ip_online: 'Um jogador com o mesmo IP já está no servidor!' - same_nick_online: '&4Alguém com o mesmo nome de usuário já está jogando no servidor!' - name_length: '&4Seu nome de usuário ou é muito curto ou é muito longo!' - characters_in_name: '&4Seu nome de usuário contém caracteres inválidos. Caracteres permitidos: %valid_chars' - kick_full_server: '&4O servidor está cheio, tente novamente mais tarde!' - country_banned: '&4O seu país está banido deste servidor!' - not_owner_error: 'Você não é o proprietário da conta. Por favor, escolha outro nome!' - invalid_name_case: 'Você deve entrar usando o nome de usuário %valid, não %invalid.' - quick_command: 'Você usou o comando muito rápido! Por favor, entre no servidor e aguarde antes de usar um comando novamente.' + same_ip_online: 'Já existe um jogador com o mesmo IP no servidor!' + same_nick_online: '&4Este nome de usuário já está no servidor!' + name_length: '&4Seu nome é curto ou longo demais!' + characters_in_name: '&4Seu nome contém caracteres inválidos. Permitidos: %valid_chars' + kick_full_server: '&4Servidor cheio; tente mais tarde!' + country_banned: '&4Seu país não pode entrar neste servidor!' + not_owner_error: 'Você não é o dono desta conta. Escolha outro nome!' + invalid_name_case: 'Entre com o nome %valid, e não %invalid.' + quick_command: 'Você usou um comando rápido demais! Entre de novo e espere antes de usar comandos.' # E-mail email: - add_email_request: '&3Por favor, adicione seu e-mail para a sua conta com o comando "/email add "' - usage_email_add: '&cUse: /email add ' - usage_email_change: '&cUse: /email change ' - new_email_invalid: '&cE-mail novo inválido, tente novamente!' - old_email_invalid: '&cE-mail antigo inválido, tente novamente!' - invalid: '&E-mail inválido, tente novamente!' - added: '&2E-mail adicionado com sucesso!' - add_not_allowed: '&cAdicionar um e-mail não é permitido.' - request_confirmation: '&cPor favor, confirme o seu endereço de e-mail!' - changed: '&2E-mail alterado com sucesso!' - change_not_allowed: '&cAlterar o e-mail não é permitido.' - email_show: '&2O seu endereço de e-mail atual é: &f%email' - no_email_for_account: '&2Você atualmente não têm endereço de e-mail associado a esta conta.' - already_used: '&4O endereço de e-mail já está sendo usado' - incomplete_settings: 'Erro: Nem todas as configurações necessárias estão definidas para o envio de e-mails. Entre em contato com um administrador.' - send_failure: '&cO e-mail não pôde ser enviado, reporte isso a um administrador!' - change_password_expired: 'Você não pode mais usar esse comando de recuperação de senha!' - email_cooldown_error: '&cUm e-mail já foi enviado, espere %time antes de enviar novamente!' - -# Recuperação de senha por e-mail + add_email_request: '&3Adicione um e-mail à conta: /email add ' + usage_email_add: '&cUso: /email add ' + usage_email_change: '&cUso: /email change ' + new_email_invalid: '&cNovo e-mail inválido; tente de novo!' + old_email_invalid: '&cE-mail antigo inválido; tente de novo!' + invalid: '&cEndereço de e-mail inválido; tente de novo!' + added: '&2E-mail adicionado à conta com sucesso!' + add_not_allowed: '&cNão é permitido adicionar e-mail.' + request_confirmation: '&cConfirme seu endereço de e-mail!' + changed: '&2E-mail alterado com sucesso!' + change_not_allowed: '&cNão é permitido alterar o e-mail.' + email_show: '&2Seu e-mail atual: &f%email' + no_email_for_account: '&2Não há e-mail associado a esta conta.' + already_used: '&4Este e-mail já está em uso' + incomplete_settings: 'Erro: faltam configurações para envio de e-mail. Contate um administrador.' + send_failure: 'Não foi possível enviar o e-mail. Contate um administrador.' + change_password_expired: 'Você não pode mais alterar a senha com este comando.' + email_cooldown_error: '&cUm e-mail foi enviado recentemente. Aguarde %time para enviar outro.' + +# Recuperação de senha recovery: - forgot_password_hint: '&3Esqueceu a sua senha? Use o comando "/email recovery "' - command_usage: '&cUse: /email recovery ' - email_sent: '&2E-mail de recuperação enviado! Por favor, verifique sua caixa de entrada!' - code: - code_sent: 'Um código de recuperação para a redefinição de senha foi enviado ao seu e-mail.' - incorrect: 'Código de recuperação inválido! Você tem %count tentativas restantes.' - tries_exceeded: 'Você excedeu o limite de tentativas de usar o código de recuperação! Use "/email recovery [email]" para gerar um novo.' - correct: 'Código de recuperação aceito!' - change_password: 'Por favor, use o comando /email setpassword para alterar sua senha!' + forgot_password_hint: '&3Esqueceu a senha? Use: /email recovery ' + command_usage: '&cUso: /email recovery ' + email_sent: '&2E-mail de recuperação enviado! Verifique sua caixa de entrada!' + code: + code_sent: 'Um código de recuperação foi enviado ao seu e-mail.' + incorrect: 'Código incorreto! Restam %count tentativas.' + tries_exceeded: 'Você excedeu as tentativas do código. Use "/email recovery [email]" para gerar outro.' + correct: 'Código confirmado!' + change_password: 'Use /email setpassword para alterar a senha agora.' # Captcha captcha: - usage_captcha: '&3Para iniciar sessão você tem que resolver um captcha, utilize o comando "/captcha %captcha_code"' - wrong_captcha: '&cCaptcha incorreto. Por favor, escreva "/captcha %captcha_code" no chat!' - valid_captcha: '&2Captcha correto!' - captcha_for_registration: 'Para se registrar você tem que resolver um código captcha, utilize o comando "/captcha %captcha_code"' - register_captcha_valid: '&2Captcha correto! Agora você pode se registrar usando /register !' + usage_captcha: '&3Para logar, resolva o captcha: /captcha %captcha_code' + wrong_captcha: '&cCaptcha errado; digite "/captcha %captcha_code" no chat!' + valid_captcha: '&2Captcha correto!' + captcha_for_registration: 'Para registrar, resolva o captcha: /captcha %captcha_code' + register_captcha_valid: '&2Captcha válido! Agora use /register' # Código de verificação verification: - code_required: '&3Esse comando é sensível e precisa de uma verificação via e-mail! Verifique sua caixa de entrada e siga as instruções do e-mail.' - command_usage: '&cUse: /verification ' - incorrect_code: '&cCódigo incorreto, utilize "/verification " com o código que você recebeu por e-mail!' - success: '&2Sua identidade foi verificada, agora você pode usar todos os comandos durante esta sessão.' - already_verified: '&2Você já pode executar comandos sensíveis durante esta sessão!' - code_expired: '&3O seu código expirou! Execute outro comando sensível para gerar um outro código.' - email_needed: '&3Para verificar sua identidade, você precisa vincular um e-mail à sua conta!' - -# Unidades de tempo + code_required: '&3Este comando é sensível e exige verificação por e-mail! Veja a caixa de entrada.' + command_usage: '&cUso: /verification ' + incorrect_code: '&cCódigo incorreto; use "/verification " com o código recebido por e-mail' + success: '&2Identidade verificada! Você pode usar comandos sensíveis nesta sessão!' + already_verified: '&2Você já pode usar comandos sensíveis nesta sessão!' + code_expired: '&3O código expirou! Execute outro comando sensível para receber um novo.' + email_needed: '&3Para verificar, vincule um e-mail à sua conta!' + +# Tempo time: second: 'segundo' seconds: 'segundos' @@ -148,29 +155,243 @@ time: day: 'dia' days: 'dias' -# Verificação em duas etapas +# Autenticação em duas etapas two_factor: - code_created: '&2O seu código secreto é %code. Você pode verificá-lo aqui %url' - confirmation_required: 'Confirme seu código com /2fa confirm ' - code_required: 'Registre o seu código de verificação em duas etapas com /2fa code ' - already_enabled: 'A verificação em duas etapas já está ativada nesta conta!' - enable_error_no_code: 'Nenhuma chave de verificação foi gerada ou ela expirou. Por favor, use /2fa add' - enable_success: 'Verificação em duas etapas ativada com sucesso para esta conta!' - enable_error_wrong_code: 'Código incorreto ou expirado! Por favor, use /2fa add' - not_enabled_error: 'A verificação em duas etapas não está ativada nesta conta. Use /2fa add' - removed_success: 'Verificação em duas etapas desativada com sucesso!' - invalid_code: 'Código inválido!' - -# 3rd party features: Bedrock Auto Login + code_created: '&2Seu código secreto é %code. Escaneie em %url' + confirmation_required: 'Confirme com /2fa confirm ' + code_required: 'Envie o código 2FA com /2fa code ' + already_enabled: 'Autenticação em duas etapas já está ativa na sua conta!' + enable_error_no_code: 'Nenhuma chave 2FA gerada ou expirou. Use /2fa add' + enable_success: 'Autenticação em duas etapas ativada com sucesso!' + enable_error_wrong_code: 'Código errado ou expirado. Use /2fa add' + not_enabled_error: '2FA não está ativo. Use /2fa add' + removed_success: 'Autenticação em duas etapas removida da conta!' + invalid_code: 'Código inválido!' + +# Bedrock auto login bedrock_auto_login: - success: '&aLogin automático Bedrock bem-sucedido!' + success: '&aLogin automático Bedrock concluído!' -# 3rd party features: Login Location Fix +# Login location fix login_location_fix: - fix_portal: '&aVocê está preso no portal durante o login.' - fix_underground: '&aVocê está preso no subsolo durante o login.' - cannot_fix_underground: '&aVocê está preso no subsolo durante o login, mas não podemos corrigir.' + fix_portal: '&aVocê ficou preso no portal durante o login.' + fix_underground: '&aVocê ficou preso no subsolo durante o login.' + cannot_fix_underground: '&aPreso no subsolo no login; não foi possível corrigir.' -# 3rd party features: Double Login Fix +# Double login fix double_login_fix: - fix_message: '&cVocê foi desconectado devido a login duplo.' + fix_message: '&cDesconectado por login duplicado.' + +# Comandos de staff (/authme, console) +admin: + reload_abort_error: '&4Erro ao recarregar o AuthMe; operação cancelada' + reload_database_type_note: '&eNota: não é possível mudar o tipo de banco no /authme reload' + spawn_failed: '&c[AuthMe] Falha no spawn; defina o spawn' + first_spawn_failed: '&c[AuthMe] Falha no primeiro spawn; defina o primeiro spawn' + set_spawn_success: '&2[AuthMe] Novo spawn definido' + set_spawn_failed: '&c[AuthMe] Falha ao definir spawn; tente de novo' + set_first_spawn_success: '&2[AuthMe] Novo primeiro spawn definido' + set_first_spawn_failed: '&c[AuthMe] Falha ao definir primeiro spawn; tente de novo' + antibot_status: '&e[AuthMe] AntiBot: %status%' + antibot_manual_enabled: '&2[AuthMe] AntiBot manual: ativado!' + antibot_manual_disabled: '&c[AuthMe] AntiBot manual: desativado!' + antibot_invalid_mode: '&4Modo AntiBot inválido!' + antibot_detailed_help: '&6Ajuda detalhada: &f%command%' + purge_player_success: 'Dados do jogador %player% removidos' + purge_player_confirm: 'Este jogador ainda está registrado! Tem certeza? Use ''/authme purgeplayer %player% force'' para forçar' + purge_lastpos_all: 'Última posição de todos os jogadores foi resetada' + purge_lastpos_one: 'Última posição de %player% foi resetada' + force_login_offline: 'O jogador precisa estar online!' + force_login_denied: 'Você não pode forçar login de %player%!' + force_login_success: 'Login forçado para %player%!' + accounts_ip_unknown: '&c[AuthMe] Este IP não existe no banco de dados.' + accounts_single: '&e[AuthMe] %player% usa uma única conta' + accounts_no_last_ip: 'Sem último IP conhecido para o jogador' + accounts_multiple: '&e[AuthMe] %player% tem %count% contas.' + accounts_list: '&e[AuthMe] %list%.' + get_ip_current: 'IP atual de %name%: %ip%:%port%' + get_ip_not_registered: '%name% não está registrado no banco' + get_ip_database: 'Banco: último IP: %lastIp%, IP de registro: %regIp%' + get_email: '&e[AuthMe] E-mail de %player%: %email%' + last_login: '&e[AuthMe] Último login de %player%: %date%' + last_login_interval: '&e[AuthMe] %player% fez login há %interval%' + last_login_ip: '&e[AuthMe] Último IP do jogador: %ip%' + last_login_never: 'nunca' + last_login_interval_parts: '%days% d %hours% h %mins% min %secs% s' + converter_list: 'Conversores: %list%' + converter_started: '&2[AuthMe] Iniciado %name% com sucesso' + totp_not_enabled: '&cO jogador ''%player%'' não tem 2FA ativo' + totp_disabled_success: '2FA desativado para ''%player%''' + help_file_updated: '&2Arquivo de ajuda ''%file%'' atualizado' + help_file_update_failed: '&4Não foi possível atualizar o arquivo de ajuda: %error%' + totp_view_disabled: '&cO jogador ''%player%'' NÃO tem 2FA ativo' + totp_view_enabled: '&2O jogador ''%player%'' tem 2FA ativo' + authme_info_running: '&aServidor com %plugin% v%version% b%build%! &c<3' + authme_info_help: '&eUse &6/authme help&e para ver a ajuda.' + authme_info_about: '&eUse &6/authme about&e para ver informações.' + purge_invalid_value: '&cO valor informado é inválido!' + purge_minimum_days: '&cSó é possível expurgar dados com mais de %days% dias' + purge_no_players: 'Nenhum jogador para expurgar' + purge_already_running: 'Expurgo já em andamento! Solicitação ignorada' + purge_progress: '&e[AuthMe] Expurgo %current%/%total%' + purge_database_success: '&2[AuthMe] Banco expurgado com sucesso' + recent_players_header: '&9[AuthMe] Jogadores que logaram recentemente' + recent_player_line: '&7- %player% (%lastlogin% com IP %ip%)' + backup_disabled: 'Backup desativado na config. Motivo: %cause%' + backup_success: 'Backup concluído com sucesso. Motivo: %cause%' + backup_failed: 'Erro no backup! Motivo: %cause%' + converter_configure_destination: 'Configure a conexão com %type% e execute o comando de novo' + converter_source_init_failed: 'Não foi possível inicializar a origem da conversão' + converter_skipped_existing: 'Ignorados jogadores que já estavam em %type%: %players%' + converter_finished: 'Banco convertido de %source% para %target%' + converter_xauth_class_not_found: 'xAuth não encontrado; coloque xAuth.jar na pasta plugins e reinicie!' + converter_xauth_plugin_not_found: '&c[AuthMe] Plugin xAuth não encontrado' + converter_xauth_h2_missing: '&e[AuthMe] Banco H2 do xAuth não encontrado; verificando MySQL ou SQLite...' + converter_xauth_no_players: '&c[AuthMe] Erro ao importar xAuthPlayers: nenhum jogador encontrado' + converter_xauth_starting: '&e[AuthMe] Iniciando importação...' + converter_xauth_success: '&2[AuthMe] Conversão do xAuth concluída' + converter_crazylogin_file_not_found: 'Arquivo CrazyLogin não encontrado; coloque %file% na pasta do AuthMe!' + converter_loginsecurity_failed: 'Falha ao converter do SQLite. Veja o log' + converter_loginsecurity_migrated: '%count% contas migradas do LoginSecurity' + converter_loginsecurity_skipped: 'Ignorados jogadores já no AuthMe: %players%' + converter_loginsecurity_file_missing: 'O arquivo ''%path%'' não existe' + converter_loginsecurity_mysql_unconfigured: 'Banco ou usuário do LoginSecurity não configurado no config.yml do AuthMe' + converter_loginsecurity_connect_failed: 'Falha ao conectar ao LoginSecurity (Sqlite = %sqlite%); veja o log' + player_only_alternative: 'Apenas jogadores! Use %command%.' + player_only: 'Este comando é só para jogadores.' + +# /authme about +about: + header: '&6==========[ &f%plugin% &6SOBRE ]==========' + version: '&6Versão: &f%plugin% v%version%&7 (build: %build%)' + database: '&6Banco de dados: &f%backend%' + authors_header: '&6Autores:' + retired_header: '&6Autores aposentados:' + developer_line: ' &f%name%&7 // &f%mcname%&7&o (%function%)' + developer_ingame: '&a&o (No jogo)' + website: '&6Site: &f%url%' + license: '&6Licença: &fGNU GPL v3.0&7&o (veja LICENSE)' + copyright: '&6Copyright: &fCopyright (c) AuthMe-Team %year%. Licenciado sob GPL v3.' + +# /authme debug +debug: + command_title: '&9Utilitários de debug do AuthMe' + command_sections_available: 'Seções disponíveis para você:' + command_section_line: '- %name%: %description%' + command_no_perm_any: '&cVocê não tem permissão para ver nenhuma seção de debug' + command_no_perm_section: '&cSem permissão para esta seção. Veja /authme debug' + spawn_title: '&9Visualizador de spawn do AuthMe' + spawn_priority: 'Prioridade de spawn: %list%' + spawn_location: 'Spawn do AuthMe: %location%' + spawn_first_location: 'Primeiro spawn do AuthMe: %location%' + spawn_priority_note: 'O spawn (e primeiro spawn) só são usados conforme a prioridade configurada!' + spawn_help_hint: 'Use ''/authme debug spawn ?'' para mais ajuda' + spawn_help_teleport: 'Use /authme spawn e /authme firstspawn para ir aos spawns.' + spawn_help_set: '/authme set(first)spawn define o (primeiro) spawn na sua posição atual.' + spawn_help_player: 'Use /authme debug spawn para ver onde ele seria teleportado.' + spawn_help_wiki: 'Mais em https://github.com/AuthMe/AuthMeReloaded/wiki/Spawn-Handling' + spawn_player_offline: 'O jogador ''%player%'' não está online!' + spawn_player_location: 'Spawn de ''%player%'': %location%' + spawn_player_note: 'Nota: este teste não inclui o primeiro spawn do AuthMe.' + mail_title: '&9Teste de e-mail do AuthMe' + mail_config_incomplete: '&cFaltam configurações no config.yml para enviar e-mail. Verifique o arquivo.' + mail_sent: 'E-mail de teste enviado para %email%' + mail_failed: '&cFalha ao enviar e-mail de teste para %email%; veja os logs' + mail_provide_address: '&cInforme um e-mail, ex.: /authme debug mail teste@exemplo.com' + mail_no_account_email: '&cNenhum e-mail na sua conta! Use /authme debug mail ' + mail_invalid: '&cE-mail inválido! Uso: /authme debug mail teste@exemplo.com' + mail_subject: 'E-mail de teste do AuthMe' + mail_body: 'Olá!
Este é um e-mail de teste enviado do servidor Minecraft (%server%) via /authme debug mail. Se você está vendo isso, o envio está funcionando.' + db_title: '&9Visualizador do banco do AuthMe' + db_enter_name: 'Digite o nome do jogador para ver os dados no banco.' + db_example: 'Exemplo: /authme debug db Bobby' + db_no_record: 'Não há registro para ''%name%''' + db_player_header: '&9[AuthMe] Jogador %nick% / %realname%' + db_summary: 'E-mail: %email%. IP: %ip%. Grupo: %group%' + db_quit_location: 'Local ao sair: %location%' + db_last_login: 'Último login: %date%' + db_registration: 'Registro: %date% com IP %regip%' + db_hash: 'Hash / salt (parcial): ''%hash%'' / ''%salt%''' + db_totp: 'TOTP (parcial): ''%totp%''' + db_date_null: 'Indisponível (null)' + db_date_zero: 'Indisponível (0)' + groups_title: '&9Grupos de permissão do AuthMe' + groups_player_not_found: 'Jogador %name% não encontrado' + groups_list: 'Grupos de %name%: %groups%' + groups_primary: 'Grupo primário: %primary%' + mysql_non_mysql: 'Valores padrão só podem ser alterados na fonte MySQL.' + mysql_change_header: '&9[AuthMe] Alteração MySQL ''%column%''' + mysql_replaced_nulls: 'NULLs substituídos pelo padrão (''%value%''), %rows% linhas' + mysql_not_null_set: 'Coluna ''%column%'' alterada para NOT NULL' + mysql_allow_nulls: 'Coluna ''%column%'' agora aceita NULL' + mysql_replaced_default_null: 'Valor padrão (''%value%'') trocado por NULL, %rows% linhas' + mysql_details_title: '&9Detalhes das colunas MySQL' + mysql_details_failed: 'Falha ao mostrar detalhes. Veja o log' + mysql_usage_title: '&9Alterador de colunas MySQL' + mysql_usage_intro: 'Adiciona ou remove restrição NOT NULL em uma coluna.' + mysql_usage_example_add: 'Exemplos: adicionar NOT NULL com' + mysql_usage_example_add_cmd: ' /authme debug mysqldef add ' + mysql_usage_example_remove: 'Remover com /authme debug mysqldef remove ' + mysql_available_columns: 'Colunas disponíveis: %columns%' + mysql_legend: ' &3@&r: not-null, &6#&r: tem padrão. Veja /authme debug mysqldef details' + mysql_column_list_error: '&cErro! Veja o console para detalhes.' + mysql_col_state_not_null: 'NOT NULL' + mysql_col_state_nullable: 'nullable' + mysql_col_no_default: 'sem padrão' + mysql_col_default: 'padrão: ''%value%''' + mysql_col_row: '%prefix% (%columnName%): %nullState%, %defaultClause%' + limbo_title: '&9Visualizador limbo do AuthMe' + limbo_usage: '/authme debug limbo : dados limbo do jogador' + limbo_available: 'Registros limbo em memória: %records%' + limbo_no_data_title: '&9Sem dados limbo do AuthMe' + limbo_no_data_detail: 'Sem dados limbo e sem jogador online ''%name%''' + limbo_info_header: '&9Jogador / limbo / limbo em disco: ''%name%''' + limbo_note_memory: 'Nota: sem informação limbo em memória' + limbo_note_offline: 'Nota: jogador offline' + limbo_note_disk: 'Nota: sem limbo salvo em disco' + limbo_row: '%title%: %player% / %memory% / %disk%' + limbo_field_is_op: 'É OP' + limbo_field_walk_speed: 'Velocidade ao andar' + limbo_field_can_fly: 'Pode voar' + limbo_field_fly_speed: 'Velocidade de voo' + limbo_field_location: 'Localização' + limbo_field_primary_group: 'Grupo prim.' + valid_title: '&9Testes de validação' + valid_intro: 'E-mails e senhas proibidos podem ser definidos no config.yml. Teste aqui.' + valid_pass_usage: ' Use &6/authme debug valid&r pass &r para testar senha' + valid_mail_usage: ' Use &6/authme debug valid&r mail &r para testar e-mail' + valid_name_usage: ' Use &6/authme debug valid&r name &r para testar nome' + valid_validate_password: '&9Validação da senha ''%password%''' + valid_valid_password: '&2Senha válida!' + valid_validate_email: '&9Validação do e-mail ''%email%''' + valid_valid_email: '&2E-mail válido!' + valid_invalid_email: '&cE-mail inválido!' + valid_validate_name: '&9Validação do nome ''%name%''' + valid_valid_name: 'Nome de usuário válido!' + perm_title: '&9Verificação de permissão do AuthMe' + perm_usage_line1: 'Verificar se um jogador tem uma permissão:' + perm_usage_example: 'Exemplo: /authme debug perm bobby minha.permissao' + perm_system: 'Sistema de permissões: %system%' + perm_player_not_exist: '&4Jogador ''%player%'' não existe' + perm_offline_check: 'Jogador ''%player%'' offline; verificando jogador offline' + perm_success: '&2Sucesso: ''%player%'' tem a permissão ''%node%''' + perm_fail: '&4Falha: ''%player%'' NÃO tem a permissão ''%node%''' + perm_default_denied: 'Permissão não é do AuthMe; usando padrão = NEGADO' + cty_title: '&9Consulta de país do AuthMe' + cty_usage_player: 'Ver jogador: /authme debug cty Bobby' + cty_usage_ip: 'Ver IP: /authme debug cty 127.123.45.67' + cty_ip_info: 'IP ''%ip%'' → país ''%code%'' (%country%)' + cty_not_blocked: '&2O país deste IP não está bloqueado' + cty_blocked: '&4O país deste IP está bloqueado no servidor' + cty_note: 'Nota: se %setting% for false, nenhum país é bloqueado' + cty_no_player: 'Não há jogador com o nome ''%name%''' + cty_no_ip: 'Sem último IP conhecido para ''%name%''' + cty_player_ip: 'Jogador ''%name%'' tem IP %ip%' + stats_title: '&9Estatísticas do AuthMe' + stats_limbo: 'LimboPlayers em memória: %count%' + stats_cache: 'Tamanho do PlayerCache: %count% (= jogadores logados)' + stats_db_total: 'Total de jogadores no banco: %count%' + stats_cache_objs: 'Objetos PlayerAuth em cache: %count%' + stats_loggers: 'Instâncias de logger: %count%' + stats_singletons: 'Classes singleton (injector): %count%' + stats_injector_breakdown: '(Reloadable: %reloadable% / SettingsDependent: %settingsDep% / HasCleanup: %cleanup%)' diff --git a/src/main/resources/messages/messages_en.yml b/src/main/resources/messages/messages_en.yml index 40ed034b44..154c033ee4 100644 --- a/src/main/resources/messages/messages_en.yml +++ b/src/main/resources/messages/messages_en.yml @@ -43,6 +43,12 @@ error: kick_for_vip: '&3A VIP player has joined the server when it was full!' kick_unresolved_hostname: '&cAn error occurred: unresolved player hostname!' tempban_max_logins: '&cYou have been temporarily banned for failing to log in too many times.' + command_parse_failed: '&4Failed to parse %plugin% command!' + unknown_authme_command: '&4Unknown command!' + command_suggest_similar: '&eDid you mean &6%command%&e?' + command_use_help: '&eUse the command &6/%label% help&e to view help.' + incorrect_command_arguments: '&4Incorrect command arguments!' + command_detailed_help_syntax: '&6Detailed help: &f/%label% help %child%' # AntiBot antibot: @@ -171,3 +177,217 @@ login_location_fix: # 3rd party features: Double Login Fix double_login_fix: fix_message: '&cYou have been disconnected due to doubled login.' + +# Staff command feedback (/authme, console) +admin: + reload_abort_error: '&4Error occurred during reload of AuthMe: aborting' + reload_database_type_note: '&eNote: cannot change database type during /authme reload' + spawn_failed: '&c[AuthMe] Spawn has failed, please try to define the spawn' + first_spawn_failed: '&c[AuthMe] First spawn has failed, please try to define the first spawn' + set_spawn_success: '&2[AuthMe] Correctly defined new spawn point' + set_spawn_failed: '&c[AuthMe] SetSpawn has failed, please retry' + set_first_spawn_success: '&2[AuthMe] Correctly defined new first spawn point' + set_first_spawn_failed: '&c[AuthMe] SetFirstSpawn has failed, please retry' + antibot_status: '&e[AuthMe] AntiBot status: %status%' + antibot_manual_enabled: '&2[AuthMe] AntiBot Manual Override: enabled!' + antibot_manual_disabled: '&c[AuthMe] AntiBot Manual Override: disabled!' + antibot_invalid_mode: '&4Invalid AntiBot mode!' + antibot_detailed_help: '&6Detailed help: &f%command%' + purge_player_success: 'Purged data for player %player%' + purge_player_confirm: 'This player is still registered! Are you sure you want to proceed? Use ''/authme purgeplayer %player% force'' to run the command anyway' + purge_lastpos_all: 'All players last position locations are now reset' + purge_lastpos_one: '%player%''s last position location is now reset' + force_login_offline: 'Player needs to be online!' + force_login_denied: 'You cannot force login the player %player%!' + force_login_success: 'Force login for %player% performed!' + accounts_ip_unknown: '&c[AuthMe] This IP does not exist in the database.' + accounts_single: '&e[AuthMe] %player% is a single account player' + accounts_no_last_ip: 'No known last IP address for player' + accounts_multiple: '&e[AuthMe] %player% has %count% accounts.' + accounts_list: '&e[AuthMe] %list%.' + get_ip_current: 'Current IP of %name% is %ip%:%port%' + get_ip_not_registered: '%name% is not registered in the database' + get_ip_database: 'Database: last IP: %lastIp%, registration IP: %regIp%' + get_email: '&e[AuthMe] %player%''s email: %email%' + last_login: '&e[AuthMe] %player% last login: %date%' + last_login_interval: '&e[AuthMe] The player %player% last logged in %interval% ago' + last_login_ip: '&e[AuthMe] Last player''s IP: %ip%' + last_login_never: 'never' + last_login_interval_parts: '%days% days %hours% hours %mins% mins %secs% secs' + converter_list: 'Converters: %list%' + converter_started: '&2[AuthMe] Successfully started %name%' + totp_not_enabled: '&cPlayer ''%player%'' does not have two-factor auth enabled' + totp_disabled_success: 'Disabled two-factor authentication successfully for ''%player%''' + help_file_updated: '&2Successfully updated the help file ''%file%''' + help_file_update_failed: '&4Could not update help file: %error%' + totp_view_disabled: '&cPlayer ''%player%'' does NOT have two-factor auth enabled' + totp_view_enabled: '&2Player ''%player%'' has enabled two-factor authentication' + authme_info_running: '&aThis server is running %plugin% v%version% b%build%! &c<3' + authme_info_help: '&eUse the command &6/authme help&e to view help.' + authme_info_about: '&eUse the command &6/authme about&e to view about.' + purge_invalid_value: '&cThe value you''ve entered is invalid!' + purge_minimum_days: '&cYou can only purge data older than %days% days' + purge_no_players: 'No players to purge' + purge_already_running: 'Purge is already in progress! Aborting purge request' + purge_progress: '&e[AuthMe] Purge progress %current%/%total%' + purge_database_success: '&2[AuthMe] Database has been purged successfully' + recent_players_header: '&9[AuthMe] Recently logged in players' + recent_player_line: '&7- %player% (%lastlogin% with IP %ip%)' + backup_disabled: 'Can''t perform a backup: disabled in configuration. Cause of the backup: %cause%' + backup_success: 'A backup has been performed successfully. Cause of the backup: %cause%' + backup_failed: 'Error while performing a backup! Cause of the backup: %cause%' + converter_configure_destination: 'Please configure your connection to %type% and re-run this command' + converter_source_init_failed: 'The data source to convert from could not be initialized' + converter_skipped_existing: 'Skipped conversion for players which were already in %type%: %players%' + converter_finished: 'Database successfully converted from %source% to %target%' + converter_xauth_class_not_found: 'xAuth has not been found, please put xAuth.jar in your plugin folder and restart!' + converter_xauth_plugin_not_found: '&c[AuthMe] xAuth plugin not found' + converter_xauth_h2_missing: '&e[AuthMe] xAuth H2 database not found, checking for MySQL or SQLite data...' + converter_xauth_no_players: '&c[AuthMe] Error while importing xAuthPlayers: did not find any players' + converter_xauth_starting: '&e[AuthMe] Starting import...' + converter_xauth_success: '&2[AuthMe] Successfully converted from xAuth database' + converter_crazylogin_file_not_found: 'CrazyLogin file not found, please put %file% in AuthMe folder!' + converter_loginsecurity_failed: 'Failed to convert from SQLite. Please see the log for more info' + converter_loginsecurity_migrated: 'Migrated %count% accounts successfully from LoginSecurity' + converter_loginsecurity_skipped: 'Skipped conversion for players which were already in AuthMe: %players%' + converter_loginsecurity_file_missing: 'The file ''%path%'' does not exist' + converter_loginsecurity_mysql_unconfigured: 'The LoginSecurity database or username is not configured in AuthMe''s config.yml' + converter_loginsecurity_connect_failed: 'Could not connect to LoginSecurity using Sqlite = %sqlite%, see log for more info' + player_only_alternative: 'Player only! Please use %command% instead.' + player_only: 'This command is only for players.' + +# /authme about +about: + header: '&6==========[ &f%plugin% &6ABOUT ]==========' + version: '&6Version: &f%plugin% v%version%&7 (build: %build%)' + database: '&6Database Implementation: &f%backend%' + authors_header: '&6Authors:' + retired_header: '&6Retired authors:' + developer_line: ' &f%name%&7 // &f%mcname%&7&o (%function%)' + developer_ingame: '&a&o (In-Game)' + website: '&6Website: &f%url%' + license: '&6License: &fGNU GPL v3.0&7&o (See LICENSE file)' + copyright: '&6Copyright: &fCopyright (c) AuthMe-Team %year%. Released under GPL v3 License.' + +# /authme debug +debug: + command_title: '&9AuthMe debug utils' + command_sections_available: 'Sections available to you:' + command_section_line: '- %name%: %description%' + command_no_perm_any: '&cYou don''t have permission to view any debug section' + command_no_perm_section: '&cYou don''t have permission for this section. See /authme debug' + spawn_title: '&9AuthMe spawn location viewer' + spawn_priority: 'Spawn priority: %list%' + spawn_location: 'AuthMe spawn location: %location%' + spawn_first_location: 'AuthMe first spawn location: %location%' + spawn_priority_note: 'AuthMe (first)spawn are only used depending on the configured priority!' + spawn_help_hint: 'Use ''/authme debug spawn ?'' for further help' + spawn_help_teleport: 'Use /authme spawn and /authme firstspawn to teleport to the spawns.' + spawn_help_set: '/authme set(first)spawn sets the (first) spawn to your current location.' + spawn_help_player: 'Use /authme debug spawn to view where a player would be teleported to.' + spawn_help_wiki: 'Read more at https://github.com/AuthMe/AuthMeReloaded/wiki/Spawn-Handling' + spawn_player_offline: 'Player ''%player%'' is not online!' + spawn_player_location: 'Player ''%player%'' has spawn location: %location%' + spawn_player_note: 'Note: this check excludes the AuthMe firstspawn.' + mail_title: '&9AuthMe test email sender' + mail_config_incomplete: '&cYou haven''t set all required configurations in config.yml for sending emails. Please check your config.yml' + mail_sent: 'Test email sent to %email% with success' + mail_failed: '&cFailed to send test mail to %email%; please check your logs' + mail_provide_address: '&cPlease provide an email address, e.g. /authme debug mail test@example.com' + mail_no_account_email: '&cNo email set for your account! Please use /authme debug mail ' + mail_invalid: '&cInvalid email! Usage: /authme debug mail test@example.com' + mail_subject: 'AuthMe test email' + mail_body: 'Hello there!
This is a sample email sent to you from a Minecraft server (%server%) via /authme debug mail. If you''re seeing this, sending emails should be fine.' + db_title: '&9AuthMe database viewer' + db_enter_name: 'Enter player name to view his data in the database.' + db_example: 'Example: /authme debug db Bobby' + db_no_record: 'No record exists for ''%name%''' + db_player_header: '&9[AuthMe] Player %nick% / %realname%' + db_summary: 'Email: %email%. IP: %ip%. Group: %group%' + db_quit_location: 'Quit location: %location%' + db_last_login: 'Last login: %date%' + db_registration: 'Registration: %date% with IP %regip%' + db_hash: 'Hash / salt (partial): ''%hash%'' / ''%salt%''' + db_totp: 'TOTP code (partial): ''%totp%''' + db_date_null: 'Not available (null)' + db_date_zero: 'Not available (0)' + groups_title: '&9AuthMe permission groups' + groups_player_not_found: 'Player %name% could not be found' + groups_list: 'Player %name% has permission groups: %groups%' + groups_primary: 'Primary group is: %primary%' + mysql_non_mysql: 'Defaults can be changed for the MySQL data source only.' + mysql_change_header: '&9[AuthMe] MySQL change ''%column%''' + mysql_replaced_nulls: 'Replaced NULLs with default value (''%value%''), modifying %rows% entries' + mysql_not_null_set: 'Changed column ''%column%'' to have NOT NULL constraint' + mysql_allow_nulls: 'Changed column ''%column%'' to allow nulls' + mysql_replaced_default_null: 'Replaced default value (''%value%'') to be NULL, modifying %rows% entries' + mysql_details_title: '&9MySQL column details' + mysql_details_failed: 'Failed while showing column details. See log for info' + mysql_usage_title: '&9MySQL column changer' + mysql_usage_intro: 'Adds or removes a NOT NULL constraint for a column.' + mysql_usage_example_add: 'Examples: add a NOT NULL constraint with' + mysql_usage_example_add_cmd: ' /authme debug mysqldef add ' + mysql_usage_example_remove: 'Remove one with /authme debug mysqldef remove ' + mysql_available_columns: 'Available columns: %columns%' + mysql_legend: ' &3@&r: not-null, &6#&r: has default. See /authme debug mysqldef details' + mysql_column_list_error: '&cAn error occurred! Please see the console for details.' + mysql_col_state_not_null: 'NOT NULL' + mysql_col_state_nullable: 'nullable' + mysql_col_no_default: 'no default' + mysql_col_default: 'default: ''%value%''' + mysql_col_row: '%prefix% (%columnName%): %nullState%, %defaultClause%' + limbo_title: '&9AuthMe limbo viewer' + limbo_usage: '/authme debug limbo : show a player''s limbo info' + limbo_available: 'Available limbo records: %records%' + limbo_no_data_title: '&9No AuthMe limbo data' + limbo_no_data_detail: 'No limbo data and no player online with name ''%name%''' + limbo_info_header: '&9Player / limbo / disk limbo info for ''%name%''' + limbo_note_memory: 'Note: no Limbo information available' + limbo_note_offline: 'Note: player is not online' + limbo_note_disk: 'Note: no Limbo on disk available' + limbo_row: '%title%: %player% / %memory% / %disk%' + limbo_field_is_op: 'Is op' + limbo_field_walk_speed: 'Walk speed' + limbo_field_can_fly: 'Can fly' + limbo_field_fly_speed: 'Fly speed' + limbo_field_location: 'Location' + limbo_field_primary_group: 'Prim. group' + valid_title: '&9Validation tests' + valid_intro: 'You can define forbidden emails and passwords in your config.yml. You can test your settings with this command.' + valid_pass_usage: ' Use &6/authme debug valid&r pass &r to check a password' + valid_mail_usage: ' Use &6/authme debug valid&r mail &r to check an email' + valid_name_usage: ' Use &6/authme debug valid&r name &r to check a username' + valid_validate_password: '&9Validation of password ''%password%''' + valid_valid_password: '&2Valid password!' + valid_validate_email: '&9Validation of email ''%email%''' + valid_valid_email: '&2Valid email!' + valid_invalid_email: '&cEmail is not valid!' + valid_validate_name: '&9Validation of username ''%name%''' + valid_valid_name: 'Valid username!' + perm_title: '&9AuthMe permission check' + perm_usage_line1: 'Check if a player has permission:' + perm_usage_example: 'Example: /authme debug perm bobby my.perm.node' + perm_system: 'Permission system type used: %system%' + perm_player_not_exist: '&4Player ''%player%'' does not exist' + perm_offline_check: 'Player ''%player%'' not online; checking with offline player' + perm_success: '&2Success: player ''%player%'' has permission ''%node%''' + perm_fail: '&4Check failed: player ''%player%'' does NOT have permission ''%node%''' + perm_default_denied: 'Did not detect AuthMe permission; using default permission = DENIED' + cty_title: '&9AuthMe country lookup' + cty_usage_player: 'Check player: /authme debug cty Bobby' + cty_usage_ip: 'Check IP address: /authme debug cty 127.123.45.67' + cty_ip_info: 'IP ''%ip%'' maps to country ''%code%'' (%country%)' + cty_not_blocked: '&2This IP address'' country is not blocked' + cty_blocked: '&4This IP address'' country is blocked from the server' + cty_note: 'Note: if %setting% is false no country is blocked' + cty_no_player: 'No player with name ''%name%''' + cty_no_ip: 'No last IP address known for ''%name%''' + cty_player_ip: 'Player ''%name%'' has IP address %ip%' + stats_title: '&9AuthMe statistics' + stats_limbo: 'LimboPlayers in memory: %count%' + stats_cache: 'PlayerCache size: %count% (= logged in players)' + stats_db_total: 'Total players in DB: %count%' + stats_cache_objs: 'Cached PlayerAuth objects: %count%' + stats_loggers: 'Total logger instances: %count%' + stats_singletons: 'Singleton Java classes: %count%' + stats_injector_breakdown: '(Reloadable: %reloadable% / SettingsDependent: %settingsDep% / HasCleanup: %cleanup%)' From cdb7d28f386085ddd5375754b8ff6ca220a83c4c Mon Sep 17 00:00:00 2001 From: cl3i550n Date: Mon, 23 Mar 2026 11:29:36 -0300 Subject: [PATCH 2/6] Update Java version in pom.xml to 21 for compatibility with Paper API 1.21.11+ --- pom.xml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 00fa11d221..614a7c284a 100644 --- a/pom.xml +++ b/pom.xml @@ -60,10 +60,11 @@ UTF-8 UTF-8 - 17 - 17 - 17 - 17 + + 21 + 21 + 21 + 21 3.8.8 From f1efd37e82344350a05ac74ec41c690eae469884 Mon Sep 17 00:00:00 2001 From: cl3i550n Date: Mon, 23 Mar 2026 12:01:18 -0300 Subject: [PATCH 3/6] Update pom.xml for repository and Java version changes - Changed project URL and SCM connections to reflect the new repository location. - Updated CI management to use GitHub Actions instead of Jenkins. - Downgraded Java version from 21 to 17 for compatibility. - Adjusted Spigot dependency version to 1.21.1-R0.1-SNAPSHOT. - Removed unused Paper API repository and dependency. --- pom.xml | 42 ++++++++++++++---------------------------- 1 file changed, 14 insertions(+), 28 deletions(-) diff --git a/pom.xml b/pom.xml index 614a7c284a..f69e6d73bb 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,8 @@ AuthMeReReloaded Fork of the first authentication plugin for the Bukkit API! 2013 - https://github.com/AuthMe/AuthMeReloaded + + https://github.com/cl3i550n/AuthMeReReloaded AuthMe-Team @@ -19,19 +20,19 @@ - scm:git:https://github.com/AuthMe/AuthMeReloaded.git - scm:git:git@github.com:AuthMe/AuthMeReloaded.git - https://github.com/AuthMe/AuthMeReloaded + scm:git:https://github.com/cl3i550n/AuthMeReReloaded.git + scm:git:git@github.com:cl3i550n/AuthMeReReloaded.git + https://github.com/cl3i550n/AuthMeReReloaded - jenkins - https://ci.codemc.io/job/AuthMe/job/AuthMeReloaded/ + GitHub Actions + https://github.com/cl3i550n/AuthMeReReloaded/actions GitHub - https://github.com/AuthMe/AuthMeReloaded/issues + https://github.com/cl3i550n/AuthMeReReloaded/issues @@ -60,11 +61,10 @@ UTF-8 UTF-8 - - 21 - 21 - 21 - 21 + 17 + 17 + 17 + 17 3.8.8 @@ -96,8 +96,8 @@ 0.10.2 1.5.0 1.3.1 - - 1.21.11-R0.1-SNAPSHOT + + 1.21.1-R0.1-SNAPSHOT 2.20.0 3.0.2 @@ -452,12 +452,6 @@ - - - papermc - https://repo.papermc.io/repository/maven-public/ - - codemc-repo @@ -744,14 +738,6 @@ - - - - io.papermc.paper - paper-api - ${dependencies.spigot.version} - provided - org.apache.logging.log4j log4j-core From d8914da1b9ff6dda3896db8c71c581da4fe2a7cf Mon Sep 17 00:00:00 2001 From: cl3i550n Date: Mon, 23 Mar 2026 12:09:05 -0300 Subject: [PATCH 4/6] Update pom.xml to set Java version to 21 and adjust Spigot dependency - Upgraded Java source and target versions from 17 to 21 for improved compatibility. - Updated Spigot dependency version to 1.21.11-R0.1-SNAPSHOT. - Added Paper API repository and dependency for AsyncPlayerSpawnLocationEvent support. --- pom.xml | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index f69e6d73bb..4f2b2d6937 100644 --- a/pom.xml +++ b/pom.xml @@ -61,10 +61,10 @@ UTF-8 UTF-8 - 17 - 17 - 17 - 17 + 21 + 21 + 21 + 21 3.8.8 @@ -97,7 +97,7 @@ 1.5.0 1.3.1 - 1.21.1-R0.1-SNAPSHOT + 1.21.11-R0.1-SNAPSHOT 2.20.0 3.0.2 @@ -452,6 +452,12 @@ + + + papermc + https://repo.papermc.io/repository/maven-public/ + + codemc-repo @@ -738,6 +744,15 @@ + + + + io.papermc.paper + paper-api + ${dependencies.spigot.version} + provided + + org.apache.logging.log4j log4j-core From c285c99c61c7d17b2f278c55bad21186d08875fa Mon Sep 17 00:00:00 2001 From: cl3i550n Date: Mon, 23 Mar 2026 12:32:34 -0300 Subject: [PATCH 5/6] Enhance Portuguese (BR) help messages for AuthMe - Added detailed descriptions and arguments for various AuthMe commands in the help_br.yml file. - Improved structure and clarity of command help texts to better assist users in understanding available functionalities. --- src/main/resources/messages/help_br.yml | 156 +++++++++++++++++++++++- 1 file changed, 153 insertions(+), 3 deletions(-) diff --git a/src/main/resources/messages/help_br.yml b/src/main/resources/messages/help_br.yml index dcad29d48e..80c63694de 100644 --- a/src/main/resources/messages/help_br.yml +++ b/src/main/resources/messages/help_br.yml @@ -1,6 +1,9 @@ # Tradução da ajuda do AuthMe (/authme help, /authme help ) # Baseado em help_en.yml — revisão e chaves novas alinhadas ao EN # Créditos anteriores: Frani (PotterCraft_), RenanYudi +# +# Chaves em falta usam o texto definido no código (inglês). Para /authme help em PT-BR, +# defina aqui cada comando sob commands.authme.. # ------------------------------------------------------- # Textos comuns da ajuda @@ -33,10 +36,16 @@ section: children: 'Comandos' # ------------------------------------------------------- -# Tradução por comando: ex. authme.reload para /authme reload, login para /login -# Use arg1, arg2... para argumentos. Chaves em falta usam o idioma padrão. -# Coloque comandos pai (ex.: authme) antes dos filhos (ex.: authme.reload). commands: + authme: + description: 'Comandos admin do AuthMe' + detailedDescription: 'Comando principal do AuthMeReloaded. Raiz de todos os comandos de administração.' + authme.help: + description: 'Ver ajuda' + detailedDescription: 'Mostra a ajuda detalhada dos comandos /authme.' + arg1: + label: 'consulta' + description: 'Comando ou termo para ver na ajuda' authme.register: description: 'Registrar um jogador' detailedDescription: 'Registra o jogador indicado com a senha indicada.' @@ -46,3 +55,144 @@ commands: arg2: label: 'senha' description: 'Senha' + authme.unregister: + description: 'Remover registro de um jogador' + detailedDescription: 'Remove o registro do jogador indicado.' + arg1: + label: 'jogador' + description: 'Nome do jogador' + authme.forcelogin: + description: 'Forçar login do jogador' + detailedDescription: 'Força o jogador indicado a fazer login.' + arg1: + label: 'jogador' + description: 'Nome do jogador (online)' + authme.password: + description: 'Alterar senha de um jogador' + detailedDescription: 'Altera a senha de um jogador.' + arg1: + label: 'jogador' + description: 'Nome do jogador' + arg2: + label: 'senha' + description: 'Nova senha' + authme.lastlogin: + description: 'Último login do jogador' + detailedDescription: 'Mostra a data do último login do jogador indicado.' + arg1: + label: 'jogador' + description: 'Nome do jogador' + authme.accounts: + description: 'Listar contas do jogador' + detailedDescription: 'Lista todas as contas de um jogador pelo nome ou IP.' + arg1: + label: 'jogador ou IP' + description: 'Nome do jogador ou endereço IP' + authme.email: + description: 'Ver e-mail do jogador' + detailedDescription: 'Mostra o e-mail do jogador, se estiver definido.' + arg1: + label: 'jogador' + description: 'Nome do jogador' + authme.setemail: + description: 'Alterar e-mail do jogador' + detailedDescription: 'Altera o endereço de e-mail do jogador indicado.' + arg1: + label: 'jogador' + description: 'Nome do jogador' + arg2: + label: 'email' + description: 'E-mail do jogador' + authme.getip: + description: 'Obter IP do jogador' + detailedDescription: 'Obtém o endereço IP do jogador online indicado.' + arg1: + label: 'jogador' + description: 'Nome do jogador' + authme.totp: + description: 'Ver se o jogador usa TOTP' + detailedDescription: 'Indica se o jogador tem autenticação em dois fatores (2FA) ativa.' + arg1: + label: 'jogador' + description: 'Nome do jogador' + authme.disabletotp: + description: 'Remover TOTP do jogador' + detailedDescription: 'Desativa a autenticação em dois fatores para o jogador.' + arg1: + label: 'jogador' + description: 'Nome do jogador' + authme.spawn: + description: 'Teleportar para o spawn' + detailedDescription: 'Teleporta para o spawn.' + authme.setspawn: + description: 'Alterar o spawn' + detailedDescription: 'Define o spawn do jogador na sua posição atual.' + authme.firstspawn: + description: 'Teleportar ao primeiro spawn' + detailedDescription: 'Teleporta para o primeiro spawn.' + authme.setfirstspawn: + description: 'Alterar o primeiro spawn' + detailedDescription: 'Define o primeiro spawn do jogador na sua posição atual.' + authme.purge: + description: 'Expurgar dados antigos' + detailedDescription: 'Remove dados do AuthMe mais antigos que o número de dias indicado.' + arg1: + label: 'dias' + description: 'Número de dias' + authme.purgeplayer: + description: 'Expurgar dados de um jogador' + detailedDescription: 'Remove os dados do jogador indicado.' + arg1: + label: 'jogador' + description: 'Jogador a expurgar' + arg2: + label: 'opções' + description: '''force'' para executar sem verificar se está registrado' + authme.backup: + description: 'Fazer backup' + detailedDescription: 'Cria um backup dos usuários registrados.' + authme.resetpos: + description: 'Limpar última posição' + detailedDescription: 'Remove a última posição conhecida do jogador ou de todos (*).' + arg1: + label: 'jogador/*' + description: 'Nome do jogador ou * para todos' + authme.purgebannedplayers: + description: 'Expurgar dados de jogadores banidos' + detailedDescription: 'Remove todos os dados AuthMe de jogadores banidos.' + authme.switchantibot: + description: 'Alternar modo AntiBot' + detailedDescription: 'Ativa ou desativa o modo AntiBot.' + arg1: + label: 'modo' + description: 'ON / OFF' + authme.reload: + description: 'Recarregar o plugin' + detailedDescription: 'Recarrega o plugin AuthMeReloaded.' + authme.version: + description: 'Informação da versão' + detailedDescription: 'Mostra informações sobre a versão instalada, desenvolvedores, contribuidores e licença.' + authme.converter: + description: 'Comando de conversão' + detailedDescription: 'Conversor para AuthMeReloaded.' + arg1: + label: 'tarefa' + description: 'Trabalho de conversão: xauth / crazylogin / rakamak / royalauth / vauth / sqliteToSql / mysqlToSqlite / loginsecurity' + authme.messages: + description: 'Adicionar textos de ajuda em falta' + detailedDescription: 'Adiciona textos em falta ao arquivo de mensagens de ajuda atual.' + authme.recent: + description: 'Jogadores que entraram recentemente' + detailedDescription: 'Mostra os últimos jogadores que fizeram login.' + authme.debug: + description: 'Funções de debug' + detailedDescription: 'Permite várias operações para depuração.' + arg1: + label: 'subcomando' + description: 'Subcomando a executar' + arg2: + label: 'arg' + description: 'Argumento (depende da seção de debug)' + arg3: + label: 'arg' + description: 'Argumento (depende da seção de debug)' From 35055165aab61fcf1b5146d7611f896a24b93d22 Mon Sep 17 00:00:00 2001 From: cl3i550n Date: Mon, 23 Mar 2026 12:38:28 -0300 Subject: [PATCH 6/6] Update pom.xml for repository URL and CI management changes - Changed project URL and SCM connections to point to the new AuthMe repository. - Updated CI management system from GitHub Actions to Jenkins. - Adjusted issue management URL to reflect the new repository location. --- pom.xml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/pom.xml b/pom.xml index 4f2b2d6937..5fa9d0a598 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ Fork of the first authentication plugin for the Bukkit API! 2013 - https://github.com/cl3i550n/AuthMeReReloaded + https://github.com/AuthMe/AuthMeReloaded AuthMe-Team @@ -20,19 +20,19 @@ - scm:git:https://github.com/cl3i550n/AuthMeReReloaded.git - scm:git:git@github.com:cl3i550n/AuthMeReReloaded.git - https://github.com/cl3i550n/AuthMeReReloaded + scm:git:https://github.com/AuthMe/AuthMeReloaded.git + scm:git:git@github.com:AuthMe/AuthMeReloaded.git + https://github.com/AuthMe/AuthMeReloaded - GitHub Actions - https://github.com/cl3i550n/AuthMeReReloaded/actions + jenkins + https://ci.codemc.io/job/AuthMe/job/AuthMeReReloaded/ GitHub - https://github.com/cl3i550n/AuthMeReReloaded/issues + https://github.com/AuthMe/AuthMeReloaded/issues