Merge branch 'master' into feature/help

This commit is contained in:
mrkirby153
2017-07-18 10:38:13 -07:00
22 changed files with 460 additions and 158 deletions
+2 -2
View File
@@ -19,10 +19,10 @@
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="acf-core" />
<orderEntry type="library" name="Maven: co.aikar:locales:1.0-SNAPSHOT" level="project" />
<orderEntry type="library" name="Maven: org.reflections:reflections:0.9.11" level="project" />
<orderEntry type="library" name="Maven: org.javassist:javassist:3.21.0-GA" level="project" />
<orderEntry type="module" module-name="acf-core" />
<orderEntry type="library" name="Maven: co.aikar:locales:1.0-SNAPSHOT" level="project" />
<orderEntry type="library" name="Maven: co.aikar:minecraft-timings:1.0.4" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: org.bukkit:bukkit:1.12-R0.1-SNAPSHOT" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: commons-lang:commons-lang:2.6" level="project" />
@@ -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<Command> 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<String> tabComplete(CommandSender sender, String cmdLine) throws IllegalArgumentException {
if (isOurCommand(cmdLine)) {
return super.tabComplete(sender, cmdLine);
} else {
return proxied.tabComplete(sender, cmdLine);
}
}
}
}
@@ -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;
}
}
@@ -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,
@@ -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<Command> 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<String> tabComplete(CommandSender sender, String cmdLine) throws IllegalArgumentException {
if (isOurCommand(cmdLine)) {
return super.tabComplete(sender, cmdLine);
} else {
return proxied.tabComplete(sender, cmdLine);
}
}
}
+12 -7
View File
@@ -18,10 +18,15 @@
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="acf-core" />
<orderEntry type="library" name="Maven: co.aikar:locales:1.0-SNAPSHOT" level="project" />
<orderEntry type="library" name="Maven: org.reflections:reflections:0.9.11" level="project" />
<orderEntry type="library" name="Maven: org.javassist:javassist:3.21.0-GA" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: io.netty:netty-codec:4.1.12.Final" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: io.netty:netty-transport:4.1.12.Final" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: io.netty:netty-buffer:4.1.12.Final" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: io.netty:netty-common:4.1.12.Final" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: io.netty:netty-resolver:4.1.12.Final" level="project" />
<orderEntry type="module" module-name="acf-core" />
<orderEntry type="library" name="Maven: co.aikar:locales:1.0-SNAPSHOT" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: net.md-5:bungeecord-api:1.12-SNAPSHOT" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: net.md-5:bungeecord-chat:1.12-SNAPSHOT" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: com.google.code.gson:gson:2.8.0" level="project" />
@@ -29,11 +34,11 @@
<orderEntry type="library" scope="PROVIDED" name="Maven: org.yaml:snakeyaml:1.18" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: net.md-5:bungeecord-event:1.12-SNAPSHOT" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: net.md-5:bungeecord-protocol:1.12-SNAPSHOT" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: io.netty:netty-codec:4.1.12.Final" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: io.netty:netty-transport:4.1.12.Final" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: io.netty:netty-buffer:4.1.12.Final" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: io.netty:netty-common:4.1.12.Final" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: io.netty:netty-resolver:4.1.12.Final" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: io.netty:netty-codec:4.1.13.Final" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: io.netty:netty-transport:4.1.13.Final" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: io.netty:netty-buffer:4.1.13.Final" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: io.netty:netty-common:4.1.13.Final" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: io.netty:netty-resolver:4.1.13.Final" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: net.sf.trove4j:trove4j:3.0.3" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: com.google.guava:guava:15.0" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: org.jetbrains:annotations:15.0" level="project" />
@@ -44,20 +44,40 @@ public class BungeeCommandManager extends CommandManager {
protected Map<String, BungeeRootCommand> 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<BungeeCommandExecutionContext> 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);
@@ -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());
}
}
@@ -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,
+1 -1
View File
@@ -16,9 +16,9 @@
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Maven: co.aikar:locales:1.0-SNAPSHOT" level="project" />
<orderEntry type="library" name="Maven: org.reflections:reflections:0.9.11" level="project" />
<orderEntry type="library" name="Maven: org.javassist:javassist:3.21.0-GA" level="project" />
<orderEntry type="library" name="Maven: co.aikar:locales:1.0-SNAPSHOT" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: com.google.guava:guava:15.0" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: org.jetbrains:annotations:15.0" level="project" />
</component>
@@ -24,6 +24,7 @@
package co.aikar.commands;
import co.aikar.locales.MessageKey;
import co.aikar.locales.MessageKeyProvider;
public interface CommandIssuer {
/**
@@ -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<Stack<CommandOperationContext>> commandOperationContext = ThreadLocal.withInitial(Stack::new);
protected Map<String, RootCommand> rootCommands = new HashMap<>();
protected CommandReplacements replacements = new CommandReplacements(this);
protected Locales locales = new Locales(this);
protected ExceptionHandler defaultExceptionHandler = null;
protected Set<Locale> supportedLanguages = Sets.newHashSet(Locale.ENGLISH);
protected Map<MessageType, MessageFormatter> formatters = new IdentityHashMap<>();
protected MessageFormatter defaultFormatter;
{
MessageFormatter plain = new MessageFormatter<Object>() {
@Override
@@ -48,6 +51,7 @@ public abstract class CommandManager {
return message;
}
};
defaultFormatter = plain;
formatters.put(MessageType.INFO, plain);
formatters.put(MessageType.SYNTAX, plain);
formatters.put(MessageType.ERROR, plain);
@@ -93,6 +97,12 @@ public abstract class CommandManager {
public abstract RootCommand createRootCommand(String cmd);
/**
* Returns a Locales Manager to add and modify language tables for your commands.
* @return
*/
public abstract Locales getLocales();
public abstract <R extends CommandExecutionContext> R createCommandContext(RegisteredCommand command, Parameter parameter, CommandIssuer sender, List<String> args, int i, Map<String, Object> passedArgs);
public abstract CommandCompletionContext createCompletionContext(RegisteredCommand command, CommandIssuer sender, String input, String config, String[] args);
@@ -116,14 +126,6 @@ public abstract class CommandManager {
return replacements;
}
/**
* Returns a Locales Manager to add and modify language tables for your commands.
* @return
*/
Locales getLocales() {
return locales;
}
public boolean hasPermission(CommandIssuer issuer, String permission) {
return permission == null || permission.isEmpty() || issuer.hasPermission(permission);
}
@@ -167,22 +169,23 @@ public abstract class CommandManager {
public void sendMessage(Object issuerArg, MessageType type, MessageKeyProvider key, String... replacements) {
sendMessage(issuerArg, type, key.getMessageKey(), replacements);
}
public 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);
if (replacements.length > 0) {
message = ACFUtil.replaceStrings(message, replacements);
}
MessageFormatter formatter = formatters.get(type);
MessageFormatter formatter = formatters.getOrDefault(type, defaultFormatter);
if (formatter != null) {
message = formatter.format(message);
}
for (String msg : ACFPatterns.NEWLINE.split(message)) {
issuer.sendMessageInternal(msg);
}
}
public Locale getIssuerLocale(CommandIssuer issuer) {
return getLocales().getDefaultLocale();
}
@@ -196,4 +199,24 @@ public abstract class CommandManager {
args
);
}
/**
* Gets a list of all currently supported languages for this manager.
* These locales will be automatically loaded from
* @return
*/
public Set<Locale> getSupportedLanguages() {
return supportedLanguages;
}
/**
* Adds a new locale to the list of automatic Locales to load Message Bundles for.
* All bundles loaded under the previous supported languages will now automatically load for this new locale too.
*
* @param locale
*/
public void addSupportedLanguage(Locale locale) {
supportedLanguages.add(locale);
getLocales().loadMissingBundles();
}
}
@@ -24,6 +24,7 @@
package co.aikar.commands;
import co.aikar.locales.MessageKey;
import co.aikar.locales.MessageKeyProvider;
public class InvalidCommandArgument extends Exception {
final boolean showSyntax;
@@ -23,44 +23,66 @@
package co.aikar.commands;
import co.aikar.locales.LanguageTable;
import co.aikar.locales.LocaleManager;
import co.aikar.locales.MessageKey;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.SetMultimap;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
@SuppressWarnings("WeakerAccess")
public class Locales {
private static final Locale[] CORE_LANGUAGES = new Locale[]{
Locale.ENGLISH
};
private final CommandManager manager;
private final LocaleManager<CommandIssuer> localeManager;
private final SetMultimap<String, Locale> loadedBundles = HashMultimap.create();
Locales(CommandManager manager) {
public Locales(CommandManager manager) {
this.manager = manager;
this.localeManager = LocaleManager.create(manager.getClass(), manager::getIssuerLocale);
this.localeManager.addMessageBundle("acf-core", CORE_LANGUAGES);
this.localeManager = LocaleManager.create(manager::getIssuerLocale);
}
public void loadLanguages() {
addMessageBundles("acf-core");
}
public Locale getDefaultLocale() {
return this.localeManager.getDefaultLocale();
}
/**
* Looks for all previously loaded bundles, and if any new Supported Languages have been added, load them.
*/
public void loadMissingBundles() {
for (Locale locale : manager.getSupportedLanguages()) {
for (String bundleName : loadedBundles.keys()) {
addMessageBundle(bundleName, locale);
}
}
}
public void addMessageBundles(String... bundleNames) {
for (String bundleName : bundleNames) {
this.localeManager.addMessageBundle(bundleName, CORE_LANGUAGES);
for (Locale locale : manager.getSupportedLanguages()) {
addMessageBundle(bundleName, locale);
}
}
}
public void addMessageBundle(String bundleName, Locale locale) {
this.localeManager.addMessageBundle(bundleName, locale);
if (!loadedBundles.containsEntry(bundleName, locale)) {
loadedBundles.put(bundleName, locale);
this.localeManager.addMessageBundle(bundleName, locale);
}
}
public void addMessageStrings(Locale locale, @NotNull Map<String, String> messages) {
Map<MessageKey, String> map = new HashMap<>(messages.size());
messages.forEach((key, value) -> map.put(MessageKey.of(key), value));
addMessages(locale, map);
}
public void addMessages(Locale locale, @NotNull Map<MessageKey, String> messages) {
this.localeManager.addMessages(locale, messages);
}
@@ -1,30 +0,0 @@
/*
* 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();
}
@@ -24,6 +24,7 @@
package co.aikar.commands;
import co.aikar.locales.MessageKey;
import co.aikar.locales.MessageKeyProvider;
/**
* Enum Name = MessageKey in lowercase prefixed with acf-core.
+3 -3
View File
@@ -21,13 +21,15 @@
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Maven: org.reflections:reflections:0.9.11" level="project" />
<orderEntry type="library" name="Maven: org.javassist:javassist:3.21.0-GA" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: com.destroystokyo.paper:paper-api:1.11.2-R0.1-SNAPSHOT" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: commons-lang:commons-lang:2.6" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: com.googlecode.json-simple:json-simple:1.1.1" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: junit:junit:4.10" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: org.hamcrest:hamcrest-core:1.1" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: com.google.code.findbugs:jsr305:1.3.9" level="project" />
<orderEntry type="library" name="Maven: com.google.guava:guava:17.0" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: com.google.guava:guava:17.0" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: com.google.code.gson:gson:2.2.4" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: org.avaje:ebean:2.8.1" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: javax.persistence:persistence-api:1.0" level="project" />
@@ -37,8 +39,6 @@
<orderEntry type="module" module-name="acf-bukkit" />
<orderEntry type="module" module-name="acf-core" />
<orderEntry type="library" name="Maven: co.aikar:locales:1.0-SNAPSHOT" level="project" />
<orderEntry type="library" name="Maven: org.reflections:reflections:0.9.11" level="project" />
<orderEntry type="library" name="Maven: org.javassist:javassist:3.21.0-GA" level="project" />
<orderEntry type="library" name="Maven: co.aikar:minecraft-timings:1.0.4" level="project" />
<orderEntry type="library" name="Maven: org.jetbrains:annotations:13.0" level="project" />
</component>
+2 -2
View File
@@ -18,11 +18,11 @@
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Maven: org.reflections:reflections:0.9.11" level="project" />
<orderEntry type="library" name="Maven: org.javassist:javassist:3.21.0-GA" level="project" />
<orderEntry type="module" module-name="acf-bukkit" />
<orderEntry type="module" module-name="acf-core" />
<orderEntry type="library" name="Maven: co.aikar:locales:1.0-SNAPSHOT" level="project" />
<orderEntry type="library" name="Maven: org.reflections:reflections:0.9.11" level="project" />
<orderEntry type="library" name="Maven: org.javassist:javassist:3.21.0-GA" level="project" />
<orderEntry type="library" name="Maven: co.aikar:minecraft-timings:1.0.4" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: com.destroystokyo.paper:paper-api:1.12-R0.1-SNAPSHOT" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: com.mojang:authlib:1.5.25" level="project" />
+2 -2
View File
@@ -18,10 +18,10 @@
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="acf-core" />
<orderEntry type="library" name="Maven: co.aikar:locales:1.0-SNAPSHOT" level="project" />
<orderEntry type="library" name="Maven: org.reflections:reflections:0.9.11" level="project" />
<orderEntry type="library" name="Maven: org.javassist:javassist:3.21.0-GA" level="project" />
<orderEntry type="module" module-name="acf-core" />
<orderEntry type="library" name="Maven: co.aikar:locales:1.0-SNAPSHOT" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: org.spongepowered:spongeapi:5.1.0" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: org.slf4j:slf4j-api:1.7.21" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: com.google.code.gson:gson:2.2.4" level="project" />
@@ -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,
@@ -30,6 +30,7 @@ import org.slf4j.Logger;
import org.spongepowered.api.Sponge;
import org.spongepowered.api.command.CommandSource;
import org.spongepowered.api.plugin.PluginContainer;
import org.spongepowered.api.text.format.TextColor;
import org.spongepowered.api.text.format.TextColors;
import java.lang.reflect.Method;
@@ -46,16 +47,42 @@ public class SpongeCommandManager extends CommandManager {
protected SpongeCommandContexts contexts;
protected SpongeCommandCompletions completions;
private Timing commandTiming;
protected SpongeLocales locales;
public SpongeCommandManager(PluginContainer plugin) {
this.plugin = plugin;
String pluginName = "acf-" + plugin.getName();
this.locales.addMessageBundles("acf-minecraft", pluginName, pluginName.toLowerCase());
getLocales().addMessageBundles("acf-minecraft", pluginName, pluginName.toLowerCase());
this.commandTiming = Timings.of(plugin, "Commands");
this.formatters.put(MessageType.ERROR, new SpongeMessageFormatter(TextColors.RED, TextColors.YELLOW, TextColors.RED));
this.formatters.put(MessageType.ERROR, defaultFormatter = new SpongeMessageFormatter(TextColors.RED, TextColors.YELLOW, TextColors.RED));
this.formatters.put(MessageType.SYNTAX, new SpongeMessageFormatter(TextColors.YELLOW, TextColors.GREEN, TextColors.WHITE));
this.formatters.put(MessageType.INFO, new SpongeMessageFormatter(TextColors.BLUE, TextColors.DARK_GREEN, TextColors.GREEN));
getLocales(); // auto load locales
}
public PluginContainer getPlugin() {
return plugin;
}
public SpongeMessageFormatter setFormat(MessageType type, SpongeMessageFormatter formatter) {
return (SpongeMessageFormatter) formatters.put(type, formatter);
}
public SpongeMessageFormatter getFormat(MessageType type) {
return (SpongeMessageFormatter) formatters.getOrDefault(type, defaultFormatter);
}
public void setFormat(MessageType type, TextColor... colors) {
SpongeMessageFormatter format = getFormat(type);
for (int i = 0; i < colors.length; i++) {
format.setColor(i, colors[i]);
}
}
public void setFormat(MessageType type, int i, TextColor color) {
SpongeMessageFormatter format = getFormat(type);
format.setColor(i, color);
}
@Override
@@ -79,6 +106,15 @@ public class SpongeCommandManager extends CommandManager {
return completions;
}
@Override
public SpongeLocales getLocales() {
if (this.locales == null) {
this.locales = new SpongeLocales(this);
this.locales.loadLanguages();
}
return locales;
}
@Override
public boolean hasRegisteredCommands() {
return !registeredCommands.isEmpty();
@@ -0,0 +1,17 @@
package co.aikar.commands;
public class SpongeLocales extends Locales{
private final SpongeCommandManager manager;
public SpongeLocales(SpongeCommandManager manager) {
super(manager);
this.manager = manager;
}
@Override
public void loadLanguages() {
super.loadLanguages();
String pluginName = "acf-" + manager.plugin.getName();
addMessageBundles("acf-minecraft", pluginName, pluginName.toLowerCase());
}
}