diff --git a/pom.xml b/pom.xml
index e92495db..574f362f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -90,6 +90,14 @@
plugin.yml
+
+ .
+ true
+ src/main/resources/
+
+ email.html
+
+
.
false
diff --git a/src/main/java/fr/xephi/authme/DataManager.java b/src/main/java/fr/xephi/authme/DataManager.java
index c3847f3b..451667ad 100644
--- a/src/main/java/fr/xephi/authme/DataManager.java
+++ b/src/main/java/fr/xephi/authme/DataManager.java
@@ -203,7 +203,7 @@ public class DataManager {
} catch (Exception ignored) {
}
}
- ConsoleLogger.info("AutoPurgeDatabase : Removed " + i + " permissions");
+ ConsoleLogger.info("AutoPurgeDatabase : Removed " + i + "permissions");
/*int i = 0;
for (String name : cleared) {
diff --git a/src/main/java/fr/xephi/authme/cache/backup/JsonCache.java b/src/main/java/fr/xephi/authme/cache/backup/JsonCache.java
index b07c74d9..38784b16 100644
--- a/src/main/java/fr/xephi/authme/cache/backup/JsonCache.java
+++ b/src/main/java/fr/xephi/authme/cache/backup/JsonCache.java
@@ -5,7 +5,6 @@ import com.google.common.io.Files;
import com.google.gson.*;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.settings.Settings;
-import fr.xephi.authme.util.Utils;
import org.bukkit.entity.Player;
import java.io.File;
@@ -109,7 +108,7 @@ public class JsonCache {
}
File file = new File(cacheDir, path);
if (file.exists()) {
- Utils.purgeDirectory(file);
+ purgeDirectory(file);
if (!file.delete()) {
ConsoleLogger.showError("Failed to remove" + player.getName() + "cache.");
}
@@ -194,4 +193,25 @@ public class JsonCache {
}
}
+ /**
+ * Delete a given directory and all its content.
+ *
+ * @param directory The directory to remove
+ */
+ private static void purgeDirectory(File directory) {
+ if (!directory.isDirectory()) {
+ return;
+ }
+ File[] files = directory.listFiles();
+ if (files == null) {
+ return;
+ }
+ for (File target : files) {
+ if (target.isDirectory()) {
+ purgeDirectory(target);
+ }
+ target.delete();
+ }
+ }
+
}
diff --git a/src/main/java/fr/xephi/authme/command/CommandUtils.java b/src/main/java/fr/xephi/authme/command/CommandUtils.java
index faed9639..e0ff117d 100644
--- a/src/main/java/fr/xephi/authme/command/CommandUtils.java
+++ b/src/main/java/fr/xephi/authme/command/CommandUtils.java
@@ -1,7 +1,12 @@
package fr.xephi.authme.command;
+import com.google.common.collect.Lists;
+import fr.xephi.authme.util.CollectionUtils;
import fr.xephi.authme.util.StringUtils;
+import java.util.ArrayList;
+import java.util.List;
+
public final class CommandUtils {
public static int getMinNumberOfArguments(CommandDescription command) {
@@ -23,10 +28,20 @@ public final class CommandUtils {
* the items ["authme", "register", "player"] it will return "authme register player".
*
* @param labels The labels to format
+ *
* @return The space-separated labels
*/
public static String labelsToString(Iterable labels) {
return StringUtils.join(" ", labels);
}
+ public static String constructCommandPath(CommandDescription command) {
+ List labels = new ArrayList<>();
+ CommandDescription currentCommand = command;
+ while (currentCommand != null) {
+ labels.add(currentCommand.getLabels().get(0));
+ currentCommand = currentCommand.getParent();
+ }
+ return "/" + labelsToString(Lists.reverse(labels));
+ }
}
diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/UnregisterAdminCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/UnregisterAdminCommand.java
index 0ef44a58..ea403554 100644
--- a/src/main/java/fr/xephi/authme/command/executable/authme/UnregisterAdminCommand.java
+++ b/src/main/java/fr/xephi/authme/command/executable/authme/UnregisterAdminCommand.java
@@ -52,7 +52,7 @@ public class UnregisterAdminCommand extends ExecutableCommand {
}
// Unregister the player
- Player target = Bukkit.getPlayer(playerNameLowerCase);
+ Player target = Utils.getPlayer(playerNameLowerCase);
PlayerCache.getInstance().removePlayer(playerNameLowerCase);
Utils.setGroup(target, Utils.GroupType.UNREGISTERED);
if (target != null && target.isOnline()) {
@@ -68,11 +68,9 @@ public class UnregisterAdminCommand extends ExecutableCommand {
LimboCache.getInstance().getLimboPlayer(playerNameLowerCase).setMessageTaskId(
scheduler.runTaskAsynchronously(plugin,
new MessageTask(plugin, playerNameLowerCase, m.retrieve(MessageKey.REGISTER_MESSAGE), interval)));
- if (Settings.applyBlindEffect)
- target.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, Settings.getRegistrationTimeout * 20, 2));
- if (!Settings.isMovementAllowed && Settings.isRemoveSpeedEnabled) {
- target.setWalkSpeed(0.0f);
- target.setFlySpeed(0.0f);
+ if (Settings.applyBlindEffect) {
+ target.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS,
+ Settings.getRegistrationTimeout * 20, 2));
}
m.send(target, MessageKey.UNREGISTERED_SUCCESS);
diff --git a/src/main/java/fr/xephi/authme/command/executable/captcha/CaptchaCommand.java b/src/main/java/fr/xephi/authme/command/executable/captcha/CaptchaCommand.java
index cca74066..2373f773 100644
--- a/src/main/java/fr/xephi/authme/command/executable/captcha/CaptchaCommand.java
+++ b/src/main/java/fr/xephi/authme/command/executable/captcha/CaptchaCommand.java
@@ -57,9 +57,7 @@ public class CaptchaCommand extends ExecutableCommand {
plugin.cap.remove(playerNameLowerCase);
String randStr = new RandomString(Settings.captchaLength).nextString();
plugin.cap.put(playerNameLowerCase, randStr);
- for (String s : m.retrieve(MessageKey.CAPTCHA_WRONG_ERROR)) {
- player.sendMessage(s.replace("THE_CAPTCHA", plugin.cap.get(playerNameLowerCase)));
- }
+ m.send(player, MessageKey.CAPTCHA_WRONG_ERROR, plugin.cap.get(playerNameLowerCase));
return;
}
diff --git a/src/main/java/fr/xephi/authme/datasource/CacheDataSource.java b/src/main/java/fr/xephi/authme/datasource/CacheDataSource.java
index 2d12a720..8b26b08c 100644
--- a/src/main/java/fr/xephi/authme/datasource/CacheDataSource.java
+++ b/src/main/java/fr/xephi/authme/datasource/CacheDataSource.java
@@ -1,5 +1,6 @@
package fr.xephi.authme.datasource;
+import com.google.common.base.Optional;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
@@ -21,7 +22,7 @@ public class CacheDataSource implements DataSource {
private final DataSource source;
private final ExecutorService exec;
- private final LoadingCache cachedAuths;
+ private final LoadingCache> cachedAuths;
/**
* Constructor for CacheDataSource.
@@ -33,9 +34,9 @@ public class CacheDataSource implements DataSource {
this.exec = Executors.newCachedThreadPool();
cachedAuths = CacheBuilder.newBuilder()
.expireAfterWrite(5, TimeUnit.MINUTES)
- .removalListener(RemovalListeners.asynchronous(new RemovalListener() {
+ .removalListener(RemovalListeners.asynchronous(new RemovalListener>() {
@Override
- public void onRemoval(RemovalNotification removalNotification) {
+ public void onRemoval(RemovalNotification> removalNotification) {
String name = removalNotification.getKey();
if (PlayerCache.getInstance().isAuthenticated(name)) {
cachedAuths.getUnchecked(name);
@@ -43,9 +44,9 @@ public class CacheDataSource implements DataSource {
}
}, exec))
.build(
- new CacheLoader() {
- public PlayerAuth load(String key) {
- return source.getAuth(key);
+ new CacheLoader>() {
+ public Optional load(String key) {
+ return Optional.fromNullable(source.getAuth(key));
}
});
}
@@ -76,7 +77,7 @@ public class CacheDataSource implements DataSource {
@Override
public synchronized PlayerAuth getAuth(String user) {
user = user.toLowerCase();
- return cachedAuths.getUnchecked(user);
+ return cachedAuths.getUnchecked(user).orNull();
}
/**
@@ -178,9 +179,9 @@ public class CacheDataSource implements DataSource {
public int purgeDatabase(long until) {
int cleared = source.purgeDatabase(until);
if (cleared > 0) {
- for (PlayerAuth auth : cachedAuths.asMap().values()) {
- if (auth != null && auth.getLastLogin() < until) {
- cachedAuths.invalidate(auth.getNickname());
+ for (Optional auth : cachedAuths.asMap().values()) {
+ if (auth.isPresent() && auth.get().getLastLogin() < until) {
+ cachedAuths.invalidate(auth.get().getNickname());
}
}
}
diff --git a/src/main/java/fr/xephi/authme/listener/AuthMeEntityListener.java b/src/main/java/fr/xephi/authme/listener/AuthMeEntityListener.java
index 30b4af72..1d407a3b 100644
--- a/src/main/java/fr/xephi/authme/listener/AuthMeEntityListener.java
+++ b/src/main/java/fr/xephi/authme/listener/AuthMeEntityListener.java
@@ -36,6 +36,7 @@ public class AuthMeEntityListener implements Listener {
}
}
+ // TODO: npc status can be used to bypass security!!!
/**
* Method onEntityDamage.
*
@@ -53,7 +54,6 @@ public class AuthMeEntityListener implements Listener {
return;
}
- // TODO: npc status can be used to bypass security!!!
if (Utils.isNPC(player)) {
return;
}
@@ -78,7 +78,6 @@ public class AuthMeEntityListener implements Listener {
return;
}
- // TODO: npc status can be used to bypass security!!!
if (Utils.isNPC((Player) entity)) {
return;
}
@@ -104,7 +103,6 @@ public class AuthMeEntityListener implements Listener {
return;
}
- // TODO: npc status can be used to bypass security!!!
if (Utils.isNPC(player)) {
return;
}
@@ -128,7 +126,6 @@ public class AuthMeEntityListener implements Listener {
return;
}
- // TODO: npc status can be used to bypass security!!!
if (Utils.isNPC((Player) entity)) {
return;
}
@@ -152,7 +149,6 @@ public class AuthMeEntityListener implements Listener {
return;
}
- // TODO: npc status can be used to bypass security!!!
if (Utils.isNPC((Player) entity)) {
return;
}
@@ -177,7 +173,6 @@ public class AuthMeEntityListener implements Listener {
return;
}
- // TODO: npc status can be used to bypass security!!!
if (Utils.isNPC((Player) entity)) {
return;
}
@@ -201,7 +196,6 @@ public class AuthMeEntityListener implements Listener {
return;
}
- // TODO: npc status can be used to bypass security!!!
if (Utils.isNPC((Player) entity)) {
return;
}
@@ -210,7 +204,6 @@ public class AuthMeEntityListener implements Listener {
}
// TODO: Need to check this, player can't throw snowball but the item is taken.
-
/**
* Method onProjectileLaunch.
*
@@ -245,7 +238,6 @@ public class AuthMeEntityListener implements Listener {
return;
}
- // TODO: npc status can be used to bypass security!!!
if (Utils.isNPC(player)) {
return;
}
@@ -270,7 +262,6 @@ public class AuthMeEntityListener implements Listener {
return;
}
- // TODO: npc status can be used to bypass security!!!
if (Utils.isNPC(player)) {
return;
}
diff --git a/src/main/java/fr/xephi/authme/listener/AuthMePlayerListener.java b/src/main/java/fr/xephi/authme/listener/AuthMePlayerListener.java
index e49215b3..337e13ec 100644
--- a/src/main/java/fr/xephi/authme/listener/AuthMePlayerListener.java
+++ b/src/main/java/fr/xephi/authme/listener/AuthMePlayerListener.java
@@ -229,7 +229,7 @@ public class AuthMePlayerListener implements Listener {
if (auth != null && !auth.getRealName().equals("Player") && !auth.getRealName().equals(event.getName())) {
event.setLoginResult(AsyncPlayerPreLoginEvent.Result.KICK_OTHER);
event.setKickMessage("You should join using username: " + ChatColor.AQUA + auth.getRealName() +
- ChatColor.RESET + "\nnot :" + ChatColor.RED + event.getName()); // TODO: write a better message
+ ChatColor.RESET + "\nnot: " + ChatColor.RED + event.getName()); // TODO: write a better message
return;
}
@@ -288,7 +288,7 @@ public class AuthMePlayerListener implements Listener {
pl.kickPlayer(m.retrieveSingle(MessageKey.KICK_FOR_VIP));
event.allow();
} else {
- ConsoleLogger.info("The player " + event.getPlayer().getName() + " tryed to join, but the server was full");
+ ConsoleLogger.info("The player " + event.getPlayer().getName() + " tried to join, but the server was full");
event.setKickMessage(m.retrieveSingle(MessageKey.KICK_FULL_SERVER));
event.setResult(PlayerLoginEvent.Result.KICK_FULL);
}
diff --git a/src/main/java/fr/xephi/authme/listener/AuthMePlayerListener16.java b/src/main/java/fr/xephi/authme/listener/AuthMePlayerListener16.java
index 0975b18a..2c3c5d3c 100644
--- a/src/main/java/fr/xephi/authme/listener/AuthMePlayerListener16.java
+++ b/src/main/java/fr/xephi/authme/listener/AuthMePlayerListener16.java
@@ -22,6 +22,7 @@ public class AuthMePlayerListener16 implements Listener {
this.plugin = plugin;
}
+ // TODO: npc status can be used to bypass security!!!
/**
* Method onPlayerEditBook.
*
@@ -33,7 +34,6 @@ public class AuthMePlayerListener16 implements Listener {
return;
}
- // TODO: npc status can be used to bypass security!!!
if (Utils.isNPC(event.getPlayer())) {
return;
}
diff --git a/src/main/java/fr/xephi/authme/listener/AuthMePlayerListener18.java b/src/main/java/fr/xephi/authme/listener/AuthMePlayerListener18.java
index dbcb1c71..f3d01028 100644
--- a/src/main/java/fr/xephi/authme/listener/AuthMePlayerListener18.java
+++ b/src/main/java/fr/xephi/authme/listener/AuthMePlayerListener18.java
@@ -22,6 +22,7 @@ public class AuthMePlayerListener18 implements Listener {
this.plugin = plugin;
}
+ // TODO: npc status can be used to bypass security!!!
/**
* Method onPlayerInteractAtEntity.
*
@@ -33,7 +34,6 @@ public class AuthMePlayerListener18 implements Listener {
return;
}
- // TODO: npc status can be used to bypass security!!!
if (Utils.isNPC(event.getPlayer())) {
return;
}
diff --git a/src/main/java/fr/xephi/authme/output/MessageKey.java b/src/main/java/fr/xephi/authme/output/MessageKey.java
index bc024abf..b93f956b 100644
--- a/src/main/java/fr/xephi/authme/output/MessageKey.java
+++ b/src/main/java/fr/xephi/authme/output/MessageKey.java
@@ -79,7 +79,7 @@ public enum MessageKey {
INVALID_NAME_LENGTH("name_len"),
- INVALID_NAME_CHARACTERS("regex"),
+ INVALID_NAME_CHARACTERS("regex", "REG_EX"),
ADD_EMAIL_MESSAGE("add_email"),
@@ -87,7 +87,7 @@ public enum MessageKey {
USAGE_CAPTCHA("usage_captcha"),
- CAPTCHA_WRONG_ERROR("wrong_captcha"),
+ CAPTCHA_WRONG_ERROR("wrong_captcha", "THE_CAPTCHA"),
CAPTCHA_SUCCESS("valid_captcha"),
@@ -119,16 +119,32 @@ public enum MessageKey {
ANTIBOT_AUTO_ENABLED_MESSAGE("antibot_auto_enabled"),
- ANTIBOT_AUTO_DISABLED_MESSAGE("antibot_auto_disabled");
+ ANTIBOT_AUTO_DISABLED_MESSAGE("antibot_auto_disabled", "%m");
private String key;
+ private String[] tags;
- MessageKey(String key) {
+ MessageKey(String key, String... tags) {
this.key = key;
+ this.tags = tags;
}
+ /**
+ * Return the key used in the messages file.
+ *
+ * @return The key
+ */
public String getKey() {
return key;
}
+
+ /**
+ * Return a list of tags (texts) that are replaced with actual content in AuthMe.
+ *
+ * @return List of tags
+ */
+ public String[] getTags() {
+ return tags;
+ }
}
diff --git a/src/main/java/fr/xephi/authme/output/Messages.java b/src/main/java/fr/xephi/authme/output/Messages.java
index ad586fd1..e27e9061 100644
--- a/src/main/java/fr/xephi/authme/output/Messages.java
+++ b/src/main/java/fr/xephi/authme/output/Messages.java
@@ -47,6 +47,31 @@ public class Messages {
}
}
+ /**
+ * Send the given message code to the player with the given tag replacements. Note that this method
+ * issues an exception if the number of supplied replacements doesn't correspond to the number of tags
+ * the message key contains.
+ *
+ * @param sender The entity to send the message to
+ * @param key The key of the message to send
+ * @param replacements The replacements to apply for the tags
+ */
+ public void send(CommandSender sender, MessageKey key, String... replacements) {
+ String message = retrieveSingle(key);
+ String[] tags = key.getTags();
+ if (replacements.length != tags.length) {
+ throw new RuntimeException("Given replacement size does not match the tags in message key '" + key + "'");
+ }
+
+ for (int i = 0; i < tags.length; ++i) {
+ message = message.replace(tags[i], replacements[i]);
+ }
+
+ for (String line : message.split("\n")) {
+ sender.sendMessage(line);
+ }
+ }
+
/**
* Retrieve the message from the text file and return it split by new line as an array.
*
diff --git a/src/main/java/fr/xephi/authme/process/join/AsynchronousJoin.java b/src/main/java/fr/xephi/authme/process/join/AsynchronousJoin.java
index 8a4bd654..dd1eb4b2 100644
--- a/src/main/java/fr/xephi/authme/process/join/AsynchronousJoin.java
+++ b/src/main/java/fr/xephi/authme/process/join/AsynchronousJoin.java
@@ -10,9 +10,9 @@ import fr.xephi.authme.events.FirstSpawnTeleportEvent;
import fr.xephi.authme.events.ProtectInventoryEvent;
import fr.xephi.authme.events.SpawnTeleportEvent;
import fr.xephi.authme.listener.AuthMePlayerListener;
-import fr.xephi.authme.permission.PlayerPermission;
import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.output.Messages;
+import fr.xephi.authme.permission.PlayerPermission;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.Spawn;
import fr.xephi.authme.task.MessageTask;
@@ -78,9 +78,9 @@ public class AsynchronousJoin {
return;
}
if (Settings.getMaxJoinPerIp > 0
- && !plugin.getPermissionsManager().hasPermission(player, PlayerPermission.ALLOW_MULTIPLE_ACCOUNTS)
- && !ip.equalsIgnoreCase("127.0.0.1")
- && !ip.equalsIgnoreCase("localhost")) {
+ && !plugin.getPermissionsManager().hasPermission(player, PlayerPermission.ALLOW_MULTIPLE_ACCOUNTS)
+ && !ip.equalsIgnoreCase("127.0.0.1")
+ && !ip.equalsIgnoreCase("localhost")) {
if (plugin.hasJoinedIp(player.getName(), ip)) {
sched.scheduleSyncDelayedTask(plugin, new Runnable() {
@@ -203,10 +203,6 @@ public class AsynchronousJoin {
if (Settings.applyBlindEffect) {
player.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, timeOut, 2));
}
- if (!Settings.isMovementAllowed && Settings.isRemoveSpeedEnabled) {
- player.setWalkSpeed(0.0f);
- player.setFlySpeed(0.0f);
- }
}
});
@@ -236,8 +232,7 @@ public class AsynchronousJoin {
? m.retrieve(MessageKey.REGISTER_EMAIL_MESSAGE)
: m.retrieve(MessageKey.REGISTER_MESSAGE);
}
- if (LimboCache.getInstance().getLimboPlayer(name) != null)
- {
+ if (LimboCache.getInstance().getLimboPlayer(name) != null) {
BukkitTask msgTask = sched.runTaskAsynchronously(plugin, new MessageTask(plugin, name, msg, msgInterval));
LimboCache.getInstance().getLimboPlayer(name).setMessageTaskId(msgTask);
}
diff --git a/src/main/java/fr/xephi/authme/process/login/AsynchronousLogin.java b/src/main/java/fr/xephi/authme/process/login/AsynchronousLogin.java
index 025defb2..b588361c 100644
--- a/src/main/java/fr/xephi/authme/process/login/AsynchronousLogin.java
+++ b/src/main/java/fr/xephi/authme/process/login/AsynchronousLogin.java
@@ -57,20 +57,10 @@ public class AsynchronousLogin {
this.database = data;
}
- /**
- * Method getIP.
- *
- * @return String
- */
protected String getIP() {
return plugin.getIP(player);
}
- /**
- * Method needsCaptcha.
- *
- * @return boolean
- */
protected boolean needsCaptcha() {
if (Settings.useCaptcha) {
if (!plugin.captcha.containsKey(name)) {
@@ -82,9 +72,7 @@ public class AsynchronousLogin {
}
if (plugin.captcha.containsKey(name) && plugin.captcha.get(name) > Settings.maxLoginTry) {
plugin.cap.putIfAbsent(name, rdm.nextString());
- for (String s : m.retrieve(MessageKey.USAGE_CAPTCHA)) {
- player.sendMessage(s.replace("THE_CAPTCHA", plugin.cap.get(name)).replace("", plugin.cap.get(name)));
- }
+ m.send(player, MessageKey.USAGE_CAPTCHA, plugin.cap.get(name));
return true;
}
}
@@ -230,12 +218,6 @@ public class AsynchronousLogin {
}
}
- /**
- * Method displayOtherAccounts.
- *
- * @param auth PlayerAuth
- * @param p Player
- */
public void displayOtherAccounts(PlayerAuth auth, Player p) {
if (!Settings.displayOtherAccounts) {
return;
diff --git a/src/main/java/fr/xephi/authme/process/login/ProcessSyncronousPlayerLogin.java b/src/main/java/fr/xephi/authme/process/login/ProcessSyncronousPlayerLogin.java
index f64b2274..8c828074 100644
--- a/src/main/java/fr/xephi/authme/process/login/ProcessSyncronousPlayerLogin.java
+++ b/src/main/java/fr/xephi/authme/process/login/ProcessSyncronousPlayerLogin.java
@@ -189,11 +189,6 @@ public class ProcessSyncronousPlayerLogin implements Runnable {
player.removePotionEffect(PotionEffectType.BLINDNESS);
}
- if (!Settings.isMovementAllowed && Settings.isRemoveSpeedEnabled) {
- player.setWalkSpeed(0.2f);
- player.setFlySpeed(0.1f);
- }
-
// The Login event now fires (as intended) after everything is processed
Bukkit.getServer().getPluginManager().callEvent(new LoginEvent(player, true));
player.saveData();
diff --git a/src/main/java/fr/xephi/authme/process/logout/ProcessSyncronousPlayerLogout.java b/src/main/java/fr/xephi/authme/process/logout/ProcessSyncronousPlayerLogout.java
index 8f34c363..4fd6a9ca 100644
--- a/src/main/java/fr/xephi/authme/process/logout/ProcessSyncronousPlayerLogout.java
+++ b/src/main/java/fr/xephi/authme/process/logout/ProcessSyncronousPlayerLogout.java
@@ -80,10 +80,6 @@ public class ProcessSyncronousPlayerLogout implements Runnable {
if (!Settings.isMovementAllowed) {
player.setAllowFlight(true);
player.setFlying(true);
- if (!Settings.isMovementAllowed && Settings.isRemoveSpeedEnabled) {
- player.setFlySpeed(0.0f);
- player.setWalkSpeed(0.0f);
- }
}
// Player is now logout... Time to fire event !
Bukkit.getServer().getPluginManager().callEvent(new LogoutEvent(player));
diff --git a/src/main/java/fr/xephi/authme/process/register/AsyncRegister.java b/src/main/java/fr/xephi/authme/process/register/AsyncRegister.java
index 668c0e3d..fb102ec9 100644
--- a/src/main/java/fr/xephi/authme/process/register/AsyncRegister.java
+++ b/src/main/java/fr/xephi/authme/process/register/AsyncRegister.java
@@ -141,8 +141,10 @@ public class AsyncRegister {
return;
}
if (!Settings.forceRegLogin) {
- PlayerCache.getInstance().addPlayer(auth);
- database.setLogged(name);
+ //PlayerCache.getInstance().addPlayer(auth);
+ //database.setLogged(name);
+ // TODO: check this...
+ plugin.getManagement().performLogin(player, "dontneed", true);
}
plugin.otherAccounts.addPlayer(player.getUniqueId());
ProcessSyncPasswordRegister sync = new ProcessSyncPasswordRegister(player, plugin);
diff --git a/src/main/java/fr/xephi/authme/process/register/ProcessSyncPasswordRegister.java b/src/main/java/fr/xephi/authme/process/register/ProcessSyncPasswordRegister.java
index 4c9136de..17916167 100644
--- a/src/main/java/fr/xephi/authme/process/register/ProcessSyncPasswordRegister.java
+++ b/src/main/java/fr/xephi/authme/process/register/ProcessSyncPasswordRegister.java
@@ -128,11 +128,6 @@ public class ProcessSyncPasswordRegister implements Runnable {
player.removePotionEffect(PotionEffectType.BLINDNESS);
}
- if (!Settings.isMovementAllowed && Settings.isRemoveSpeedEnabled) {
- player.setWalkSpeed(0.0f);
- player.setFlySpeed(0.0f);
- }
-
// The LoginEvent now fires (as intended) after everything is processed
plugin.getServer().getPluginManager().callEvent(new LoginEvent(player, true));
player.saveData();
diff --git a/src/main/java/fr/xephi/authme/process/unregister/AsynchronousUnregister.java b/src/main/java/fr/xephi/authme/process/unregister/AsynchronousUnregister.java
index da5d19f9..53c54b3e 100644
--- a/src/main/java/fr/xephi/authme/process/unregister/AsynchronousUnregister.java
+++ b/src/main/java/fr/xephi/authme/process/unregister/AsynchronousUnregister.java
@@ -104,10 +104,6 @@ public class AsynchronousUnregister {
if (Settings.applyBlindEffect) {
player.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, timeOut, 2));
}
- if (!Settings.isMovementAllowed && Settings.isRemoveSpeedEnabled) {
- player.setWalkSpeed(0.0f);
- player.setFlySpeed(0.0f);
- }
m.send(player, MessageKey.UNREGISTERED_SUCCESS);
ConsoleLogger.info(player.getDisplayName() + " unregistered himself");
Utils.teleportToSpawn(player);
diff --git a/src/main/java/fr/xephi/authme/util/Utils.java b/src/main/java/fr/xephi/authme/util/Utils.java
index e45b04a8..c96f47c6 100644
--- a/src/main/java/fr/xephi/authme/util/Utils.java
+++ b/src/main/java/fr/xephi/authme/util/Utils.java
@@ -15,7 +15,6 @@ import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Player;
-import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
@@ -207,27 +206,6 @@ public final class Utils {
}
}
- /**
- * Delete a given directory and all his content.
- *
- * @param directory File
- */
- public static void purgeDirectory(File directory) {
- if (!directory.isDirectory()) {
- return;
- }
- File[] files = directory.listFiles();
- if (files == null) {
- return;
- }
- for (File target : files) {
- if (target.isDirectory()) {
- purgeDirectory(target);
- }
- target.delete();
- }
- }
-
/**
* Safe way to retrieve the list of online players from the server. Depending on the
* implementation of the server, either an array of {@link Player} instances is being returned,
diff --git a/src/main/resources/messages/messages_cz.yml b/src/main/resources/messages/messages_cz.yml
index 591e4e75..4108ea5a 100644
--- a/src/main/resources/messages/messages_cz.yml
+++ b/src/main/resources/messages/messages_cz.yml
@@ -38,7 +38,7 @@ regex: '&cTvuj nick obsahuje nepovolene znaky. Pripustne znaky jsou: REG_EX'
add_email: '&cPridej prosim svuj email pomoci : /email add TvujEmail TvujEmail'
recovery_email: '&cZapomel jsi heslo? Zadej: /email recovery '
usage_captcha: '&cPouzij: /captcha '
-wrong_captcha: '&cSpatne opsana Captcha, pouzij prosim: /captcha CAPTCHA_TEXT'
+wrong_captcha: '&cSpatne opsana Captcha, pouzij prosim: /captcha THE_CAPTCHA'
valid_captcha: '&cZadana captcha je v poradku!'
kick_forvip: '&cVIP Hrac se pripojil na plny server!'
kick_fullserver: '&cServer je plne obsazen, zkus to pozdeji prosim!'
diff --git a/src/main/resources/messages/messages_en.yml b/src/main/resources/messages/messages_en.yml
index fdb361a3..2d26cb1f 100644
--- a/src/main/resources/messages/messages_en.yml
+++ b/src/main/resources/messages/messages_en.yml
@@ -14,7 +14,7 @@ user_regged: '&cYou already have registered this username!'
usage_reg: '&cUsage: /register '
max_reg: '&cYou have exceeded the maximum number of registrations for your connection!'
no_perm: '&4You don''t have the permission to perform this action!'
-error: '&4An unexpected error occurred, please contact an Administrator!'
+error: '&4An unexpected error occurred, please contact an administrator!'
login_msg: '&cPlease, login with the command "/login "'
reg_msg: '&3Please, register to the server with the command "/register "'
reg_email_msg: '&3Please, register to the server with the command "/register "'
@@ -39,20 +39,20 @@ regex: '&4Your username contains illegal characters. Allowed chars: REG_EX'
add_email: '&3Please add your email to your account with the command "/email add "'
recovery_email: '&3Forgot your password? Please use the command "/email recovery "'
usage_captcha: '&3To login you have to solve a captcha code, please use the command "/captcha "'
-wrong_captcha: '&cWrong Captcha, please type "/captcha THE_CAPTCHA" into the chat!'
+wrong_captcha: '&cWrong captcha, please type "/captcha THE_CAPTCHA" into the chat!'
valid_captcha: '&2Captcha code solved correctly!'
-kick_forvip: '&3A VIP Player has joined the server when it was full!'
+kick_forvip: '&3A VIP player has joined the server when it was full!'
kick_fullserver: '&4The server is full, try again later!'
usage_email_add: '&cUsage: /email add '
usage_email_change: '&cUsage: /email change '
usage_email_recovery: '&cUsage: /email recovery '
-new_email_invalid: '&cInvalid New Email, try again!'
-old_email_invalid: '&cInvalid Old Email, try again!'
-email_invalid: '&cInvalid Email address, try again!'
+new_email_invalid: '&cInvalid new email, try again!'
+old_email_invalid: '&cInvalid old email, try again!'
+email_invalid: '&cInvalid email address, try again!'
email_added: '&2Email address successfully added to your account!'
email_confirm: '&cPlease confirm your email address!'
email_changed: '&2Email address changed correctly!'
-email_send: '&2Recovery email sent correctly! Check your email inbox!'
+email_send: '&2Recovery email sent successfully! Please check your email inbox!'
email_exists: '&cA recovery email was already sent! You can discard it and send a new one using the command below:'
country_banned: '&4Your country is banned from this server!'
antibot_auto_enabled: '&4[AntiBotService] AntiBot enabled due to the huge number of connections!'
diff --git a/src/main/resources/messages/messages_es.yml b/src/main/resources/messages/messages_es.yml
index 850d750a..a7066330 100644
--- a/src/main/resources/messages/messages_es.yml
+++ b/src/main/resources/messages/messages_es.yml
@@ -39,7 +39,7 @@ regex: '&cTu usuario tiene carácteres no admitidos, los cuales son: REG_EX'
add_email: '&cPor favor agrega tu e-mail con: /email add tuEmail confirmarEmail'
recovery_email: '&c¿Olvidaste tu contraseña? Por favor usa /email recovery '
usage_captcha: '&cUso: /captcha '
-wrong_captcha: '&cCaptcha incorrecto, please use : /captcha EL_CAPTCHA'
+wrong_captcha: '&cCaptcha incorrecto, please use : /captcha THE_CAPTCHA'
valid_captcha: '&c¡ Captcha ingresado correctamente !'
kick_forvip: '&cUn jugador VIP ha ingresado al servidor lleno!'
kick_fullserver: '&cEl servidor está lleno, lo sentimos!'
diff --git a/src/main/resources/messages/messages_hu.yml b/src/main/resources/messages/messages_hu.yml
index 3245ce1a..f52e4f2b 100644
--- a/src/main/resources/messages/messages_hu.yml
+++ b/src/main/resources/messages/messages_hu.yml
@@ -1,4 +1,4 @@
-reg_only: Csak regisztrált játékosoknak! Jelentkezni a yndicraft@freemail.hu e-mail címen lehet
+reg_only: Csak regisztrált játékosoknak! Jelentkezni a mail@email.com e-mail címen lehet
usage_unreg: '&cHasználat: /unregister jelszó'
registered: '&aSikeres regisztráció. Üdvözöllek!'
user_regged: '&cJátékosnév már regisztrálva'
diff --git a/src/test/java/fr/xephi/authme/command/CommandInitializerTest.java b/src/test/java/fr/xephi/authme/command/CommandInitializerTest.java
index 66e77450..3df6cd13 100644
--- a/src/test/java/fr/xephi/authme/command/CommandInitializerTest.java
+++ b/src/test/java/fr/xephi/authme/command/CommandInitializerTest.java
@@ -5,6 +5,7 @@ import fr.xephi.authme.permission.PermissionNode;
import fr.xephi.authme.util.StringUtils;
import fr.xephi.authme.util.WrapperMock;
import org.junit.BeforeClass;
+import org.junit.Ignore;
import org.junit.Test;
import java.util.ArrayList;
@@ -269,6 +270,42 @@ public class CommandInitializerTest {
walkThroughCommands(commands, adminPermissionChecker);
}
+ /**
+ * Tests that multiple CommandDescription instances pointing to the same ExecutableCommand use the same
+ * count of arguments.
+ */
+ @Test
+ @Ignore // TODO #306 ljacqu 20151214: Un-ignore this test and fix the offending command
+ public void shouldPointToSameExecutableCommandWithConsistentArgumentCount() {
+ // given
+ final Map, Integer> mandatoryArguments = new HashMap<>();
+ final Map, Integer> totalArguments = new HashMap<>();
+
+ BiConsumer argChecker = new BiConsumer() {
+ @Override
+ public void accept(CommandDescription command, int depth) {
+ testCollectionForCommand(command, CommandUtils.getMinNumberOfArguments(command), mandatoryArguments);
+ testCollectionForCommand(command, CommandUtils.getMaxNumberOfArguments(command), totalArguments);
+ }
+ private void testCollectionForCommand(CommandDescription command, int argCount,
+ Map, Integer> collection) {
+ final Class extends ExecutableCommand> clazz = command.getExecutableCommand().getClass();
+ Integer existingCount = collection.get(clazz);
+ if (existingCount != null) {
+ String commandDescription = "Command with label '" + command.getLabels().get(0) + "' and parent '"
+ + (command.getParent() != null ? command.getLabels().get(0) : "null") + "' ";
+ assertThat(commandDescription + "should point to " + clazz + " with arguments consistent to others",
+ argCount, equalTo(existingCount));
+ } else {
+ collection.put(clazz, argCount);
+ }
+ }
+ };
+
+ // when / then
+ walkThroughCommands(commands, argChecker);
+ }
+
// ------------
// Helper methods
diff --git a/src/test/java/fr/xephi/authme/output/MessagesIntegrationTest.java b/src/test/java/fr/xephi/authme/output/MessagesIntegrationTest.java
index aa7367e2..343a5687 100644
--- a/src/test/java/fr/xephi/authme/output/MessagesIntegrationTest.java
+++ b/src/test/java/fr/xephi/authme/output/MessagesIntegrationTest.java
@@ -2,9 +2,11 @@ package fr.xephi.authme.output;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.util.WrapperMock;
+import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.junit.Before;
import org.junit.Test;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
import java.io.File;
@@ -14,6 +16,8 @@ import static org.hamcrest.Matchers.arrayWithSize;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.startsWith;
import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
/**
@@ -137,4 +141,58 @@ public class MessagesIntegrationTest {
verify(player).sendMessage(line);
}
}
+
+ @Test
+ public void shouldSendMessageToPlayerWithTagReplacement() {
+ // given
+ MessageKey key = MessageKey.CAPTCHA_WRONG_ERROR;
+ CommandSender sender = Mockito.mock(CommandSender.class);
+
+ // when
+ messages.send(sender, key, "1234");
+
+ // then
+ ArgumentCaptor captor = ArgumentCaptor.forClass(String.class);
+ verify(sender, times(1)).sendMessage(captor.capture());
+ String message = captor.getValue();
+ assertThat(message, equalTo("Use /captcha 1234 to solve the captcha"));
+ }
+
+ @Test
+ public void shouldNotThrowForKeyWithNoTagReplacements() {
+ // given
+ MessageKey key = MessageKey.CAPTCHA_WRONG_ERROR;
+ CommandSender sender = mock(CommandSender.class);
+
+ // when
+ messages.send(sender, key);
+
+ // then
+ ArgumentCaptor captor = ArgumentCaptor.forClass(String.class);
+ verify(sender, times(1)).sendMessage(captor.capture());
+ String message = captor.getValue();
+ assertThat(message, equalTo("Use /captcha THE_CAPTCHA to solve the captcha"));
+ }
+
+ @Test(expected = RuntimeException.class)
+ public void shouldThrowForInvalidReplacementCount() {
+ // given
+ MessageKey key = MessageKey.CAPTCHA_WRONG_ERROR;
+
+ // when
+ messages.send(mock(CommandSender.class), key, "rep", "rep2");
+
+ // then - expect exception
+ }
+
+ @Test(expected = RuntimeException.class)
+ public void shouldThrowForReplacementsOnKeyWithNoTags() {
+ // given
+ MessageKey key = MessageKey.UNKNOWN_USER;
+
+ // when
+ messages.send(mock(CommandSender.class), key, "Replacement");
+
+ // then - expect exception
+ }
}
diff --git a/src/test/java/fr/xephi/authme/permission/AdminPermissionTest.java b/src/test/java/fr/xephi/authme/permission/AdminPermissionTest.java
index 9a8625ac..0c2c2b16 100644
--- a/src/test/java/fr/xephi/authme/permission/AdminPermissionTest.java
+++ b/src/test/java/fr/xephi/authme/permission/AdminPermissionTest.java
@@ -13,9 +13,9 @@ import static org.junit.Assert.fail;
public class AdminPermissionTest {
@Test
- public void shouldStartWithAuthMePrefix() {
+ public void shouldStartWithAuthMeAdminPrefix() {
// given
- String requiredPrefix = "authme.";
+ String requiredPrefix = "authme.admin.";
// when/then
for (AdminPermission permission : AdminPermission.values()) {
@@ -26,20 +26,6 @@ public class AdminPermissionTest {
}
}
- @Test
- public void shouldContainAdminBranch() {
- // given
- String requiredBranch = ".admin.";
-
- // when/then
- for (AdminPermission permission : AdminPermission.values()) {
- if (!permission.getNode().contains(requiredBranch)) {
- fail("The permission '" + permission + "' does not contain with the required branch '"
- + requiredBranch + "'");
- }
- }
- }
-
@Test
public void shouldHaveUniqueNodes() {
// given
diff --git a/src/test/java/fr/xephi/authme/permission/PlayerPermissionTest.java b/src/test/java/fr/xephi/authme/permission/PlayerPermissionTest.java
index 6afc0ac0..632a2cf3 100644
--- a/src/test/java/fr/xephi/authme/permission/PlayerPermissionTest.java
+++ b/src/test/java/fr/xephi/authme/permission/PlayerPermissionTest.java
@@ -13,32 +13,13 @@ import static org.junit.Assert.fail;
public class PlayerPermissionTest {
@Test
- public void shouldStartWithAuthMePrefix() {
+ public void shouldStartWithPlayerPrefix() {
// given
- String requiredPrefix = "authme.";
+ String playerBranch = "authme.player.";
// when/then
for (PlayerPermission permission : PlayerPermission.values()) {
- if (!permission.getNode().startsWith(requiredPrefix)) {
- fail("The permission '" + permission + "' does not start with the required prefix '" + requiredPrefix
- + "'");
- }
- }
- }
-
- @Test
- public void shouldContainPlayerBranch() {
- // given
- String playerBranch = ".player.";
- String adminBranch = ".admin.";
-
- // when/then
- for (PlayerPermission permission : PlayerPermission.values()) {
- if (permission.getNode().contains(adminBranch)) {
- fail("The permission '" + permission + "' should not use a node with the admin-specific branch '"
- + adminBranch + "'");
-
- } else if (!permission.getNode().contains(playerBranch)) {
+ if (!permission.getNode().startsWith(playerBranch)) {
fail("The permission '" + permission + "' should use a node with the player-specific branch '"
+ playerBranch + "'");
}
diff --git a/src/test/resources/messages_test.yml b/src/test/resources/messages_test.yml
index 23dd12bd..73aea93e 100644
--- a/src/test/resources/messages_test.yml
+++ b/src/test/resources/messages_test.yml
@@ -4,3 +4,4 @@ not_logged_in: 'Apostrophes '' should be loaded correctly, don''t you think?'
reg_voluntarily: 'You can register yourself to the server with the command "/register "'
usage_log: '&cUsage: /login '
wrong_pwd: '&cWrong password!'
+wrong_captcha: 'Use /captcha THE_CAPTCHA to solve the captcha'
diff --git a/src/tools/commands/CommandPageCreater.java b/src/tools/commands/CommandPageCreater.java
new file mode 100644
index 00000000..4d74dfba
--- /dev/null
+++ b/src/tools/commands/CommandPageCreater.java
@@ -0,0 +1,70 @@
+package commands;
+
+import fr.xephi.authme.command.CommandArgumentDescription;
+import fr.xephi.authme.command.CommandDescription;
+import fr.xephi.authme.command.CommandInitializer;
+import fr.xephi.authme.command.CommandPermissions;
+import fr.xephi.authme.command.CommandUtils;
+import fr.xephi.authme.permission.PermissionNode;
+import utils.ANewMap;
+import utils.FileUtils;
+import utils.TagReplacer;
+import utils.ToolTask;
+import utils.ToolsConstants;
+
+import java.util.Map;
+import java.util.Scanner;
+import java.util.Set;
+
+public class CommandPageCreater implements ToolTask {
+
+ @Override
+ public String getTaskName() {
+ return "createCommandPage";
+ }
+
+ @Override
+ public void execute(Scanner scanner) {
+ final Set baseCommands = CommandInitializer.getBaseCommands();
+ final String template = FileUtils.readFromFile(ToolsConstants.TOOLS_SOURCE_ROOT
+ + "commands/command_entry.tpl.md");
+
+ StringBuilder commandsResult = new StringBuilder();
+ for (CommandDescription command : baseCommands) {
+ Map tags = ANewMap
+ .with("command", CommandUtils.constructCommandPath(command))
+ .and("description", command.getDetailedDescription())
+ .and("arguments", formatArguments(command.getArguments()))
+ .and("permissions", formatPermissions(command.getCommandPermissions()))
+ .build();
+ commandsResult.append(TagReplacer.applyReplacements(template, tags));
+ }
+
+ FileUtils.generateFileFromTemplate(
+ ToolsConstants.TOOLS_SOURCE_ROOT + "commands/commands.tpl.md",
+ ToolsConstants.DOCS_FOLDER + "commands.md",
+ ANewMap.with("commands", commandsResult.toString()).build());
+ }
+
+ private static String formatPermissions(CommandPermissions permissions) {
+ if (permissions == null) {
+ return "";
+ }
+ String result = "";
+ for (PermissionNode node : permissions.getPermissionNodes()) {
+ result += node.getNode() + " ";
+ }
+ return result;
+ }
+
+ private static String formatArguments(Iterable arguments) {
+ StringBuilder result = new StringBuilder();
+ for (CommandArgumentDescription argument : arguments) {
+ String argumentName = argument.isOptional()
+ ? "[" + argument.getDescription() + "]"
+ : "<" + argument.getDescription() + ">";
+ result.append(argumentName).append(" ");
+ }
+ return result.toString();
+ }
+}
diff --git a/src/tools/commands/command_entry.tpl.md b/src/tools/commands/command_entry.tpl.md
new file mode 100644
index 00000000..c39b1deb
--- /dev/null
+++ b/src/tools/commands/command_entry.tpl.md
@@ -0,0 +1,2 @@
+{command}: {description} _{arguments}_
+[permissions]Permission: {permissions}[/permissions]
diff --git a/src/tools/commands/commands.tpl.md b/src/tools/commands/commands.tpl.md
new file mode 100644
index 00000000..f2334c1b
--- /dev/null
+++ b/src/tools/commands/commands.tpl.md
@@ -0,0 +1,4 @@
+## AuthMe commands
+You can use the following commands to use the functions of AuthMe:
+
+{commands}
diff --git a/src/tools/messages/MessageFileVerifier.java b/src/tools/messages/MessageFileVerifier.java
index 75e9927e..904ea1af 100644
--- a/src/tools/messages/MessageFileVerifier.java
+++ b/src/tools/messages/MessageFileVerifier.java
@@ -1,11 +1,15 @@
package messages;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Multimap;
import fr.xephi.authme.output.MessageKey;
import utils.FileUtils;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -22,6 +26,7 @@ public class MessageFileVerifier {
private final Set unknownKeys = new HashSet<>();
// Map with the missing key and a boolean indicating whether or not it was added to the file by this object
private final Map missingKeys = new HashMap<>();
+ private final Multimap missingTags = HashMultimap.create();
/**
* Create a verifier that verifies the given messages file.
@@ -53,8 +58,17 @@ public class MessageFileVerifier {
return missingKeys;
}
+ /**
+ * Return the collection of tags the message key defines that aren't present in the read line.
+ *
+ * @return Collection of missing tags per message key. Key = message key, value = missing tag.
+ */
+ public Multimap getMissingTags() {
+ return missingTags;
+ }
+
private void verifyKeys() {
- Set messageKeys = getAllMessageKeys();
+ List messageKeys = getAllMessageKeys();
List fileLines = FileUtils.readLinesFromFile(messagesFile);
for (String line : fileLines) {
// Skip comments and empty lines
@@ -64,22 +78,38 @@ public class MessageFileVerifier {
}
// All keys that remain are keys that are absent in the file
- for (String missingKey : messageKeys) {
- missingKeys.put(missingKey, false);
+ for (MessageKey missingKey : messageKeys) {
+ missingKeys.put(missingKey.getKey(), false);
}
}
- private void processKeyInFile(String line, Set messageKeys) {
+ private void processKeyInFile(String line, List messageKeys) {
if (line.indexOf(':') == -1) {
System.out.println("Skipping line in unknown format: '" + line + "'");
return;
}
- final String key = line.substring(0, line.indexOf(':'));
- if (messageKeys.contains(key)) {
- messageKeys.remove(key);
- } else {
- unknownKeys.add(key);
+ final String readKey = line.substring(0, line.indexOf(':'));
+ boolean foundKey = false;
+ for (Iterator it = messageKeys.iterator(); it.hasNext(); ) {
+ MessageKey messageKey = it.next();
+ if (messageKey.getKey().equals(readKey)) {
+ checkTagsInMessage(readKey, line.substring(line.indexOf(':')), messageKey.getTags());
+ it.remove();
+ foundKey = true;
+ break;
+ }
+ }
+ if (!foundKey) {
+ unknownKeys.add(readKey);
+ }
+ }
+
+ private void checkTagsInMessage(String key, String message, String[] tags) {
+ for (String tag : tags) {
+ if (!message.contains(tag)) {
+ missingTags.put(key, tag);
+ }
}
}
@@ -105,11 +135,7 @@ public class MessageFileVerifier {
FileUtils.appendToFile(messagesFile, sb.toString());
}
- private static Set getAllMessageKeys() {
- Set messageKeys = new HashSet<>(MessageKey.values().length);
- for (MessageKey key : MessageKey.values()) {
- messageKeys.add(key.getKey());
- }
- return messageKeys;
+ private static List getAllMessageKeys() {
+ return new ArrayList<>(Arrays.asList(MessageKey.values()));
}
}
diff --git a/src/tools/messages/VerifyMessagesTask.java b/src/tools/messages/VerifyMessagesTask.java
index 2a371216..19eacf24 100644
--- a/src/tools/messages/VerifyMessagesTask.java
+++ b/src/tools/messages/VerifyMessagesTask.java
@@ -1,5 +1,6 @@
package messages;
+import com.google.common.collect.Multimap;
import fr.xephi.authme.util.StringUtils;
import utils.FileUtils;
import utils.ToolTask;
@@ -84,6 +85,11 @@ public final class VerifyMessagesTask implements ToolTask {
if (!unknownKeys.isEmpty()) {
System.out.println(" Unknown keys: " + unknownKeys);
}
+
+ Multimap missingTags = verifier.getMissingTags();
+ for (Map.Entry entry : missingTags.entries()) {
+ System.out.println(" Missing tag '" + entry.getValue() + "' in entry with key '" + entry.getKey() + "'");
+ }
}
private static void verifyFileAndAddKeys(MessageFileVerifier verifier, Map defaultMessages) {
@@ -106,6 +112,11 @@ public final class VerifyMessagesTask implements ToolTask {
if (!unknownKeys.isEmpty()) {
System.out.println(" Unknown keys: " + unknownKeys);
}
+
+ Multimap missingTags = verifier.getMissingTags();
+ for (Map.Entry entry : missingTags.entries()) {
+ System.out.println(" Missing tag '" + entry.getValue() + "' in entry with key '" + entry.getKey() + "'");
+ }
}
private static Map constructDefaultMessages() {
diff --git a/src/tools/permissions/PermissionsListWriter.java b/src/tools/permissions/PermissionsListWriter.java
index 1d06b8ce..5958e077 100644
--- a/src/tools/permissions/PermissionsListWriter.java
+++ b/src/tools/permissions/PermissionsListWriter.java
@@ -47,7 +47,7 @@ public class PermissionsListWriter implements ToolTask {
private static void generateAndWriteFile() {
final String permissionsTagValue = generatePermissionsList();
- Map tags = ANewMap.with("permissions", permissionsTagValue).build();
+ Map tags = ANewMap.with("permissions", permissionsTagValue).build();
FileUtils.generateFileFromTemplate(
ToolsConstants.TOOLS_SOURCE_ROOT + "permissions/permission_nodes.tpl.md", PERMISSIONS_OUTPUT_FILE, tags);
System.out.println("Wrote to '" + PERMISSIONS_OUTPUT_FILE + "'");
@@ -62,8 +62,8 @@ public class PermissionsListWriter implements ToolTask {
StringBuilder sb = new StringBuilder();
for (Map.Entry entry : permissions.entrySet()) {
- Map tags = ANewMap.
- with("node", entry.getKey())
+ Map tags = ANewMap
+ .with("node", entry.getKey())
.and("description", entry.getValue())
.build();
sb.append(TagReplacer.applyReplacements(template, tags));
diff --git a/src/tools/utils/FileUtils.java b/src/tools/utils/FileUtils.java
index 5ad5ab25..49bcab9f 100644
--- a/src/tools/utils/FileUtils.java
+++ b/src/tools/utils/FileUtils.java
@@ -18,10 +18,9 @@ public final class FileUtils {
private FileUtils() {
}
- public static void generateFileFromTemplate(String templateFile, String destinationFile, Map tags) {
+ public static void generateFileFromTemplate(String templateFile, String destinationFile, Map tags) {
String template = readFromFile(templateFile);
String result = TagReplacer.applyReplacements(template, tags);
-
writeToFile(destinationFile, result);
}
diff --git a/src/tools/utils/TagReplacer.java b/src/tools/utils/TagReplacer.java
index 404857b7..29a9b91c 100644
--- a/src/tools/utils/TagReplacer.java
+++ b/src/tools/utils/TagReplacer.java
@@ -1,5 +1,7 @@
package utils;
+import fr.xephi.authme.util.StringUtils;
+
import java.util.Date;
import java.util.Map;
@@ -21,10 +23,15 @@ public class TagReplacer {
* any occurrences of "{foo}" to "bar".
* @return The filled template
*/
- public static String applyReplacements(String template, Map tags) {
+ public static String applyReplacements(String template, Map tags) {
String result = template;
- for (Map.Entry tagRule : tags.entrySet()) {
- result = result.replace("{" + tagRule.getKey() + "}", tagRule.getValue().toString());
+ for (Map.Entry tagRule : tags.entrySet()) {
+ final String name = tagRule.getKey();
+ final String value = tagRule.getValue();
+
+ String replacement = StringUtils.isEmpty(value) ? "" : "\\1";
+ result = result.replaceAll("\\[" + name + "\\](.*?)\\[/" + name + "\\]", replacement);
+ result = result.replace("{" + tagRule.getKey() + "}", tagRule.getValue());
}
return applyReplacements(result);