SteamWar/SpigotCore
Archiviert
13
0
Add SWCommandUtils
Add InternalCommand
Add InternalTabComplete
Dieser Commit ist enthalten in:
yoyosource 2021-03-12 14:14:58 +01:00
Ursprung 49831d498d
Commit 43a9de08a0
4 geänderte Dateien mit 339 neuen und 0 gelöschten Zeilen

Datei anzeigen

@ -0,0 +1,54 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2020 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.command;
import org.bukkit.command.CommandSender;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
class InternalCommand {
private SWCommand swCommand;
private Method method;
private Parameter[] parameters;
InternalCommand(SWCommand swCommand, Method method) {
this.swCommand = swCommand;
this.method = method;
parameters = method.getParameters();
}
boolean invoke(CommandSender commandSender, String[] args) {
if (args.length < parameters.length - 1) return false;
Object[] objects = SWCommandUtils.generateArgumentArray(commandSender, parameters, args);
try {
method.setAccessible(true);
method.invoke(swCommand, objects);
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new SecurityException(e.getMessage(), e);
} catch (InvocationTargetException e) {
return false;
}
return true;
}
}

Datei anzeigen

@ -0,0 +1,53 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2020 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.command;
import org.bukkit.command.CommandSender;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
class InternalTabComplete {
private SWCommand swCommand;
private Method method;
private Parameter[] parameters;
InternalTabComplete(SWCommand swCommand, Method method) {
this.swCommand = swCommand;
this.method = method;
parameters = method.getParameters();
}
SWCommandUtils.TabComplete invoke(CommandSender commandSender, String[] args) {
if (args.length < parameters.length - 1) return null;
Object[] objects = SWCommandUtils.generateArgumentArray(commandSender, parameters, args);
try {
method.setAccessible(true);
return (SWCommandUtils.TabComplete) method.invoke(swCommand, objects);
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new SecurityException(e.getMessage(), e);
} catch (InvocationTargetException e) {
return null;
}
}
}

Datei anzeigen

@ -0,0 +1,102 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2020 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.command;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.*;
import java.util.function.Consumer;
public abstract class SWCommand {
private final Set<InternalCommand> commandSet = new HashSet<>();
private final Set<InternalTabComplete> tabCompleteSet = new HashSet<>();
private Consumer<CommandSender> helpMessage = sender -> {};
protected SWCommand(String command, String... aliases) {
SWCommandUtils.commandMap.register("steamwar", new Command(command, "", "/" + command, Arrays.asList(aliases)) {
@Override
public boolean execute(CommandSender sender, String alias, String[] args) {
for (InternalCommand internalCommand : commandSet) {
if (internalCommand.invoke(sender, args)) {
return false;
}
}
return false;
}
@Override
public List<String> tabComplete(CommandSender sender, String alias, String[] args) throws IllegalArgumentException {
List<String> strings = new ArrayList<>();
for (InternalTabComplete internalTabComplete : tabCompleteSet) {
SWCommandUtils.TabComplete tabComplete = internalTabComplete.invoke(sender, args);
if (tabComplete != null) {
strings.addAll(tabComplete.tabCompletes);
}
}
return strings;
}
});
}
protected final void register(String methodName) {
if (methodName.equals("onCommand")) return;
if (methodName.equals("onTabComplete")) return;
Method[] methods = this.getClass().getDeclaredMethods();
for (Method method : methods) {
if (!validMethod(method)) continue;
if (method.getReturnType() == Void.TYPE) {
commandSet.add(new InternalCommand(this, method));
}
if (method.getReturnType() == SWCommandUtils.TabComplete.class) {
tabCompleteSet.add(new InternalTabComplete(this, method));
}
}
}
private boolean validMethod(Method method) {
Parameter[] parameters = method.getParameters();
if (parameters.length == 0) return false;
if (!CommandSender.class.isAssignableFrom(parameters[0].getType())) return false;
for (int i = 1; i < parameters.length; i++) {
Parameter parameter = parameters[i];
Class<?> clazz = parameter.getType();
if (parameter.isVarArgs() && i == parameters.length - 1) {
clazz = parameter.getType().getComponentType();
}
if (clazz.isEnum()) continue;
if (!SWCommandUtils.MAPPER_FUNCTIONS.containsKey(clazz)) return false;
}
return true;
}
protected final void setHelpMessage(Consumer<CommandSender> helpMessage) {
assert helpMessage != null;
this.helpMessage = helpMessage;
}
protected final <T extends CommandSender> void sendHelpMessage(T sender) {
helpMessage.accept(sender);
}
}

