From 09acbcdb05f34e0043116f1866904b0ff0f03ddd Mon Sep 17 00:00:00 2001 From: Ali Moghnieh Date: Tue, 28 Jun 2016 03:40:47 +0100 Subject: [PATCH] Implement Command Cooldowns. Resolves #110 --- .../essentials/EssentialsPlayerListener.java | 45 +++++++++- .../com/earth2me/essentials/ISettings.java | 10 +++ .../src/com/earth2me/essentials/IUser.java | 10 +++ .../src/com/earth2me/essentials/Settings.java | 89 +++++++++++++++++++ .../src/com/earth2me/essentials/UserData.java | 87 ++++++++++++++++++ Essentials/src/config.yml | 18 ++++ Essentials/src/messages.properties | 1 + Essentials/src/messages_cs.properties | 3 +- Essentials/src/messages_da.properties | 3 +- Essentials/src/messages_de.properties | 1 + Essentials/src/messages_en.properties | 1 + Essentials/src/messages_es.properties | 3 +- Essentials/src/messages_et.properties | 3 +- Essentials/src/messages_fi.properties | 3 +- Essentials/src/messages_fr.properties | 1 + Essentials/src/messages_hu.properties | 3 +- Essentials/src/messages_it.properties | 3 +- Essentials/src/messages_ko.properties | 3 +- Essentials/src/messages_lt.properties | 3 +- Essentials/src/messages_nl.properties | 3 +- Essentials/src/messages_pl.properties | 3 +- Essentials/src/messages_pt.properties | 3 +- Essentials/src/messages_pt_BR.properties | 3 +- Essentials/src/messages_ro.properties | 3 +- Essentials/src/messages_ru.properties | 3 +- Essentials/src/messages_sv.properties | 3 +- Essentials/src/messages_tr.properties | 3 +- Essentials/src/messages_zh.properties | 3 +- Essentials/src/messages_zh_HK.properties | 3 +- Essentials/src/messages_zh_TW.properties | 3 +- 30 files changed, 302 insertions(+), 21 deletions(-) diff --git a/Essentials/src/com/earth2me/essentials/EssentialsPlayerListener.java b/Essentials/src/com/earth2me/essentials/EssentialsPlayerListener.java index a51daa968..1f3d7ff4c 100644 --- a/Essentials/src/com/earth2me/essentials/EssentialsPlayerListener.java +++ b/Essentials/src/com/earth2me/essentials/EssentialsPlayerListener.java @@ -4,6 +4,7 @@ import com.earth2me.essentials.textreader.IText; import com.earth2me.essentials.textreader.KeywordReplacer; import com.earth2me.essentials.textreader.TextInput; import com.earth2me.essentials.textreader.TextPager; +import com.earth2me.essentials.utils.DateUtil; import com.earth2me.essentials.utils.LocationUtil; import net.ess3.api.IEssentials; import org.bukkit.GameMode; @@ -26,11 +27,15 @@ import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.ItemStack; import java.io.IOException; +import java.util.Date; +import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Locale; +import java.util.Map.Entry; import java.util.logging.Level; import java.util.logging.Logger; +import java.util.regex.Pattern; import static com.earth2me.essentials.I18n.tl; @@ -399,10 +404,48 @@ public class EssentialsPlayerListener implements Listener { broadcast = false; } } + final User user = ess.getUser(player); if (update) { - final User user = ess.getUser(player); user.updateActivity(broadcast); } + + if (ess.getSettings().isCommandCooldownsEnabled() && pluginCommand != null) { + int argStartIndex = event.getMessage().indexOf(" "); + String args = argStartIndex == -1 ? event.getMessage() // No arguments present + : event.getMessage().substring(argStartIndex); // arguments start at argStartIndex; substring from there. + String fullCommand = pluginCommand.getName() + " " + args; + + // Used to determine whether a user already has an existing cooldown + // If so, no need to check for (and write) new ones. + boolean cooldownFound = false; + + // Iterate over a copy of getCommandCooldowns in case of concurrent modifications + for (Entry entry : new HashMap<>(user.getCommandCooldowns()).entrySet()) { + // Remove any expired cooldowns + if (entry.getValue() <= System.currentTimeMillis()) { + user.clearCommandCooldown(entry.getKey()); + // Don't break in case there are other command cooldowns left to clear. + } else if (entry.getKey().matcher(fullCommand).matches()) { + // User's current cooldown hasn't expired, inform and terminate cooldown code. + if (entry.getValue() > System.currentTimeMillis()) { + String commandCooldownTime = DateUtil.formatDateDiff(entry.getValue()); + user.sendMessage(tl("commandCooldown", commandCooldownTime)); + cooldownFound = true; + event.setCancelled(true); + break; + } + } + } + + if (!cooldownFound) { + Entry cooldownEntry = ess.getSettings().getCommandCooldownEntry(fullCommand); + + if (cooldownEntry != null) { + Date expiry = new Date(System.currentTimeMillis() + cooldownEntry.getValue()); + user.addCommandCooldown(cooldownEntry.getKey(), expiry, ess.getSettings().isCommandCooldownPersistent(fullCommand)); + } + } + } } @EventHandler(priority = EventPriority.NORMAL) diff --git a/Essentials/src/com/earth2me/essentials/ISettings.java b/Essentials/src/com/earth2me/essentials/ISettings.java index 441ea45dc..3d7e5918b 100644 --- a/Essentials/src/com/earth2me/essentials/ISettings.java +++ b/Essentials/src/com/earth2me/essentials/ISettings.java @@ -10,7 +10,9 @@ import org.bukkit.event.EventPriority; import java.math.BigDecimal; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Set; +import java.util.regex.Pattern; public interface ISettings extends IConf { @@ -247,4 +249,12 @@ public interface ISettings extends IConf { boolean isSpawnOnJoin(); boolean isTeleportToCenterLocation(); + + boolean isCommandCooldownsEnabled(); + + long getCommandCooldownMs(String label); + + Entry getCommandCooldownEntry(String label); + + boolean isCommandCooldownPersistent(String label); } diff --git a/Essentials/src/com/earth2me/essentials/IUser.java b/Essentials/src/com/earth2me/essentials/IUser.java index f01fad053..057738822 100644 --- a/Essentials/src/com/earth2me/essentials/IUser.java +++ b/Essentials/src/com/earth2me/essentials/IUser.java @@ -7,9 +7,11 @@ import org.bukkit.Location; import org.bukkit.entity.Player; import java.math.BigDecimal; +import java.util.Date; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.regex.Pattern; public interface IUser { @@ -138,6 +140,14 @@ public interface IUser { Map getConfigMap(); Map getConfigMap(String node); + + Map getCommandCooldowns(); + + Date getCommandCooldownExpiry(String label); + + void addCommandCooldown(Pattern pattern, Date expiresAt, boolean save); + + boolean clearCommandCooldown(Pattern pattern); /* * PlayerExtension diff --git a/Essentials/src/com/earth2me/essentials/Settings.java b/Essentials/src/com/earth2me/essentials/Settings.java index f34a75507..8c69e5564 100644 --- a/Essentials/src/com/earth2me/essentials/Settings.java +++ b/Essentials/src/com/earth2me/essentials/Settings.java @@ -16,10 +16,13 @@ import org.bukkit.inventory.ItemStack; import java.io.File; import java.math.BigDecimal; import java.util.*; +import java.util.Map.Entry; import java.util.logging.Level; import java.util.logging.Logger; import static com.earth2me.essentials.I18n.tl; +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; public class Settings implements net.ess3.api.ISettings { @@ -532,6 +535,7 @@ public class Settings implements net.ess3.api.ISettings { customQuitMessage = _getCustomQuitMessage(); isCustomQuitMessage = !customQuitMessage.equals("none"); muteCommands = _getMuteCommands(); + commandCooldowns = _getCommandCooldowns(); } private List itemSpawnBl = new ArrayList(); @@ -1173,4 +1177,89 @@ public class Settings implements net.ess3.api.ISettings { public boolean isTeleportToCenterLocation() { return config.getBoolean("teleport-to-center", true); } + + + private Map commandCooldowns; + + private Map _getCommandCooldowns() { + if (!config.isConfigurationSection("command-cooldowns")) { + return null; + } + ConfigurationSection section = config.getConfigurationSection("command-cooldowns"); + Map result = new LinkedHashMap<>(); + for (String cmdEntry : section.getKeys(false)) { + Pattern pattern = null; + + /* ================================ + * >> Regex + * ================================ */ + if (cmdEntry.startsWith("^")) { + try { + pattern = Pattern.compile(cmdEntry.substring(1)); + } catch (PatternSyntaxException e) { + ess.getLogger().warning("Command cooldown error: " + e.getMessage()); + } + } else { + // Escape above Regex + if (cmdEntry.startsWith("\\^")) { + cmdEntry = cmdEntry.substring(1); + } + String cmd = cmdEntry + .replaceAll("\\*", ".*"); // Wildcards are accepted as asterisk * as known universally. + pattern = Pattern.compile(cmd + "( .*)?"); // This matches arguments, if present, to "ignore" them from the feature. + } + + /* ================================ + * >> Process cooldown value + * ================================ */ + Object value = section.get(cmdEntry); + if (!(value instanceof Number) && value instanceof String) { + try { + value = Double.parseDouble(value.toString()); + } catch (NumberFormatException ignored) { + } + } + if (!(value instanceof Number)) { + ess.getLogger().warning("Command cooldown error: '" + value + "' is not a valid cooldown"); + continue; + } + double cooldown = ((Number) value).doubleValue(); + if (cooldown < 1) { + ess.getLogger().warning("Command cooldown with very short " + cooldown + " cooldown."); + } + + result.put(pattern, (long) cooldown * 1000); // convert to milliseconds + } + return result; + } + + @Override + public boolean isCommandCooldownsEnabled() { + return commandCooldowns != null; + } + + @Override + public long getCommandCooldownMs(String label) { + Entry result = getCommandCooldownEntry(label); + return result != null ? result.getValue() : -1; // return cooldown in milliseconds + } + + @Override + public Entry getCommandCooldownEntry(String label) { + if (isCommandCooldownsEnabled()) { + for (Entry entry : this.commandCooldowns.entrySet()) { + // Check if label matches current pattern (command-cooldown in config) + if (entry.getKey().matcher(label).matches()) { + return entry; + } + } + } + return null; + } + + @Override + public boolean isCommandCooldownPersistent(String label) { + // TODO: enable per command cooldown specification for persistence. + return config.getBoolean("command-cooldown-persistence", true); + } } diff --git a/Essentials/src/com/earth2me/essentials/UserData.java b/Essentials/src/com/earth2me/essentials/UserData.java index eecf3ff1a..ee4a06b1a 100644 --- a/Essentials/src/com/earth2me/essentials/UserData.java +++ b/Essentials/src/com/earth2me/essentials/UserData.java @@ -2,6 +2,7 @@ package com.earth2me.essentials; import com.earth2me.essentials.utils.NumberUtil; import com.earth2me.essentials.utils.StringUtil; +import com.google.common.collect.ImmutableMap; import net.ess3.api.IEssentials; import net.ess3.api.InvalidWorldException; import net.ess3.api.MaxMoneyException; @@ -13,6 +14,8 @@ import org.bukkit.inventory.ItemStack; import java.io.File; import java.math.BigDecimal; import java.util.*; +import java.util.Map.Entry; +import java.util.regex.Pattern; import static com.earth2me.essentials.I18n.tl; @@ -85,6 +88,7 @@ public abstract class UserData extends PlayerExtension implements IConf { ignoredPlayers = _getIgnoredPlayers(); logoutLocation = _getLogoutLocation(); lastAccountName = _getLastAccountName(); + commandCooldowns = _getCommandCooldowns(); } private BigDecimal money; @@ -792,6 +796,89 @@ public abstract class UserData extends PlayerExtension implements IConf { return new HashMap(); } + // Pattern, Date. Pattern for less pattern creations + private Map commandCooldowns; + + private Map _getCommandCooldowns() { + if (!config.isConfigurationSection("timestamps.command-cooldowns")) { + return null; + } + + // See saveCommandCooldowns() for deserialization explanation + List> section = config.getMapList("timestamps.command-cooldowns"); + HashMap result = new HashMap<>(); + for (Map map : section) { + Pattern pattern = Pattern.compile(map.get("pattern").toString()); + long expiry = ((Number) map.get("expiry")).longValue(); + result.put(pattern, expiry); + } + return result; + } + + public Map getCommandCooldowns() { + if (this.commandCooldowns == null) { + return Collections.emptyMap(); + } + return Collections.unmodifiableMap(this.commandCooldowns); + } + + public Date getCommandCooldownExpiry(String label) { + if (commandCooldowns != null) { + for (Entry entry : this.commandCooldowns.entrySet()) { + if (entry.getKey().matcher(label).matches()) { + return new Date(entry.getValue()); + } + } + } + return null; + } + + public void addCommandCooldown(Pattern pattern, Date expiresAt, boolean save) { + if (this.commandCooldowns == null) { + this.commandCooldowns = new HashMap<>(); + } + this.commandCooldowns.put(pattern, expiresAt.getTime()); + if (save) { + saveCommandCooldowns(); + } + } + + public boolean clearCommandCooldown(Pattern pattern) { + if (this.commandCooldowns == null) { + return false; // false for no modification + } + + if(this.commandCooldowns.remove(pattern) != null) { + saveCommandCooldowns(); + return true; + } + return false; + } + + private void saveCommandCooldowns() { + // Serialization explanation: + // + // Serialization is done as a map list instead of a config section due to limitations. + // When serializing patterns (which commonly include full stops .) Bukkit/Essentials config framework + // interprets it as a path separator, thus it breaks up the regex into sub nodes causing invalid syntax. + // Thus each command cooldown is instead stored as a Map of {pattern: .., expiry: ..} to work around this. + List serialized = new ArrayList<>(); + for (Entry entry : this.commandCooldowns.entrySet()) { + // Don't save expired cooldowns + if (entry.getValue() < System.currentTimeMillis()) { + continue; + } + + Map map = ImmutableMap.builder() + .put("pattern", entry.getKey().pattern()) + .put("expiry", entry.getValue()) + .build(); + serialized.add(map); + } + config.setProperty("timestamps.command-cooldowns", serialized); + save(); + } + public UUID getConfigUUID() { return config.uuid; } diff --git a/Essentials/src/config.yml b/Essentials/src/config.yml index 1967fb9fa..92e5b8dae 100644 --- a/Essentials/src/config.yml +++ b/Essentials/src/config.yml @@ -484,6 +484,24 @@ send-fly-enable-on-join: true # Give someone permission to teleport to a world with essentials.time.world.. world-time-permissions: false +# Specify cooldown for both Essentials commands and external commands as well. +# All commands do not start with a Forward Slash (/). Instead of /msg, write msg +# +# Wildcards are supported. E.g. +# - '*i*': 50 +# adds a 50 second cooldown to all commands that include the letter i +# +# EssentialsX supports regex by starting the command with a caret ^ +# For example, to target commands starting with ban and not banip the following would be used: +# '^ban([^ip])( .*)?': 60 # 60 seconds /ban cooldown. +# Note: If you have a command that starts with ^, then you can escape it using backslash (\). e.g. \^command: 123 +command-cooldowns: +# feed: 100 # 100 second cooldown on /feed command +# '*': 5 # 5 Second cooldown on all commands + +# Whether command cooldowns should be persistent past server shutdowns +command-cooldown-persistence: true + ############################################################ # +------------------------------------------------------+ # # | EssentialsHome | # diff --git a/Essentials/src/messages.properties b/Essentials/src/messages.properties index b041a857d..468de474a 100644 --- a/Essentials/src/messages.properties +++ b/Essentials/src/messages.properties @@ -573,3 +573,4 @@ msgEnabled=\u00a76Receiving messages \u00a7cenabled\u00a76. msgEnabledFor=\u00a76Receiving messages \u00a7cenabled \u00a76for \u00a7c{0}\u00a76. msgIgnore=\u00a7c{0} \u00a74has messages disabled. minimumPayAmount=\u00a7cThe minimum amount you can pay is {0}. +commandCooldown=\u00a7cYou cannot type that command for {0}. diff --git a/Essentials/src/messages_cs.properties b/Essentials/src/messages_cs.properties index 62331ff98..85c856620 100644 --- a/Essentials/src/messages_cs.properties +++ b/Essentials/src/messages_cs.properties @@ -561,4 +561,5 @@ createdKit=\u00a76Created kit \u00a7c{0} \u00a76with \u00a7c{1} \u00a76entries a spectator=spectator kitContains=\u00a76Kit \u00a7c{0} \u00a76contains: kitItem=\u00a76- \u00a7f{0} -invalidBanner=\u00a74Invalid banner syntax. \ No newline at end of file +invalidBanner=\u00a74Invalid banner syntax. +commandCooldown=\u00a7cYou cannot type that command for {0}. diff --git a/Essentials/src/messages_da.properties b/Essentials/src/messages_da.properties index 502da6dd0..d71561c5d 100644 --- a/Essentials/src/messages_da.properties +++ b/Essentials/src/messages_da.properties @@ -561,4 +561,5 @@ createdKit=\u00a76Created kit \u00a7c{0} \u00a76with \u00a7c{1} \u00a76entries a spectator=spectator kitContains=\u00a76Kit \u00a7c{0} \u00a76contains: kitItem=\u00a76- \u00a7f{0} -invalidBanner=\u00a74Invalid banner syntax. \ No newline at end of file +invalidBanner=\u00a74Invalid banner syntax. +commandCooldown=\u00a7cYou cannot type that command for {0}. diff --git a/Essentials/src/messages_de.properties b/Essentials/src/messages_de.properties index ec874e740..99617a552 100644 --- a/Essentials/src/messages_de.properties +++ b/Essentials/src/messages_de.properties @@ -566,3 +566,4 @@ spectator=Zuschauer kitContains=\u00a76Ausr\u00fcstung \u00a7c{0} \u00a76enth\u00e4lt: kitItem=\u00a76- \u00a7f{0} invalidBanner=\u00a74Ung\u00fcltige Banner-Syntax. +commandCooldown=\u00a7cYou cannot type that command for {0}. diff --git a/Essentials/src/messages_en.properties b/Essentials/src/messages_en.properties index 890945bbe..cd4e49922 100644 --- a/Essentials/src/messages_en.properties +++ b/Essentials/src/messages_en.properties @@ -566,3 +566,4 @@ msgDisabled=\u00a76Receiving messages \u00a7cdisabled\u00a76. msgDisabledFor=\u00a76Receiving messages \u00a7cdisabled \u00a76for \u00a7c{0}\u00a76. msgEnabled=\u00a76Receiving messages \u00a7cenabled\u00a76. msgEnabledFor=\u00a76Receiving messages \u00a7cenabled \u00a76for \u00a7c{0}\u00a76. +commandCooldown=\u00a7cYou cannot type that command for {0}. diff --git a/Essentials/src/messages_es.properties b/Essentials/src/messages_es.properties index 6acbe1784..95ae950ec 100644 --- a/Essentials/src/messages_es.properties +++ b/Essentials/src/messages_es.properties @@ -561,4 +561,5 @@ createdKit=\u00a76Created kit \u00a7c{0} \u00a76with \u00a7c{1} \u00a76entries a spectator=spectator kitContains=\u00a76Kit \u00a7c{0} \u00a76contains: kitItem=\u00a76- \u00a7f{0} -invalidBanner=\u00a74Invalid banner syntax. \ No newline at end of file +invalidBanner=\u00a74Invalid banner syntax. +commandCooldown=\u00a7cYou cannot type that command for {0}. diff --git a/Essentials/src/messages_et.properties b/Essentials/src/messages_et.properties index 0e0d1a033..d20e50e9b 100644 --- a/Essentials/src/messages_et.properties +++ b/Essentials/src/messages_et.properties @@ -561,4 +561,5 @@ createdKit=\u00a76Created kit \u00a7c{0} \u00a76with \u00a7c{1} \u00a76entries a spectator=spectator kitContains=\u00a76Kit \u00a7c{0} \u00a76contains: kitItem=\u00a76- \u00a7f{0} -invalidBanner=\u00a74Invalid banner syntax. \ No newline at end of file +invalidBanner=\u00a74Invalid banner syntax. +commandCooldown=\u00a7cYou cannot type that command for {0}. diff --git a/Essentials/src/messages_fi.properties b/Essentials/src/messages_fi.properties index 444f51c68..35a5e2825 100644 --- a/Essentials/src/messages_fi.properties +++ b/Essentials/src/messages_fi.properties @@ -561,4 +561,5 @@ createdKit=\u00a76Created kit \u00a7c{0} \u00a76with \u00a7c{1} \u00a76entries a spectator=spectator kitContains=\u00a76Kit \u00a7c{0} \u00a76contains: kitItem=\u00a76- \u00a7f{0} -invalidBanner=\u00a74Invalid banner syntax. \ No newline at end of file +invalidBanner=\u00a74Invalid banner syntax. +commandCooldown=\u00a7cYou cannot type that command for {0}. diff --git a/Essentials/src/messages_fr.properties b/Essentials/src/messages_fr.properties index 271092aa6..e41b0ffec 100644 --- a/Essentials/src/messages_fr.properties +++ b/Essentials/src/messages_fr.properties @@ -567,3 +567,4 @@ msgDisabled=\u00a76R\u00e9ception des messages \u00a7cd\u00e9sactiv\u00e9e\u00a7 msgDisabledFor=\u00a76R\u00e9ception des messages \u00a7cd\u00e9sactiv\u00e9e \u00a76pour \u00a7c{0}\u00a76. msgEnabled=\u00a76R\u00e9ception des messages \u00a7cactiv\u00e9e\u00a76. msgEnabledFor=\u00a76R\u00e9ception des messages \u00a7cactiv\u00e9e \u00a76pour \u00a7c{0}\u00a76. +commandCooldown=\u00a7cYou cannot type that command for {0}. diff --git a/Essentials/src/messages_hu.properties b/Essentials/src/messages_hu.properties index 6891a24c4..90d649857 100644 --- a/Essentials/src/messages_hu.properties +++ b/Essentials/src/messages_hu.properties @@ -561,4 +561,5 @@ createdKit=\u00a76Created kit \u00a7c{0} \u00a76with \u00a7c{1} \u00a76entries a spectator=spectator kitContains=\u00a76Kit \u00a7c{0} \u00a76contains: kitItem=\u00a76- \u00a7f{0} -invalidBanner=\u00a74Invalid banner syntax. \ No newline at end of file +invalidBanner=\u00a74Invalid banner syntax. +commandCooldown=\u00a7cYou cannot type that command for {0}. diff --git a/Essentials/src/messages_it.properties b/Essentials/src/messages_it.properties index 512514fef..898530d5c 100644 --- a/Essentials/src/messages_it.properties +++ b/Essentials/src/messages_it.properties @@ -561,4 +561,5 @@ createdKit=\u00a76Created kit \u00a7c{0} \u00a76with \u00a7c{1} \u00a76entries a spectator=spectator kitContains=\u00a76Kit \u00a7c{0} \u00a76contains: kitItem=\u00a76- \u00a7f{0} -invalidBanner=\u00a74Invalid banner syntax. \ No newline at end of file +invalidBanner=\u00a74Invalid banner syntax. +commandCooldown=\u00a7cYou cannot type that command for {0}. diff --git a/Essentials/src/messages_ko.properties b/Essentials/src/messages_ko.properties index 3d25cfee3..0f4bf3dc1 100644 --- a/Essentials/src/messages_ko.properties +++ b/Essentials/src/messages_ko.properties @@ -561,4 +561,5 @@ createdKit=\u00a76Created kit \u00a7c{0} \u00a76with \u00a7c{1} \u00a76entries a spectator=spectator kitContains=\u00a76Kit \u00a7c{0} \u00a76contains: kitItem=\u00a76- \u00a7f{0} -invalidBanner=\u00a74Invalid banner syntax. \ No newline at end of file +invalidBanner=\u00a74Invalid banner syntax. +commandCooldown=\u00a7cYou cannot type that command for {0}. diff --git a/Essentials/src/messages_lt.properties b/Essentials/src/messages_lt.properties index ad725fa02..627776457 100644 --- a/Essentials/src/messages_lt.properties +++ b/Essentials/src/messages_lt.properties @@ -561,4 +561,5 @@ createdKit=\u00a76Created kit \u00a7c{0} \u00a76with \u00a7c{1} \u00a76entries a spectator=spectator kitContains=\u00a76Kit \u00a7c{0} \u00a76contains: kitItem=\u00a76- \u00a7f{0} -invalidBanner=\u00a74Invalid banner syntax. \ No newline at end of file +invalidBanner=\u00a74Invalid banner syntax. +commandCooldown=\u00a7cYou cannot type that command for {0}. diff --git a/Essentials/src/messages_nl.properties b/Essentials/src/messages_nl.properties index 924769a81..edabe4837 100644 --- a/Essentials/src/messages_nl.properties +++ b/Essentials/src/messages_nl.properties @@ -561,4 +561,5 @@ createdKit=\u00a76Created kit \u00a7c{0} \u00a76with \u00a7c{1} \u00a76entries a spectator=spectator kitContains=\u00a76Kit \u00a7c{0} \u00a76contains: kitItem=\u00a76- \u00a7f{0} -invalidBanner=\u00a74Invalid banner syntax. \ No newline at end of file +invalidBanner=\u00a74Invalid banner syntax. +commandCooldown=\u00a7cYou cannot type that command for {0}. diff --git a/Essentials/src/messages_pl.properties b/Essentials/src/messages_pl.properties index 3db93ccf2..0362569fd 100644 --- a/Essentials/src/messages_pl.properties +++ b/Essentials/src/messages_pl.properties @@ -561,4 +561,5 @@ createdKit=\u00a76Created kit \u00a7c{0} \u00a76with \u00a7c{1} \u00a76entries a spectator=spectator kitContains=\u00a76Kit \u00a7c{0} \u00a76contains: kitItem=\u00a76- \u00a7f{0} -invalidBanner=\u00a74Invalid banner syntax. \ No newline at end of file +invalidBanner=\u00a74Invalid banner syntax. +commandCooldown=\u00a7cYou cannot type that command for {0}. diff --git a/Essentials/src/messages_pt.properties b/Essentials/src/messages_pt.properties index b1c8b901d..0b152889d 100644 --- a/Essentials/src/messages_pt.properties +++ b/Essentials/src/messages_pt.properties @@ -561,4 +561,5 @@ createdKit=\u00a76Created kit \u00a7c{0} \u00a76with \u00a7c{1} \u00a76entries a spectator=spectator kitContains=\u00a76Kit \u00a7c{0} \u00a76contains: kitItem=\u00a76- \u00a7f{0} -invalidBanner=\u00a74Invalid banner syntax. \ No newline at end of file +invalidBanner=\u00a74Invalid banner syntax. +commandCooldown=\u00a7cYou cannot type that command for {0}. diff --git a/Essentials/src/messages_pt_BR.properties b/Essentials/src/messages_pt_BR.properties index 4487392fe..ee3fa4126 100644 --- a/Essentials/src/messages_pt_BR.properties +++ b/Essentials/src/messages_pt_BR.properties @@ -561,4 +561,5 @@ createdKit=\u00a76Created kit \u00a7c{0} \u00a76with \u00a7c{1} \u00a76entries a spectator=spectator kitContains=\u00a76Kit \u00a7c{0} \u00a76contains: kitItem=\u00a76- \u00a7f{0} -invalidBanner=\u00a74Invalid banner syntax. \ No newline at end of file +invalidBanner=\u00a74Invalid banner syntax. +commandCooldown=\u00a7cYou cannot type that command for {0}. diff --git a/Essentials/src/messages_ro.properties b/Essentials/src/messages_ro.properties index a5a4f91e3..1f8263573 100644 --- a/Essentials/src/messages_ro.properties +++ b/Essentials/src/messages_ro.properties @@ -561,4 +561,5 @@ createdKit=\u00a76Created kit \u00a7c{0} \u00a76with \u00a7c{1} \u00a76entries a spectator=spectator kitContains=\u00a76Kit \u00a7c{0} \u00a76contains: kitItem=\u00a76- \u00a7f{0} -invalidBanner=\u00a74Invalid banner syntax. \ No newline at end of file +invalidBanner=\u00a74Invalid banner syntax. +commandCooldown=\u00a7cYou cannot type that command for {0}. diff --git a/Essentials/src/messages_ru.properties b/Essentials/src/messages_ru.properties index 3a30983da..b5f99ddaf 100644 --- a/Essentials/src/messages_ru.properties +++ b/Essentials/src/messages_ru.properties @@ -561,4 +561,5 @@ createdKit=\u00a76Created kit \u00a7c{0} \u00a76with \u00a7c{1} \u00a76entries a spectator=spectator kitContains=\u00a76Kit \u00a7c{0} \u00a76contains: kitItem=\u00a76- \u00a7f{0} -invalidBanner=\u00a74Invalid banner syntax. \ No newline at end of file +invalidBanner=\u00a74Invalid banner syntax. +commandCooldown=\u00a7cYou cannot type that command for {0}. diff --git a/Essentials/src/messages_sv.properties b/Essentials/src/messages_sv.properties index 0239686bb..fbd3aaab5 100644 --- a/Essentials/src/messages_sv.properties +++ b/Essentials/src/messages_sv.properties @@ -561,4 +561,5 @@ createdKit=\u00a76Created kit \u00a7c{0} \u00a76with \u00a7c{1} \u00a76entries a spectator=spectator kitContains=\u00a76Kit \u00a7c{0} \u00a76contains: kitItem=\u00a76- \u00a7f{0} -invalidBanner=\u00a74Invalid banner syntax. \ No newline at end of file +invalidBanner=\u00a74Invalid banner syntax. +commandCooldown=\u00a7cYou cannot type that command for {0}. diff --git a/Essentials/src/messages_tr.properties b/Essentials/src/messages_tr.properties index eadf42d33..44b632062 100644 --- a/Essentials/src/messages_tr.properties +++ b/Essentials/src/messages_tr.properties @@ -561,4 +561,5 @@ createdKit=\u00a76Created kit \u00a7c{0} \u00a76with \u00a7c{1} \u00a76entries a spectator=spectator kitContains=\u00a76Kit \u00a7c{0} \u00a76contains: kitItem=\u00a76- \u00a7f{0} -invalidBanner=\u00a74Invalid banner syntax. \ No newline at end of file +invalidBanner=\u00a74Invalid banner syntax. +commandCooldown=\u00a7cYou cannot type that command for {0}. diff --git a/Essentials/src/messages_zh.properties b/Essentials/src/messages_zh.properties index 6ca498600..75da8adad 100644 --- a/Essentials/src/messages_zh.properties +++ b/Essentials/src/messages_zh.properties @@ -561,4 +561,5 @@ createdKit=\u00a76Created kit \u00a7c{0} \u00a76with \u00a7c{1} \u00a76entries a spectator=spectator kitContains=\u00a76Kit \u00a7c{0} \u00a76contains: kitItem=\u00a76- \u00a7f{0} -invalidBanner=\u00a74Invalid banner syntax. \ No newline at end of file +invalidBanner=\u00a74Invalid banner syntax. +commandCooldown=\u00a7cYou cannot type that command for {0}. diff --git a/Essentials/src/messages_zh_HK.properties b/Essentials/src/messages_zh_HK.properties index 1c267dd5f..41fee37e6 100644 --- a/Essentials/src/messages_zh_HK.properties +++ b/Essentials/src/messages_zh_HK.properties @@ -561,4 +561,5 @@ createdKit=\u00a76Created kit \u00a7c{0} \u00a76with \u00a7c{1} \u00a76entries a spectator=spectator kitContains=\u00a76Kit \u00a7c{0} \u00a76contains: kitItem=\u00a76- \u00a7f{0} -invalidBanner=\u00a74Invalid banner syntax. \ No newline at end of file +invalidBanner=\u00a74Invalid banner syntax. +commandCooldown=\u00a7cYou cannot type that command for {0}. diff --git a/Essentials/src/messages_zh_TW.properties b/Essentials/src/messages_zh_TW.properties index 0467d380f..edfdc927d 100644 --- a/Essentials/src/messages_zh_TW.properties +++ b/Essentials/src/messages_zh_TW.properties @@ -561,4 +561,5 @@ createdKit=\u00a76Created kit \u00a7c{0} \u00a76with \u00a7c{1} \u00a76entries a spectator=spectator kitContains=\u00a76Kit \u00a7c{0} \u00a76contains: kitItem=\u00a76- \u00a7f{0} -invalidBanner=\u00a74Invalid banner syntax. \ No newline at end of file +invalidBanner=\u00a74Invalid banner syntax. +commandCooldown=\u00a7cYou cannot type that command for {0}.