Merge branch '2.x' into custom-currency-formatting

This commit is contained in:
Ali Moghnieh 2016-07-05 18:46:01 +01:00
commit d37433e81c
37 changed files with 364 additions and 40 deletions

View File

@ -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,17 +404,56 @@ 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<Pattern, Long> 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<Pattern, Long> 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)
public void onPlayerChangedWorldFlyReset(final PlayerChangedWorldEvent event) {
final User user = ess.getUser(event.getPlayer());
if (user.getBase().getGameMode() != GameMode.CREATIVE
&& user.getBase().getGameMode() != GameMode.SPECTATOR
// COMPAT: String compare for 1.7.10
&& !user.getBase().getGameMode().name().equals("SPECTATOR")
&& !user.isAuthorized("essentials.fly")) {
user.getBase().setFallDistance(0f);
user.getBase().setAllowFlight(false);

View File

@ -9,9 +9,9 @@ import java.util.logging.Level;
public class EssentialsTimer implements Runnable {
private final transient IEssentials ess;
private final transient Set<UUID> onlineUsers = new HashSet<UUID>();
private final transient Set<UUID> onlineUsers = new HashSet<>(); // Field is necessary for hidden users
private transient long lastPoll = System.nanoTime();
private final LinkedList<Double> history = new LinkedList<Double>();
private final LinkedList<Double> history = new LinkedList<>();
private int skip1 = 0;
private int skip2 = 0;
private final long maxTime = 10 * 1000000;
@ -76,6 +76,11 @@ public class EssentialsTimer implements Runnable {
}
}
final User user = ess.getUser(iterator.next());
// Not sure why this would happen, but it does
if (user == null) {
iterator.remove();
continue;
}
if (user.getLastOnlineActivity() < currentTime && user.getLastOnlineActivity() > user.getLastLogout()) {
if (!user.isHidden()) {
user.setLastLogout(user.getLastOnlineActivity());

View File

@ -12,7 +12,9 @@ import java.math.BigDecimal;
import java.text.NumberFormat;
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,6 +249,16 @@ public interface ISettings extends IConf {
boolean isWorldTimePermissions();
boolean isSpawnOnJoin();
boolean isTeleportToCenterLocation();
boolean isCommandCooldownsEnabled();
long getCommandCooldownMs(String label);
Entry<Pattern, Long> getCommandCooldownEntry(String label);
boolean isCommandCooldownPersistent(String label);
NumberFormat getCurrencyFormat();
}

View File

@ -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<String, Object> getConfigMap();
Map<String, Object> getConfigMap(String node);
Map<Pattern, Long> getCommandCooldowns();
Date getCommandCooldownExpiry(String label);
void addCommandCooldown(Pattern pattern, Date expiresAt, boolean save);
boolean clearCommandCooldown(Pattern pattern);
/*
* PlayerExtension

View File

@ -25,10 +25,13 @@ import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.util.*;
import java.util.Locale.Category;
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;
import com.google.common.base.Preconditions;
@ -543,7 +546,7 @@ public class Settings implements net.ess3.api.ISettings {
customQuitMessage = _getCustomQuitMessage();
isCustomQuitMessage = !customQuitMessage.equals("none");
muteCommands = _getMuteCommands();
commandCooldowns = _getCommandCooldowns();
currencyFormat = _getCurrencyFormat();
}
@ -1182,6 +1185,96 @@ public class Settings implements net.ess3.api.ISettings {
return config.getBoolean("spawn-on-join", false);
}
@Override
public boolean isTeleportToCenterLocation() {
return config.getBoolean("teleport-to-center", true);
}
private Map<Pattern, Long> commandCooldowns;
private Map<Pattern, Long> _getCommandCooldowns() {
if (!config.isConfigurationSection("command-cooldowns")) {
return null;
}
ConfigurationSection section = config.getConfigurationSection("command-cooldowns");
Map<Pattern, Long> 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<Pattern, Long> result = getCommandCooldownEntry(label);
return result != null ? result.getValue() : -1; // return cooldown in milliseconds
}
@Override
public Entry<Pattern, Long> getCommandCooldownEntry(String label) {
if (isCommandCooldownsEnabled()) {
for (Entry<Pattern, Long> 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);
}
private NumberFormat currencyFormat;
private NumberFormat _getCurrencyFormat() {

View File

@ -117,7 +117,7 @@ public class Teleport implements net.ess3.api.ITeleport {
protected void now(IUser teleportee, ITarget target, TeleportCause cause) throws Exception {
cancel(false);
teleportee.setLastLocation();
final Location loc = target.getLocation();
Location loc = target.getLocation();
if (LocationUtil.isBlockUnsafeForUser(teleportee, loc.getWorld(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())) {
if (ess.getSettings().isTeleportSafetyEnabled()) {
@ -127,7 +127,7 @@ public class Teleport implements net.ess3.api.ITeleport {
if (ess.getSettings().isForceDisableTeleportSafety()) {
teleportee.getBase().teleport(loc, cause);
} else {
teleportee.getBase().teleport(LocationUtil.getSafeDestination(teleportee, loc), cause);
teleportee.getBase().teleport(LocationUtil.getSafeDestination(ess, teleportee, loc), cause);
}
} else {
throw new Exception(tl("unsafeTeleportDestination", loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()));
@ -139,7 +139,10 @@ public class Teleport implements net.ess3.api.ITeleport {
if (ess.getSettings().isForceDisableTeleportSafety()) {
teleportee.getBase().teleport(loc, cause);
} else {
teleportee.getBase().teleport(LocationUtil.getRoundedDestination(loc), cause);
if (ess.getSettings().isTeleportToCenterLocation()) {
loc = LocationUtil.getRoundedDestination(loc);
}
teleportee.getBase().teleport(loc, cause);
}
}
}

View File

@ -256,7 +256,7 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
} else if (nick.equalsIgnoreCase(getName())) {
nickname = nick;
} else {
nickname = ess.getSettings().getNicknamePrefix() + nick;
nickname = FormatUtil.replaceFormat(ess.getSettings().getNicknamePrefix()) + nick;
suffix = "§r";
}

View File

@ -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;
@ -93,6 +97,11 @@ public abstract class UserData extends PlayerExtension implements IConf {
BigDecimal result = ess.getSettings().getStartingBalance();
BigDecimal maxMoney = ess.getSettings().getMaxMoney();
BigDecimal minMoney = ess.getSettings().getMinMoney();
// NPC banks are not actual player banks, as such they do not have player starting balance.
if (isNPC()) {
result = BigDecimal.ZERO;
}
if (config.hasProperty("money")) {
result = config.getBigDecimal("money", result);
@ -787,6 +796,89 @@ public abstract class UserData extends PlayerExtension implements IConf {
return new HashMap<String, Object>();
}
// Pattern, Date. Pattern for less pattern creations
private Map<Pattern, Long> commandCooldowns;
private Map<Pattern, Long> _getCommandCooldowns() {
if (!config.isConfigurationSection("timestamps.command-cooldowns")) {
return null;
}
// See saveCommandCooldowns() for deserialization explanation
List<Map<?, ?>> section = config.getMapList("timestamps.command-cooldowns");
HashMap<Pattern, Long> 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<Pattern, Long> getCommandCooldowns() {
if (this.commandCooldowns == null) {
return Collections.emptyMap();
}
return Collections.unmodifiableMap(this.commandCooldowns);
}
public Date getCommandCooldownExpiry(String label) {
if (commandCooldowns != null) {
for (Entry<Pattern, Long> 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<Object> serialized = new ArrayList<>();
for (Entry<Pattern, Long> 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;
}

View File

@ -96,7 +96,7 @@ public class Commandbalancetop extends EssentialsCommand {
} else {
for (UUID u : ess.getUserMap().getAllUniqueUsers()) {
final User user = ess.getUserMap().getUser(u);
if (user != null) {
if (user != null && !user.isNPC()) { // Don't list NPCs in output
final BigDecimal userMoney = user.getMoney();
user.updateMoneyCache(userMoney);
totalMoney = totalMoney.add(userMoney);

View File

@ -38,9 +38,9 @@ public class Commandtp extends EssentialsCommand {
if (!user.isAuthorized("essentials.tp.position")) {
throw new Exception(tl("noPerm", "essentials.tp.position"));
}
final double x2 = args[0].startsWith("~") ? user.getLocation().getX() + (args[0].length() > 1 ? Integer.parseInt(args[0].substring(1)) : 0) : Integer.parseInt(args[0]);
final double y2 = args[1].startsWith("~") ? user.getLocation().getY() + (args[1].length() > 1 ? Integer.parseInt(args[1].substring(1)) : 0) : Integer.parseInt(args[1]);
final double z2 = args[2].startsWith("~") ? user.getLocation().getZ() + (args[2].length() > 1 ? Integer.parseInt(args[2].substring(1)) : 0) : Integer.parseInt(args[2]);
final double x2 = args[0].startsWith("~") ? user.getLocation().getX() + (args[0].length() > 1 ? Double.parseDouble(args[0].substring(1)) : 0) : Double.parseDouble(args[0]);
final double y2 = args[1].startsWith("~") ? user.getLocation().getY() + (args[1].length() > 1 ? Double.parseDouble(args[1].substring(1)) : 0) : Double.parseDouble(args[1]);
final double z2 = args[2].startsWith("~") ? user.getLocation().getZ() + (args[2].length() > 1 ? Double.parseDouble(args[2].substring(1)) : 0) : Double.parseDouble(args[2]);
if (x2 > 30000000 || y2 > 30000000 || z2 > 30000000 || x2 < -30000000 || y2 < -30000000 || z2 < -30000000) {
throw new NotEnoughArgumentsException(tl("teleportInvalidLocation"));
}
@ -56,9 +56,9 @@ public class Commandtp extends EssentialsCommand {
throw new Exception(tl("noPerm", "essentials.tp.position"));
}
final User target2 = getPlayer(server, user, args, 0);
final double x = args[1].startsWith("~") ? target2.getLocation().getX() + (args[1].length() > 1 ? Integer.parseInt(args[1].substring(1)) : 0) : Integer.parseInt(args[1]);
final double y = args[2].startsWith("~") ? target2.getLocation().getY() + (args[2].length() > 1 ? Integer.parseInt(args[2].substring(1)) : 0) : Integer.parseInt(args[2]);
final double z = args[3].startsWith("~") ? target2.getLocation().getZ() + (args[3].length() > 1 ? Integer.parseInt(args[3].substring(1)) : 0) : Integer.parseInt(args[3]);
final double x = args[1].startsWith("~") ? target2.getLocation().getX() + (args[1].length() > 1 ? Double.parseDouble(args[1].substring(1)) : 0) : Double.parseDouble(args[1]);
final double y = args[2].startsWith("~") ? target2.getLocation().getY() + (args[2].length() > 1 ? Double.parseDouble(args[2].substring(1)) : 0) : Double.parseDouble(args[2]);
final double z = args[3].startsWith("~") ? target2.getLocation().getZ() + (args[3].length() > 1 ? Double.parseDouble(args[3].substring(1)) : 0) : Double.parseDouble(args[3]);
if (x > 30000000 || y > 30000000 || z > 30000000 || x < -30000000 || y < -30000000 || z < -30000000) {
throw new NotEnoughArgumentsException(tl("teleportInvalidLocation"));
}
@ -104,9 +104,9 @@ public class Commandtp extends EssentialsCommand {
target.sendMessage(tl("teleportAtoB", Console.NAME, toPlayer.getDisplayName()));
target.getTeleport().now(toPlayer.getBase(), false, TeleportCause.COMMAND);
} else if (args.length > 3) {
final double x = args[1].startsWith("~") ? target.getLocation().getX() + (args[1].length() > 1 ? Integer.parseInt(args[1].substring(1)) : 0) : Integer.parseInt(args[1]);
final double y = args[2].startsWith("~") ? target.getLocation().getY() + (args[2].length() > 1 ? Integer.parseInt(args[2].substring(1)) : 0) : Integer.parseInt(args[2]);
final double z = args[3].startsWith("~") ? target.getLocation().getZ() + (args[3].length() > 1 ? Integer.parseInt(args[3].substring(1)) : 0) : Integer.parseInt(args[3]);
final double x = args[1].startsWith("~") ? target.getLocation().getX() + (args[1].length() > 1 ? Double.parseDouble(args[1].substring(1)) : 0) : Double.parseDouble(args[1]);
final double y = args[2].startsWith("~") ? target.getLocation().getY() + (args[2].length() > 1 ? Double.parseDouble(args[2].substring(1)) : 0) : Double.parseDouble(args[2]);
final double z = args[3].startsWith("~") ? target.getLocation().getZ() + (args[3].length() > 1 ? Double.parseDouble(args[3].substring(1)) : 0) : Double.parseDouble(args[3]);
if (x > 30000000 || y > 30000000 || z > 30000000 || x < -30000000 || y < -30000000 || z < -30000000) {
throw new NotEnoughArgumentsException(tl("teleportInvalidLocation"));
}

View File

@ -45,6 +45,9 @@ public class EssentialsSign {
final SignCreateEvent signEvent = new SignCreateEvent(sign, this, user);
ess.getServer().getPluginManager().callEvent(signEvent);
if (signEvent.isCancelled()) {
if (ess.getSettings().isDebug()) {
ess.getLogger().info("SignCreateEvent cancelled for sign " + signEvent.getEssentialsSign().getName());
}
return false;
}

View File

@ -13,6 +13,9 @@ import java.util.*;
import static com.earth2me.essentials.I18n.tl;
import com.earth2me.essentials.Essentials;
import com.earth2me.essentials.IEssentials;
public class LocationUtil {
// The player can stand inside these materials
@ -261,12 +264,26 @@ public class LocationUtil {
return new Location(world, x + 0.5, y, z + 0.5, loc.getYaw(), loc.getPitch());
}
/**
* @deprecated Use {@link #getSafeDestination(IEssentials, IUser, Location)}
*/
@Deprecated
public static Location getSafeDestination(final IUser user, final Location loc) throws Exception {
return getSafeDestination(null, user, loc);
}
public static Location getSafeDestination(final IEssentials ess, final IUser user, final Location loc) throws Exception {
if (user.getBase().isOnline() && loc.getWorld().equals(user.getBase().getWorld()) && (user.getBase().getGameMode() == GameMode.CREATIVE || user.isGodModeEnabled()) && user.getBase().getAllowFlight()) {
if (shouldFly(loc)) {
user.getBase().setFlying(true);
}
return getRoundedDestination(loc);
// ess can be null if old deprecated method is calling it.
System.out.println((ess == null) + " " + ess.getSettings().isTeleportToCenterLocation());
if (ess == null || ess.getSettings().isTeleportToCenterLocation()) {
return getRoundedDestination(loc);
} else {
return loc;
}
}
return getSafeDestination(loc);
}

View File

@ -64,6 +64,9 @@ teleport-delay: 0
# This will also prevent the player attacking other players.
teleport-invulnerability: 4
# Whether to make all teleportations go to the center of the block; where the x and z coordinates decimal become .5
teleport-to-center: true
# The delay, in seconds, required between /heal or /feed attempts.
heal-cooldown: 60
@ -481,6 +484,24 @@ send-fly-enable-on-join: true
# Give someone permission to teleport to a world with essentials.time.world.<worldname>.
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 | #

View File

@ -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}.

View File

@ -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.
invalidBanner=\u00a74Invalid banner syntax.
commandCooldown=\u00a7cYou cannot type that command for {0}.

View File

@ -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.
invalidBanner=\u00a74Invalid banner syntax.
commandCooldown=\u00a7cYou cannot type that command for {0}.

View File

@ -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}.

View File

@ -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}.

View File

@ -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.
invalidBanner=\u00a74Invalid banner syntax.
commandCooldown=\u00a7cYou cannot type that command for {0}.

View File

@ -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.
invalidBanner=\u00a74Invalid banner syntax.
commandCooldown=\u00a7cYou cannot type that command for {0}.

View File

@ -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.
invalidBanner=\u00a74Invalid banner syntax.
commandCooldown=\u00a7cYou cannot type that command for {0}.

View File

@ -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}.

