geforkt von Mirrors/FastAsyncWorldEdit
Generalized commands handler so that other plugins (WorldGuard, CraftBook, etc.) can use it too.
Dieser Commit ist enthalten in:
Ursprung
01f7be3ba3
Commit
e91c837949
@ -16,7 +16,7 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.sk89q.util.commands;
|
package com.sk89q.minecraft.util.commands;
|
||||||
|
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
@ -16,7 +16,7 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.sk89q.util.commands;
|
package com.sk89q.minecraft.util.commands;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
@ -17,7 +17,7 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.sk89q.worldedit.commands;
|
package com.sk89q.minecraft.util.commands;
|
||||||
|
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
342
src/com/sk89q/minecraft/util/commands/CommandsManager.java
Normale Datei
342
src/com/sk89q/minecraft/util/commands/CommandsManager.java
Normale Datei
@ -0,0 +1,342 @@
|
|||||||
|
// $Id$
|
||||||
|
/*
|
||||||
|
* WorldEdit
|
||||||
|
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sk89q.minecraft.util.commands;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import com.sk89q.util.StringUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manager for handling commands.
|
||||||
|
*
|
||||||
|
* @author sk89q
|
||||||
|
*/
|
||||||
|
public class CommandsManager {
|
||||||
|
/**
|
||||||
|
* Mapping of nested commands (including aliases) with a description.
|
||||||
|
*/
|
||||||
|
public Map<Method, Map<String, Method>> commands
|
||||||
|
= new HashMap<Method, Map<String, Method>>();
|
||||||
|
/**
|
||||||
|
* Mapping of commands (not including aliases) with a description.
|
||||||
|
*/
|
||||||
|
public Map<String, String> descs = new HashMap<String, String>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register an object that contains commands (denoted by the
|
||||||
|
* <code>com.sk89q.util.commands.Command</code> annotation. The methods are
|
||||||
|
* cached into a map for later usage and it reduces the overhead of
|
||||||
|
* reflection (method lookup via reflection is relatively slow).
|
||||||
|
*
|
||||||
|
* @param cls
|
||||||
|
*/
|
||||||
|
public void register(Class<?> cls) {
|
||||||
|
registerMethods(cls, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register the methods of a class.
|
||||||
|
*
|
||||||
|
* @param cls
|
||||||
|
* @param parent
|
||||||
|
*/
|
||||||
|
private void registerMethods(Class<?> cls, Method parent) {
|
||||||
|
Map<String, Method> map;
|
||||||
|
|
||||||
|
// Make a new hash map to cache the commands for this class
|
||||||
|
// as looking up methods via reflection is fairly slow
|
||||||
|
if (commands.containsKey(parent)) {
|
||||||
|
map = commands.get(parent);
|
||||||
|
} else {
|
||||||
|
map = new HashMap<String, Method>();
|
||||||
|
commands.put(parent, map);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Method method : cls.getMethods()) {
|
||||||
|
if (!method.isAnnotationPresent(Command.class)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Command cmd = method.getAnnotation(Command.class);
|
||||||
|
|
||||||
|
// Cache the aliases too
|
||||||
|
for (String alias : cmd.aliases()) {
|
||||||
|
map.put(alias, method);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build a list of commands and their usage details, at least for
|
||||||
|
// root level commands
|
||||||
|
if (parent == null) {
|
||||||
|
if (cmd.usage().length() == 0) {
|
||||||
|
descs.put(cmd.aliases()[0], cmd.desc());
|
||||||
|
} else {
|
||||||
|
descs.put(cmd.aliases()[0], cmd.usage() + " - " + cmd.desc());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look for nested commands -- if there are any, those have
|
||||||
|
// to be cached too so that they can be quickly looked
|
||||||
|
// up when processing commands
|
||||||
|
if (method.isAnnotationPresent(NestedCommand.class)) {
|
||||||
|
NestedCommand nestedCmd = method.getAnnotation(NestedCommand.class);
|
||||||
|
|
||||||
|
for (Class<?> nestedCls : nestedCmd.value()) {
|
||||||
|
registerMethods(nestedCls, method);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks to see whether there is a command.
|
||||||
|
*
|
||||||
|
* @param command
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean hasCommand(String command) {
|
||||||
|
return commands.get(null).containsKey(command.toLowerCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a list of command descriptions.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Map<String, String> getCommands() {
|
||||||
|
return descs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the usage string for a command.
|
||||||
|
*
|
||||||
|
* @param args
|
||||||
|
* @param level
|
||||||
|
* @param cmd
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private String getUsage(String[] args, int level, Command cmd) {
|
||||||
|
StringBuilder command = new StringBuilder();
|
||||||
|
|
||||||
|
command.append("/");
|
||||||
|
|
||||||
|
for (int i = 0; i <= level; i++) {
|
||||||
|
command.append(args[i] + " ");
|
||||||
|
}
|
||||||
|
|
||||||
|
command.append(cmd.flags().length() > 0 ? "[-" + cmd.flags() + "] " : "");
|
||||||
|
command.append(cmd.usage());
|
||||||
|
|
||||||
|
return command.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the usage string for a nested command.
|
||||||
|
*
|
||||||
|
* @param args
|
||||||
|
* @param level
|
||||||
|
* @param method
|
||||||
|
* @param palyer
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private String getNestedUsage(String[] args, int level, Method method,
|
||||||
|
CommandsPlayer player) {
|
||||||
|
StringBuilder command = new StringBuilder();
|
||||||
|
|
||||||
|
command.append("/");
|
||||||
|
|
||||||
|
for (int i = 0; i <= level; i++) {
|
||||||
|
command.append(args[i] + " ");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Map<String, Method> map = commands.get(method);
|
||||||
|
|
||||||
|
command.append("<");
|
||||||
|
|
||||||
|
List<String> allowedCommands = new ArrayList<String>();
|
||||||
|
|
||||||
|
for (Map.Entry<String, Method> entry : map.entrySet()) {
|
||||||
|
Method childMethod = entry.getValue();
|
||||||
|
|
||||||
|
if (hasPermission(childMethod, player)) {
|
||||||
|
Command childCmd = childMethod.getAnnotation(Command.class);
|
||||||
|
|
||||||
|
allowedCommands.add(childCmd.aliases()[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allowedCommands.size() > 0) {
|
||||||
|
command.append(StringUtil.joinString(allowedCommands, "|", 0));
|
||||||
|
} else {
|
||||||
|
command.append("action");
|
||||||
|
}
|
||||||
|
|
||||||
|
command.append(">");
|
||||||
|
|
||||||
|
return command.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempt to execute a command.
|
||||||
|
*
|
||||||
|
* @param args
|
||||||
|
* @param player
|
||||||
|
* @param methodArgs
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean execute(String[] args, CommandsPlayer player,
|
||||||
|
Object[] methodArgs) throws Throwable {
|
||||||
|
return executeMethod(null, args, player, methodArgs, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempt to execute a command.
|
||||||
|
*
|
||||||
|
* @param parent
|
||||||
|
* @param args
|
||||||
|
* @param player
|
||||||
|
* @param methodArgs
|
||||||
|
* @param level
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean executeMethod(Method parent, String[] args,
|
||||||
|
CommandsPlayer player, Object[] methodArgs, int level)
|
||||||
|
throws Throwable {
|
||||||
|
String cmdName = args[level];
|
||||||
|
|
||||||
|
Map<String, Method> map = commands.get(parent);
|
||||||
|
Method method = map.get(cmdName.toLowerCase());
|
||||||
|
|
||||||
|
if (method == null) {
|
||||||
|
if (parent == null) { // Root
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
player.printError(getNestedUsage(args, level - 1, method, player));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!checkPermissions(method, player)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int argsCount = args.length - 1 - level;
|
||||||
|
|
||||||
|
if (method.isAnnotationPresent(NestedCommand.class)) {
|
||||||
|
if (argsCount == 0) {
|
||||||
|
player.printError(getNestedUsage(args, level, method, player));
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return executeMethod(method, args, player, methodArgs, level + 1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Command cmd = method.getAnnotation(Command.class);
|
||||||
|
|
||||||
|
String[] newArgs = new String[args.length - level];
|
||||||
|
System.arraycopy(args, level, newArgs, 0, args.length - level);
|
||||||
|
|
||||||
|
CommandContext context = new CommandContext(newArgs);
|
||||||
|
|
||||||
|
if (context.argsLength() < cmd.min()) {
|
||||||
|
player.printError("Too few arguments.");
|
||||||
|
player.printError(getUsage(args, level, cmd));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd.max() != -1 && context.argsLength() > cmd.max()) {
|
||||||
|
player.printError("Too many arguments.");
|
||||||
|
player.printError(getUsage(args, level, cmd));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (char flag : context.getFlags()) {
|
||||||
|
if (cmd.flags().indexOf(String.valueOf(flag)) == -1) {
|
||||||
|
player.printError("Unknown flag: " + flag);
|
||||||
|
player.printError(getUsage(args, level, cmd));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
methodArgs[0] = context;
|
||||||
|
|
||||||
|
try {
|
||||||
|
method.invoke(null, methodArgs);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
throw e.getCause();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks permissions, prints an error if needed.
|
||||||
|
*
|
||||||
|
* @param method
|
||||||
|
* @param player
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private boolean checkPermissions(Method method, CommandsPlayer player) {
|
||||||
|
if (!method.isAnnotationPresent(CommandPermissions.class)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
CommandPermissions perms = method.getAnnotation(CommandPermissions.class);
|
||||||
|
|
||||||
|
for (String perm : perms.value()) {
|
||||||
|
if (player.hasPermission(perm)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
player.printError("You don't have permission for this command.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether a player has access to a command.
|
||||||
|
*
|
||||||
|
* @param method
|
||||||
|
* @param player
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private boolean hasPermission(Method method, CommandsPlayer player) {
|
||||||
|
CommandPermissions perms = method.getAnnotation(CommandPermissions.class);
|
||||||
|
if (perms == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String perm : perms.value()) {
|
||||||
|
if (player.hasPermission(perm)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
25
src/com/sk89q/minecraft/util/commands/CommandsPlayer.java
Normale Datei
25
src/com/sk89q/minecraft/util/commands/CommandsPlayer.java
Normale Datei
@ -0,0 +1,25 @@
|
|||||||
|
// $Id$
|
||||||
|
/*
|
||||||
|
* WorldEdit
|
||||||
|
* Copyright (C) 2010, 2011 sk89q <http://www.sk89q.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sk89q.minecraft.util.commands;
|
||||||
|
|
||||||
|
public interface CommandsPlayer {
|
||||||
|
public void printError(String msg);
|
||||||
|
public boolean hasPermission(String perm);
|
||||||
|
}
|
@ -17,7 +17,7 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.sk89q.util.commands;
|
package com.sk89q.minecraft.util.commands;
|
||||||
|
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
332
src/com/sk89q/util/commands/CommandsManager.java
Normale Datei
332
src/com/sk89q/util/commands/CommandsManager.java
Normale Datei
@ -0,0 +1,332 @@
|
|||||||
|
// $Id$
|
||||||
|
/*
|
||||||
|
* WorldEdit
|
||||||
|
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sk89q.util.commands;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import com.sk89q.util.StringUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manager for handling commands.
|
||||||
|
*
|
||||||
|
* @author sk89q
|
||||||
|
*/
|
||||||
|
public abstract class CommandsManager {
|
||||||
|
/**
|
||||||
|
* Mapping of nested commands (including aliases) with a description.
|
||||||
|
*/
|
||||||
|
public Map<Method, Map<String, Method>> commands
|
||||||
|
= new HashMap<Method, Map<String, Method>>();
|
||||||
|
/**
|
||||||
|
* Mapping of commands (not including aliases) with a description.
|
||||||
|
*/
|
||||||
|
public Map<String, String> descs = new HashMap<String, String>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register an object that contains commands (denoted by the
|
||||||
|
* <code>com.sk89q.util.commands.Command</code> annotation. The methods are
|
||||||
|
* cached into a map for later usage and it reduces the overhead of
|
||||||
|
* reflection (method lookup via reflection is relatively slow).
|
||||||
|
*
|
||||||
|
* @param cls
|
||||||
|
*/
|
||||||
|
public void register(Class<?> cls) {
|
||||||
|
registerMethods(cls, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register the methods of a class.
|
||||||
|
*
|
||||||
|
* @param cls
|
||||||
|
* @param parent
|
||||||
|
*/
|
||||||
|
private void registerMethods(Class<?> cls, Method parent) {
|
||||||
|
Map<String, Method> map;
|
||||||
|
|
||||||
|
if (commands.containsKey(parent)) {
|
||||||
|
map = commands.get(parent);
|
||||||
|
} else {
|
||||||
|
map = new HashMap<String, Method>();
|
||||||
|
commands.put(parent, map);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Method method : cls.getMethods()) {
|
||||||
|
if (!method.isAnnotationPresent(Command.class)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Command cmd = method.getAnnotation(Command.class);
|
||||||
|
|
||||||
|
// Cache the commands
|
||||||
|
for (String alias : cmd.aliases()) {
|
||||||
|
map.put(alias, method);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build a list of commands and their usage details
|
||||||
|
if (cmd.usage().length() == 0) {
|
||||||
|
descs.put(cmd.aliases()[0], cmd.desc());
|
||||||
|
} else {
|
||||||
|
descs.put(cmd.aliases()[0], cmd.usage() + " - " + cmd.desc());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (method.isAnnotationPresent(NestedCommand.class)) {
|
||||||
|
NestedCommand nestedCmd = method.getAnnotation(NestedCommand.class);
|
||||||
|
|
||||||
|
for (Class<?> nestedCls : nestedCmd.value()) {
|
||||||
|
registerMethods(nestedCls, method);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks to see whether there is a command.
|
||||||
|
*
|
||||||
|
* @param command
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean hasCommand(String command) {
|
||||||
|
return commands.get(null).containsKey(command.toLowerCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a list of command descriptions.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Map<String, String> getCommands() {
|
||||||
|
return descs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the usage string for a command.
|
||||||
|
*
|
||||||
|
* @param args
|
||||||
|
* @param level
|
||||||
|
* @param cmd
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private String getUsage(String[] args, int level, Command cmd) {
|
||||||
|
StringBuilder command = new StringBuilder();
|
||||||
|
|
||||||
|
command.append("/");
|
||||||
|
|
||||||
|
for (int i = 0; i <= level; i++) {
|
||||||
|
command.append(args[i] + " ");
|
||||||
|
}
|
||||||
|
|
||||||
|
command.append(cmd.flags().length() > 0 ? "[-" + cmd.flags() + "] " : "");
|
||||||
|
command.append(cmd.usage());
|
||||||
|
|
||||||
|
return command.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the usage string for a nested command.
|
||||||
|
*
|
||||||
|
* @param args
|
||||||
|
* @param level
|
||||||
|
* @param method
|
||||||
|
* @param palyer
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private String getNestedUsage(String[] args, int level, Method method,
|
||||||
|
CommandsPlayer player) {
|
||||||
|
StringBuilder command = new StringBuilder();
|
||||||
|
|
||||||
|
command.append("/");
|
||||||
|
|
||||||
|
for (int i = 0; i <= level; i++) {
|
||||||
|
command.append(args[i] + " ");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Map<String, Method> map = commands.get(method);
|
||||||
|
|
||||||
|
command.append("<");
|
||||||
|
|
||||||
|
List<String> allowedCommands = new ArrayList<String>();
|
||||||
|
|
||||||
|
for (Map.Entry<String, Method> entry : map.entrySet()) {
|
||||||
|
Method childMethod = entry.getValue();
|
||||||
|
|
||||||
|
if (hasPermission(childMethod, player)) {
|
||||||
|
Command childCmd = childMethod.getAnnotation(Command.class);
|
||||||
|
|
||||||
|
allowedCommands.add(childCmd.aliases()[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allowedCommands.size() > 0) {
|
||||||
|
command.append(StringUtil.joinString(allowedCommands, "|", 0));
|
||||||
|
} else {
|
||||||
|
command.append("action");
|
||||||
|
}
|
||||||
|
|
||||||
|
command.append(">");
|
||||||
|
|
||||||
|
return command.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempt to execute a command.
|
||||||
|
*
|
||||||
|
* @param args
|
||||||
|
* @param player
|
||||||
|
* @param methodArgs
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean execute(String[] args, CommandsPlayer player,
|
||||||
|
Object[] methodArgs) throws Throwable {
|
||||||
|
return executeMethod(null, args, we, session, player, editSession, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempt to execute a command.
|
||||||
|
*
|
||||||
|
* @param parent
|
||||||
|
* @param args
|
||||||
|
* @param player
|
||||||
|
* @param methodArgs
|
||||||
|
* @param level
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean executeMethod(Method parent, String[] args,
|
||||||
|
CommandsPlayer player, Object[] methodArgs, int level)
|
||||||
|
throws Throwable {
|
||||||
|
String cmdName = args[level];
|
||||||
|
|
||||||
|
Map<String, Method> map = commands.get(parent);
|
||||||
|
Method method = map.get(cmdName.toLowerCase());
|
||||||
|
|
||||||
|
if (method == null) {
|
||||||
|
if (parent == null) { // Root
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
player.printError(getNestedUsage(args, level - 1, method, player));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!checkPermissions(method, player)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int argsCount = args.length - 1 - level;
|
||||||
|
|
||||||
|
if (method.isAnnotationPresent(NestedCommand.class)) {
|
||||||
|
if (argsCount == 0) {
|
||||||
|
player.printError(getNestedUsage(args, level, method, player));
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return executeMethod(method, args, player, methodArgs, level + 1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Command cmd = method.getAnnotation(Command.class);
|
||||||
|
|
||||||
|
String[] newArgs = new String[args.length - level];
|
||||||
|
System.arraycopy(args, level, newArgs, 0, args.length - level);
|
||||||
|
|
||||||
|
CommandContext context = new CommandContext(newArgs);
|
||||||
|
|
||||||
|
if (context.argsLength() < cmd.min()) {
|
||||||
|
player.printError("Too few arguments.");
|
||||||
|
player.printError(getUsage(args, level, cmd));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd.max() != -1 && context.argsLength() > cmd.max()) {
|
||||||
|
player.printError("Too many arguments.");
|
||||||
|
player.printError(getUsage(args, level, cmd));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (char flag : context.getFlags()) {
|
||||||
|
if (cmd.flags().indexOf(String.valueOf(flag)) == -1) {
|
||||||
|
player.printError("Unknown flag: " + flag);
|
||||||
|
player.printError(getUsage(args, level, cmd));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
method.invoke(null, methodArgs);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
throw e.getCause();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks permissions, prints an error if needed.
|
||||||
|
*
|
||||||
|
* @param method
|
||||||
|
* @param player
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private abstract boolean checkPermissions(Method method, CommandsPlayer player) {
|
||||||
|
if (!method.isAnnotationPresent(CommandPermissions.class)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
CommandPermissions perms = method.getAnnotation(CommandPermissions.class);
|
||||||
|
|
||||||
|
for (String perm : perms.value()) {
|
||||||
|
if (player.hasPermission(perm)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
player.printError("You don't have permission for this command.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether a player has access to a command.
|
||||||
|
*
|
||||||
|
* @param method
|
||||||
|
* @param player
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private boolean hasPermission(Method method, CommandsPlayer player) {
|
||||||
|
CommandPermissions perms = method.getAnnotation(CommandPermissions.class);
|
||||||
|
if (perms == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String perm : perms.value()) {
|
||||||
|
if (player.hasPermission(perm)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
24
src/com/sk89q/util/commands/CommandsPlayer.java
Normale Datei
24
src/com/sk89q/util/commands/CommandsPlayer.java
Normale Datei
@ -0,0 +1,24 @@
|
|||||||
|
// $Id$
|
||||||
|
/*
|
||||||
|
* WorldEdit
|
||||||
|
* Copyright (C) 2010, 2011 sk89q <http://www.sk89q.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sk89q.util.commands;
|
||||||
|
|
||||||
|
public interface CommandsPlayer {
|
||||||
|
public void printError(String msg);
|
||||||
|
}
|
@ -20,6 +20,7 @@
|
|||||||
package com.sk89q.worldedit;
|
package com.sk89q.worldedit;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import com.sk89q.minecraft.util.commands.CommandsPlayer;
|
||||||
import com.sk89q.worldedit.bags.BlockBag;
|
import com.sk89q.worldedit.bags.BlockBag;
|
||||||
import com.sk89q.worldedit.blocks.BlockType;
|
import com.sk89q.worldedit.blocks.BlockType;
|
||||||
import com.sk89q.worldedit.util.TargetBlock;
|
import com.sk89q.worldedit.util.TargetBlock;
|
||||||
@ -28,7 +29,7 @@ import com.sk89q.worldedit.util.TargetBlock;
|
|||||||
*
|
*
|
||||||
* @author sk89q
|
* @author sk89q
|
||||||
*/
|
*/
|
||||||
public abstract class LocalPlayer {
|
public abstract class LocalPlayer implements CommandsPlayer {
|
||||||
/**
|
/**
|
||||||
* Server.
|
* Server.
|
||||||
*/
|
*/
|
||||||
|
@ -29,6 +29,8 @@ import java.util.logging.Level;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import javax.script.ScriptException;
|
import javax.script.ScriptException;
|
||||||
|
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||||
|
import com.sk89q.minecraft.util.commands.CommandsManager;
|
||||||
import com.sk89q.util.StringUtil;
|
import com.sk89q.util.StringUtil;
|
||||||
import com.sk89q.worldedit.LocalSession.CompassMode;
|
import com.sk89q.worldedit.LocalSession.CompassMode;
|
||||||
import com.sk89q.worldedit.bags.BlockBag;
|
import com.sk89q.worldedit.bags.BlockBag;
|
||||||
@ -840,8 +842,11 @@ public class WorldEdit {
|
|||||||
+ StringUtil.joinString(split, " "));
|
+ StringUtil.joinString(split, " "));
|
||||||
}
|
}
|
||||||
|
|
||||||
return commands.execute(split, this,
|
Object[] methodArgs = new Object[] {
|
||||||
session, player, editSession);
|
null, this, session, player, editSession
|
||||||
|
};
|
||||||
|
|
||||||
|
return commands.execute(split, player, methodArgs);
|
||||||
} finally {
|
} finally {
|
||||||
session.remember(editSession);
|
session.remember(editSession);
|
||||||
editSession.flushQueue();
|
editSession.flushQueue();
|
||||||
|
@ -19,8 +19,9 @@
|
|||||||
|
|
||||||
package com.sk89q.worldedit.commands;
|
package com.sk89q.worldedit.commands;
|
||||||
|
|
||||||
import com.sk89q.util.commands.Command;
|
import com.sk89q.minecraft.util.commands.Command;
|
||||||
import com.sk89q.util.commands.CommandContext;
|
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||||
|
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||||
import com.sk89q.worldedit.CuboidClipboard;
|
import com.sk89q.worldedit.CuboidClipboard;
|
||||||
import com.sk89q.worldedit.EditSession;
|
import com.sk89q.worldedit.EditSession;
|
||||||
import com.sk89q.worldedit.LocalConfiguration;
|
import com.sk89q.worldedit.LocalConfiguration;
|
||||||
|
@ -21,8 +21,9 @@ package com.sk89q.worldedit.commands;
|
|||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import com.sk89q.util.commands.Command;
|
import com.sk89q.minecraft.util.commands.Command;
|
||||||
import com.sk89q.util.commands.CommandContext;
|
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||||
|
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||||
import com.sk89q.worldedit.*;
|
import com.sk89q.worldedit.*;
|
||||||
import com.sk89q.worldedit.data.NestedFileChunkStore;
|
import com.sk89q.worldedit.data.NestedFileChunkStore;
|
||||||
|
|
||||||
|
@ -21,8 +21,9 @@ package com.sk89q.worldedit.commands;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import com.sk89q.util.commands.Command;
|
import com.sk89q.minecraft.util.commands.Command;
|
||||||
import com.sk89q.util.commands.CommandContext;
|
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||||
|
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||||
import com.sk89q.worldedit.*;
|
import com.sk89q.worldedit.*;
|
||||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||||
import com.sk89q.worldedit.data.DataException;
|
import com.sk89q.worldedit.data.DataException;
|
||||||
|
@ -19,8 +19,9 @@
|
|||||||
|
|
||||||
package com.sk89q.worldedit.commands;
|
package com.sk89q.worldedit.commands;
|
||||||
|
|
||||||
import com.sk89q.util.commands.Command;
|
import com.sk89q.minecraft.util.commands.Command;
|
||||||
import com.sk89q.util.commands.CommandContext;
|
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||||
|
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||||
import com.sk89q.worldedit.*;
|
import com.sk89q.worldedit.*;
|
||||||
import com.sk89q.worldedit.blocks.ItemType;
|
import com.sk89q.worldedit.blocks.ItemType;
|
||||||
|
|
||||||
|
@ -19,8 +19,9 @@
|
|||||||
|
|
||||||
package com.sk89q.worldedit.commands;
|
package com.sk89q.worldedit.commands;
|
||||||
|
|
||||||
import com.sk89q.util.commands.Command;
|
import com.sk89q.minecraft.util.commands.Command;
|
||||||
import com.sk89q.util.commands.CommandContext;
|
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||||
|
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||||
import com.sk89q.worldedit.*;
|
import com.sk89q.worldedit.*;
|
||||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||||
import com.sk89q.worldedit.util.TreeGenerator;
|
import com.sk89q.worldedit.util.TreeGenerator;
|
||||||
|
@ -19,8 +19,9 @@
|
|||||||
|
|
||||||
package com.sk89q.worldedit.commands;
|
package com.sk89q.worldedit.commands;
|
||||||
|
|
||||||
import com.sk89q.util.commands.Command;
|
import com.sk89q.minecraft.util.commands.Command;
|
||||||
import com.sk89q.util.commands.CommandContext;
|
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||||
|
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||||
import com.sk89q.worldedit.*;
|
import com.sk89q.worldedit.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -19,8 +19,9 @@
|
|||||||
|
|
||||||
package com.sk89q.worldedit.commands;
|
package com.sk89q.worldedit.commands;
|
||||||
|
|
||||||
import com.sk89q.util.commands.Command;
|
import com.sk89q.minecraft.util.commands.Command;
|
||||||
import com.sk89q.util.commands.CommandContext;
|
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||||
|
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||||
import com.sk89q.worldedit.*;
|
import com.sk89q.worldedit.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -20,8 +20,9 @@
|
|||||||
package com.sk89q.worldedit.commands;
|
package com.sk89q.worldedit.commands;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import com.sk89q.util.commands.Command;
|
import com.sk89q.minecraft.util.commands.Command;
|
||||||
import com.sk89q.util.commands.CommandContext;
|
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||||
|
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||||
import com.sk89q.worldedit.*;
|
import com.sk89q.worldedit.*;
|
||||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||||
import com.sk89q.worldedit.filters.GaussianKernel;
|
import com.sk89q.worldedit.filters.GaussianKernel;
|
||||||
|
@ -20,8 +20,9 @@
|
|||||||
package com.sk89q.worldedit.commands;
|
package com.sk89q.worldedit.commands;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import com.sk89q.util.commands.Command;
|
import com.sk89q.minecraft.util.commands.Command;
|
||||||
import com.sk89q.util.commands.CommandContext;
|
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||||
|
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||||
import com.sk89q.worldedit.*;
|
import com.sk89q.worldedit.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -21,8 +21,9 @@ package com.sk89q.worldedit.commands;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import com.sk89q.util.commands.Command;
|
import com.sk89q.minecraft.util.commands.Command;
|
||||||
import com.sk89q.util.commands.CommandContext;
|
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||||
|
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||||
import com.sk89q.worldedit.*;
|
import com.sk89q.worldedit.*;
|
||||||
import com.sk89q.worldedit.data.ChunkStore;
|
import com.sk89q.worldedit.data.ChunkStore;
|
||||||
import com.sk89q.worldedit.regions.Region;
|
import com.sk89q.worldedit.regions.Region;
|
||||||
|
@ -22,8 +22,9 @@ package com.sk89q.worldedit.commands;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import com.sk89q.util.commands.Command;
|
import com.sk89q.minecraft.util.commands.Command;
|
||||||
import com.sk89q.util.commands.CommandContext;
|
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||||
|
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||||
import com.sk89q.worldedit.*;
|
import com.sk89q.worldedit.*;
|
||||||
import com.sk89q.worldedit.data.ChunkStore;
|
import com.sk89q.worldedit.data.ChunkStore;
|
||||||
import com.sk89q.worldedit.data.DataException;
|
import com.sk89q.worldedit.data.DataException;
|
||||||
|
@ -19,8 +19,10 @@
|
|||||||
|
|
||||||
package com.sk89q.worldedit.commands;
|
package com.sk89q.worldedit.commands;
|
||||||
|
|
||||||
import com.sk89q.util.commands.Command;
|
import com.sk89q.minecraft.util.commands.Command;
|
||||||
import com.sk89q.util.commands.CommandContext;
|
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||||
|
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||||
|
import com.sk89q.minecraft.util.commands.NestedCommand;
|
||||||
import com.sk89q.worldedit.*;
|
import com.sk89q.worldedit.*;
|
||||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||||
import com.sk89q.worldedit.superpickaxe.*;
|
import com.sk89q.worldedit.superpickaxe.*;
|
||||||
|
@ -20,8 +20,9 @@
|
|||||||
package com.sk89q.worldedit.commands;
|
package com.sk89q.worldedit.commands;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import com.sk89q.util.commands.Command;
|
import com.sk89q.minecraft.util.commands.Command;
|
||||||
import com.sk89q.util.commands.CommandContext;
|
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||||
|
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||||
import com.sk89q.worldedit.*;
|
import com.sk89q.worldedit.*;
|
||||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||||
import com.sk89q.worldedit.patterns.*;
|
import com.sk89q.worldedit.patterns.*;
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.sk89q.worldedit.commands;
|
package com.sk89q.util.commands;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
@ -27,13 +27,13 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import com.sk89q.util.StringUtil;
|
import com.sk89q.util.StringUtil;
|
||||||
import com.sk89q.util.commands.Command;
|
import com.sk89q.util.commands.Command;
|
||||||
import com.sk89q.util.commands.CommandContext;
|
|
||||||
import com.sk89q.util.commands.NestedCommand;
|
import com.sk89q.util.commands.NestedCommand;
|
||||||
import com.sk89q.worldedit.EditSession;
|
import com.sk89q.worldedit.EditSession;
|
||||||
import com.sk89q.worldedit.LocalPlayer;
|
import com.sk89q.worldedit.LocalPlayer;
|
||||||
import com.sk89q.worldedit.LocalSession;
|
import com.sk89q.worldedit.LocalSession;
|
||||||
import com.sk89q.worldedit.WorldEdit;
|
import com.sk89q.worldedit.WorldEdit;
|
||||||
import com.sk89q.worldedit.WorldEditException;
|
import com.sk89q.worldedit.WorldEditException;
|
||||||
|
import com.sk89q.worldedit.commands.CommandPermissions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manager for handling commands.
|
* Manager for handling commands.
|
@ -23,9 +23,9 @@ import java.io.*;
|
|||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import com.sk89q.minecraft.util.commands.Command;
|
||||||
|
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||||
import com.sk89q.util.StringUtil;
|
import com.sk89q.util.StringUtil;
|
||||||
import com.sk89q.util.commands.Command;
|
|
||||||
import com.sk89q.worldedit.commands.CommandPermissions;
|
|
||||||
|
|
||||||
public class DocumentationPrinter {
|
public class DocumentationPrinter {
|
||||||
public static void main(String[] args) throws IOException {
|
public static void main(String[] args) throws IOException {
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren