mirror of
https://github.com/aikar/commands.git
synced 2026-05-31 06:11:55 +00:00
Refactor stuff away from static and exposed Command Contexts - Fixes #2
This commit is contained in:
@@ -23,10 +23,6 @@
|
||||
|
||||
package co.aikar.commands;
|
||||
|
||||
import co.aikar.commands.managers.BukkitCommandManager;
|
||||
import co.aikar.commands.managers.CommandManager;
|
||||
import co.aikar.commands.managers.PaperCommandManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
/**
|
||||
|
||||
@@ -44,6 +44,7 @@ import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
@@ -61,6 +62,8 @@ public abstract class BaseCommand extends Command {
|
||||
protected String execSubcommand;
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
protected String[] origArgs;
|
||||
CommandManager manager = null;
|
||||
Map<String, Command> registeredCommands = new HashMap<>();
|
||||
|
||||
public BaseCommand(Plugin plugin) {
|
||||
this(plugin, null);
|
||||
@@ -139,8 +142,8 @@ public abstract class BaseCommand extends Command {
|
||||
register(getName(), this);
|
||||
}
|
||||
|
||||
private boolean register(String name, Command cmd) {
|
||||
return Bukkit.getServer().getCommandMap().register(name.toLowerCase(), plugin.getName().toLowerCase(), cmd);
|
||||
private void register(String name, Command cmd) {
|
||||
this.registeredCommands.put(name.toLowerCase(), cmd);
|
||||
}
|
||||
|
||||
private void registerSubcommand(Method method, String subCommand) {
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* 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.commands.annotation.Optional;
|
||||
import co.aikar.commands.contexts.OnlinePlayer;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class BukkitCommandContexts extends CommandContexts {
|
||||
|
||||
BukkitCommandContexts(CommandManager manager) {
|
||||
super(manager);
|
||||
|
||||
registerContext(OnlinePlayer.class, (c) -> {
|
||||
final String playercheck = c.popFirstArg();
|
||||
Player player = CommandUtil.findPlayerSmart(c.getSender(), playercheck);
|
||||
if (player == null) {
|
||||
CommandUtil.sendMsg(c.getSender(), "&cCould not find a player by the name " + playercheck);
|
||||
throw new InvalidCommandArgument(false);
|
||||
}
|
||||
return new OnlinePlayer(player);
|
||||
});
|
||||
registerSenderAwareContext(World.class, (c) -> {
|
||||
String firstArg = c.getFirstArg();
|
||||
World world = firstArg != null ? Bukkit.getWorld(firstArg) : null;
|
||||
if (world != null) {
|
||||
c.popFirstArg();
|
||||
}
|
||||
if (world == null && c.getSender() instanceof Player) {
|
||||
world = ((Entity) c.getSender()).getWorld();
|
||||
}
|
||||
if (world == null) {
|
||||
throw new InvalidCommandArgument("Invalid World");
|
||||
}
|
||||
return world;
|
||||
});
|
||||
registerSenderAwareContext(CommandSender.class, CommandExecutionContext::getSender);
|
||||
registerSenderAwareContext(Player.class, (c) -> {
|
||||
Player player = c.getSender() instanceof Player ? (Player) c.getSender() : null;
|
||||
if (player == null && !c.hasAnnotation(Optional.class)) {
|
||||
throw new InvalidCommandArgument("Requires a player to run this command", false);
|
||||
}
|
||||
if (player != null && c.hasFlag("itemheld") && !CommandUtil.isValidItem(player.getInventory().getItemInMainHand())) {
|
||||
throw new InvalidCommandArgument("You must be holding an item in your main hand.", false);
|
||||
}
|
||||
return player;
|
||||
});
|
||||
}
|
||||
}
|
||||
+20
-7
@@ -21,28 +21,41 @@
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package co.aikar.commands.managers;
|
||||
package co.aikar.commands;
|
||||
|
||||
import co.aikar.commands.BaseCommand;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class BukkitCommandManager implements CommandManager {
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
protected final Plugin plugin;
|
||||
private CommandContexts contexts;
|
||||
|
||||
public BukkitCommandManager(Plugin plugin) {
|
||||
this.plugin = plugin;
|
||||
this.contexts = new CommandContexts(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandContexts getCommandContexts() {
|
||||
return contexts;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean register(BaseCommand command) {
|
||||
return Bukkit.getServer().getCommandMap().register(this.plugin.getDescription().getName(), command);
|
||||
}
|
||||
command.manager = this;
|
||||
final String plugin = this.plugin.getName().toLowerCase();
|
||||
boolean allSuccess = true;
|
||||
for (Map.Entry<String, Command> entry : command.registeredCommands.entrySet()) {
|
||||
if (!Bukkit.getServer().getCommandMap().register(entry.getKey().toLowerCase(), plugin, entry.getValue())) {
|
||||
allSuccess = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean register(BaseCommand command, String commandName) {
|
||||
return Bukkit.getServer().getCommandMap().register(commandName, this.plugin.getDescription().getName(), command);
|
||||
return allSuccess;
|
||||
}
|
||||
}
|
||||
@@ -32,23 +32,22 @@ import co.aikar.commands.contexts.OnlinePlayer;
|
||||
import co.aikar.commands.contexts.SenderAwareContextResolver;
|
||||
import com.google.common.collect.Maps;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public final class CommandContexts {
|
||||
private static final Map<Class<?>, ContextResolver<?>> contextMap = Maps.newHashMap();
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public class CommandContexts {
|
||||
private final CommandManager manager;
|
||||
private final Map<Class<?>, ContextResolver<?>> contextMap = Maps.newHashMap();
|
||||
|
||||
private CommandContexts() {}
|
||||
|
||||
public static void initialize() {
|
||||
CommandContexts(CommandManager manager) {
|
||||
this.manager = manager;
|
||||
registerContext(Integer.class, (c) -> {
|
||||
try {
|
||||
return CommandUtil.parseNumber(c.popFirstArg(), c.hasFlag("suffixes")).intValue();
|
||||
@@ -118,40 +117,6 @@ public final class CommandContexts {
|
||||
return result;
|
||||
});
|
||||
|
||||
registerContext(OnlinePlayer.class, (c) -> {
|
||||
final String playercheck = c.popFirstArg();
|
||||
Player player = CommandUtil.findPlayerSmart(c.getSender(), playercheck);
|
||||
if (player == null) {
|
||||
CommandUtil.sendMsg(c.getSender(), "&cCould not find a player by the name " + playercheck);
|
||||
throw new InvalidCommandArgument(false);
|
||||
}
|
||||
return new OnlinePlayer(player);
|
||||
});
|
||||
registerSenderAwareContext(World.class, (c) -> {
|
||||
String firstArg = c.getFirstArg();
|
||||
World world = firstArg != null ? Bukkit.getWorld(firstArg) : null;
|
||||
if (world != null) {
|
||||
c.popFirstArg();
|
||||
}
|
||||
if (world == null && c.getSender() instanceof Player) {
|
||||
world = ((Entity) c.getSender()).getWorld();
|
||||
}
|
||||
if (world == null) {
|
||||
throw new InvalidCommandArgument("Invalid World");
|
||||
}
|
||||
return world;
|
||||
});
|
||||
registerSenderAwareContext(CommandSender.class, CommandExecutionContext::getSender);
|
||||
registerSenderAwareContext(Player.class, (c) -> {
|
||||
Player player = c.getSender() instanceof Player ? (Player) c.getSender() : null;
|
||||
if (player == null && !c.hasAnnotation(Optional.class)) {
|
||||
throw new InvalidCommandArgument("Requires a player to run this command", false);
|
||||
}
|
||||
if (player != null && c.hasFlag("itemheld") && !isValidItem(player.getInventory().getItemInMainHand())) {
|
||||
throw new InvalidCommandArgument("You must be holding an item in your main hand.", false);
|
||||
}
|
||||
return player;
|
||||
});
|
||||
registerContext(Enum.class, (c) -> {
|
||||
final String first = c.popFirstArg();
|
||||
Class<? extends Enum<?>> enumCls = (Class<? extends Enum<?>>) c.getParam().getType();
|
||||
@@ -164,14 +129,14 @@ public final class CommandContexts {
|
||||
});
|
||||
}
|
||||
|
||||
public static <T> void registerSenderAwareContext(Class<T> context, SenderAwareContextResolver<T> supplier) {
|
||||
public <T> void registerSenderAwareContext(Class<T> context, SenderAwareContextResolver<T> supplier) {
|
||||
contextMap.put(context, supplier);
|
||||
}
|
||||
public static <T> void registerContext(Class<T> context, ContextResolver<T> supplier) {
|
||||
public <T> void registerContext(Class<T> context, ContextResolver<T> supplier) {
|
||||
contextMap.put(context, supplier);
|
||||
}
|
||||
|
||||
public static ContextResolver<?> getResolver(Class<?> type) {
|
||||
public ContextResolver<?> getResolver(Class<?> type) {
|
||||
Class<?> rootType = type;
|
||||
do {
|
||||
if (type == Object.class) {
|
||||
@@ -187,7 +152,4 @@ public final class CommandContexts {
|
||||
CommandLog.exception(new InvalidConfigurationException("No context resolver defined for " + rootType.getName()));
|
||||
return null;
|
||||
}
|
||||
private static boolean isValidItem(ItemStack item) {
|
||||
return item != null && item.getType() != Material.AIR && item.getAmount() > 0;
|
||||
}
|
||||
}
|
||||
|
||||
+7
-12
@@ -21,12 +21,16 @@
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package co.aikar.commands.managers;
|
||||
|
||||
import co.aikar.commands.BaseCommand;
|
||||
package co.aikar.commands;
|
||||
|
||||
public interface CommandManager {
|
||||
|
||||
/**
|
||||
* Gets the command contexts registered
|
||||
* @return Command Contexts
|
||||
*/
|
||||
CommandContexts getCommandContexts();
|
||||
|
||||
/**
|
||||
* Registers a command with ACF
|
||||
*
|
||||
@@ -34,13 +38,4 @@ public interface CommandManager {
|
||||
* @return boolean
|
||||
*/
|
||||
boolean register(BaseCommand command);
|
||||
|
||||
/**
|
||||
* Registers a command with ACF
|
||||
*
|
||||
* @param command The command to register
|
||||
* @param commandName Specific command name to register as
|
||||
* @return boolean
|
||||
*/
|
||||
boolean register(BaseCommand command, String commandName);
|
||||
}
|
||||
@@ -34,6 +34,7 @@ import org.bukkit.World;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -880,6 +881,11 @@ final class CommandUtil {
|
||||
}
|
||||
return timingProvider.newTiming(cmd, command);
|
||||
}
|
||||
|
||||
static boolean isValidItem(ItemStack item) {
|
||||
return item != null && item.getType() != Material.AIR && item.getAmount() > 0;
|
||||
}
|
||||
|
||||
private enum TimingType {
|
||||
SPIGOT() {
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package co.aikar.commands.managers;
|
||||
package co.aikar.commands;
|
||||
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
@@ -48,18 +48,18 @@ import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class RegisteredCommand {
|
||||
public final BaseCommand scope;
|
||||
private final BaseCommand scope;
|
||||
public final String command;
|
||||
public final Method method;
|
||||
public final String prefSubCommand;
|
||||
public final Parameter[] parameters;
|
||||
public final ContextResolver<?>[] resolvers;
|
||||
public final String syntax;
|
||||
private final Method method;
|
||||
final String prefSubCommand;
|
||||
final Parameter[] parameters;
|
||||
final ContextResolver<?>[] resolvers;
|
||||
final String syntax;
|
||||
|
||||
public final CommandPermission perm;
|
||||
public final CommandCompletion complete;
|
||||
public final int nonSenderAwareResolvers;
|
||||
public final int optionalResolvers;
|
||||
private final CommandPermission perm;
|
||||
final CommandCompletion complete;
|
||||
final int nonSenderAwareResolvers;
|
||||
final int optionalResolvers;
|
||||
CommandTiming timing;
|
||||
|
||||
RegisteredCommand(BaseCommand scope, String command, Method method, String prefSubCommand) {
|
||||
@@ -83,7 +83,7 @@ public class RegisteredCommand {
|
||||
for (int i = 0; i < parameters.length; i++) {
|
||||
final Parameter parameter = parameters[i];
|
||||
final Class<?> type = parameter.getType();
|
||||
final ContextResolver<?> resolver = CommandContexts.getResolver(type);
|
||||
final ContextResolver<?> resolver = scope.manager.getCommandContexts().getResolver(type);
|
||||
if (resolver != null) {
|
||||
resolvers[i] = resolver;
|
||||
|
||||
@@ -117,7 +117,7 @@ public class RegisteredCommand {
|
||||
this.optionalResolvers = optionalResolvers;
|
||||
}
|
||||
|
||||
public void invoke(CommandSender sender, List<String> args) {
|
||||
void invoke(CommandSender sender, List<String> args) {
|
||||
if (!scope.canExecute(sender, this)) {
|
||||
return;
|
||||
}
|
||||
@@ -191,7 +191,7 @@ public class RegisteredCommand {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasPermission(CommandSender check) {
|
||||
boolean hasPermission(CommandSender check) {
|
||||
return perm == null || !(check instanceof Player) || check.hasPermission(perm.value());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user