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 extends PermissionNode> 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..80c63694de 100644
--- a/src/main/resources/messages/help_br.yml
+++ b/src/main/resources/messages/help_br.yml
@@ -1,46 +1,198 @@
-# 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
+#
+# 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..
# -------------------------------------------------------
-# 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")
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:
+ 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.'
+ arg1:
+ label: 'jogador'
+ description: 'Nome do jogador'
+ 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)'
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%)'