diff --git a/docs/acf-velocity/co/aikar/commands/ACFVelocityUtil.html b/docs/acf-velocity/co/aikar/commands/ACFVelocityUtil.html index 431f8045..19f060ae 100644 --- a/docs/acf-velocity/co/aikar/commands/ACFVelocityUtil.html +++ b/docs/acf-velocity/co/aikar/commands/ACFVelocityUtil.html @@ -76,7 +76,7 @@ loadScripts(document, 'script');

-
public class ACFVelocityUtil +
public class ACFVelocityUtil extends Object
@@ -141,7 +141,7 @@ loadScripts(document, 'script');
  • ACFVelocityUtil

    -
    public ACFVelocityUtil()
    +
    public ACFVelocityUtil()
  • @@ -155,13 +155,13 @@ loadScripts(document, 'script');
  • color

    -
    public static net.kyori.adventure.text.TextComponent color(String message)
    +
    public static net.kyori.adventure.text.TextComponent color(String message)
  • findPlayerSmart

    -
    public static com.velocitypowered.api.proxy.Player findPlayerSmart(com.velocitypowered.api.proxy.ProxyServer server, +
    public static com.velocitypowered.api.proxy.Player findPlayerSmart(com.velocitypowered.api.proxy.ProxyServer server, co.aikar.commands.CommandIssuer issuer, String search)
    @@ -169,13 +169,13 @@ loadScripts(document, 'script');
  • isValidName

    -
    public static boolean isValidName(String name)
    +
    public static boolean isValidName(String name)
  • validate

    -
    public static <T> T validate(T object, +
    public static <T> T validate(T object, String message, Object... values)
    diff --git a/docs/acf-velocity/co/aikar/commands/VelocityCommandCompletions.html b/docs/acf-velocity/co/aikar/commands/VelocityCommandCompletions.html index f3e19413..309850a8 100644 --- a/docs/acf-velocity/co/aikar/commands/VelocityCommandCompletions.html +++ b/docs/acf-velocity/co/aikar/commands/VelocityCommandCompletions.html @@ -74,7 +74,7 @@ loadScripts(document, 'script');

    -
    public class VelocityCommandCompletions +
    public class VelocityCommandCompletions extends co.aikar.commands.CommandCompletions<VelocityCommandCompletionContext>
    @@ -126,7 +126,7 @@ loadScripts(document, 'script');
  • VelocityCommandCompletions

    -
    public VelocityCommandCompletions(com.velocitypowered.api.proxy.ProxyServer server, +
    public VelocityCommandCompletions(com.velocitypowered.api.proxy.ProxyServer server, co.aikar.commands.CommandManager manager)
  • diff --git a/docs/acf-velocity/co/aikar/commands/VelocityCommandIssuer.html b/docs/acf-velocity/co/aikar/commands/VelocityCommandIssuer.html index 079d53d6..c396037b 100644 --- a/docs/acf-velocity/co/aikar/commands/VelocityCommandIssuer.html +++ b/docs/acf-velocity/co/aikar/commands/VelocityCommandIssuer.html @@ -80,7 +80,7 @@ loadScripts(document, 'script');
    co.aikar.commands.CommandIssuer

    -
    public class VelocityCommandIssuer +
    public class VelocityCommandIssuer extends Object implements co.aikar.commands.CommandIssuer
    @@ -147,7 +147,7 @@ implements co.aikar.commands.CommandIssuer
  • getIssuer

    -
    public com.velocitypowered.api.command.CommandSource getIssuer()
    +
    public com.velocitypowered.api.command.CommandSource getIssuer()
    Specified by:
    getIssuer in interface co.aikar.commands.CommandIssuer
    @@ -157,13 +157,13 @@ implements co.aikar.commands.CommandIssuer
  • getPlayer

    -
    public com.velocitypowered.api.proxy.Player getPlayer()
    +
    public com.velocitypowered.api.proxy.Player getPlayer()
  • getManager

    -
    public co.aikar.commands.CommandManager getManager()
    +
    public co.aikar.commands.CommandManager getManager()
    Specified by:
    getManager in interface co.aikar.commands.CommandIssuer
    @@ -173,7 +173,7 @@ implements co.aikar.commands.CommandIssuer
  • isPlayer

    -
    public boolean isPlayer()
    +
    public boolean isPlayer()
    Specified by:
    isPlayer in interface co.aikar.commands.CommandIssuer
    @@ -184,7 +184,7 @@ implements co.aikar.commands.CommandIssuer

    getUniqueId

    @NotNull -public @NotNull UUID getUniqueId()
    +public @NotNull UUID getUniqueId()
    Specified by:
    getUniqueId in interface co.aikar.commands.CommandIssuer
    @@ -194,7 +194,7 @@ implements co.aikar.commands.CommandIssuer
  • sendMessageInternal

    -
    public void sendMessageInternal(String message)
    +
    public void sendMessageInternal(String message)
    Specified by:
    sendMessageInternal in interface co.aikar.commands.CommandIssuer
    @@ -204,7 +204,7 @@ implements co.aikar.commands.CommandIssuer
  • hasPermission

    -
    public boolean hasPermission(String name)
    +
    public boolean hasPermission(String name)
    Specified by:
    hasPermission in interface co.aikar.commands.CommandIssuer
    @@ -214,7 +214,7 @@ implements co.aikar.commands.CommandIssuer
  • equals

    -
    public boolean equals(Object o)
    +
    public boolean equals(Object o)
    Overrides:
    equals in class Object
    @@ -224,7 +224,7 @@ implements co.aikar.commands.CommandIssuer
  • hashCode

    -
    public int hashCode()
    +
    public int hashCode()
    Overrides:
    hashCode in class Object
    diff --git a/docs/acf-velocity/co/aikar/commands/VelocityCommandManager.html b/docs/acf-velocity/co/aikar/commands/VelocityCommandManager.html index 22b973b7..3b17bd0f 100644 --- a/docs/acf-velocity/co/aikar/commands/VelocityCommandManager.html +++ b/docs/acf-velocity/co/aikar/commands/VelocityCommandManager.html @@ -78,7 +78,7 @@ loadScripts(document, 'script');

    -
    public class VelocityCommandManager +
    public class VelocityCommandManager extends co.aikar.commands.CommandManager<com.velocitypowered.api.command.CommandSource,VelocityCommandIssuer,net.kyori.adventure.text.format.NamedTextColor,VelocityMessageFormatter,VelocityCommandExecutionContext,VelocityConditionContext>
    @@ -246,37 +246,37 @@ loadScripts(document, 'script');
  • proxy

    -
    protected final com.velocitypowered.api.proxy.ProxyServer proxy
    +
    protected final com.velocitypowered.api.proxy.ProxyServer proxy
  • plugin

    -
    protected final com.velocitypowered.api.plugin.PluginContainer plugin
    +
    protected final com.velocitypowered.api.plugin.PluginContainer plugin
  • registeredCommands

    - +
  • contexts

    - +
  • completions

    - +
  • locales

    - +
  • @@ -290,7 +290,7 @@ loadScripts(document, 'script');
  • VelocityCommandManager

    -
    public VelocityCommandManager(com.velocitypowered.api.proxy.ProxyServer proxy, +
    public VelocityCommandManager(com.velocitypowered.api.proxy.ProxyServer proxy, Object plugin)
  • @@ -305,19 +305,19 @@ loadScripts(document, 'script');
  • getProxy

    -
    public com.velocitypowered.api.proxy.ProxyServer getProxy()
    +
    public com.velocitypowered.api.proxy.ProxyServer getProxy()
  • getPlugin

    -
    public com.velocitypowered.api.plugin.PluginContainer getPlugin()
    +
    public com.velocitypowered.api.plugin.PluginContainer getPlugin()
  • getCommandContexts

    -
    public co.aikar.commands.CommandContexts<VelocityCommandExecutionContext> getCommandContexts()
    +
    public co.aikar.commands.CommandContexts<VelocityCommandExecutionContext> getCommandContexts()
    Specified by:
    getCommandContexts in class co.aikar.commands.CommandManager<com.velocitypowered.api.command.CommandSource,VelocityCommandIssuer,net.kyori.adventure.text.format.NamedTextColor,VelocityMessageFormatter,VelocityCommandExecutionContext,VelocityConditionContext>
    @@ -327,7 +327,7 @@ loadScripts(document, 'script');
  • getCommandCompletions

    -
    public co.aikar.commands.CommandCompletions<VelocityCommandCompletionContext> getCommandCompletions()
    +
    public co.aikar.commands.CommandCompletions<VelocityCommandCompletionContext> getCommandCompletions()
    Specified by:
    getCommandCompletions in class co.aikar.commands.CommandManager<com.velocitypowered.api.command.CommandSource,VelocityCommandIssuer,net.kyori.adventure.text.format.NamedTextColor,VelocityMessageFormatter,VelocityCommandExecutionContext,VelocityConditionContext>
    @@ -337,7 +337,7 @@ loadScripts(document, 'script');
  • getLocales

    - +
    Specified by:
    getLocales in class co.aikar.commands.CommandManager<com.velocitypowered.api.command.CommandSource,VelocityCommandIssuer,net.kyori.adventure.text.format.NamedTextColor,VelocityMessageFormatter,VelocityCommandExecutionContext,VelocityConditionContext>
    @@ -347,13 +347,13 @@ loadScripts(document, 'script');
  • readLocale

    -
    public void readLocale(com.velocitypowered.api.proxy.Player player)
    +
    public void readLocale(com.velocitypowered.api.proxy.Player player)
  • registerCommand

    -
    public void registerCommand(co.aikar.commands.BaseCommand command)
    +
    public void registerCommand(co.aikar.commands.BaseCommand command)
    Specified by:
    registerCommand in class co.aikar.commands.CommandManager<com.velocitypowered.api.command.CommandSource,VelocityCommandIssuer,net.kyori.adventure.text.format.NamedTextColor,VelocityMessageFormatter,VelocityCommandExecutionContext,VelocityConditionContext>
    @@ -363,32 +363,32 @@ loadScripts(document, 'script');
  • registerCommand

    -
    public void registerCommand(co.aikar.commands.BaseCommand command, +
    public void registerCommand(co.aikar.commands.BaseCommand command, boolean force)
  • unregisterCommand

    -
    public void unregisterCommand(co.aikar.commands.BaseCommand command)
    +
    public void unregisterCommand(co.aikar.commands.BaseCommand command)
  • unregisterCommand

    -
    public void unregisterCommand(VelocityRootCommand command)
    +
    public void unregisterCommand(VelocityRootCommand command)
  • unregisterCommands

    -
    public void unregisterCommands()
    +
    public void unregisterCommands()
  • hasRegisteredCommands

    -
    public boolean hasRegisteredCommands()
    +
    public boolean hasRegisteredCommands()
    Specified by:
    hasRegisteredCommands in class co.aikar.commands.CommandManager<com.velocitypowered.api.command.CommandSource,VelocityCommandIssuer,net.kyori.adventure.text.format.NamedTextColor,VelocityMessageFormatter,VelocityCommandExecutionContext,VelocityConditionContext>
    @@ -398,7 +398,7 @@ loadScripts(document, 'script');
  • isCommandIssuer

    -
    public boolean isCommandIssuer(Class<?> aClass)
    +
    public boolean isCommandIssuer(Class<?> aClass)
    Specified by:
    isCommandIssuer in class co.aikar.commands.CommandManager<com.velocitypowered.api.command.CommandSource,VelocityCommandIssuer,net.kyori.adventure.text.format.NamedTextColor,VelocityMessageFormatter,VelocityCommandExecutionContext,VelocityConditionContext>
    @@ -408,7 +408,7 @@ loadScripts(document, 'script');
  • getCommandIssuer

    - +
    Specified by:
    getCommandIssuer in class co.aikar.commands.CommandManager<com.velocitypowered.api.command.CommandSource,VelocityCommandIssuer,net.kyori.adventure.text.format.NamedTextColor,VelocityMessageFormatter,VelocityCommandExecutionContext,VelocityConditionContext>
    @@ -418,7 +418,7 @@ loadScripts(document, 'script');
  • createRootCommand

    -
    public co.aikar.commands.RootCommand createRootCommand(String cmd)
    +
    public co.aikar.commands.RootCommand createRootCommand(String cmd)
    Specified by:
    createRootCommand in class co.aikar.commands.CommandManager<com.velocitypowered.api.command.CommandSource,VelocityCommandIssuer,net.kyori.adventure.text.format.NamedTextColor,VelocityMessageFormatter,VelocityCommandExecutionContext,VelocityConditionContext>
    @@ -428,7 +428,7 @@ loadScripts(document, 'script');
  • getRegisteredRootCommands

    -
    public Collection<co.aikar.commands.RootCommand> getRegisteredRootCommands()
    +
    public Collection<co.aikar.commands.RootCommand> getRegisteredRootCommands()
    Specified by:
    getRegisteredRootCommands in class co.aikar.commands.CommandManager<com.velocitypowered.api.command.CommandSource,VelocityCommandIssuer,net.kyori.adventure.text.format.NamedTextColor,VelocityMessageFormatter,VelocityCommandExecutionContext,VelocityConditionContext>
    @@ -438,7 +438,7 @@ loadScripts(document, 'script');
  • createCommandContext

    -
    public VelocityCommandExecutionContext createCommandContext(co.aikar.commands.RegisteredCommand command, +
    public VelocityCommandExecutionContext createCommandContext(co.aikar.commands.RegisteredCommand command, co.aikar.commands.CommandParameter parameter, co.aikar.commands.CommandIssuer sender, List<String> args, @@ -453,7 +453,7 @@ loadScripts(document, 'script');
  • createCompletionContext

    -
    public co.aikar.commands.CommandCompletionContext createCompletionContext(co.aikar.commands.RegisteredCommand command, +
    public co.aikar.commands.CommandCompletionContext createCompletionContext(co.aikar.commands.RegisteredCommand command, co.aikar.commands.CommandIssuer sender, String input, String config, @@ -467,7 +467,7 @@ loadScripts(document, 'script');
  • createRegisteredCommand

    -
    public co.aikar.commands.RegisteredCommand createRegisteredCommand(co.aikar.commands.BaseCommand command, +
    public co.aikar.commands.RegisteredCommand createRegisteredCommand(co.aikar.commands.BaseCommand command, String cmdName, Method method, String prefSubCommand)
    @@ -480,7 +480,7 @@ loadScripts(document, 'script');
  • createConditionContext

    -
    public VelocityConditionContext createConditionContext(co.aikar.commands.CommandIssuer issuer, +
    public VelocityConditionContext createConditionContext(co.aikar.commands.CommandIssuer issuer, String config)
    Overrides:
    @@ -491,7 +491,7 @@ loadScripts(document, 'script');
  • log

    -
    public void log(co.aikar.commands.LogLevel level, +
    public void log(co.aikar.commands.LogLevel level, String message, Throwable throwable)
    @@ -503,7 +503,7 @@ loadScripts(document, 'script');
  • getCommandPrefix

    -
    public String getCommandPrefix(co.aikar.commands.CommandIssuer issuer)
    +
    public String getCommandPrefix(co.aikar.commands.CommandIssuer issuer)
    Overrides:
    getCommandPrefix in class co.aikar.commands.CommandManager<com.velocitypowered.api.command.CommandSource,VelocityCommandIssuer,net.kyori.adventure.text.format.NamedTextColor,VelocityMessageFormatter,VelocityCommandExecutionContext,VelocityConditionContext>
    diff --git a/docs/acf-velocity/src-html/co/aikar/commands/ACFVelocityUtil.html b/docs/acf-velocity/src-html/co/aikar/commands/ACFVelocityUtil.html index 8dcba4c2..35615682 100644 --- a/docs/acf-velocity/src-html/co/aikar/commands/ACFVelocityUtil.html +++ b/docs/acf-velocity/src-html/co/aikar/commands/ACFVelocityUtil.html @@ -13,83 +13,82 @@
    001package co.aikar.commands;
     002
    -003import java.util.ArrayList;
    -004import java.util.Collection;
    -005import java.util.Collections;
    -006import java.util.List;
    -007import java.util.Optional;
    -008import java.util.stream.Collectors;
    -009
    -010import com.velocitypowered.api.command.CommandSource;
    -011import com.velocitypowered.api.proxy.Player;
    -012import com.velocitypowered.api.proxy.ProxyServer;
    -013
    -014import net.kyori.adventure.text.TextComponent;
    -015import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
    -016
    -017public class ACFVelocityUtil {
    -018
    -019    public static TextComponent color(String message) {
    -020        return LegacyComponentSerializer.legacySection().deserialize(message);
    -021    }
    -022
    -023    public static Player findPlayerSmart(ProxyServer server, CommandIssuer issuer, String search) {
    -024        CommandSource requester = issuer.getIssuer();
    -025        String name = ACFUtil.replace(search, ":confirm", "");
    -026        if (!isValidName(name)) {
    -027            issuer.sendError(MinecraftMessageKeys.IS_NOT_A_VALID_NAME, "{name}", name);
    -028            return null;
    -029        }
    -030
    -031        List<Player> matches = new ArrayList<>(matchPlayer(server, name));
    -032
    -033        if (matches.size() > 1) {
    -034            String allMatches = matches.stream().map(Player::getUsername).collect(Collectors.joining(", "));
    -035            issuer.sendError(MinecraftMessageKeys.MULTIPLE_PLAYERS_MATCH, "{search}", name, "{all}", allMatches);
    -036            return null;
    -037        }
    -038
    -039        if (matches.isEmpty()) {
    -040            issuer.sendError(MinecraftMessageKeys.NO_PLAYER_FOUND_SERVER, "{search}", name);
    -041            return null;
    -042        }
    -043
    -044        return matches.get(0);
    -045    }
    -046
    -047    /*
    -048     * Original code written by md_5
    -049     *
    -050     * Modified to work with Velocity by Crypnotic
    -051     */
    -052    private static Collection<Player> matchPlayer(ProxyServer server, final String partialName) {
    -053        // A better error message might be nice. This just mimics the previous output
    -054        if (partialName == null) {
    -055            throw new NullPointerException("partialName");
    -056        }
    -057
    -058        Optional<Player> exactMatch = server.getPlayer(partialName);
    -059        //noinspection OptionalIsPresent
    -060        if (exactMatch.isPresent()) {
    -061            return Collections.singleton(exactMatch.get());
    -062        }
    -063
    -064        return server.getAllPlayers().stream()
    -065                .filter(player -> player.getUsername().regionMatches(true, 0, partialName, 0, partialName.length()))
    -066                .collect(Collectors.toList());
    -067    }
    -068
    -069    public static boolean isValidName(String name) {
    -070        return name != null && !name.isEmpty() && ACFPatterns.VALID_NAME_PATTERN.matcher(name).matches();
    -071    }
    -072
    -073    public static <T> T validate(T object, String message, Object... values) {
    -074        if (object == null) {
    -075            throw new NullPointerException(String.format(message, values));
    -076        }
    -077        return object;
    -078    }
    -079}
    +003import com.velocitypowered.api.command.CommandSource;
    +004import com.velocitypowered.api.proxy.Player;
    +005import com.velocitypowered.api.proxy.ProxyServer;
    +006import net.kyori.adventure.text.TextComponent;
    +007import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
    +008
    +009import java.util.ArrayList;
    +010import java.util.Collection;
    +011import java.util.Collections;
    +012import java.util.List;
    +013import java.util.Optional;
    +014import java.util.stream.Collectors;
    +015
    +016public class ACFVelocityUtil {
    +017
    +018    public static TextComponent color(String message) {
    +019        return LegacyComponentSerializer.legacySection().deserialize(message);
    +020    }
    +021
    +022    public static Player findPlayerSmart(ProxyServer server, CommandIssuer issuer, String search) {
    +023        CommandSource requester = issuer.getIssuer();
    +024        String name = ACFUtil.replace(search, ":confirm", "");
    +025        if (!isValidName(name)) {
    +026            issuer.sendError(MinecraftMessageKeys.IS_NOT_A_VALID_NAME, "{name}", name);
    +027            return null;
    +028        }
    +029
    +030        List<Player> matches = new ArrayList<>(matchPlayer(server, name));
    +031
    +032        if (matches.size() > 1) {
    +033            String allMatches = matches.stream().map(Player::getUsername).collect(Collectors.joining(", "));
    +034            issuer.sendError(MinecraftMessageKeys.MULTIPLE_PLAYERS_MATCH, "{search}", name, "{all}", allMatches);
    +035            return null;
    +036        }
    +037
    +038        if (matches.isEmpty()) {
    +039            issuer.sendError(MinecraftMessageKeys.NO_PLAYER_FOUND_SERVER, "{search}", name);
    +040            return null;
    +041        }
    +042
    +043        return matches.get(0);
    +044    }
    +045
    +046    /*
    +047     * Original code written by md_5
    +048     *
    +049     * Modified to work with Velocity by Crypnotic
    +050     */
    +051    private static Collection<Player> matchPlayer(ProxyServer server, final String partialName) {
    +052        // A better error message might be nice. This just mimics the previous output
    +053        if (partialName == null) {
    +054            throw new NullPointerException("partialName");
    +055        }
    +056
    +057        Optional<Player> exactMatch = server.getPlayer(partialName);
    +058        //noinspection OptionalIsPresent
    +059        if (exactMatch.isPresent()) {
    +060            return Collections.singleton(exactMatch.get());
    +061        }
    +062
    +063        return server.getAllPlayers().stream()
    +064                .filter(player -> player.getUsername().regionMatches(true, 0, partialName, 0, partialName.length()))
    +065                .collect(Collectors.toList());
    +066    }
    +067
    +068    public static boolean isValidName(String name) {
    +069        return name != null && !name.isEmpty() && ACFPatterns.VALID_NAME_PATTERN.matcher(name).matches();
    +070    }
    +071
    +072    public static <T> T validate(T object, String message, Object... values) {
    +073        if (object == null) {
    +074            throw new NullPointerException(String.format(message, values));
    +075        }
    +076        return object;
    +077    }
    +078}
     
     
     
    diff --git a/docs/acf-velocity/src-html/co/aikar/commands/VelocityCommandCompletions.html b/docs/acf-velocity/src-html/co/aikar/commands/VelocityCommandCompletions.html
    index c75c0bb9..649be4e8 100644
    --- a/docs/acf-velocity/src-html/co/aikar/commands/VelocityCommandCompletions.html
    +++ b/docs/acf-velocity/src-html/co/aikar/commands/VelocityCommandCompletions.html
    @@ -36,58 +36,57 @@
     023
     024package co.aikar.commands;
     025
    -026import java.util.ArrayList;
    -027import java.util.Arrays;
    -028import java.util.Set;
    -029import java.util.stream.Collectors;
    -030import java.util.stream.Stream;
    -031
    -032import com.velocitypowered.api.command.CommandSource;
    -033import com.velocitypowered.api.proxy.Player;
    -034import com.velocitypowered.api.proxy.ProxyServer;
    -035
    -036import co.aikar.commands.apachecommonslang.ApacheCommonsLangUtil;
    -037import net.kyori.adventure.text.format.NamedTextColor;
    -038import net.kyori.adventure.text.format.TextDecoration;
    -039import net.kyori.adventure.text.format.TextFormat;
    -040
    -041public class VelocityCommandCompletions extends CommandCompletions<VelocityCommandCompletionContext> {
    -042
    -043    public VelocityCommandCompletions(ProxyServer server, CommandManager manager) {
    -044        super(manager);
    -045        registerAsyncCompletion("chatcolors", c -> {
    -046            Stream<TextFormat> colors = NamedTextColor.NAMES.values().stream().map(namedTextColor -> namedTextColor);
    -047            if (!c.hasConfig("colorsonly")) {
    -048                colors = Stream.concat(colors, Stream.of(TextDecoration.values()));
    -049            }
    -050            String filter = c.getConfig("filter");
    -051            if (filter != null) {
    -052                Set<String> filters = Arrays.stream(ACFPatterns.COLON.split(filter)).map(ACFUtil::simplifyString)
    -053                        .collect(Collectors.toSet());
    -054
    -055                colors = colors.filter(color -> filters.contains(ACFUtil.simplifyString(color.toString())));
    -056            }
    -057
    -058            return colors.map(color -> ACFUtil.simplifyString(color.toString())).collect(Collectors.toList());
    -059        });
    -060        registerCompletion("players", c -> {
    -061            CommandSource sender = c.getSender();
    -062            ACFVelocityUtil.validate(sender, "Sender cannot be null");
    -063            String input = c.getInput();
    -064
    -065            ArrayList<String> matchedPlayers = new ArrayList<>();
    -066            for (Player player : server.getAllPlayers()) {
    -067                String name = player.getUsername();
    -068                if (ApacheCommonsLangUtil.startsWithIgnoreCase(name, input)) {
    -069                    matchedPlayers.add(name);
    -070                }
    -071            }
    -072
    -073            matchedPlayers.sort(String.CASE_INSENSITIVE_ORDER);
    -074            return matchedPlayers;
    -075        });
    -076    }
    -077}
    +026import co.aikar.commands.apachecommonslang.ApacheCommonsLangUtil;
    +027import com.velocitypowered.api.command.CommandSource;
    +028import com.velocitypowered.api.proxy.Player;
    +029import com.velocitypowered.api.proxy.ProxyServer;
    +030import net.kyori.adventure.text.format.NamedTextColor;
    +031import net.kyori.adventure.text.format.TextDecoration;
    +032import net.kyori.adventure.text.format.TextFormat;
    +033
    +034import java.util.ArrayList;
    +035import java.util.Arrays;
    +036import java.util.Set;
    +037import java.util.stream.Collectors;
    +038import java.util.stream.Stream;
    +039
    +040public class VelocityCommandCompletions extends CommandCompletions<VelocityCommandCompletionContext> {
    +041
    +042    public VelocityCommandCompletions(ProxyServer server, CommandManager manager) {
    +043        super(manager);
    +044        registerAsyncCompletion("chatcolors", c -> {
    +045            Stream<TextFormat> colors = NamedTextColor.NAMES.values().stream().map(namedTextColor -> namedTextColor);
    +046            if (!c.hasConfig("colorsonly")) {
    +047                colors = Stream.concat(colors, Stream.of(TextDecoration.values()));
    +048            }
    +049            String filter = c.getConfig("filter");
    +050            if (filter != null) {
    +051                Set<String> filters = Arrays.stream(ACFPatterns.COLON.split(filter)).map(ACFUtil::simplifyString)
    +052                        .collect(Collectors.toSet());
    +053
    +054                colors = colors.filter(color -> filters.contains(ACFUtil.simplifyString(color.toString())));
    +055            }
    +056
    +057            return colors.map(color -> ACFUtil.simplifyString(color.toString())).collect(Collectors.toList());
    +058        });
    +059        registerCompletion("players", c -> {
    +060            CommandSource sender = c.getSender();
    +061            ACFVelocityUtil.validate(sender, "Sender cannot be null");
    +062            String input = c.getInput();
    +063
    +064            ArrayList<String> matchedPlayers = new ArrayList<>();
    +065            for (Player player : server.getAllPlayers()) {
    +066                String name = player.getUsername();
    +067                if (ApacheCommonsLangUtil.startsWithIgnoreCase(name, input)) {
    +068                    matchedPlayers.add(name);
    +069                }
    +070            }
    +071
    +072            matchedPlayers.sort(String.CASE_INSENSITIVE_ORDER);
    +073            return matchedPlayers;
    +074        });
    +075    }
    +076}
     
     
     
    diff --git a/docs/acf-velocity/src-html/co/aikar/commands/VelocityCommandContexts.html b/docs/acf-velocity/src-html/co/aikar/commands/VelocityCommandContexts.html
    index a11f9337..a0adafb7 100644
    --- a/docs/acf-velocity/src-html/co/aikar/commands/VelocityCommandContexts.html
    +++ b/docs/acf-velocity/src-html/co/aikar/commands/VelocityCommandContexts.html
    @@ -36,19 +36,19 @@
     023
     024package co.aikar.commands;
     025
    -026import java.util.stream.Collectors;
    -027import java.util.stream.Stream;
    -028
    -029import com.velocitypowered.api.command.CommandSource;
    -030import com.velocitypowered.api.proxy.Player;
    -031import com.velocitypowered.api.proxy.ProxyServer;
    -032
    -033import co.aikar.commands.velocity.contexts.OnlinePlayer;
    -034import net.kyori.adventure.text.format.NamedTextColor;
    -035import net.kyori.adventure.text.format.TextColor;
    -036import net.kyori.adventure.text.format.TextDecoration;
    -037import net.kyori.adventure.text.format.TextFormat;
    -038import org.jetbrains.annotations.Nullable;
    +026import co.aikar.commands.velocity.contexts.OnlinePlayer;
    +027import com.velocitypowered.api.command.CommandSource;
    +028import com.velocitypowered.api.proxy.Player;
    +029import com.velocitypowered.api.proxy.ProxyServer;
    +030import net.kyori.adventure.text.format.NamedTextColor;
    +031import net.kyori.adventure.text.format.TextDecoration;
    +032import net.kyori.adventure.text.format.TextFormat;
    +033
    +034import net.kyori.adventure.text.format.TextColor;
    +035import org.jetbrains.annotations.Nullable;
    +036
    +037import java.util.stream.Collectors;
    +038import java.util.stream.Stream;
     039
     040public class VelocityCommandContexts extends CommandContexts<VelocityCommandExecutionContext> {
     041
    diff --git a/docs/acf-velocity/src-html/co/aikar/commands/VelocityCommandIssuer.html b/docs/acf-velocity/src-html/co/aikar/commands/VelocityCommandIssuer.html
    index bc45dde7..4717ba78 100644
    --- a/docs/acf-velocity/src-html/co/aikar/commands/VelocityCommandIssuer.html
    +++ b/docs/acf-velocity/src-html/co/aikar/commands/VelocityCommandIssuer.html
    @@ -36,79 +36,77 @@
     023
     024package co.aikar.commands;
     025
    -026import java.nio.charset.StandardCharsets;
    -027import java.util.Objects;
    -028import java.util.UUID;
    +026import com.velocitypowered.api.command.CommandSource;
    +027import com.velocitypowered.api.proxy.Player;
    +028import org.jetbrains.annotations.NotNull;
     029
    -030import org.jetbrains.annotations.NotNull;
    -031
    -032import com.velocitypowered.api.command.CommandSource;
    -033import com.velocitypowered.api.proxy.Player;
    -034
    -035public class VelocityCommandIssuer implements CommandIssuer {
    -036    private final VelocityCommandManager manager;
    -037    private final CommandSource source;
    -038
    -039    VelocityCommandIssuer(VelocityCommandManager manager, CommandSource source) {
    -040        this.manager = manager;
    -041        this.source = source;
    -042    }
    -043
    -044
    -045    @Override
    -046    public CommandSource getIssuer() {
    -047        return source;
    -048    }
    -049
    -050    public Player getPlayer() {
    -051        return isPlayer() ? (Player) source : null;
    -052    }
    -053
    -054    @Override
    -055    public CommandManager getManager() {
    -056        return manager;
    -057    }
    -058
    -059    @Override
    -060    public boolean isPlayer() {
    -061        return source instanceof Player;
    -062    }
    -063
    -064    @Override
    -065    public @NotNull UUID getUniqueId() {
    -066        if (isPlayer()) {
    -067            return ((Player) source).getUniqueId();
    -068        }
    -069
    -070        // TODO: Find a better solution for this
    -071        //generate a unique id based of the name (like for the console command sender)
    -072        return UUID.randomUUID();
    -073    }
    -074
    -075    @Override
    -076    public void sendMessageInternal(String message) {
    -077        source.sendMessage(ACFVelocityUtil.color(message));
    -078    }
    -079
    -080    @Override
    -081    public boolean hasPermission(String name) {
    -082        return source.hasPermission(name);
    -083    }
    -084
    -085
    -086    @Override
    -087    public boolean equals(Object o) {
    -088        if (this == o) return true;
    -089        if (o == null || getClass() != o.getClass()) return false;
    -090        VelocityCommandIssuer that = (VelocityCommandIssuer) o;
    -091        return Objects.equals(source, that.source);
    -092    }
    -093
    -094    @Override
    -095    public int hashCode() {
    -096        return Objects.hash(source);
    -097    }
    -098}
    +030import java.util.Objects;
    +031import java.util.UUID;
    +032
    +033public class VelocityCommandIssuer implements CommandIssuer {
    +034    private final VelocityCommandManager manager;
    +035    private final CommandSource source;
    +036
    +037    VelocityCommandIssuer(VelocityCommandManager manager, CommandSource source) {
    +038        this.manager = manager;
    +039        this.source = source;
    +040    }
    +041
    +042
    +043    @Override
    +044    public CommandSource getIssuer() {
    +045        return source;
    +046    }
    +047
    +048    public Player getPlayer() {
    +049        return isPlayer() ? (Player) source : null;
    +050    }
    +051
    +052    @Override
    +053    public CommandManager getManager() {
    +054        return manager;
    +055    }
    +056
    +057    @Override
    +058    public boolean isPlayer() {
    +059        return source instanceof Player;
    +060    }
    +061
    +062    @Override
    +063    public @NotNull UUID getUniqueId() {
    +064        if (isPlayer()) {
    +065            return ((Player) source).getUniqueId();
    +066        }
    +067
    +068        // TODO: Find a better solution for this
    +069        //generate a unique id based of the name (like for the console command sender)
    +070        return UUID.randomUUID();
    +071    }
    +072
    +073    @Override
    +074    public void sendMessageInternal(String message) {
    +075        source.sendMessage(ACFVelocityUtil.color(message));
    +076    }
    +077
    +078    @Override
    +079    public boolean hasPermission(String name) {
    +080        return source.hasPermission(name);
    +081    }
    +082
    +083
    +084    @Override
    +085    public boolean equals(Object o) {
    +086        if (this == o) return true;
    +087        if (o == null || getClass() != o.getClass()) return false;
    +088        VelocityCommandIssuer that = (VelocityCommandIssuer) o;
    +089        return Objects.equals(source, that.source);
    +090    }
    +091
    +092    @Override
    +093    public int hashCode() {
    +094        return Objects.hash(source);
    +095    }
    +096}
     
     
     
    diff --git a/docs/acf-velocity/src-html/co/aikar/commands/VelocityCommandManager.html b/docs/acf-velocity/src-html/co/aikar/commands/VelocityCommandManager.html
    index 956a047c..4ecfa13c 100644
    --- a/docs/acf-velocity/src-html/co/aikar/commands/VelocityCommandManager.html
    +++ b/docs/acf-velocity/src-html/co/aikar/commands/VelocityCommandManager.html
    @@ -36,220 +36,217 @@
     023
     024package co.aikar.commands;
     025
    -026import java.lang.reflect.Method;
    -027import java.util.Collection;
    -028import java.util.Collections;
    -029import java.util.HashMap;
    -030import java.util.List;
    -031import java.util.Locale;
    -032import java.util.Map;
    -033
    -034import com.velocitypowered.api.command.CommandMeta;
    -035import net.kyori.adventure.text.format.TextColor;
    -036import org.slf4j.Logger;
    -037import org.slf4j.LoggerFactory;
    -038
    -039import com.velocitypowered.api.command.CommandSource;
    -040import com.velocitypowered.api.plugin.Plugin;
    -041import com.velocitypowered.api.plugin.PluginContainer;
    -042import com.velocitypowered.api.proxy.Player;
    -043import com.velocitypowered.api.proxy.ProxyServer;
    +026import co.aikar.commands.apachecommonslang.ApacheCommonsExceptionUtil;
    +027import com.velocitypowered.api.command.CommandMeta;
    +028import com.velocitypowered.api.command.CommandSource;
    +029import com.velocitypowered.api.plugin.Plugin;
    +030import com.velocitypowered.api.plugin.PluginContainer;
    +031import com.velocitypowered.api.proxy.Player;
    +032import com.velocitypowered.api.proxy.ProxyServer;
    +033import net.kyori.adventure.text.format.NamedTextColor;
    +034import org.slf4j.Logger;
    +035import org.slf4j.LoggerFactory;
    +036
    +037import java.lang.reflect.Method;
    +038import java.util.Collection;
    +039import java.util.Collections;
    +040import java.util.HashMap;
    +041import java.util.List;
    +042import java.util.Locale;
    +043import java.util.Map;
     044
    -045import co.aikar.commands.apachecommonslang.ApacheCommonsExceptionUtil;
    -046import net.kyori.adventure.text.format.NamedTextColor;
    +045public class VelocityCommandManager extends
    +046        CommandManager<CommandSource, VelocityCommandIssuer, NamedTextColor, VelocityMessageFormatter, VelocityCommandExecutionContext, VelocityConditionContext> {
     047
    -048public class VelocityCommandManager extends
    -049        CommandManager<CommandSource, VelocityCommandIssuer, NamedTextColor, VelocityMessageFormatter, VelocityCommandExecutionContext, VelocityConditionContext> {
    -050
    -051    protected final ProxyServer proxy;
    -052    protected final PluginContainer plugin;
    -053    protected Map<String, VelocityRootCommand> registeredCommands = new HashMap<>();
    -054    protected VelocityCommandContexts contexts;
    -055    protected VelocityCommandCompletions completions;
    -056    protected VelocityLocales locales;
    -057
    -058    public VelocityCommandManager(ProxyServer proxy, Object plugin) {
    -059        this.proxy = proxy;
    -060        this.plugin = proxy.getPluginManager().getPlugin(plugin.getClass().getAnnotation(Plugin.class).id()).get();
    -061        this.formatters.put(MessageType.ERROR, defaultFormatter = new VelocityMessageFormatter(NamedTextColor.RED, NamedTextColor.YELLOW, NamedTextColor.RED));
    -062        this.formatters.put(MessageType.SYNTAX, new VelocityMessageFormatter(NamedTextColor.YELLOW, NamedTextColor.GREEN, NamedTextColor.WHITE));
    -063        this.formatters.put(MessageType.INFO, new VelocityMessageFormatter(NamedTextColor.BLUE, NamedTextColor.DARK_GREEN, NamedTextColor.GREEN));
    -064        this.formatters.put(MessageType.HELP, new VelocityMessageFormatter(NamedTextColor.AQUA, NamedTextColor.GREEN, NamedTextColor.YELLOW));
    -065
    -066        getLocales();
    -067
    -068        proxy.getEventManager().register(plugin, new ACFVelocityListener(this, this.plugin, proxy));
    -069
    -070        registerDependency(plugin.getClass(), plugin);
    -071        registerDependency(Plugin.class, plugin);
    -072        registerDependency(ProxyServer.class, proxy);
    -073    }
    -074
    -075    public ProxyServer getProxy() {
    -076        return this.proxy;
    -077    }
    -078
    -079    public PluginContainer getPlugin() {
    -080        return this.plugin;
    -081    }
    -082
    -083    @Override
    -084    public synchronized CommandContexts<VelocityCommandExecutionContext> getCommandContexts() {
    -085        if (this.contexts == null) {
    -086            this.contexts = new VelocityCommandContexts(proxy, this);
    -087        }
    -088        return contexts;
    -089    }
    -090
    -091    @Override
    -092    public synchronized CommandCompletions<VelocityCommandCompletionContext> getCommandCompletions() {
    -093        if (this.completions == null) {
    -094            this.completions = new VelocityCommandCompletions(proxy, this);
    -095        }
    -096        return completions;
    -097    }
    -098
    -099    @Override
    -100    public VelocityLocales getLocales() {
    -101        if (this.locales == null) {
    -102            this.locales = new VelocityLocales(this);
    -103            this.locales.loadLanguages();
    -104        }
    -105        return locales;
    -106    }
    -107
    -108    public void readLocale(Player player) {
    -109        if (!player.isActive()) {
    -110            return;
    -111        }
    -112
    -113        //This can be null if we didn't received a settings packet
    -114        Locale locale = player.getPlayerSettings().getLocale();
    -115        if (locale != null) {
    -116            setIssuerLocale(player, player.getPlayerSettings().getLocale());
    -117        }
    -118    }
    -119
    -120    @Override
    -121    public void registerCommand(BaseCommand command) {
    -122        registerCommand(command, false);
    -123    }
    -124
    -125    public void registerCommand(BaseCommand command, boolean force) {
    -126        command.onRegister(this);
    -127        for (Map.Entry<String, RootCommand> entry : command.registeredCommands.entrySet()) {
    -128            String commandName = entry.getKey().toLowerCase(Locale.ENGLISH);
    -129            VelocityRootCommand velocityCommand = (VelocityRootCommand) entry.getValue();
    -130            if (!velocityCommand.isRegistered) {
    -131                if (force) {
    -132                    proxy.getCommandManager().unregister(commandName);
    -133                }
    -134                CommandMeta meta = proxy.getCommandManager().metaBuilder(commandName).build();
    -135                proxy.getCommandManager().register(meta, velocityCommand);
    -136            }
    -137            velocityCommand.isRegistered = true;
    -138            registeredCommands.put(commandName, velocityCommand);
    -139        }
    -140    }
    -141
    -142    public void unregisterCommand(BaseCommand command) {
    -143        for (Map.Entry<String, RootCommand> entry : command.registeredCommands.entrySet()) {
    -144            String commandName = entry.getKey().toLowerCase(Locale.ENGLISH);
    -145            VelocityRootCommand velocityCommand = (VelocityRootCommand) entry.getValue();
    -146            velocityCommand.getSubCommands().values().removeAll(command.subCommands.values());
    -147            if (velocityCommand.getSubCommands().isEmpty() && velocityCommand.isRegistered) {
    -148                unregisterCommand(velocityCommand);
    -149                velocityCommand.isRegistered = false;
    -150                registeredCommands.remove(commandName);
    -151            }
    -152        }
    -153    }
    -154
    -155    public void unregisterCommand(VelocityRootCommand command) {
    -156        proxy.getCommandManager().unregister(command.getCommandName());
    -157    }
    -158
    -159    public void unregisterCommands() {
    -160        for (Map.Entry<String, VelocityRootCommand> entry : registeredCommands.entrySet()) {
    -161            unregisterCommand(entry.getValue());
    -162        }
    -163    }
    -164
    -165    @Override
    -166    public boolean hasRegisteredCommands() {
    -167        return !registeredCommands.isEmpty();
    -168    }
    -169
    -170    @Override
    -171    public boolean isCommandIssuer(Class<?> aClass) {
    -172        return CommandSource.class.isAssignableFrom(aClass);
    -173    }
    -174
    -175    @Override
    -176    public VelocityCommandIssuer getCommandIssuer(Object issuer) {
    -177        if (!(issuer instanceof CommandSource)) {
    -178            throw new IllegalArgumentException(issuer.getClass().getName() + " is not a Command Issuer.");
    -179        }
    -180        return new VelocityCommandIssuer(this, (CommandSource) issuer);
    -181    }
    -182
    -183    @Override
    -184    public RootCommand createRootCommand(String cmd) {
    -185        return new VelocityRootCommand(this, cmd);
    -186    }
    -187
    -188    @Override
    -189    public Collection<RootCommand> getRegisteredRootCommands() {
    -190        return Collections.unmodifiableCollection(registeredCommands.values());
    -191    }
    -192
    -193    @Override
    -194    public VelocityCommandExecutionContext createCommandContext(RegisteredCommand command, CommandParameter parameter, CommandIssuer sender, List<String> args, int i, Map<String, Object> passedArgs) {
    -195        return new VelocityCommandExecutionContext(command, parameter, (VelocityCommandIssuer) sender, args, i, passedArgs);
    -196    }
    -197
    -198    @Override
    -199    public CommandCompletionContext createCompletionContext(RegisteredCommand command, CommandIssuer sender, String input, String config, String[] args) {
    -200        return new VelocityCommandCompletionContext(command, (VelocityCommandIssuer) sender, input, config, args);
    -201    }
    -202
    -203    @Override
    -204    public RegisteredCommand createRegisteredCommand(BaseCommand command, String cmdName, Method method, String prefSubCommand) {
    -205        return new RegisteredCommand(command, cmdName, method, prefSubCommand);
    -206    }
    -207
    -208    @Override
    -209    public VelocityConditionContext createConditionContext(CommandIssuer issuer, String config) {
    -210        return new VelocityConditionContext((VelocityCommandIssuer) issuer, config);
    -211    }
    -212
    -213    @Override
    -214    public void log(LogLevel level, String message, Throwable throwable) {
    -215        // TODO: Find better solution
    -216        Logger logger = LoggerFactory.getLogger(plugin.getClass());
    -217        if (level == LogLevel.INFO) {
    -218            logger.info(LogLevel.LOG_PREFIX + message);
    -219        } else {
    -220            logger.warn(LogLevel.LOG_PREFIX + message);
    -221        }
    -222
    -223        if (throwable != null) {
    -224            for (String line : ACFPatterns.NEWLINE.split(ApacheCommonsExceptionUtil.getFullStackTrace(throwable))) {
    -225                if (level == LogLevel.INFO) {
    -226                    logger.info(LogLevel.LOG_PREFIX + line);
    -227                } else {
    -228                    logger.warn(LogLevel.LOG_PREFIX + line);
    -229                }
    -230            }
    -231        }
    -232    }
    -233
    -234
    -235    @Override
    -236    public String getCommandPrefix(CommandIssuer issuer) {
    -237        return issuer.isPlayer() ? "/" : "";
    -238    }
    -239}
    +048    protected final ProxyServer proxy;
    +049    protected final PluginContainer plugin;
    +050    protected Map<String, VelocityRootCommand> registeredCommands = new HashMap<>();
    +051    protected VelocityCommandContexts contexts;
    +052    protected VelocityCommandCompletions completions;
    +053    protected VelocityLocales locales;
    +054
    +055    public VelocityCommandManager(ProxyServer proxy, Object plugin) {
    +056        this.proxy = proxy;
    +057        this.plugin = proxy.getPluginManager().getPlugin(plugin.getClass().getAnnotation(Plugin.class).id()).get();
    +058        this.formatters.put(MessageType.ERROR, defaultFormatter = new VelocityMessageFormatter(NamedTextColor.RED, NamedTextColor.YELLOW, NamedTextColor.RED));
    +059        this.formatters.put(MessageType.SYNTAX, new VelocityMessageFormatter(NamedTextColor.YELLOW, NamedTextColor.GREEN, NamedTextColor.WHITE));
    +060        this.formatters.put(MessageType.INFO, new VelocityMessageFormatter(NamedTextColor.BLUE, NamedTextColor.DARK_GREEN, NamedTextColor.GREEN));
    +061        this.formatters.put(MessageType.HELP, new VelocityMessageFormatter(NamedTextColor.AQUA, NamedTextColor.GREEN, NamedTextColor.YELLOW));
    +062
    +063        getLocales();
    +064
    +065        proxy.getEventManager().register(plugin, new ACFVelocityListener(this, this.plugin, proxy));
    +066
    +067        registerDependency(plugin.getClass(), plugin);
    +068        registerDependency(Plugin.class, plugin);
    +069        registerDependency(ProxyServer.class, proxy);
    +070    }
    +071
    +072    public ProxyServer getProxy() {
    +073        return this.proxy;
    +074    }
    +075
    +076    public PluginContainer getPlugin() {
    +077        return this.plugin;
    +078    }
    +079
    +080    @Override
    +081    public synchronized CommandContexts<VelocityCommandExecutionContext> getCommandContexts() {
    +082        if (this.contexts == null) {
    +083            this.contexts = new VelocityCommandContexts(proxy, this);
    +084        }
    +085        return contexts;
    +086    }
    +087
    +088    @Override
    +089    public synchronized CommandCompletions<VelocityCommandCompletionContext> getCommandCompletions() {
    +090        if (this.completions == null) {
    +091            this.completions = new VelocityCommandCompletions(proxy, this);
    +092        }
    +093        return completions;
    +094    }
    +095
    +096    @Override
    +097    public VelocityLocales getLocales() {
    +098        if (this.locales == null) {
    +099            this.locales = new VelocityLocales(this);
    +100            this.locales.loadLanguages();
    +101        }
    +102        return locales;
    +103    }
    +104
    +105    public void readLocale(Player player) {
    +106        if (!player.isActive()) {
    +107            return;
    +108        }
    +109
    +110        //This can be null if we didn't received a settings packet
    +111        Locale locale = player.getPlayerSettings().getLocale();
    +112        if (locale != null) {
    +113            setIssuerLocale(player, player.getPlayerSettings().getLocale());
    +114        }
    +115    }
    +116
    +117    @Override
    +118    public void registerCommand(BaseCommand command) {
    +119        registerCommand(command, false);
    +120    }
    +121
    +122    public void registerCommand(BaseCommand command, boolean force) {
    +123        command.onRegister(this);
    +124        for (Map.Entry<String, RootCommand> entry : command.registeredCommands.entrySet()) {
    +125            String commandName = entry.getKey().toLowerCase(Locale.ENGLISH);
    +126            VelocityRootCommand velocityCommand = (VelocityRootCommand) entry.getValue();
    +127            if (!velocityCommand.isRegistered) {
    +128                if (force) {
    +129                    proxy.getCommandManager().unregister(commandName);
    +130                }
    +131                CommandMeta meta = proxy.getCommandManager().metaBuilder(commandName).build();
    +132                proxy.getCommandManager().register(meta, velocityCommand);
    +133            }
    +134            velocityCommand.isRegistered = true;
    +135            registeredCommands.put(commandName, velocityCommand);
    +136        }
    +137    }
    +138
    +139    public void unregisterCommand(BaseCommand command) {
    +140        for (Map.Entry<String, RootCommand> entry : command.registeredCommands.entrySet()) {
    +141            String commandName = entry.getKey().toLowerCase(Locale.ENGLISH);
    +142            VelocityRootCommand velocityCommand = (VelocityRootCommand) entry.getValue();
    +143            velocityCommand.getSubCommands().values().removeAll(command.subCommands.values());
    +144            if (velocityCommand.getSubCommands().isEmpty() && velocityCommand.isRegistered) {
    +145                unregisterCommand(velocityCommand);
    +146                velocityCommand.isRegistered = false;
    +147                registeredCommands.remove(commandName);
    +148            }
    +149        }
    +150    }
    +151
    +152    public void unregisterCommand(VelocityRootCommand command) {
    +153        proxy.getCommandManager().unregister(command.getCommandName());
    +154    }
    +155
    +156    public void unregisterCommands() {
    +157        for (Map.Entry<String, VelocityRootCommand> entry : registeredCommands.entrySet()) {
    +158            unregisterCommand(entry.getValue());
    +159        }
    +160    }
    +161
    +162    @Override
    +163    public boolean hasRegisteredCommands() {
    +164        return !registeredCommands.isEmpty();
    +165    }
    +166
    +167    @Override
    +168    public boolean isCommandIssuer(Class<?> aClass) {
    +169        return CommandSource.class.isAssignableFrom(aClass);
    +170    }
    +171
    +172    @Override
    +173    public VelocityCommandIssuer getCommandIssuer(Object issuer) {
    +174        if (!(issuer instanceof CommandSource)) {
    +175            throw new IllegalArgumentException(issuer.getClass().getName() + " is not a Command Issuer.");
    +176        }
    +177        return new VelocityCommandIssuer(this, (CommandSource) issuer);
    +178    }
    +179
    +180    @Override
    +181    public RootCommand createRootCommand(String cmd) {
    +182        return new VelocityRootCommand(this, cmd);
    +183    }
    +184
    +185    @Override
    +186    public Collection<RootCommand> getRegisteredRootCommands() {
    +187        return Collections.unmodifiableCollection(registeredCommands.values());
    +188    }
    +189
    +190    @Override
    +191    public VelocityCommandExecutionContext createCommandContext(RegisteredCommand command, CommandParameter parameter, CommandIssuer sender, List<String> args, int i, Map<String, Object> passedArgs) {
    +192        return new VelocityCommandExecutionContext(command, parameter, (VelocityCommandIssuer) sender, args, i, passedArgs);
    +193    }
    +194
    +195    @Override
    +196    public CommandCompletionContext createCompletionContext(RegisteredCommand command, CommandIssuer sender, String input, String config, String[] args) {
    +197        return new VelocityCommandCompletionContext(command, (VelocityCommandIssuer) sender, input, config, args);
    +198    }
    +199
    +200    @Override
    +201    public RegisteredCommand createRegisteredCommand(BaseCommand command, String cmdName, Method method, String prefSubCommand) {
    +202        return new RegisteredCommand(command, cmdName, method, prefSubCommand);
    +203    }
    +204
    +205    @Override
    +206    public VelocityConditionContext createConditionContext(CommandIssuer issuer, String config) {
    +207        return new VelocityConditionContext((VelocityCommandIssuer) issuer, config);
    +208    }
    +209
    +210    @Override
    +211    public void log(LogLevel level, String message, Throwable throwable) {
    +212        // TODO: Find better solution
    +213        Logger logger = LoggerFactory.getLogger(plugin.getClass());
    +214        if (level == LogLevel.INFO) {
    +215            logger.info(LogLevel.LOG_PREFIX + message);
    +216        } else {
    +217            logger.warn(LogLevel.LOG_PREFIX + message);
    +218        }
    +219
    +220        if (throwable != null) {
    +221            for (String line : ACFPatterns.NEWLINE.split(ApacheCommonsExceptionUtil.getFullStackTrace(throwable))) {
    +222                if (level == LogLevel.INFO) {
    +223                    logger.info(LogLevel.LOG_PREFIX + line);
    +224                } else {
    +225                    logger.warn(LogLevel.LOG_PREFIX + line);
    +226                }
    +227            }
    +228        }
    +229    }
    +230
    +231
    +232    @Override
    +233    public String getCommandPrefix(CommandIssuer issuer) {
    +234        return issuer.isPlayer() ? "/" : "";
    +235    }
    +236}
     
     
     
    diff --git a/docs/acf-velocity/src-html/co/aikar/commands/VelocityRootCommand.html b/docs/acf-velocity/src-html/co/aikar/commands/VelocityRootCommand.html
    index af667dab..4dd6e04b 100644
    --- a/docs/acf-velocity/src-html/co/aikar/commands/VelocityRootCommand.html
    +++ b/docs/acf-velocity/src-html/co/aikar/commands/VelocityRootCommand.html
    @@ -109,8 +109,7 @@
     096    public CompletableFuture<List<String>> suggestAsync(Invocation invocation) {
     097        return CompletableFuture.completedFuture(getTabCompletions(manager.getCommandIssuer(invocation.source()), getCommandName(), invocation.arguments()));
     098    }
    -099
    -100}
    +099}
     
     
     
    diff --git a/velocity/pom.xml b/velocity/pom.xml
    index 303aa2bf..66d82f59 100644
    --- a/velocity/pom.xml
    +++ b/velocity/pom.xml
    @@ -32,7 +32,7 @@
     		
     			com.velocitypowered
     			velocity-api
    -			3.0.1-SNAPSHOT
    +			3.1.0
     			provided
     		
     	
    diff --git a/velocity/src/main/java/co/aikar/commands/ACFVelocityUtil.java b/velocity/src/main/java/co/aikar/commands/ACFVelocityUtil.java
    index 2e9f960c..9ef3cf82 100644
    --- a/velocity/src/main/java/co/aikar/commands/ACFVelocityUtil.java
    +++ b/velocity/src/main/java/co/aikar/commands/ACFVelocityUtil.java
    @@ -1,5 +1,11 @@
     package co.aikar.commands;
     
    +import com.velocitypowered.api.command.CommandSource;
    +import com.velocitypowered.api.proxy.Player;
    +import com.velocitypowered.api.proxy.ProxyServer;
    +import net.kyori.adventure.text.TextComponent;
    +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
    +
     import java.util.ArrayList;
     import java.util.Collection;
     import java.util.Collections;
    @@ -7,13 +13,6 @@ import java.util.List;
     import java.util.Optional;
     import java.util.stream.Collectors;
     
    -import com.velocitypowered.api.command.CommandSource;
    -import com.velocitypowered.api.proxy.Player;
    -import com.velocitypowered.api.proxy.ProxyServer;
    -
    -import net.kyori.adventure.text.TextComponent;
    -import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
    -
     public class ACFVelocityUtil {
     
         public static TextComponent color(String message) {
    diff --git a/velocity/src/main/java/co/aikar/commands/VelocityCommandCompletions.java b/velocity/src/main/java/co/aikar/commands/VelocityCommandCompletions.java
    index 332013f1..22afcdd7 100644
    --- a/velocity/src/main/java/co/aikar/commands/VelocityCommandCompletions.java
    +++ b/velocity/src/main/java/co/aikar/commands/VelocityCommandCompletions.java
    @@ -23,21 +23,20 @@
     
     package co.aikar.commands;
     
    +import co.aikar.commands.apachecommonslang.ApacheCommonsLangUtil;
    +import com.velocitypowered.api.command.CommandSource;
    +import com.velocitypowered.api.proxy.Player;
    +import com.velocitypowered.api.proxy.ProxyServer;
    +import net.kyori.adventure.text.format.NamedTextColor;
    +import net.kyori.adventure.text.format.TextDecoration;
    +import net.kyori.adventure.text.format.TextFormat;
    +
     import java.util.ArrayList;
     import java.util.Arrays;
     import java.util.Set;
     import java.util.stream.Collectors;
     import java.util.stream.Stream;
     
    -import com.velocitypowered.api.command.CommandSource;
    -import com.velocitypowered.api.proxy.Player;
    -import com.velocitypowered.api.proxy.ProxyServer;
    -
    -import co.aikar.commands.apachecommonslang.ApacheCommonsLangUtil;
    -import net.kyori.adventure.text.format.NamedTextColor;
    -import net.kyori.adventure.text.format.TextDecoration;
    -import net.kyori.adventure.text.format.TextFormat;
    -
     public class VelocityCommandCompletions extends CommandCompletions {
     
         public VelocityCommandCompletions(ProxyServer server, CommandManager manager) {
    diff --git a/velocity/src/main/java/co/aikar/commands/VelocityCommandContexts.java b/velocity/src/main/java/co/aikar/commands/VelocityCommandContexts.java
    index ce4d1daa..628f0a44 100644
    --- a/velocity/src/main/java/co/aikar/commands/VelocityCommandContexts.java
    +++ b/velocity/src/main/java/co/aikar/commands/VelocityCommandContexts.java
    @@ -23,20 +23,20 @@
     
     package co.aikar.commands;
     
    -import java.util.stream.Collectors;
    -import java.util.stream.Stream;
    -
    +import co.aikar.commands.velocity.contexts.OnlinePlayer;
     import com.velocitypowered.api.command.CommandSource;
     import com.velocitypowered.api.proxy.Player;
     import com.velocitypowered.api.proxy.ProxyServer;
    -
    -import co.aikar.commands.velocity.contexts.OnlinePlayer;
     import net.kyori.adventure.text.format.NamedTextColor;
    -import net.kyori.adventure.text.format.TextColor;
     import net.kyori.adventure.text.format.TextDecoration;
     import net.kyori.adventure.text.format.TextFormat;
    +
    +import net.kyori.adventure.text.format.TextColor;
     import org.jetbrains.annotations.Nullable;
     
    +import java.util.stream.Collectors;
    +import java.util.stream.Stream;
    +
     public class VelocityCommandContexts extends CommandContexts {
     
         VelocityCommandContexts(ProxyServer server, CommandManager manager) {
    diff --git a/velocity/src/main/java/co/aikar/commands/VelocityCommandIssuer.java b/velocity/src/main/java/co/aikar/commands/VelocityCommandIssuer.java
    index 755cf35f..eb5da27d 100644
    --- a/velocity/src/main/java/co/aikar/commands/VelocityCommandIssuer.java
    +++ b/velocity/src/main/java/co/aikar/commands/VelocityCommandIssuer.java
    @@ -23,14 +23,12 @@
     
     package co.aikar.commands;
     
    -import java.nio.charset.StandardCharsets;
    -import java.util.Objects;
    -import java.util.UUID;
    -
    -import org.jetbrains.annotations.NotNull;
    -
     import com.velocitypowered.api.command.CommandSource;
     import com.velocitypowered.api.proxy.Player;
    +import org.jetbrains.annotations.NotNull;
    +
    +import java.util.Objects;
    +import java.util.UUID;
     
     public class VelocityCommandIssuer implements CommandIssuer {
         private final VelocityCommandManager manager;
    diff --git a/velocity/src/main/java/co/aikar/commands/VelocityCommandManager.java b/velocity/src/main/java/co/aikar/commands/VelocityCommandManager.java
    index a94e00e0..8e80ac10 100644
    --- a/velocity/src/main/java/co/aikar/commands/VelocityCommandManager.java
    +++ b/velocity/src/main/java/co/aikar/commands/VelocityCommandManager.java
    @@ -23,6 +23,17 @@
     
     package co.aikar.commands;
     
    +import co.aikar.commands.apachecommonslang.ApacheCommonsExceptionUtil;
    +import com.velocitypowered.api.command.CommandMeta;
    +import com.velocitypowered.api.command.CommandSource;
    +import com.velocitypowered.api.plugin.Plugin;
    +import com.velocitypowered.api.plugin.PluginContainer;
    +import com.velocitypowered.api.proxy.Player;
    +import com.velocitypowered.api.proxy.ProxyServer;
    +import net.kyori.adventure.text.format.NamedTextColor;
    +import org.slf4j.Logger;
    +import org.slf4j.LoggerFactory;
    +
     import java.lang.reflect.Method;
     import java.util.Collection;
     import java.util.Collections;
    @@ -31,20 +42,6 @@ import java.util.List;
     import java.util.Locale;
     import java.util.Map;
     
    -import com.velocitypowered.api.command.CommandMeta;
    -import net.kyori.adventure.text.format.TextColor;
    -import org.slf4j.Logger;
    -import org.slf4j.LoggerFactory;
    -
    -import com.velocitypowered.api.command.CommandSource;
    -import com.velocitypowered.api.plugin.Plugin;
    -import com.velocitypowered.api.plugin.PluginContainer;
    -import com.velocitypowered.api.proxy.Player;
    -import com.velocitypowered.api.proxy.ProxyServer;
    -
    -import co.aikar.commands.apachecommonslang.ApacheCommonsExceptionUtil;
    -import net.kyori.adventure.text.format.NamedTextColor;
    -
     public class VelocityCommandManager extends
             CommandManager {
     
    diff --git a/velocity/src/main/java/co/aikar/commands/VelocityRootCommand.java b/velocity/src/main/java/co/aikar/commands/VelocityRootCommand.java
    index b4a7933c..38c2ac45 100644
    --- a/velocity/src/main/java/co/aikar/commands/VelocityRootCommand.java
    +++ b/velocity/src/main/java/co/aikar/commands/VelocityRootCommand.java
    @@ -96,5 +96,4 @@ public class VelocityRootCommand implements SimpleCommand, RootCommand {
         public CompletableFuture> suggestAsync(Invocation invocation) {
             return CompletableFuture.completedFuture(getTabCompletions(manager.getCommandIssuer(invocation.source()), getCommandName(), invocation.arguments()));
         }
    -
     }