Datei anzeigen

@ -0,0 +1,130 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2020 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.command;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandMap;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.lang.reflect.Field;
import java.lang.reflect.Parameter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.function.BiFunction;
import java.util.function.Function;
class SWCommandUtils {
private SWCommandUtils() {
throw new IllegalStateException("Utility Class");
}
static final Map<Class<?>, Function<String, ?>> MAPPER_FUNCTIONS = new HashMap<>();
static final Function<String, ?> ERROR_FUNCTION = s -> {
throw new SecurityException(s);
};
static final BiFunction<Class<Enum<?>>, String, Enum<?>> ENUM_MAPPER = (enumClass, s) -> {
Enum<?>[] enums = enumClass.getEnumConstants();
for (Enum<?> e : enums) {
if (e.name().equals(s)) return e;
}
return null;
};
static {
MAPPER_FUNCTIONS.put(boolean.class, Boolean::parseBoolean);
MAPPER_FUNCTIONS.put(Boolean.class, Boolean::parseBoolean);
MAPPER_FUNCTIONS.put(float.class, Float::parseFloat);
MAPPER_FUNCTIONS.put(Float.class, Float::parseFloat);
MAPPER_FUNCTIONS.put(double.class, Double::parseDouble);
MAPPER_FUNCTIONS.put(Double.class, Double::parseDouble);
MAPPER_FUNCTIONS.put(int.class, Integer::parseInt);
MAPPER_FUNCTIONS.put(Integer.class, Integer::parseInt);
MAPPER_FUNCTIONS.put(String.class, s -> s);
MAPPER_FUNCTIONS.put(StringBuilder.class, StringBuilder::new);
MAPPER_FUNCTIONS.put(Player.class, Bukkit::getPlayer);
MAPPER_FUNCTIONS.put(UUID.class, UUID::fromString);
}
static final CommandMap commandMap;
static {
try {
final Field commandMapField = Bukkit.getServer().getClass().getDeclaredField("commandMap");
commandMapField.setAccessible(true);
commandMap = (CommandMap) commandMapField.get(Bukkit.getServer());
} catch (NoSuchFieldException | IllegalAccessException exception) {
Bukkit.shutdown();
throw new SecurityException("Oh shit. Commands cannot be register.", exception);
}
}
public static Object[] generateArgumentArray(CommandSender commandSender, Parameter[] parameters, String[] args) {
Object[] arguments = new Object[args.length + 1];
boolean varArgs = false;
if (parameters[parameters.length - 1].isVarArgs()) {
varArgs = true;
arguments = new Object[parameters.length];
}
arguments[0] = parameters[0].getType().cast(commandSender);
for (int i = 1; i < parameters.length - (varArgs ? 1 : 0); i++) {
Class<?> clazz = parameters[i].getType();
arguments[i] = mapper(clazz).apply(args[i - 1]);
}
if (varArgs) {
Object[] varArgument = new Object[args.length - parameters.length + 2];
arguments[arguments.length - 1] = varArgument;
Function<String, Object> mapper = mapper(parameters[parameters.length - 1].getType().getComponentType());
int index = 0;
for (int i = parameters.length - 2; i < args.length; i++) {
varArgument[index++] = mapper.apply(args[i]);
}
}
return arguments;
}
@SuppressWarnings("unchecked")
private static Function<String, Object> mapper(Class<?> clazz) {
if (clazz.isEnum()) {
Class<Enum<?>> enumClass = (Class<Enum<?>>) clazz;
return s -> ENUM_MAPPER.apply(enumClass, s);
} else {
return s -> MAPPER_FUNCTIONS.getOrDefault(clazz, ERROR_FUNCTION).apply(s);
}
}
public static class TabComplete {
final List<String> tabCompletes;
public TabComplete(List<String> tabCompletes) {
this.tabCompletes = tabCompletes;
}
}
}