View File

@ -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.
invalidBanner=\u00a74Invalid banner syntax.
commandCooldown=\u00a7cYou cannot type that command for {0}.

View File

@ -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.
invalidBanner=\u00a74Invalid banner syntax.
commandCooldown=\u00a7cYou cannot type that command for {0}.

View File

@ -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.
invalidBanner=\u00a74Invalid banner syntax.
commandCooldown=\u00a7cYou cannot type that command for {0}.

View File

@ -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.
invalidBanner=\u00a74Invalid banner syntax.
commandCooldown=\u00a7cYou cannot type that command for {0}.

View File

@ -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.
invalidBanner=\u00a74Invalid banner syntax.
commandCooldown=\u00a7cYou cannot type that command for {0}.

View File

@ -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.
invalidBanner=\u00a74Invalid banner syntax.
commandCooldown=\u00a7cYou cannot type that command for {0}.

View File

@ -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.
invalidBanner=\u00a74Invalid banner syntax.
commandCooldown=\u00a7cYou cannot type that command for {0}.

View File

@ -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.
invalidBanner=\u00a74Invalid banner syntax.
commandCooldown=\u00a7cYou cannot type that command for {0}.

View File

@ -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.
invalidBanner=\u00a74Invalid banner syntax.
commandCooldown=\u00a7cYou cannot type that command for {0}.

View File

@ -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.
invalidBanner=\u00a74Invalid banner syntax.
commandCooldown=\u00a7cYou cannot type that command for {0}.

View File

@ -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.
invalidBanner=\u00a74Invalid banner syntax.
commandCooldown=\u00a7cYou cannot type that command for {0}.

View File

@ -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.
invalidBanner=\u00a74Invalid banner syntax.
commandCooldown=\u00a7cYou cannot type that command for {0}.

View File

@ -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.
invalidBanner=\u00a74Invalid banner syntax.
commandCooldown=\u00a7cYou cannot type that command for {0}.

View File

@ -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.
invalidBanner=\u00a74Invalid banner syntax.
commandCooldown=\u00a7cYou cannot type that command for {0}.

View File

@ -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.
invalidBanner=\u00a74Invalid banner syntax.
commandCooldown=\u00a7cYou cannot type that command for {0}.