diff --git a/.gitignore b/.gitignore
index cfe9fa50..fe5b3b35 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,6 +7,7 @@
.idea/dictionaries
.idea/misc.xml
.idea/libraries
+.idea/uiDesigner.xml
.idea/kotlinc.xml
diff --git a/.idea/codeInsightSettings.xml b/.idea/codeInsightSettings.xml
new file mode 100644
index 00000000..e3f4d2b0
--- /dev/null
+++ b/.idea/codeInsightSettings.xml
@@ -0,0 +1,8 @@
+
+
+
+
+ java.awt
+
+
+
\ No newline at end of file
diff --git a/.idea/fileTemplates/includes/File Header.java b/.idea/fileTemplates/includes/File Header.java
new file mode 100644
index 00000000..e69de29b
diff --git a/bukkit/acf-bukkit.iml b/bukkit/acf-bukkit.iml
index 5e19d3d6..ab67942b 100644
--- a/bukkit/acf-bukkit.iml
+++ b/bukkit/acf-bukkit.iml
@@ -14,6 +14,7 @@
+
diff --git a/bukkit/pom.xml b/bukkit/pom.xml
index 121655e4..e720ee8d 100644
--- a/bukkit/pom.xml
+++ b/bukkit/pom.xml
@@ -86,5 +86,10 @@
+
+
+ ${project.basedir}/../languages/minecraft/
+
+
diff --git a/bukkit/src/main/java/co/aikar/commands/ACFBukkitUtil.java b/bukkit/src/main/java/co/aikar/commands/ACFBukkitUtil.java
index 99c59aaa..ff643718 100644
--- a/bukkit/src/main/java/co/aikar/commands/ACFBukkitUtil.java
+++ b/bukkit/src/main/java/co/aikar/commands/ACFBukkitUtil.java
@@ -23,6 +23,7 @@
package co.aikar.commands;
+import co.aikar.locales.MessageKey;
import com.google.common.collect.Iterables;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
@@ -60,6 +61,12 @@ public class ACFBukkitUtil {
return ChatColor.translateAlternateColorCodes('&', message);
}
+ public static void sendMsg(CommandIssuer issuer, MessageKey key, String... replacements) {
+ sendMsg(issuer, MessageType.INFO, key, replacements);
+ }
+ public static void sendMsg(CommandIssuer issuer, MessageType type, MessageKey key, String... replacements) {
+ issuer.sendMessage(type, key, replacements);
+ }
public static void sendMsg(CommandSender player, String message) {
message = color(message);
for (String msg : ACFPatterns.NEWLINE.split(message)) {
@@ -232,6 +239,14 @@ public class ACFBukkitUtil {
return loc1.getWorld() == loc2.getWorld() && loc1.distance(loc2) <= dist;
}
+ /**
+ * Please move to the CommandIssuer version
+ * @param requester
+ * @param origName
+ * @deprecated
+ * @return
+ */
+ @Deprecated
public static Player findPlayerSmart(CommandSender requester, String origName) {
if (origName == null) {
return null;
@@ -278,8 +293,60 @@ public class ACFBukkitUtil {
Player player = Iterables.getOnlyElement(confirmList);
sendMsg(requester,
"&cWarning: " + player.getDisplayName() + "&c is vanished. Do not blow their cover!\n" +
- "&cTo confirm your action, add &f:confirm&c to the end of their name. \n" +
- "&bEx: &e/g " + player.getName() + ":confirm");
+ "&cTo confirm your action, add &f:confirm&c to the end of their name. \n" +
+ "&bEx: &e/g " + player.getName() + ":confirm");
+ return null;
+ }
+ }
+
+ return matches.get(0);
+ }
+ public static Player findPlayerSmart(CommandIssuer issuer, String origName) {
+ CommandSender requester = issuer.getIssuer();
+ if (origName == null) {
+ return null;
+ }
+ String name = ACFUtil.replace(origName, ":confirm", "");
+ if (name.length() < 3) {
+ issuer.sendError(BukkitMessageKeys.USERNAME_TOO_SHORT);
+ return null;
+ }
+ if (!isValidName(name)) {
+ issuer.sendError(BukkitMessageKeys.IS_NOT_A_VALID_NAME, "{name}", name);
+ return null;
+ }
+
+ List matches = Bukkit.getServer().matchPlayer(name);
+ List confirmList = new ArrayList<>();
+
+ // Remove confirmList players from smart matching.
+ Iterator iter = matches.iterator();
+ while (iter.hasNext()) {
+ Player player = iter.next();
+ if (requester instanceof Player && !((Player) requester).canSee(player)) {
+ if (requester.hasPermission("acf.seevanish")) {
+ if (!origName.endsWith(":confirm")) {
+ confirmList.add(player);
+ iter.remove();
+ }
+ } else {
+ iter.remove();
+ }
+ }
+ }
+
+ if (matches.size() > 1 || confirmList.size() > 1) {
+ requester.sendMessage("§cMultiple players matched '" + name + "', please be more specific");
+ return null;
+ }
+
+ if (matches.isEmpty()) {
+ if (confirmList.isEmpty()) {
+ requester.sendMessage("§cNo player matching '" + name + "' is connected to this server");
+ return null;
+ } else {
+ Player player = Iterables.getOnlyElement(confirmList);
+ issuer.sendMessage(MessageType.INFO, BukkitMessageKeys.PLAYER_IS_VANISHED_CONFIRM, "{vanished}", player.getName());
return null;
}
}
diff --git a/bukkit/src/main/java/co/aikar/commands/BukkitCommandContexts.java b/bukkit/src/main/java/co/aikar/commands/BukkitCommandContexts.java
index 853ac64e..a0491973 100644
--- a/bukkit/src/main/java/co/aikar/commands/BukkitCommandContexts.java
+++ b/bukkit/src/main/java/co/aikar/commands/BukkitCommandContexts.java
@@ -47,7 +47,7 @@ public class BukkitCommandContexts extends CommandContexts getOnlinePlayer(c.getSender(), c.popFirstArg(), c.hasAnnotation(Optional.class)));
+ registerContext(OnlinePlayer.class, c -> getOnlinePlayer(c.getIssuer(), c.popFirstArg(), c.hasAnnotation(Optional.class)));
registerContext(OnlinePlayer[].class, (c) -> {
CommandSender sender = c.getSender();
final String input = c.popFirstArg();
@@ -59,7 +59,7 @@ public class BukkitCommandContexts extends CommandContexts {
Player player = c.getSender() instanceof Player ? (Player) c.getSender() : null;
if (player == null && !c.hasAnnotation(Optional.class)) {
- throw new InvalidCommandArgument("Requires a player to run this command", false);
+ throw new InvalidCommandArgument(MessageKeys.NOT_ALLOWED_ON_CONSOLE, false);
}
PlayerInventory inventory = player != null ? player.getInventory() : null;
if (inventory != null && c.hasFlag("itemheld") && !ACFBukkitUtil.isValidItem(inventory.getItem(inventory.getHeldItemSlot()))) {
- throw new InvalidCommandArgument("You must be holding an item in your main hand.", false);
+ throw new InvalidCommandArgument(BukkitMessageKeys.YOU_MUST_BE_HOLDING_ITEM, false);
}
return player;
});
@@ -113,9 +113,9 @@ public class BukkitCommandContexts extends CommandContexts ChatColor.YELLOW + ACFUtil.simplifyString(color.name()))
- .collect(Collectors.joining("&c, "));
+ .collect(Collectors.joining(", "));
- throw new InvalidCommandArgument("Please specify one of: " + valid);
+ throw new InvalidCommandArgument(MessageKeys.PLEASE_SPECIFY_ONE_OF, "{valid}", valid);
}
return match;
});
@@ -132,13 +132,14 @@ public class BukkitCommandContexts extends CommandContexts {
- BukkitCommandExecutionContext(RegisteredCommand cmd, Parameter param, CommandIssuer sender, List args,
+public class BukkitCommandExecutionContext extends CommandExecutionContext {
+ BukkitCommandExecutionContext(RegisteredCommand cmd, Parameter param, BukkitCommandIssuer sender, List args,
int index, Map passedArgs) {
super(cmd, param, sender, args, index, passedArgs);
}
diff --git a/bukkit/src/main/java/co/aikar/commands/BukkitCommandManager.java b/bukkit/src/main/java/co/aikar/commands/BukkitCommandManager.java
index 270f85dd..2dc33819 100644
--- a/bukkit/src/main/java/co/aikar/commands/BukkitCommandManager.java
+++ b/bukkit/src/main/java/co/aikar/commands/BukkitCommandManager.java
@@ -65,6 +65,7 @@ public class BukkitCommandManager extends CommandManager {
@SuppressWarnings("JavaReflectionMemberAccess")
public BukkitCommandManager(Plugin plugin) {
this.plugin = plugin;
+ this.locales.addMessageBundle("acf-minecraft", Locale.ENGLISH);
this.timingManager = TimingManager.of(plugin);
this.commandTiming = this.timingManager.of("Commands");
CommandMap commandMap = null;
@@ -193,7 +194,8 @@ public class BukkitCommandManager extends CommandManager {
@Override
public R createCommandContext(RegisteredCommand command, Parameter parameter, CommandIssuer sender, List args, int i, Map passedArgs) {
- return (R) new BukkitCommandExecutionContext(command, parameter, sender, args, i, passedArgs);
+ //noinspection unchecked
+ return (R) new BukkitCommandExecutionContext(command, parameter, (BukkitCommandIssuer) sender, args, i, passedArgs);
}
@Override
diff --git a/bukkit/src/main/java/co/aikar/commands/BukkitMessageKeys.java b/bukkit/src/main/java/co/aikar/commands/BukkitMessageKeys.java
new file mode 100644
index 00000000..63a39976
--- /dev/null
+++ b/bukkit/src/main/java/co/aikar/commands/BukkitMessageKeys.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package co.aikar.commands;
+
+import co.aikar.locales.MessageKey;
+
+public enum BukkitMessageKeys implements MessageKeyProvider {
+ INVALID_WORLD,
+ YOU_MUST_BE_HOLDING_ITEM,
+ PLAYER_IS_VANISHED_CONFIRM, USERNAME_TOO_SHORT, IS_NOT_A_VALID_NAME;
+
+ private final MessageKey key = MessageKey.of(this.name().toLowerCase());
+ public MessageKey getMessageKey() {
+ return key;
+ }
+}
diff --git a/bungee/pom.xml b/bungee/pom.xml
index e3189cf6..b2841d05 100644
--- a/bungee/pom.xml
+++ b/bungee/pom.xml
@@ -36,5 +36,12 @@
provided
+
+
+
+ ${project.basedir}/../languages/minecraft/
+
+
+
diff --git a/bungee/src/main/java/co/aikar/commands/ACFBungeeUtil.java b/bungee/src/main/java/co/aikar/commands/ACFBungeeUtil.java
index 55e8948b..096edca5 100644
--- a/bungee/src/main/java/co/aikar/commands/ACFBungeeUtil.java
+++ b/bungee/src/main/java/co/aikar/commands/ACFBungeeUtil.java
@@ -23,6 +23,7 @@
package co.aikar.commands;
+import co.aikar.locales.MessageKey;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.ProxyServer;
@@ -38,6 +39,12 @@ public class ACFBungeeUtil {
return ChatColor.translateAlternateColorCodes('&', message);
}
+ public static void sendMsg(CommandIssuer issuer, MessageKey key, String... replacements) {
+ sendMsg(issuer, MessageType.INFO, key, replacements);
+ }
+ public static void sendMsg(CommandIssuer issuer, MessageType type, MessageKey key, String... replacements) {
+ issuer.sendMessage(type, key, replacements);
+ }
public static void sendMsg(CommandSender player, String message) {
message = color(message);
for (String msg : ACFPatterns.NEWLINE.split(message)) {
diff --git a/bungee/src/main/java/co/aikar/commands/BungeeCommandContexts.java b/bungee/src/main/java/co/aikar/commands/BungeeCommandContexts.java
index cb9a0924..0fb83c17 100644
--- a/bungee/src/main/java/co/aikar/commands/BungeeCommandContexts.java
+++ b/bungee/src/main/java/co/aikar/commands/BungeeCommandContexts.java
@@ -44,7 +44,8 @@ public class BungeeCommandContexts extends CommandContexts {
ProxiedPlayer proxiedPlayer = c.getSender() instanceof ProxiedPlayer ? (ProxiedPlayer) c.getSender() : null;
if (proxiedPlayer == null && !c.hasAnnotation(Optional.class)) {
- throw new InvalidCommandArgument("Requires a player to run this command", false);
+ throw new InvalidCommandArgument(MessageKeys.NOT_ALLOWED_ON_CONSOLE, false);
}
return proxiedPlayer;
});
@@ -74,9 +75,9 @@ public class BungeeCommandContexts extends CommandContexts ChatColor.YELLOW + ACFUtil.simplifyString(color.name()))
- .collect(Collectors.joining("&c, "));
+ .collect(Collectors.joining(", "));
- throw new InvalidCommandArgument("Please specify one of: " + valid);
+ throw new InvalidCommandArgument(MessageKeys.PLEASE_SPECIFY_ONE_OF, "{valid}", valid);
}
return match;
});
diff --git a/bungee/src/main/java/co/aikar/commands/BungeeCommandExecutionContext.java b/bungee/src/main/java/co/aikar/commands/BungeeCommandExecutionContext.java
index e8439177..01853b79 100644
--- a/bungee/src/main/java/co/aikar/commands/BungeeCommandExecutionContext.java
+++ b/bungee/src/main/java/co/aikar/commands/BungeeCommandExecutionContext.java
@@ -29,9 +29,9 @@ import java.lang.reflect.Parameter;
import java.util.List;
import java.util.Map;
-public class BungeeCommandExecutionContext extends CommandExecutionContext {
+public class BungeeCommandExecutionContext extends CommandExecutionContext {
- BungeeCommandExecutionContext(RegisteredCommand cmd, Parameter param, CommandIssuer sender, List args, int index, Map passedArgs) {
+ BungeeCommandExecutionContext(RegisteredCommand cmd, Parameter param, BungeeCommandIssuer sender, List args, int index, Map passedArgs) {
super(cmd, param, sender, args, index, passedArgs);
}
diff --git a/bungee/src/main/java/co/aikar/commands/BungeeCommandManager.java b/bungee/src/main/java/co/aikar/commands/BungeeCommandManager.java
index 93e484bb..879ce531 100644
--- a/bungee/src/main/java/co/aikar/commands/BungeeCommandManager.java
+++ b/bungee/src/main/java/co/aikar/commands/BungeeCommandManager.java
@@ -33,6 +33,7 @@ import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.HashMap;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -47,6 +48,7 @@ public class BungeeCommandManager extends CommandManager {
public BungeeCommandManager(Plugin plugin) {
this.plugin = plugin;
+ this.locales.addMessageBundle("acf-minecraft", Locale.ENGLISH);
this.formatters.put(MessageType.ERROR, new BungeeMessageFormatter(ChatColor.RED, ChatColor.YELLOW, ChatColor.RED));
this.formatters.put(MessageType.SYNTAX, new BungeeMessageFormatter(ChatColor.YELLOW, ChatColor.GREEN, ChatColor.WHITE));
this.formatters.put(MessageType.INFO, new BungeeMessageFormatter(ChatColor.BLUE, ChatColor.DARK_GREEN, ChatColor.GREEN));
@@ -112,7 +114,7 @@ public class BungeeCommandManager extends CommandManager {
@Override
public R createCommandContext(RegisteredCommand command, Parameter parameter, CommandIssuer sender, List args, int i, Map passedArgs) {
//noinspection unchecked
- return (R) new BungeeCommandExecutionContext(command, parameter, sender, args, i, passedArgs);
+ return (R) new BungeeCommandExecutionContext(command, parameter, (BungeeCommandIssuer) sender, args, i, passedArgs);
}
@Override
diff --git a/core/pom.xml b/core/pom.xml
index f34f4908..5f80262b 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -85,5 +85,10 @@
+
+
+ ${project.basedir}/../languages/core/
+
+
diff --git a/core/src/main/java/co/aikar/commands/BaseCommand.java b/core/src/main/java/co/aikar/commands/BaseCommand.java
index 36395ae3..203617b1 100644
--- a/core/src/main/java/co/aikar/commands/BaseCommand.java
+++ b/core/src/main/java/co/aikar/commands/BaseCommand.java
@@ -200,7 +200,7 @@ public abstract class BaseCommand {
if (parameters.length == 1) {
subCommand = (BaseCommand) declaredConstructor.newInstance(this);
} else {
- manager.log(LogLevel.INFO, "Found unusable constructor: " + declaredConstructor.getName() + "(" + Stream.of(parameters).map(p -> p.getType().getSimpleName() + " " + p.getName()).collect(Collectors.joining(", ")) + ")");
+ manager.log(LogLevel.INFO, "Found unusable constructor: " + declaredConstructor.getName() + "(" + Stream.of(parameters).map(p -> p.getType().getSimpleName() + " " + p.getName()).collect(Collectors.joining(", ")) + ")");
}
}
if (subCommand != null) {
diff --git a/core/src/main/java/co/aikar/commands/CommandContexts.java b/core/src/main/java/co/aikar/commands/CommandContexts.java
index 8f34b2a5..81173e13 100644
--- a/core/src/main/java/co/aikar/commands/CommandContexts.java
+++ b/core/src/main/java/co/aikar/commands/CommandContexts.java
@@ -29,14 +29,13 @@ import co.aikar.commands.annotation.Values;
import co.aikar.commands.contexts.ContextResolver;
import co.aikar.commands.contexts.IssuerAwareContextResolver;
import co.aikar.commands.contexts.IssuerOnlyContextResolver;
-import co.aikar.commands.contexts.SenderAwareContextResolver;
import com.google.common.collect.Maps;
import java.util.List;
import java.util.Map;
@SuppressWarnings("WeakerAccess")
-public class CommandContexts > {
+public class CommandContexts > {
protected final Map, ContextResolver, R>> contextMap = Maps.newHashMap();
protected final CommandManager manager;
@@ -46,14 +45,14 @@ public class CommandContexts > {
try {
return ACFUtil.parseNumber(c.popFirstArg(), c.hasFlag("suffixes")).intValue();
} catch (NumberFormatException e) {
- throw new InvalidCommandArgument("Must be a number");
+ throw new InvalidCommandArgument(MessageKeys.MUST_BE_A_NUMBER);
}
});
registerContext(Long.class, (c) -> {
try {
return ACFUtil.parseNumber(c.popFirstArg(), c.hasFlag("suffixes")).longValue();
} catch (NumberFormatException e) {
- throw new InvalidCommandArgument("Must be a number");
+ throw new InvalidCommandArgument(MessageKeys.MUST_BE_A_NUMBER);
}
});
@@ -61,21 +60,21 @@ public class CommandContexts > {
try {
return ACFUtil.parseNumber(c.popFirstArg(), c.hasFlag("suffixes")).floatValue();
} catch (NumberFormatException e) {
- throw new InvalidCommandArgument("Must be a number");
+ throw new InvalidCommandArgument(MessageKeys.MUST_BE_A_NUMBER);
}
});
registerContext(Double.class, (c) -> {
try {
return ACFUtil.parseNumber(c.popFirstArg(), c.hasFlag("suffixes")).doubleValue();
} catch (NumberFormatException e) {
- throw new InvalidCommandArgument("Must be a number");
+ throw new InvalidCommandArgument(MessageKeys.MUST_BE_A_NUMBER);
}
});
registerContext(Number.class, (c) -> {
try {
return ACFUtil.parseNumber(c.popFirstArg(), c.hasFlag("suffixes"));
} catch (NumberFormatException e) {
- throw new InvalidCommandArgument("Must be a number");
+ throw new InvalidCommandArgument(MessageKeys.MUST_BE_A_NUMBER);
}
});
registerContext(Boolean.class, (c) -> {
@@ -99,12 +98,12 @@ public class CommandContexts > {
Integer maxLen = c.getFlagValue("maxlen", (Integer) null);
if (minLen != null) {
if (ret.length() < minLen) {
- throw new InvalidCommandArgument("Must be at least " + minLen + " characters long");
+ throw new InvalidCommandArgument(MessageKeys.MUST_BE_MIN_LENGTH, "{min}", String.valueOf(minLen));
}
}
if (maxLen != null) {
if (ret.length() > maxLen) {
- throw new InvalidCommandArgument("Must be less " + maxLen + " characters long");
+ throw new InvalidCommandArgument(MessageKeys.MUST_BE_MAX_LENGTH, "{max}", String.valueOf(maxLen));
}
}
@@ -142,7 +141,7 @@ public class CommandContexts > {
Enum> match = ACFUtil.simpleMatch(enumCls, first);
if (match == null) {
List names = ACFUtil.enumNames(enumCls);
- throw new InvalidCommandArgument("Please specify one of: " + ACFUtil.join(names));
+ throw new InvalidCommandArgument(MessageKeys.PLEASE_SPECIFY_ONE_OF, "{valid}", ACFUtil.join(names));
}
return match;
});
diff --git a/core/src/main/java/co/aikar/commands/CommandExecutionContext.java b/core/src/main/java/co/aikar/commands/CommandExecutionContext.java
index 4e6d4863..06ae90d1 100644
--- a/core/src/main/java/co/aikar/commands/CommandExecutionContext.java
+++ b/core/src/main/java/co/aikar/commands/CommandExecutionContext.java
@@ -37,16 +37,16 @@ import java.util.List;
import java.util.Map;
@SuppressWarnings({"WeakerAccess", "unused"})
-public class CommandExecutionContext {
+public class CommandExecutionContext {
private final RegisteredCommand cmd;
private final Parameter param;
- protected final CommandIssuer issuer;
+ protected final I issuer;
private final List args;
private final int index;
private final Map passedArgs;
private final Map flags;
- CommandExecutionContext(RegisteredCommand cmd, Parameter param, CommandIssuer sender, List args,
+ CommandExecutionContext(RegisteredCommand cmd, Parameter param, I sender, List args,
int index, Map passedArgs) {
this.cmd = cmd;
this.param = param;
@@ -157,7 +157,7 @@ public class CommandExecutionContext {
return this.param;
}
- public CommandIssuer getIssuer() {
+ public I getIssuer() {
return this.issuer;
}
diff --git a/core/src/main/java/co/aikar/commands/CommandIssuer.java b/core/src/main/java/co/aikar/commands/CommandIssuer.java
index 5c4a5d03..738ba950 100644
--- a/core/src/main/java/co/aikar/commands/CommandIssuer.java
+++ b/core/src/main/java/co/aikar/commands/CommandIssuer.java
@@ -56,6 +56,27 @@ public interface CommandIssuer {
*/
boolean hasPermission(String permission);
+ default void sendError(MessageKeyProvider key, String... replacements) {
+ sendMessage(MessageType.ERROR, key.getMessageKey(), replacements);
+ }
+ default void sendSyntax(MessageKeyProvider key, String... replacements) {
+ sendMessage(MessageType.SYNTAX, key.getMessageKey(), replacements);
+ }
+ default void sendInfo(MessageKeyProvider key, String... replacements) {
+ sendMessage(MessageType.INFO, key.getMessageKey(), replacements);
+ }
+ default void sendError(MessageKey key, String... replacements) {
+ sendMessage(MessageType.ERROR, key, replacements);
+ }
+ default void sendSyntax(MessageKey key, String... replacements) {
+ sendMessage(MessageType.SYNTAX, key, replacements);
+ }
+ default void sendInfo(MessageKey key, String... replacements) {
+ sendMessage(MessageType.INFO, key, replacements);
+ }
+ default void sendMessage(MessageType type, MessageKeyProvider key, String... replacements) {
+ sendMessage(type, key.getMessageKey(), replacements);
+ }
default void sendMessage(MessageType type, MessageKey key, String... replacements) {
getManager().sendMessage(this, type, key, replacements);
}
diff --git a/core/src/main/java/co/aikar/commands/CommandManager.java b/core/src/main/java/co/aikar/commands/CommandManager.java
index 4379465f..3ec465e2 100644
--- a/core/src/main/java/co/aikar/commands/CommandManager.java
+++ b/core/src/main/java/co/aikar/commands/CommandManager.java
@@ -27,7 +27,6 @@ import co.aikar.locales.MessageKey;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
-import java.util.EnumMap;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.List;
@@ -151,6 +150,9 @@ abstract class CommandManager {
return result;
}
+ protected void sendMessage(Object issuerArg, MessageType type, MessageKeyProvider key, String... replacements) {
+ sendMessage(issuerArg, type, key.getMessageKey(), replacements);
+ }
protected void sendMessage(Object issuerArg, MessageType type, MessageKey key, String... replacements) {
CommandIssuer issuer = issuerArg instanceof CommandIssuer ? (CommandIssuer) issuerArg : getCommandIssuer(issuerArg);
String message = getLocales().getMessage(issuer, key);
@@ -161,7 +163,9 @@ abstract class CommandManager {
if (formatter != null) {
message = formatter.format(message);
}
- issuer.sendMessageInternal(message);
+ for (String msg : ACFPatterns.NEWLINE.split(message)) {
+ issuer.sendMessageInternal(msg);
+ }
}
diff --git a/core/src/main/java/co/aikar/commands/InvalidCommandArgument.java b/core/src/main/java/co/aikar/commands/InvalidCommandArgument.java
index 41711633..43d2f3ca 100644
--- a/core/src/main/java/co/aikar/commands/InvalidCommandArgument.java
+++ b/core/src/main/java/co/aikar/commands/InvalidCommandArgument.java
@@ -23,19 +23,52 @@
package co.aikar.commands;
+import co.aikar.locales.MessageKey;
+
public class InvalidCommandArgument extends Exception {
- public boolean showSyntax = true;
+ final boolean showSyntax;
+ final MessageKey key;
+ final String[] replacements;
+
public InvalidCommandArgument() {
- this(null);
+ this((String) null, true);
}
public InvalidCommandArgument(boolean showSyntax) {
this(null, showSyntax);
}
- public InvalidCommandArgument(String message) {
- this(message, true);
+ public InvalidCommandArgument(MessageKeyProvider key, String... replacements) {
+ this(key.getMessageKey(), replacements);
}
+ public InvalidCommandArgument(MessageKey key, String... replacements) {
+ this(key, true, replacements);
+ }
+ public InvalidCommandArgument(MessageKeyProvider key, boolean showSyntax, String... replacements) {
+ this(key.getMessageKey(), showSyntax, replacements);
+ }
+ public InvalidCommandArgument(MessageKey key, boolean showSyntax, String... replacements) {
+ super(key.getKey(), null, false, false);
+ this.showSyntax = showSyntax;
+ this.key = key;
+ this.replacements = replacements;
+ }
+
+ /**
+ * Please move to a MessageKey
+ * @deprecated
+ */
+ @Deprecated
+ public InvalidCommandArgument(String message) {
+ this(message, true);
+ }
+ /**
+ * Please move to a MessageKey
+ * @deprecated
+ */
+ @Deprecated
public InvalidCommandArgument(String message, boolean showSyntax) {
super(message, null, false, false);
this.showSyntax = showSyntax;
+ this.replacements = null;
+ this.key = null;
}
}
diff --git a/core/src/main/java/co/aikar/commands/MessageKeyProvider.java b/core/src/main/java/co/aikar/commands/MessageKeyProvider.java
new file mode 100644
index 00000000..3b88cc9a
--- /dev/null
+++ b/core/src/main/java/co/aikar/commands/MessageKeyProvider.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package co.aikar.commands;
+
+import co.aikar.locales.MessageKey;
+
+public interface MessageKeyProvider {
+ MessageKey getMessageKey();
+}
diff --git a/core/src/main/java/co/aikar/commands/MessageKeys.java b/core/src/main/java/co/aikar/commands/MessageKeys.java
index cdd2b34d..64716ada 100644
--- a/core/src/main/java/co/aikar/commands/MessageKeys.java
+++ b/core/src/main/java/co/aikar/commands/MessageKeys.java
@@ -25,13 +25,26 @@ package co.aikar.commands;
import co.aikar.locales.MessageKey;
+/**
+ * Enum Name = MessageKey in lowercase
+ */
@SuppressWarnings("WeakerAccess")
-public class MessageKeys {
- public static final MessageKey PERMISSION_DENIED = MessageKey.of("permission_denied");
- public static final MessageKey ERROR_GENERIC_LOGGED = MessageKey.of("error_generic_logged");
- public static final MessageKey UNKNOWN_COMMAND = MessageKey.of("unknown_command");
- public static final MessageKey INVALID_SYNTAX = MessageKey.of("invalid_syntax");
- public static final MessageKey ERROR_PREFIX = MessageKey.of("error_prefix");
- public static final MessageKey ERROR_PERFORMING_COMMAND = MessageKey.of("error_performing_command");
- public static final MessageKey INFO_MESSAGE = MessageKey.of("info_message");
+public enum MessageKeys implements MessageKeyProvider {
+ PERMISSION_DENIED,
+ ERROR_GENERIC_LOGGED,
+ UNKNOWN_COMMAND,
+ INVALID_SYNTAX,
+ ERROR_PREFIX,
+ ERROR_PERFORMING_COMMAND,
+ INFO_MESSAGE,
+ PLEASE_SPECIFY_ONE_OF,
+ MUST_BE_A_NUMBER,
+ MUST_BE_MIN_LENGTH,
+ MUST_BE_MAX_LENGTH,
+ NOT_ALLOWED_ON_CONSOLE, COULD_NOT_FIND_PLAYER;
+
+ private final MessageKey key = MessageKey.of(this.name().toLowerCase());
+ public MessageKey getMessageKey() {
+ return key;
+ }
}
diff --git a/core/src/main/java/co/aikar/commands/RegisteredCommand.java b/core/src/main/java/co/aikar/commands/RegisteredCommand.java
index 48a10043..c3e6772a 100644
--- a/core/src/main/java/co/aikar/commands/RegisteredCommand.java
+++ b/core/src/main/java/co/aikar/commands/RegisteredCommand.java
@@ -47,7 +47,7 @@ import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
-public class RegisteredCommand > {
+public class RegisteredCommand > {
final BaseCommand scope;
public final String command;
private final Method method;
@@ -153,10 +153,13 @@ public class RegisteredCommand > {
+public interface ContextResolver > {
T getContext(C c) throws InvalidCommandArgument;
}
diff --git a/core/src/main/java/co/aikar/commands/contexts/IssuerAwareContextResolver.java b/core/src/main/java/co/aikar/commands/contexts/IssuerAwareContextResolver.java
index 9be13e2a..b157b28b 100644
--- a/core/src/main/java/co/aikar/commands/contexts/IssuerAwareContextResolver.java
+++ b/core/src/main/java/co/aikar/commands/contexts/IssuerAwareContextResolver.java
@@ -24,6 +24,7 @@
package co.aikar.commands.contexts;
import co.aikar.commands.CommandExecutionContext;
+import co.aikar.commands.CommandIssuer;
-public interface IssuerAwareContextResolver> extends ContextResolver {}
+public interface IssuerAwareContextResolver> extends ContextResolver {}
diff --git a/core/src/main/java/co/aikar/commands/contexts/IssuerOnlyContextResolver.java b/core/src/main/java/co/aikar/commands/contexts/IssuerOnlyContextResolver.java
index 32450e92..b99c9d1b 100644
--- a/core/src/main/java/co/aikar/commands/contexts/IssuerOnlyContextResolver.java
+++ b/core/src/main/java/co/aikar/commands/contexts/IssuerOnlyContextResolver.java
@@ -24,10 +24,11 @@
package co.aikar.commands.contexts;
import co.aikar.commands.CommandExecutionContext;
+import co.aikar.commands.CommandIssuer;
/**
* A context resolver that will never consume input, and only resolves using the context of the issuer of the command
* @param
* @param
*/
-public interface IssuerOnlyContextResolver> extends ContextResolver {}
+public interface IssuerOnlyContextResolver> extends ContextResolver {}
diff --git a/core/src/main/java/co/aikar/commands/contexts/SenderAwareContextResolver.java b/core/src/main/java/co/aikar/commands/contexts/SenderAwareContextResolver.java
index 4daefe00..fa7a7730 100644
--- a/core/src/main/java/co/aikar/commands/contexts/SenderAwareContextResolver.java
+++ b/core/src/main/java/co/aikar/commands/contexts/SenderAwareContextResolver.java
@@ -24,6 +24,7 @@
package co.aikar.commands.contexts;
import co.aikar.commands.CommandExecutionContext;
+import co.aikar.commands.CommandIssuer;
/**
* Wrapper for IssuerAwareContextResolver
@@ -32,4 +33,4 @@ import co.aikar.commands.CommandExecutionContext;
* @see IssuerAwareContextResolver
*/
@Deprecated
-public interface SenderAwareContextResolver> extends IssuerAwareContextResolver {}
+public interface SenderAwareContextResolver> extends IssuerAwareContextResolver {}
diff --git a/core/src/main/resources/acf-core_en.properties b/core/src/main/resources/acf-core_en.properties
deleted file mode 100644
index 755c9474..00000000
--- a/core/src/main/resources/acf-core_en.properties
+++ /dev/null
@@ -1,7 +0,0 @@
-permission_denied = I'm sorry, but you do not have permission to perform this command.
-error_generic_logged = An error occured. This problem has been logged. Sorry for the inconvienence.
-unknown_command = Unknown Command, please type /help
-invalid_syntax = Usage: {command} {syntax}
-error_prefix = Error: {message}
-error_performing_command = I'm sorry, but there was an error performing this command.
-info_message = {message}
diff --git a/example/src/main/java/co/aikar/acfexample/SomeObject.java b/example/src/main/java/co/aikar/acfexample/SomeObject.java
index 2077309c..b4cb1f53 100644
--- a/example/src/main/java/co/aikar/acfexample/SomeObject.java
+++ b/example/src/main/java/co/aikar/acfexample/SomeObject.java
@@ -25,6 +25,7 @@ package co.aikar.acfexample;
import co.aikar.commands.BukkitCommandExecutionContext;
import co.aikar.commands.InvalidCommandArgument;
+import co.aikar.commands.MessageKeys;
import co.aikar.commands.contexts.ContextResolver;
public abstract class SomeObject {
@@ -41,9 +42,6 @@ public abstract class SomeObject {
public static ContextResolver getContextResolver() {
return (c) -> {
String first = c.popFirstArg();
- if (first == null) {
- throw new InvalidCommandArgument("Must supply a number");
- }
if ("1".equals(first)) {
return new Test1();
} else if ("2".equals(first)) {
@@ -52,7 +50,7 @@ public abstract class SomeObject {
try {
return new TestOther(Integer.parseInt(first));
} catch (NumberFormatException ignored) {
- throw new InvalidCommandArgument("Must be a valid number");
+ throw new InvalidCommandArgument(MessageKeys.MUST_BE_A_NUMBER);
}
}
};
diff --git a/languages/core/acf-core_en.properties b/languages/core/acf-core_en.properties
new file mode 100644
index 00000000..8bac7ade
--- /dev/null
+++ b/languages/core/acf-core_en.properties
@@ -0,0 +1,35 @@
+# Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+permission_denied = I'm sorry, but you do not have permission to perform this command.
+error_generic_logged = An error occured. This problem has been logged. Sorry for the inconvienence.
+unknown_command = Unknown Command, please type /help
+invalid_syntax = Usage: {command} {syntax}
+error_prefix = Error: {message}
+error_performing_command = I'm sorry, but there was an error performing this command.
+info_message = {message}
+please_specify_one_of = Error: Please specify one of ({valid}).
+must_be_a_number = Error: Must be a number
+must_be_min_length = Error: Must be at least {min} characters long.
+must_be_max_length = Error: Must be less than {max} characters long.
+not_allowed_on_console = Error: Console may not execute this command.
+could_not_find_player = Error: Could not find a player by the name: {search}
diff --git a/languages/minecraft/acf-minecraft_en.properties b/languages/minecraft/acf-minecraft_en.properties
new file mode 100644
index 00000000..ef7535b4
--- /dev/null
+++ b/languages/minecraft/acf-minecraft_en.properties
@@ -0,0 +1,32 @@
+#
+# Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+invalid_world = Error: That world does not exists.
+you_must_be_holding_item = Error: You must be holding an item in your main hand.
+player_is_vanished_confirm = \
+ Warning: {vanished} is vanished. Do not blow their cover!\n\
+ To confirm your action, add :confirm to the end of their name.\n\
+ Ex: {vanished}:confirm
+username_too_short = Error: Username too short, must be at least three characters.
+is_not_a_valid_name = Error: {name} is not a valid username.
+multiple_players_matched = Error: Multiple players matched {search}, please be more specific.
diff --git a/sponge/pom.xml b/sponge/pom.xml
index bf96924d..828d8460 100644
--- a/sponge/pom.xml
+++ b/sponge/pom.xml
@@ -60,4 +60,11 @@
provided
+
+
+
+ ${project.basedir}/../languages/minecraft/
+
+
+
diff --git a/sponge/src/main/java/co/aikar/commands/SpongeCommandExecutionContext.java b/sponge/src/main/java/co/aikar/commands/SpongeCommandExecutionContext.java
index a9570ce1..700e6996 100644
--- a/sponge/src/main/java/co/aikar/commands/SpongeCommandExecutionContext.java
+++ b/sponge/src/main/java/co/aikar/commands/SpongeCommandExecutionContext.java
@@ -29,9 +29,9 @@ import java.lang.reflect.Parameter;
import java.util.List;
import java.util.Map;
-public class SpongeCommandExecutionContext extends CommandExecutionContext {
+public class SpongeCommandExecutionContext extends CommandExecutionContext {
- SpongeCommandExecutionContext(RegisteredCommand cmd, Parameter param, CommandIssuer sender, List args,
+ SpongeCommandExecutionContext(RegisteredCommand cmd, Parameter param, SpongeCommandIssuer sender, List args,
int index, Map passedArgs) {
super(cmd, param, sender, args, index, passedArgs);
}
diff --git a/sponge/src/main/java/co/aikar/commands/SpongeCommandManager.java b/sponge/src/main/java/co/aikar/commands/SpongeCommandManager.java
index 2d902f8a..41e83d6e 100644
--- a/sponge/src/main/java/co/aikar/commands/SpongeCommandManager.java
+++ b/sponge/src/main/java/co/aikar/commands/SpongeCommandManager.java
@@ -36,6 +36,7 @@ import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.HashMap;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
@SuppressWarnings("WeakerAccess")
@@ -49,6 +50,7 @@ public class SpongeCommandManager extends CommandManager {
public SpongeCommandManager(PluginContainer plugin) {
this.plugin = plugin;
+ this.locales.addMessageBundle("acf-minecraft", Locale.ENGLISH);
this.commandTiming = Timings.of(plugin, "Commands");
this.formatters.put(MessageType.ERROR, new SpongeMessageFormatter(TextColors.RED, TextColors.YELLOW, TextColors.RED));
@@ -117,7 +119,7 @@ public class SpongeCommandManager extends CommandManager {
@Override
public R createCommandContext(RegisteredCommand command, Parameter parameter, CommandIssuer sender, List args, int i, Map passedArgs) {
//noinspection unchecked
- return (R) new SpongeCommandExecutionContext(command, parameter, sender, args, i, passedArgs);
+ return (R) new SpongeCommandExecutionContext(command, parameter, (SpongeCommandIssuer) sender, args, i, passedArgs);
}
@Override