diff --git a/bukkit/acf-bukkit.iml b/bukkit/acf-bukkit.iml
index 81e6649a..579fdd23 100644
--- a/bukkit/acf-bukkit.iml
+++ b/bukkit/acf-bukkit.iml
@@ -19,10 +19,10 @@
-
-
+
+
diff --git a/bukkit/src/main/java/co/aikar/commands/BukkitCommandManager.java b/bukkit/src/main/java/co/aikar/commands/BukkitCommandManager.java
index fe5e12f0..cab82955 100644
--- a/bukkit/src/main/java/co/aikar/commands/BukkitCommandManager.java
+++ b/bukkit/src/main/java/co/aikar/commands/BukkitCommandManager.java
@@ -30,7 +30,6 @@ import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Server;
import org.bukkit.command.Command;
-import org.bukkit.command.CommandException;
import org.bukkit.command.CommandMap;
import org.bukkit.command.CommandSender;
import org.bukkit.command.SimpleCommandMap;
@@ -38,13 +37,13 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.server.PluginDisableEvent;
import org.bukkit.plugin.Plugin;
+import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Field;
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;
@@ -61,14 +60,22 @@ public class BukkitCommandManager extends CommandManager {
protected BukkitCommandContexts contexts;
protected BukkitCommandCompletions completions;
MCTiming commandTiming;
+ protected BukkitLocales locales;
@SuppressWarnings("JavaReflectionMemberAccess")
public BukkitCommandManager(Plugin plugin) {
this.plugin = plugin;
- String pluginName = "acf-" + plugin.getDescription().getName();
- this.locales.addMessageBundles("acf-minecraft", pluginName, pluginName.toLowerCase());
this.timingManager = TimingManager.of(plugin);
this.commandTiming = this.timingManager.of("Commands");
+ this.commandMap = hookCommandMap();
+ this.formatters.put(MessageType.ERROR, defaultFormatter = new BukkitMessageFormatter(ChatColor.RED, ChatColor.YELLOW, ChatColor.RED));
+ this.formatters.put(MessageType.SYNTAX, new BukkitMessageFormatter(ChatColor.YELLOW, ChatColor.GREEN, ChatColor.WHITE));
+ this.formatters.put(MessageType.INFO, new BukkitMessageFormatter(ChatColor.BLUE, ChatColor.DARK_GREEN, ChatColor.GREEN));
+ Bukkit.getPluginManager().registerEvents(new ACFBukkitListener(plugin), plugin);
+ getLocales(); // auto load locales
+ }
+
+ @NotNull private CommandMap hookCommandMap() {
CommandMap commandMap = null;
try {
Server server = Bukkit.getServer();
@@ -80,7 +87,8 @@ public class BukkitCommandManager extends CommandManager {
this.log(LogLevel.ERROR, "We are going to try to hijack it back and resolve this, but you are now in dangerous territory.");
this.log(LogLevel.ERROR, "We can not guarantee things are going to work.");
Field cmField = server.getClass().getDeclaredField("commandMap");
- cmField.set(server, commandMap = new ProxyCommandMap(commandMap));
+ commandMap = new ProxyCommandMap(this, commandMap);
+ cmField.set(server, commandMap);
this.log(LogLevel.INFO, "Injected Proxy Command Map... good luck...");
}
Field knownCommands = SimpleCommandMap.class.getDeclaredField("knownCommands");
@@ -91,17 +99,33 @@ public class BukkitCommandManager extends CommandManager {
this.log(LogLevel.ERROR, "Failed to get Command Map. ACF will not function.");
ACFUtil.sneaky(e);
}
- this.commandMap = commandMap;
- this.formatters.put(MessageType.ERROR, new BukkitMessageFormatter(ChatColor.RED, ChatColor.YELLOW, ChatColor.RED));
- this.formatters.put(MessageType.SYNTAX, new BukkitMessageFormatter(ChatColor.YELLOW, ChatColor.GREEN, ChatColor.WHITE));
- this.formatters.put(MessageType.INFO, new BukkitMessageFormatter(ChatColor.BLUE, ChatColor.DARK_GREEN, ChatColor.GREEN));
- Bukkit.getPluginManager().registerEvents(new ACFBukkitListener(plugin), plugin);
+ return commandMap;
}
public Plugin getPlugin() {
return this.plugin;
}
+ public BukkitMessageFormatter setFormat(MessageType type, BukkitMessageFormatter formatter) {
+ return (BukkitMessageFormatter) formatters.put(type, formatter);
+ }
+
+ public BukkitMessageFormatter getFormat(MessageType type) {
+ return (BukkitMessageFormatter) formatters.getOrDefault(type, defaultFormatter);
+ }
+
+ public void setFormat(MessageType type, ChatColor... colors) {
+ BukkitMessageFormatter format = getFormat(type);
+ for (int i = 0; i < colors.length; i++) {
+ format.setColor(i, colors[i]);
+ }
+ }
+
+ public void setFormat(MessageType type, int i, ChatColor color) {
+ BukkitMessageFormatter format = getFormat(type);
+ format.setColor(i, color);
+ }
+
@Override
public boolean isCommandIssuer(Class> type) {
return CommandSender.class.isAssignableFrom(type);
@@ -123,6 +147,17 @@ public class BukkitCommandManager extends CommandManager {
return completions;
}
+
+ @Override
+ public BukkitLocales getLocales() {
+ if (this.locales == null) {
+ this.locales = new BukkitLocales(this);
+ this.locales.loadLanguages();
+ }
+ return locales;
+ }
+
+
@Override
public boolean hasRegisteredCommands() {
return !registeredCommands.isEmpty();
@@ -240,79 +275,4 @@ public class BukkitCommandManager extends CommandManager {
}
}
}
-
- class ProxyCommandMap extends SimpleCommandMap {
-
- CommandMap proxied;
-
- ProxyCommandMap(CommandMap proxied) {
- super(Bukkit.getServer());
- this.proxied = proxied;
- }
-
- @Override
- public void registerAll(String fallbackPrefix, List commands) {
- proxied.registerAll(fallbackPrefix, commands);
- }
-
- @Override
- public boolean register(String label, String fallbackPrefix, Command command) {
- if (isOurCommand(command)) {
- return super.register(label, fallbackPrefix, command);
- } else {
- return proxied.register(label, fallbackPrefix, command);
- }
- }
-
- boolean isOurCommand(String cmdLine) {
- String[] args = ACFPatterns.SPACE.split(cmdLine);
- return args.length != 0 && isOurCommand(knownCommands.get(args[0].toLowerCase(Locale.ENGLISH)));
-
- }
- boolean isOurCommand(Command command) {
- return command instanceof RootCommand && ((RootCommand) command).getManager() == BukkitCommandManager.this;
- }
-
- @Override
- public boolean register(String fallbackPrefix, Command command) {
- if (isOurCommand(command)) {
- return super.register(fallbackPrefix, command);
- } else {
- return proxied.register(fallbackPrefix, command);
- }
- }
-
- @Override
- public boolean dispatch(CommandSender sender, String cmdLine) throws CommandException {
- if (isOurCommand(cmdLine)) {
- return super.dispatch(sender, cmdLine);
- } else {
- return proxied.dispatch(sender, cmdLine);
- }
- }
-
- @Override
- public void clearCommands() {
- super.clearCommands();;
- proxied.clearCommands();
- }
-
- @Override
- public Command getCommand(String name) {
- if (isOurCommand(name)) {
- return super.getCommand(name);
- } else {
- return proxied.getCommand(name);
- }
- }
-
- @Override
- public List tabComplete(CommandSender sender, String cmdLine) throws IllegalArgumentException {
- if (isOurCommand(cmdLine)) {
- return super.tabComplete(sender, cmdLine);
- } else {
- return proxied.tabComplete(sender, cmdLine);
- }
- }
- }
}
diff --git a/bukkit/src/main/java/co/aikar/commands/BukkitLocales.java b/bukkit/src/main/java/co/aikar/commands/BukkitLocales.java
new file mode 100644
index 00000000..da0ee649
--- /dev/null
+++ b/bukkit/src/main/java/co/aikar/commands/BukkitLocales.java
@@ -0,0 +1,104 @@
+/*
+ * 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;
+import org.bukkit.configuration.ConfigurationSection;
+import org.bukkit.configuration.InvalidConfigurationException;
+import org.bukkit.configuration.file.FileConfiguration;
+import org.bukkit.configuration.file.YamlConfiguration;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Locale;
+
+public class BukkitLocales extends Locales {
+ private final BukkitCommandManager manager;
+
+ public BukkitLocales(BukkitCommandManager manager) {
+ super(manager);
+ this.manager = manager;
+ }
+
+ @Override
+ public void loadLanguages() {
+ super.loadLanguages();
+ String pluginName = "acf-" + manager.plugin.getDescription().getName();
+ addMessageBundles("acf-minecraft", pluginName, pluginName.toLowerCase());
+ }
+
+ /**
+ * Loads the given file
+ * @param file
+ * @param locale
+ * @return If any language keys were added
+ * @throws IOException
+ * @throws InvalidConfigurationException
+ */
+ public boolean loadYamlLanguageFile(File file, Locale locale) throws IOException, InvalidConfigurationException {
+ YamlConfiguration yamlConfiguration = new YamlConfiguration();
+ yamlConfiguration.load(file);
+ return loadLanguage(yamlConfiguration, locale);
+ }
+
+ /**
+ * Loads a file out of the plugins data folder by the given name
+ * @param file
+ * @param locale
+ * @return If any language keys were added
+ * @throws IOException
+ * @throws InvalidConfigurationException
+ */
+ public boolean loadYamlLanguageFile(String file, Locale locale) throws IOException, InvalidConfigurationException {
+ YamlConfiguration yamlConfiguration = new YamlConfiguration();
+ yamlConfiguration.load(new File(this.manager.plugin.getDataFolder(), file));
+ return loadLanguage(yamlConfiguration, locale);
+ }
+
+ /**
+ * Loads every message from the Configuration object. Any nested values will be treated as namespace
+ * so acf-core:\n\tfoo: bar will be acf-core.foo = bar
+ * @param config
+ * @param locale
+ * @return If any language keys were added
+ */
+ public boolean loadLanguage(FileConfiguration config, Locale locale) {
+ boolean loaded = false;
+ for (String parentKey : config.getKeys(false)) {
+ ConfigurationSection inner = config.getConfigurationSection(parentKey);
+ if (inner == null) {
+ continue;
+ }
+ for (String key : inner.getKeys(false)) {
+ String value = inner.getString(key);
+ if (value != null && !value.isEmpty()) {
+ addMessage(locale, MessageKey.of(parentKey + "." + key), value);
+ loaded = true;
+ }
+ }
+ }
+
+ return loaded;
+ }
+}
diff --git a/bukkit/src/main/java/co/aikar/commands/MinecraftMessageKeys.java b/bukkit/src/main/java/co/aikar/commands/MinecraftMessageKeys.java
index e438b2e1..5503a5be 100644
--- a/bukkit/src/main/java/co/aikar/commands/MinecraftMessageKeys.java
+++ b/bukkit/src/main/java/co/aikar/commands/MinecraftMessageKeys.java
@@ -24,6 +24,7 @@
package co.aikar.commands;
import co.aikar.locales.MessageKey;
+import co.aikar.locales.MessageKeyProvider;
public enum MinecraftMessageKeys implements MessageKeyProvider {
INVALID_WORLD,
diff --git a/bukkit/src/main/java/co/aikar/commands/ProxyCommandMap.java b/bukkit/src/main/java/co/aikar/commands/ProxyCommandMap.java
new file mode 100644
index 00000000..834ced43
--- /dev/null
+++ b/bukkit/src/main/java/co/aikar/commands/ProxyCommandMap.java
@@ -0,0 +1,111 @@
+/*
+ * 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 org.bukkit.Bukkit;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandException;
+import org.bukkit.command.CommandMap;
+import org.bukkit.command.CommandSender;
+import org.bukkit.command.SimpleCommandMap;
+
+import java.util.List;
+import java.util.Locale;
+
+class ProxyCommandMap extends SimpleCommandMap {
+
+ private BukkitCommandManager manager;
+ CommandMap proxied;
+
+ ProxyCommandMap(BukkitCommandManager manager, CommandMap proxied) {
+ super(Bukkit.getServer());
+ this.manager = manager;
+ this.proxied = proxied;
+ }
+
+ @Override
+ public void registerAll(String fallbackPrefix, List commands) {
+ proxied.registerAll(fallbackPrefix, commands);
+ }
+
+ @Override
+ public boolean register(String label, String fallbackPrefix, Command command) {
+ if (isOurCommand(command)) {
+ return super.register(label, fallbackPrefix, command);
+ } else {
+ return proxied.register(label, fallbackPrefix, command);
+ }
+ }
+
+ boolean isOurCommand(String cmdLine) {
+ String[] args = ACFPatterns.SPACE.split(cmdLine);
+ return args.length != 0 && isOurCommand(knownCommands.get(args[0].toLowerCase(Locale.ENGLISH)));
+
+ }
+ boolean isOurCommand(Command command) {
+ return command instanceof RootCommand && ((RootCommand) command).getManager() == manager;
+ }
+
+ @Override
+ public boolean register(String fallbackPrefix, Command command) {
+ if (isOurCommand(command)) {
+ return super.register(fallbackPrefix, command);
+ } else {
+ return proxied.register(fallbackPrefix, command);
+ }
+ }
+
+ @Override
+ public boolean dispatch(CommandSender sender, String cmdLine) throws CommandException {
+ if (isOurCommand(cmdLine)) {
+ return super.dispatch(sender, cmdLine);
+ } else {
+ return proxied.dispatch(sender, cmdLine);
+ }
+ }
+
+ @Override
+ public void clearCommands() {
+ super.clearCommands();;
+ proxied.clearCommands();
+ }
+
+ @Override
+ public Command getCommand(String name) {
+ if (isOurCommand(name)) {
+ return super.getCommand(name);
+ } else {
+ return proxied.getCommand(name);
+ }
+ }
+
+ @Override
+ public List tabComplete(CommandSender sender, String cmdLine) throws IllegalArgumentException {
+ if (isOurCommand(cmdLine)) {
+ return super.tabComplete(sender, cmdLine);
+ } else {
+ return proxied.tabComplete(sender, cmdLine);
+ }
+ }
+}
diff --git a/bungee/acf-bungee.iml b/bungee/acf-bungee.iml
index 6fce7dba..1314a2c7 100644
--- a/bungee/acf-bungee.iml
+++ b/bungee/acf-bungee.iml
@@ -18,10 +18,15 @@
-
-
+
+
+
+
+
+
+
@@ -29,11 +34,11 @@
-
-
-
-
-
+
+
+
+
+
diff --git a/bungee/src/main/java/co/aikar/commands/BungeeCommandManager.java b/bungee/src/main/java/co/aikar/commands/BungeeCommandManager.java
index 002665d7..0a8b7a59 100644
--- a/bungee/src/main/java/co/aikar/commands/BungeeCommandManager.java
+++ b/bungee/src/main/java/co/aikar/commands/BungeeCommandManager.java
@@ -44,20 +44,40 @@ public class BungeeCommandManager extends CommandManager {
protected Map registeredCommands = new HashMap<>();
protected BungeeCommandContexts contexts;
protected BungeeCommandCompletions completions;
+ protected BungeeLocales locales;
public BungeeCommandManager(Plugin plugin) {
this.plugin = plugin;
- String pluginName = "acf-" + plugin.getDescription().getName();
- this.locales.addMessageBundles("acf-minecraft", pluginName, pluginName.toLowerCase());
- this.formatters.put(MessageType.ERROR, new BungeeMessageFormatter(ChatColor.RED, ChatColor.YELLOW, ChatColor.RED));
+ this.formatters.put(MessageType.ERROR, defaultFormatter = 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));
+ getLocales(); // auto load locales
}
public Plugin getPlugin() {
return this.plugin;
}
+ public BungeeMessageFormatter setFormat(MessageType type, BungeeMessageFormatter formatter) {
+ return (BungeeMessageFormatter) formatters.put(type, formatter);
+ }
+
+ public BungeeMessageFormatter getFormat(MessageType type) {
+ return (BungeeMessageFormatter) formatters.getOrDefault(type, defaultFormatter);
+ }
+
+ public void setFormat(MessageType type, ChatColor... colors) {
+ BungeeMessageFormatter format = getFormat(type);
+ for (int i = 0; i < colors.length; i++) {
+ format.setColor(i, colors[i]);
+ }
+ }
+
+ public void setFormat(MessageType type, int i, ChatColor color) {
+ BungeeMessageFormatter format = getFormat(type);
+ format.setColor(i, color);
+ }
+
@Override
public synchronized CommandContexts getCommandContexts() {
if (this.contexts == null) {
@@ -74,6 +94,16 @@ public class BungeeCommandManager extends CommandManager {
return completions;
}
+ @Override
+ public BungeeLocales getLocales() {
+ if (this.locales == null) {
+ this.locales = new BungeeLocales(this);
+ this.locales.loadLanguages();
+ }
+ return locales;
+ }
+
+
@Override
public void registerCommand(BaseCommand command) {
command.onRegister(this);
diff --git a/bungee/src/main/java/co/aikar/commands/BungeeLocales.java b/bungee/src/main/java/co/aikar/commands/BungeeLocales.java
new file mode 100644
index 00000000..e77a7d17
--- /dev/null
+++ b/bungee/src/main/java/co/aikar/commands/BungeeLocales.java
@@ -0,0 +1,18 @@
+package co.aikar.commands;
+
+public class BungeeLocales extends Locales {
+ private final BungeeCommandManager manager;
+
+ public BungeeLocales(BungeeCommandManager manager) {
+ super(manager);
+
+ this.manager = manager;
+ }
+
+ @Override
+ public void loadLanguages() {
+ super.loadLanguages();
+ String pluginName = "acf-" + manager.plugin.getDescription().getName();
+ addMessageBundles("acf-minecraft", pluginName, pluginName.toLowerCase());
+ }
+}
diff --git a/bungee/src/main/java/co/aikar/commands/MinecraftMessageKeys.java b/bungee/src/main/java/co/aikar/commands/MinecraftMessageKeys.java
index af84b083..4b3df34d 100644
--- a/bungee/src/main/java/co/aikar/commands/MinecraftMessageKeys.java
+++ b/bungee/src/main/java/co/aikar/commands/MinecraftMessageKeys.java
@@ -1,6 +1,7 @@
package co.aikar.commands;
import co.aikar.locales.MessageKey;
+import co.aikar.locales.MessageKeyProvider;
public enum MinecraftMessageKeys implements MessageKeyProvider {
USERNAME_TOO_SHORT,
diff --git a/core/acf-core.iml b/core/acf-core.iml
index 750c642e..f609017e 100644
--- a/core/acf-core.iml
+++ b/core/acf-core.iml
@@ -16,9 +16,9 @@
-
+
diff --git a/core/src/main/java/co/aikar/commands/CommandIssuer.java b/core/src/main/java/co/aikar/commands/CommandIssuer.java
index 738ba950..6a253cfd 100644
--- a/core/src/main/java/co/aikar/commands/CommandIssuer.java
+++ b/core/src/main/java/co/aikar/commands/CommandIssuer.java
@@ -24,6 +24,7 @@
package co.aikar.commands;
import co.aikar.locales.MessageKey;
+import co.aikar.locales.MessageKeyProvider;
public interface CommandIssuer {
/**
diff --git a/core/src/main/java/co/aikar/commands/CommandManager.java b/core/src/main/java/co/aikar/commands/CommandManager.java
index 067f308c..633d3829 100644
--- a/core/src/main/java/co/aikar/commands/CommandManager.java
+++ b/core/src/main/java/co/aikar/commands/CommandManager.java
@@ -24,6 +24,8 @@
package co.aikar.commands;
import co.aikar.locales.MessageKey;
+import co.aikar.locales.MessageKeyProvider;
+import com.google.common.collect.Sets;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
@@ -38,9 +40,10 @@ public abstract class CommandManager {
static ThreadLocal> commandOperationContext = ThreadLocal.withInitial(Stack::new);
protected Map rootCommands = new HashMap<>();
protected CommandReplacements replacements = new CommandReplacements(this);
- protected Locales locales = new Locales(this);
protected ExceptionHandler defaultExceptionHandler = null;
+ protected Set supportedLanguages = Sets.newHashSet(Locale.ENGLISH);
protected Map formatters = new IdentityHashMap<>();
+ protected MessageFormatter defaultFormatter;
{
MessageFormatter plain = new MessageFormatter