diff --git a/SpigotCore_Main/src/de/steamwar/command/CommandParseException.java b/SpigotCore_Main/src/de/steamwar/command/CommandParseException.java
new file mode 100644
index 0000000..b47cace
--- /dev/null
+++ b/SpigotCore_Main/src/de/steamwar/command/CommandParseException.java
@@ -0,0 +1,42 @@
+/*
+ * 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 .
+ */
+
+package de.steamwar.command;
+
+public class CommandParseException extends Exception {
+
+ public CommandParseException() {
+ }
+
+ public CommandParseException(String message) {
+ super(message);
+ }
+
+ public CommandParseException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public CommandParseException(Throwable cause) {
+ super(cause);
+ }
+
+ public CommandParseException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
+ super(message, cause, enableSuppression, writableStackTrace);
+ }
+}
diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java
new file mode 100644
index 0000000..72cda65
--- /dev/null
+++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java
@@ -0,0 +1,224 @@
+/*
+ * 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 .
+ */
+
+package de.steamwar.command;
+
+import org.bukkit.Bukkit;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+
+import java.lang.annotation.*;
+import java.lang.reflect.Method;
+import java.lang.reflect.Parameter;
+import java.util.*;
+import java.util.function.BiConsumer;
+import java.util.function.IntPredicate;
+import java.util.logging.Level;
+
+public abstract class SWCommand {
+
+ private final Command command;
+ private final List commandSet = new ArrayList<>();
+ private final List commandHelpSet = new ArrayList<>();
+ private final Map> localTypeMapper = new HashMap<>();
+
+ protected SWCommand(String command) {
+ this(command, new String[0]);
+ }
+
+ protected SWCommand(String command, String... aliases) {
+ this.command = new Command(command, "", "/" + command, Arrays.asList(aliases)) {
+ @Override
+ public boolean execute(CommandSender sender, String alias, String[] args) {
+ for (SubCommand subCommand : commandSet) {
+ if (subCommand.invoke(sender, args)) {
+ return false;
+ }
+ }
+ for (SubCommand subCommand : commandHelpSet) {
+ if (subCommand.invoke(sender, args)) {
+ return false;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public List tabComplete(CommandSender sender, String alias, String[] args) throws IllegalArgumentException {
+ List strings = new ArrayList<>();
+ for (SubCommand subCommand : commandSet) {
+ List tabCompletes = subCommand.tabComplete(sender, args);
+ if (tabCompletes != null) {
+ strings.addAll(tabCompletes);
+ }
+ }
+ strings = new ArrayList<>(strings);
+ for (int i = strings.size() - 1; i >= 0; i--) {
+ if (!strings.get(i).toLowerCase().startsWith(args[args.length - 1].toLowerCase())) {
+ strings.remove(i);
+ }
+ }
+ return strings;
+ }
+ };
+ register();
+
+ for (Method method : getClass().getDeclaredMethods()) {
+ addMapper(Mapper.class, method, i -> i == 0, false, TypeMapper.class, (anno, typeMapper) -> {
+ if (anno.local()) {
+ localTypeMapper.put(anno.value(), typeMapper);
+ } else {
+ SWCommandUtils.addMapper(anno.value(), typeMapper);
+ }
+ });
+ addMapper(ClassMapper.class, method, i -> i == 0, false, TypeMapper.class, (anno, typeMapper) -> {
+ if (anno.local()) {
+ localTypeMapper.put(anno.value().getTypeName(), typeMapper);
+ } else {
+ SWCommandUtils.addMapper(anno.value().getTypeName(), typeMapper);
+ }
+ });
+ add(Register.class, method, i -> i > 0, true, null, (anno, parameters) -> {
+ if (!anno.help()) {
+ return;
+ }
+ if (parameters.length != 2) {
+ Bukkit.getLogger().log(Level.WARNING, "The method '" + method.toString() + "' is lacking parameters or has too many");
+ }
+ if (!parameters[parameters.length - 1].isVarArgs()) {
+ Bukkit.getLogger().log(Level.WARNING, "The method '" + method.toString() + "' is lacking the varArgs parameters as last Argument");
+ }
+ if (parameters[parameters.length - 1].getType().getComponentType() != String.class) {
+ Bukkit.getLogger().log(Level.WARNING, "The method '" + method.toString() + "' is lacking the varArgs parameters of type '" + String.class.getTypeName() + "' as last Argument");
+ return;
+ }
+ commandHelpSet.add(new SubCommand(this, method, anno.value()));
+ });
+ }
+ for (Method method : getClass().getDeclaredMethods()) {
+ add(Register.class, method, i -> i > 0, true, null, (anno, parameters) -> {
+ if (anno.help()) {
+ return;
+ }
+ 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();
+ }
+ Mapper mapper = parameter.getAnnotation(Mapper.class);
+ if (clazz.isEnum() && mapper == null && !SWCommandUtils.MAPPER_FUNCTIONS.containsKey(clazz.getTypeName())) {
+ continue;
+ }
+ String name = clazz.getTypeName();
+ if (mapper != null) {
+ name = mapper.value();
+ }
+ if (!SWCommandUtils.MAPPER_FUNCTIONS.containsKey(name) && !localTypeMapper.containsKey(name)) {
+ Bukkit.getLogger().log(Level.WARNING, "The parameter '" + parameter.toString() + "' is using an unsupported Mapper of type '" + name + "'");
+ return;
+ }
+ }
+ commandSet.add(new SubCommand(this, method, anno.value(), localTypeMapper));
+ });
+
+ this.commandSet.sort((o1, o2) -> {
+ int compare = Integer.compare(-o1.subCommand.length, -o2.subCommand.length);
+ if (compare != 0) {
+ return compare;
+ } else {
+ int i1 = o1.varArgType != null ? Integer.MAX_VALUE : o1.arguments.length;
+ int i2 = o2.varArgType != null ? Integer.MAX_VALUE : o2.arguments.length;
+ return Integer.compare(i1, i2);
+ }
+ });
+ commandHelpSet.sort(Comparator.comparingInt(o -> -o.subCommand.length));
+ }
+ }
+
+ private void add(Class annotation, Method method, IntPredicate parameterTester, boolean firstParameter, Class> returnType, BiConsumer consumer) {
+ T anno = SWCommandUtils.getAnnotation(method, annotation);
+ if (anno == null) {
+ return;
+ }
+
+ Parameter[] parameters = method.getParameters();
+ if (!parameterTester.test(parameters.length)) {
+ Bukkit.getLogger().log(Level.WARNING, "The method '" + method.toString() + "' is lacking parameters or has too many");
+ return;
+ }
+ if (firstParameter && !CommandSender.class.isAssignableFrom(parameters[0].getType())) {
+ Bukkit.getLogger().log(Level.WARNING, "The method '" + method.toString() + "' is lacking the first parameter of type '" + CommandSender.class.getTypeName() + "'");
+ return;
+ }
+ if (returnType != null && method.getReturnType() != returnType) {
+ Bukkit.getLogger().log(Level.WARNING, "The method '" + method.toString() + "' is lacking the desired return type '" + returnType.getTypeName() + "'");
+ return;
+ }
+ consumer.accept(anno, parameters);
+ }
+
+ private void addMapper(Class annotation, Method method, IntPredicate parameterTester, boolean firstParameter, Class> returnType, BiConsumer> consumer) {
+ add(annotation, method, parameterTester, firstParameter, returnType, (anno, parameters) -> {
+ try {
+ method.setAccessible(true);
+ Object object = method.invoke(this);
+ consumer.accept(anno, (TypeMapper>) object);
+ } catch (Exception e) {
+ throw new SecurityException(e.getMessage(), e);
+ }
+ });
+ }
+
+ protected void unregister() {
+ SWCommandUtils.knownCommandMap.remove(command.getName());
+ for (String alias : command.getAliases()) {
+ SWCommandUtils.knownCommandMap.remove(alias);
+ }
+ command.unregister(SWCommandUtils.commandMap);
+ }
+
+ protected void register() {
+ SWCommandUtils.commandMap.register("steamwar", this.command);
+ }
+
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target({ElementType.METHOD})
+ protected @interface Register {
+ String[] value() default {};
+
+ boolean help() default false;
+ }
+
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target({ElementType.PARAMETER, ElementType.METHOD})
+ protected @interface Mapper {
+ String value();
+
+ boolean local() default false;
+ }
+
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target({ElementType.METHOD})
+ protected @interface ClassMapper {
+ Class> value();
+
+ boolean local() default false;
+ }
+}
diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java
new file mode 100644
index 0000000..da927ad
--- /dev/null
+++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java
@@ -0,0 +1,195 @@
+/*
+ * 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 .
+ */
+
+package de.steamwar.command;
+
+import org.bukkit.Bukkit;
+import org.bukkit.GameMode;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandMap;
+import org.bukkit.command.CommandSender;
+import org.bukkit.command.SimpleCommandMap;
+import org.bukkit.entity.Player;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.*;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+public class SWCommandUtils {
+
+ private SWCommandUtils() {
+ throw new IllegalStateException("Utility Class");
+ }
+
+ static final Map> MAPPER_FUNCTIONS = new HashMap<>();
+
+ static final TypeMapper> ERROR_FUNCTION = createMapper(s -> {
+ throw new SecurityException();
+ }, s -> Collections.emptyList());
+
+ static final BiFunction>, String, Enum>> ENUM_MAPPER = (enumClass, s) -> {
+ Enum>[] enums = enumClass.getEnumConstants();
+ for (Enum> e : enums) {
+ if (e.name().equalsIgnoreCase(s)) return e;
+ }
+ return null;
+ };
+
+ static {
+ addMapper(boolean.class, Boolean.class, createMapper(Boolean::parseBoolean, s -> Arrays.asList("true", "false")));
+ addMapper(float.class, Float.class, createMapper(numberMapper(Float::parseFloat), numberCompleter(Float::parseFloat)));
+ addMapper(double.class, Double.class, createMapper(numberMapper(Double::parseDouble), numberCompleter(Double::parseDouble)));
+ addMapper(int.class, Integer.class, createMapper(numberMapper(Integer::parseInt), numberCompleter(Integer::parseInt)));
+ MAPPER_FUNCTIONS.put(String.class.getTypeName(), createMapper(s -> s, Collections::singletonList));
+ MAPPER_FUNCTIONS.put(Player.class.getTypeName(), createMapper(Bukkit::getPlayer, s -> Bukkit.getOnlinePlayers().stream().map(Player::getName).collect(Collectors.toList())));
+ MAPPER_FUNCTIONS.put(GameMode.class.getTypeName(), createMapper(s -> {
+ s = s.toLowerCase();
+ if (s.equals("s") || s.equals("survival") || s.equals("0")) return GameMode.SURVIVAL;
+ if (s.equals("c") || s.equals("creative") || s.equals("1")) return GameMode.CREATIVE;
+ if (s.equals("sp") || s.equals("spectator") || s.equals("3")) return GameMode.SPECTATOR;
+ if (s.equals("a") || s.equals("adventure") || s.equals("2")) return GameMode.ADVENTURE;
+ return null;
+ }, s -> Arrays.asList("s", "survival", "0", "c", "creative", "1", "sp", "spectator", "3", "a", "adventure", "2")));
+ }
+
+ private static void addMapper(Class> clazz, Class> alternativeClazz, TypeMapper> mapper) {
+ MAPPER_FUNCTIONS.put(clazz.getTypeName(), mapper);
+ MAPPER_FUNCTIONS.put(alternativeClazz.getTypeName(), mapper);
+ }
+
+ static final CommandMap commandMap;
+ static final Map knownCommandMap;
+
+ 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 registered.", exception);
+ }
+ try {
+ final Field knownCommandsField = SimpleCommandMap.class.getDeclaredField("knownCommands");
+ knownCommandsField.setAccessible(true);
+ knownCommandMap = (Map) knownCommandsField.get(commandMap);
+ } catch (NoSuchFieldException | IllegalAccessException exception) {
+ Bukkit.shutdown();
+ throw new SecurityException("Oh shit. Commands cannot be registered.", exception);
+ }
+ }
+
+ static Object[] generateArgumentArray(TypeMapper>[] parameters, String[] args, Class> varArgType, String[] subCommand) throws CommandParseException {
+ Object[] arguments = new Object[parameters.length + 1];
+ int index = 0;
+ while (index < subCommand.length) {
+ if (!args[index].equalsIgnoreCase(subCommand[index])) {
+ throw new CommandParseException();
+ }
+ index++;
+ }
+
+ if (varArgType != null && index > args.length - 1) {
+ Object varArgument = Array.newInstance(varArgType, 0);
+ arguments[arguments.length - 1] = varArgument;
+ } else {
+ for (int i = 0; i < parameters.length - (varArgType != null ? 1 : 0); i++) {
+ arguments[i + 1] = parameters[i].map(Arrays.copyOf(args, index), args[index]);
+ index++;
+ if (arguments[i + 1] == null) {
+ throw new CommandParseException();
+ }
+ }
+
+ if (varArgType != null) {
+ int length = args.length - parameters.length - subCommand.length + 1;
+ Object varArgument = Array.newInstance(varArgType, length);
+ arguments[arguments.length - 1] = varArgument;
+
+ for (int i = 0; i < length; i++) {
+ Object value = parameters[parameters.length - 1].map(Arrays.copyOf(args, index), args[index]);
+ if (value == null) {
+ throw new CommandParseException();
+ }
+ Array.set(varArgument, i, value);
+ index++;
+ }
+ }
+ }
+ return arguments;
+ }
+
+ public static void addMapper(Class clazz, TypeMapper mapper) {
+ addMapper(clazz.getTypeName(), mapper);
+ }
+
+ public static void addMapper(String name, TypeMapper> mapper) {
+ if (MAPPER_FUNCTIONS.containsKey(name)) return;
+ MAPPER_FUNCTIONS.put(name, mapper);
+ }
+
+ public static TypeMapper createMapper(Function mapper, Function> tabCompleter) {
+ return createMapper(mapper, (commandSender, s) -> tabCompleter.apply(s));
+ }
+
+ public static TypeMapper createMapper(Function mapper, BiFunction> tabCompleter) {
+ return new TypeMapper() {
+ @Override
+ public T map(String[] previous, String s) {
+ return mapper.apply(s);
+ }
+
+ @Override
+ public List tabCompletes(CommandSender commandSender, String[] previous, String s) {
+ return tabCompleter.apply(commandSender, s);
+ }
+ };
+ }
+
+ private static Function numberMapper(Function mapper) {
+ return s -> {
+ try {
+ return mapper.apply(s);
+ } catch (NumberFormatException e) {
+ return null;
+ }
+ };
+ }
+
+ private static Function> numberCompleter(Function mapper) {
+ return s -> {
+ try {
+ mapper.apply(s);
+ return Collections.singletonList(s);
+ } catch (Exception e) {
+ return Collections.emptyList();
+ }
+ };
+ }
+
+ static T getAnnotation(Method method, Class annotation) {
+ if (method.getAnnotations().length != 1) return null;
+ return method.getAnnotation(annotation);
+ }
+}
diff --git a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java
new file mode 100644
index 0000000..343cbd0
--- /dev/null
+++ b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java
@@ -0,0 +1,143 @@
+/*
+ * 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 .
+ */
+
+package de.steamwar.command;
+
+import org.bukkit.command.CommandSender;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Parameter;
+import java.util.*;
+import java.util.function.Function;
+
+class SubCommand {
+
+ private SWCommand swCommand;
+ private Method method;
+ String[] subCommand;
+ TypeMapper>[] arguments;
+ private Function commandSenderFunction;
+ Class> varArgType = null;
+
+ public SubCommand(SWCommand swCommand, Method method, String[] subCommand) {
+ this(swCommand, method, subCommand, new HashMap<>());
+ }
+
+ public SubCommand(SWCommand swCommand, Method method, String[] subCommand, Map> localTypeMapper) {
+ this.swCommand = swCommand;
+ this.method = method;
+
+ Parameter[] parameters = method.getParameters();
+ commandSenderFunction = sender -> parameters[0].getType().cast(sender);
+ this.subCommand = subCommand;
+
+ arguments = new TypeMapper[parameters.length - 1];
+ for (int i = 1; i < parameters.length; i++) {
+ Parameter parameter = parameters[i];
+ Class> clazz = parameter.getType();
+ if (parameter.isVarArgs()) {
+ clazz = clazz.getComponentType();
+ varArgType = clazz;
+ }
+
+ SWCommand.Mapper mapper = parameter.getAnnotation(SWCommand.Mapper.class);
+ if (clazz.isEnum() && mapper == null && !SWCommandUtils.MAPPER_FUNCTIONS.containsKey(clazz.getTypeName()) && !localTypeMapper.containsKey(clazz.getTypeName())) {
+ Class> enumClass = (Class>) clazz;
+ List tabCompletes = new ArrayList<>();
+ for (Enum> enumConstant : enumClass.getEnumConstants()) {
+ tabCompletes.add(enumConstant.name().toLowerCase());
+ }
+ arguments[i - 1] = SWCommandUtils.createMapper(s -> SWCommandUtils.ENUM_MAPPER.apply(enumClass, s), s -> tabCompletes);
+ continue;
+ }
+
+ String name = clazz.getTypeName();
+ if (mapper != null) {
+ name = mapper.value();
+ }
+ if (localTypeMapper.containsKey(name)) {
+ arguments[i - 1] = localTypeMapper.getOrDefault(name, SWCommandUtils.ERROR_FUNCTION);
+ } else {
+ arguments[i - 1] = SWCommandUtils.MAPPER_FUNCTIONS.getOrDefault(name, SWCommandUtils.ERROR_FUNCTION);
+ }
+ }
+ }
+
+ boolean invoke(CommandSender commandSender, String[] args) {
+ if (args.length < arguments.length + subCommand.length - (varArgType != null ? 1 : 0)) {
+ return false;
+ }
+ if (varArgType == null && args.length > arguments.length + subCommand.length) {
+ return false;
+ }
+ try {
+ Object[] objects = SWCommandUtils.generateArgumentArray(arguments, args, varArgType, subCommand);
+ objects[0] = commandSenderFunction.apply(commandSender);
+ method.setAccessible(true);
+ method.invoke(swCommand, objects);
+ } catch (IllegalAccessException | RuntimeException | InvocationTargetException e) {
+ throw new SecurityException(e.getMessage(), e);
+ } catch (CommandParseException e) {
+ return false;
+ }
+ return true;
+ }
+
+ List tabComplete(CommandSender commandSender, String[] args) {
+ if (varArgType == null && args.length > arguments.length + subCommand.length) {
+ return null;
+ }
+ int index = 0;
+ List argsList = new LinkedList<>(Arrays.asList(args));
+ for (String value : subCommand) {
+ String s = argsList.remove(0);
+ if (argsList.isEmpty()) return Collections.singletonList(value);
+ if (!value.equalsIgnoreCase(s)) return null;
+ index++;
+ }
+ for (TypeMapper> argument : arguments) {
+ String s = argsList.remove(0);
+ if (argsList.isEmpty()) return argument.tabCompletes(commandSender, Arrays.copyOf(args, args.length - 1), s);
+ try {
+ if (argument.map(Arrays.copyOf(args, index), s) == null) {
+ return null;
+ }
+ } catch (Exception e) {
+ return null;
+ }
+ index++;
+ }
+ if (varArgType != null && !argsList.isEmpty()) {
+ while (!argsList.isEmpty()) {
+ String s = argsList.remove(0);
+ if (argsList.isEmpty()) return arguments[arguments.length - 1].tabCompletes(commandSender, Arrays.copyOf(args, args.length - 1), s);
+ try {
+ if (arguments[arguments.length - 1].map(Arrays.copyOf(args, index), s) == null) {
+ return null;
+ }
+ } catch (Exception e) {
+ return null;
+ }
+ index++;
+ }
+ }
+ return null;
+ }
+}
diff --git a/SpigotCore_Main/src/de/steamwar/command/TypeMapper.java b/SpigotCore_Main/src/de/steamwar/command/TypeMapper.java
new file mode 100644
index 0000000..27b04f7
--- /dev/null
+++ b/SpigotCore_Main/src/de/steamwar/command/TypeMapper.java
@@ -0,0 +1,30 @@
+/*
+ * 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 .
+ */
+
+package de.steamwar.command;
+
+import org.bukkit.command.CommandSender;
+
+import java.util.List;
+
+public interface TypeMapper {
+ T map(String[] previousArguments, String s);
+
+ List tabCompletes(CommandSender commandSender, String[] previousArguments, String s);
+}
diff --git a/SpigotCore_Main/src/de/steamwar/comms/PacketIdManager.java b/SpigotCore_Main/src/de/steamwar/comms/PacketIdManager.java
index 2407d6a..97a7d9b 100644
--- a/SpigotCore_Main/src/de/steamwar/comms/PacketIdManager.java
+++ b/SpigotCore_Main/src/de/steamwar/comms/PacketIdManager.java
@@ -24,6 +24,7 @@ public class PacketIdManager {
//0x0(X) Standalone Packets
public final static byte PING_PACKET = 0x01;
public final static byte TABLIST_NAME = 0x02;
+ public static final byte PREPARE_SCHEM = 0x03;
//0x1(X) Bungee Inventory
public final static byte INVENTORY_PACKET = 0x10;
public final static byte INVENTORY_CALLBACK_PACKET = 0x11;
diff --git a/SpigotCore_Main/src/de/steamwar/comms/packets/PrepareSchemPacket.java b/SpigotCore_Main/src/de/steamwar/comms/packets/PrepareSchemPacket.java
new file mode 100644
index 0000000..99f2ecc
--- /dev/null
+++ b/SpigotCore_Main/src/de/steamwar/comms/packets/PrepareSchemPacket.java
@@ -0,0 +1,51 @@
+/*
+ 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 .
+*/
+
+package de.steamwar.comms.packets;
+
+import com.google.common.io.ByteArrayDataOutput;
+import de.steamwar.comms.PacketIdManager;
+import de.steamwar.sql.Schematic;
+import de.steamwar.sql.SchematicType;
+import de.steamwar.sql.SteamwarUser;
+
+public class PrepareSchemPacket extends SpigotPacket{
+
+ private final SteamwarUser user;
+ private final Schematic schematic;
+ private final SchematicType schematicType;
+
+ public PrepareSchemPacket(SteamwarUser user, Schematic schematic, SchematicType schematicType){
+ this.user = user;
+ this.schematic = schematic;
+ this.schematicType = schematicType;
+ }
+
+ @Override
+ public int getName() {
+ return PacketIdManager.PREPARE_SCHEM;
+ }
+
+ @Override
+ public void writeVars(ByteArrayDataOutput byteArrayDataOutput) {
+ byteArrayDataOutput.writeInt(user.getId());
+ byteArrayDataOutput.writeInt(schematic.getSchemID());
+ byteArrayDataOutput.writeUTF(schematicType.toDB());
+ }
+}
diff --git a/SpigotCore_Main/src/de/steamwar/sql/BauweltMember.java b/SpigotCore_Main/src/de/steamwar/sql/BauweltMember.java
index 9c1734d..4e0ed39 100644
--- a/SpigotCore_Main/src/de/steamwar/sql/BauweltMember.java
+++ b/SpigotCore_Main/src/de/steamwar/sql/BauweltMember.java
@@ -29,16 +29,14 @@ import java.util.UUID;
public class BauweltMember{
private final int bauweltID;
private final int memberID;
- private boolean build;
private boolean worldEdit;
private boolean world;
private static final List members = new ArrayList<>();
- private BauweltMember(int ownerID, int memberID, boolean build, boolean worldEdit, boolean world, boolean updateDB){
+ private BauweltMember(int ownerID, int memberID, boolean worldEdit, boolean world, boolean updateDB){
bauweltID = ownerID;
this.memberID = memberID;
- this.build = build;
this.worldEdit = worldEdit;
this.world = world;
if(updateDB)
@@ -46,12 +44,12 @@ public class BauweltMember{
members.add(this);
}
- public BauweltMember(int ownerID, int memberID, boolean build, boolean worldEdit, boolean world){
- this(ownerID, memberID, build, worldEdit, world, true);
+ public BauweltMember(int ownerID, int memberID, boolean worldEdit, boolean world){
+ this(ownerID, memberID, worldEdit, world, true);
}
- public BauweltMember(UUID ownerID, UUID memberID, boolean build, boolean worldEdit, boolean world){
- this(SteamwarUser.get(ownerID).getId(), SteamwarUser.get(memberID).getId(), build, worldEdit, world, true);
+ public BauweltMember(UUID ownerID, UUID memberID, boolean worldEdit, boolean world){
+ this(SteamwarUser.get(ownerID).getId(), SteamwarUser.get(memberID).getId(), worldEdit, world, true);
}
public void remove(){
@@ -60,8 +58,8 @@ public class BauweltMember{
}
private void updateDB(){
- SQL.update("INSERT INTO BauweltMember (BauweltID, MemberID, Build, WorldEdit, World) VALUES (?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE Build = VALUES(Build), WorldEdit = VALUES(WorldEdit), World = VALUES(World)",
- bauweltID, memberID, build, worldEdit, world);
+ SQL.update("INSERT INTO BauweltMember (BauweltID, MemberID, WorldEdit, World) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE WorldEdit = VALUES(WorldEdit), World = VALUES(World)",
+ bauweltID, memberID, worldEdit, world);
}
public static BauweltMember getBauMember(UUID ownerID, UUID memberID){
@@ -77,10 +75,9 @@ public class BauweltMember{
if(member == null || !member.next()){
return null;
}
- boolean build = member.getBoolean("Build");
boolean worldEdit = member.getBoolean("WorldEdit");
boolean testblock = member.getBoolean("World");
- return new BauweltMember(ownerID, memberID, build, worldEdit, testblock, false);
+ return new BauweltMember(ownerID, memberID, worldEdit, testblock, false);
} catch (SQLException e) {
throw new SecurityException("Did not get member", e);
}
@@ -96,10 +93,9 @@ public class BauweltMember{
List members = new LinkedList<>();
while(memberlist.next()){
int memberID = memberlist.getInt("MemberID");
- boolean build = memberlist.getBoolean("Build");
boolean worldEdit = memberlist.getBoolean("WorldEdit");
boolean testblock = memberlist.getBoolean("World");
- members.add(new BauweltMember(bauweltID, memberID, build, worldEdit, testblock, false));
+ members.add(new BauweltMember(bauweltID, memberID, worldEdit, testblock, false));
}
return members;
}catch(SQLException e){
@@ -115,15 +111,6 @@ public class BauweltMember{
return memberID;
}
- public boolean isBuild() {
- return build;
- }
-
- public void setBuild(boolean build) {
- this.build = build;
- updateDB();
- }
-
public boolean isWorldEdit() {
return worldEdit;
}