From 3e6f8c9b9158fba754dc034f2d2c3808e7b9fee0 Mon Sep 17 00:00:00 2001 From: YoyoNow Date: Sun, 4 Aug 2024 20:37:28 +0200 Subject: [PATCH] Add CommonCore module --- CommonCore/build.gradle.kts | 14 + .../de/steamwar/ImplementationProvider.java | 34 ++ .../de/steamwar/linkage/AllowedContexts.java | 36 ++ .../src/de/steamwar/linkage/Context.java | 25 + .../src/de/steamwar/linkage/EventMode.java | 44 ++ .../de/steamwar/linkage/LinkageProcessor.java | 352 +++++++++++ .../src/de/steamwar/linkage/LinkageType.java | 36 ++ .../src/de/steamwar/linkage/Linked.java | 28 + .../de/steamwar/linkage/LinkedInstance.java | 30 + .../src/de/steamwar/linkage/MaxVersion.java | 32 + .../src/de/steamwar/linkage/MinVersion.java | 32 + .../src/de/steamwar/linkage/PluginCheck.java | 42 ++ .../src/de/steamwar/linkage/api/Disable.java | 24 + .../src/de/steamwar/linkage/api/Enable.java | 24 + .../src/de/steamwar/linkage/api/Plain.java | 23 + .../de/steamwar/linkage/plan/BuildPlan.java | 89 +++ .../steamwar/linkage/plan/FieldBuilder.java | 44 ++ .../steamwar/linkage/plan/MethodBuilder.java | 70 +++ .../linkage/plan/ParameterBuilder.java | 35 ++ .../linkage/types/Disable_GENERIC.java | 39 ++ .../linkage/types/Enable_GENERIC.java | 39 ++ .../linkage/types/Listener_BUNGEE.java | 41 ++ .../linkage/types/Listener_SPIGOT.java | 105 ++++ .../linkage/types/PacketHandler_GENERIC.java | 39 ++ .../steamwar/linkage/types/Plain_GENERIC.java | 39 ++ .../linkage/types/SWCommand_BUNGEE.java | 39 ++ .../linkage/types/SWCommand_SPIGOT.java | 39 ++ .../steamwar/network/packets/MetaInfos.java | 23 + .../network/packets/NetworkPacket.java | 62 ++ .../network/packets/PacketHandler.java | 77 +++ .../packets/client/ExecuteCommandPacket.java | 37 ++ .../packets/client/ImALobbyPacket.java | 28 + .../client/InventoryCallbackPacket.java | 88 +++ .../packets/client/PrepareSchemPacket.java | 38 ++ .../client/RequestSchematicSearchPacket.java | 39 ++ .../packets/common/FightEndsPacket.java | 42 ++ .../packets/common/FightInfoPacket.java | 49 ++ .../packets/server/BaumemberUpdatePacket.java | 29 + .../packets/server/CloseInventoryPacket.java | 36 ++ .../packets/server/InventoryPacket.java | 41 ++ .../server/LocaleInvalidationPacket.java | 35 ++ .../network/packets/server/PingPacket.java | 35 ++ .../packets/server/StartingServerPacket.java | 35 ++ .../src/de/steamwar/sql/BannedUserIPs.java | 67 +++ .../src/de/steamwar/sql/BauweltMember.java | 123 ++++ .../src/de/steamwar/sql/CheckedSchematic.java | 86 +++ CommonCore/src/de/steamwar/sql/Event.java | 109 ++++ .../src/de/steamwar/sql/EventFight.java | 136 +++++ CommonCore/src/de/steamwar/sql/Fight.java | 124 ++++ .../src/de/steamwar/sql/FightPlayer.java | 65 ++ .../src/de/steamwar/sql/IgnoreSystem.java | 59 ++ CommonCore/src/de/steamwar/sql/Mod.java | 101 ++++ .../de/steamwar/sql/NoClipboardException.java | 23 + CommonCore/src/de/steamwar/sql/NodeData.java | 92 +++ .../src/de/steamwar/sql/NodeDownload.java | 69 +++ .../src/de/steamwar/sql/NodeMember.java | 91 +++ .../src/de/steamwar/sql/PollAnswer.java | 77 +++ .../src/de/steamwar/sql/Punishment.java | 140 +++++ CommonCore/src/de/steamwar/sql/Referee.java | 44 ++ CommonCore/src/de/steamwar/sql/Replay.java | 74 +++ .../src/de/steamwar/sql/SQLWrapper.java | 33 ++ .../src/de/steamwar/sql/SWException.java | 68 +++ CommonCore/src/de/steamwar/sql/SchemElo.java | 56 ++ .../src/de/steamwar/sql/SchematicNode.java | 559 ++++++++++++++++++ .../src/de/steamwar/sql/SchematicType.java | 124 ++++ CommonCore/src/de/steamwar/sql/Script.java | 84 +++ CommonCore/src/de/steamwar/sql/Season.java | 61 ++ CommonCore/src/de/steamwar/sql/Session.java | 45 ++ .../src/de/steamwar/sql/SteamwarUser.java | 362 ++++++++++++ CommonCore/src/de/steamwar/sql/Team.java | 140 +++++ .../src/de/steamwar/sql/TeamTeilnahme.java | 70 +++ CommonCore/src/de/steamwar/sql/Token.java | 110 ++++ CommonCore/src/de/steamwar/sql/Tutorial.java | 94 +++ .../src/de/steamwar/sql/UserConfig.java | 73 +++ CommonCore/src/de/steamwar/sql/UserElo.java | 188 ++++++ CommonCore/src/de/steamwar/sql/UserPerm.java | 90 +++ .../src/de/steamwar/sql/internal/Field.java | 34 ++ .../de/steamwar/sql/internal/SQLConfig.java | 34 ++ .../sql/internal/SelectStatement.java | 72 +++ .../steamwar/sql/internal/SqlTypeMapper.java | 115 ++++ .../de/steamwar/sql/internal/Statement.java | 298 ++++++++++ .../src/de/steamwar/sql/internal/Table.java | 137 +++++ .../testsrc/de/steamwar/RandomGenerator.java | 83 +++ .../de/steamwar/network/AllPackets.java | 80 +++ .../steamwar/network/PacketHandlerTest.java | 52 ++ .../de/steamwar/network/PacketTest.java | 38 ++ .../de/steamwar/network/TestPacket.java | 30 + .../steamwar/network/TestPacketHandler.java | 30 + 88 files changed, 6728 insertions(+) create mode 100644 CommonCore/src/de/steamwar/ImplementationProvider.java create mode 100644 CommonCore/src/de/steamwar/linkage/AllowedContexts.java create mode 100644 CommonCore/src/de/steamwar/linkage/Context.java create mode 100644 CommonCore/src/de/steamwar/linkage/EventMode.java create mode 100644 CommonCore/src/de/steamwar/linkage/LinkageProcessor.java create mode 100644 CommonCore/src/de/steamwar/linkage/LinkageType.java create mode 100644 CommonCore/src/de/steamwar/linkage/Linked.java create mode 100644 CommonCore/src/de/steamwar/linkage/LinkedInstance.java create mode 100644 CommonCore/src/de/steamwar/linkage/MaxVersion.java create mode 100644 CommonCore/src/de/steamwar/linkage/MinVersion.java create mode 100644 CommonCore/src/de/steamwar/linkage/PluginCheck.java create mode 100644 CommonCore/src/de/steamwar/linkage/api/Disable.java create mode 100644 CommonCore/src/de/steamwar/linkage/api/Enable.java create mode 100644 CommonCore/src/de/steamwar/linkage/api/Plain.java create mode 100644 CommonCore/src/de/steamwar/linkage/plan/BuildPlan.java create mode 100644 CommonCore/src/de/steamwar/linkage/plan/FieldBuilder.java create mode 100644 CommonCore/src/de/steamwar/linkage/plan/MethodBuilder.java create mode 100644 CommonCore/src/de/steamwar/linkage/plan/ParameterBuilder.java create mode 100644 CommonCore/src/de/steamwar/linkage/types/Disable_GENERIC.java create mode 100644 CommonCore/src/de/steamwar/linkage/types/Enable_GENERIC.java create mode 100644 CommonCore/src/de/steamwar/linkage/types/Listener_BUNGEE.java create mode 100644 CommonCore/src/de/steamwar/linkage/types/Listener_SPIGOT.java create mode 100644 CommonCore/src/de/steamwar/linkage/types/PacketHandler_GENERIC.java create mode 100644 CommonCore/src/de/steamwar/linkage/types/Plain_GENERIC.java create mode 100644 CommonCore/src/de/steamwar/linkage/types/SWCommand_BUNGEE.java create mode 100644 CommonCore/src/de/steamwar/linkage/types/SWCommand_SPIGOT.java create mode 100644 CommonCore/src/de/steamwar/network/packets/MetaInfos.java create mode 100644 CommonCore/src/de/steamwar/network/packets/NetworkPacket.java create mode 100644 CommonCore/src/de/steamwar/network/packets/PacketHandler.java create mode 100644 CommonCore/src/de/steamwar/network/packets/client/ExecuteCommandPacket.java create mode 100644 CommonCore/src/de/steamwar/network/packets/client/ImALobbyPacket.java create mode 100644 CommonCore/src/de/steamwar/network/packets/client/InventoryCallbackPacket.java create mode 100644 CommonCore/src/de/steamwar/network/packets/client/PrepareSchemPacket.java create mode 100644 CommonCore/src/de/steamwar/network/packets/client/RequestSchematicSearchPacket.java create mode 100644 CommonCore/src/de/steamwar/network/packets/common/FightEndsPacket.java create mode 100644 CommonCore/src/de/steamwar/network/packets/common/FightInfoPacket.java create mode 100644 CommonCore/src/de/steamwar/network/packets/server/BaumemberUpdatePacket.java create mode 100644 CommonCore/src/de/steamwar/network/packets/server/CloseInventoryPacket.java create mode 100644 CommonCore/src/de/steamwar/network/packets/server/InventoryPacket.java create mode 100644 CommonCore/src/de/steamwar/network/packets/server/LocaleInvalidationPacket.java create mode 100644 CommonCore/src/de/steamwar/network/packets/server/PingPacket.java create mode 100644 CommonCore/src/de/steamwar/network/packets/server/StartingServerPacket.java create mode 100644 CommonCore/src/de/steamwar/sql/BannedUserIPs.java create mode 100644 CommonCore/src/de/steamwar/sql/BauweltMember.java create mode 100644 CommonCore/src/de/steamwar/sql/CheckedSchematic.java create mode 100644 CommonCore/src/de/steamwar/sql/Event.java create mode 100644 CommonCore/src/de/steamwar/sql/EventFight.java create mode 100644 CommonCore/src/de/steamwar/sql/Fight.java create mode 100644 CommonCore/src/de/steamwar/sql/FightPlayer.java create mode 100644 CommonCore/src/de/steamwar/sql/IgnoreSystem.java create mode 100644 CommonCore/src/de/steamwar/sql/Mod.java create mode 100644 CommonCore/src/de/steamwar/sql/NoClipboardException.java create mode 100644 CommonCore/src/de/steamwar/sql/NodeData.java create mode 100644 CommonCore/src/de/steamwar/sql/NodeDownload.java create mode 100644 CommonCore/src/de/steamwar/sql/NodeMember.java create mode 100644 CommonCore/src/de/steamwar/sql/PollAnswer.java create mode 100644 CommonCore/src/de/steamwar/sql/Punishment.java create mode 100644 CommonCore/src/de/steamwar/sql/Referee.java create mode 100644 CommonCore/src/de/steamwar/sql/Replay.java create mode 100644 CommonCore/src/de/steamwar/sql/SQLWrapper.java create mode 100644 CommonCore/src/de/steamwar/sql/SWException.java create mode 100644 CommonCore/src/de/steamwar/sql/SchemElo.java create mode 100644 CommonCore/src/de/steamwar/sql/SchematicNode.java create mode 100644 CommonCore/src/de/steamwar/sql/SchematicType.java create mode 100644 CommonCore/src/de/steamwar/sql/Script.java create mode 100644 CommonCore/src/de/steamwar/sql/Season.java create mode 100644 CommonCore/src/de/steamwar/sql/Session.java create mode 100644 CommonCore/src/de/steamwar/sql/SteamwarUser.java create mode 100644 CommonCore/src/de/steamwar/sql/Team.java create mode 100644 CommonCore/src/de/steamwar/sql/TeamTeilnahme.java create mode 100644 CommonCore/src/de/steamwar/sql/Token.java create mode 100644 CommonCore/src/de/steamwar/sql/Tutorial.java create mode 100644 CommonCore/src/de/steamwar/sql/UserConfig.java create mode 100644 CommonCore/src/de/steamwar/sql/UserElo.java create mode 100644 CommonCore/src/de/steamwar/sql/UserPerm.java create mode 100644 CommonCore/src/de/steamwar/sql/internal/Field.java create mode 100644 CommonCore/src/de/steamwar/sql/internal/SQLConfig.java create mode 100644 CommonCore/src/de/steamwar/sql/internal/SelectStatement.java create mode 100644 CommonCore/src/de/steamwar/sql/internal/SqlTypeMapper.java create mode 100644 CommonCore/src/de/steamwar/sql/internal/Statement.java create mode 100644 CommonCore/src/de/steamwar/sql/internal/Table.java create mode 100644 CommonCore/testsrc/de/steamwar/RandomGenerator.java create mode 100644 CommonCore/testsrc/de/steamwar/network/AllPackets.java create mode 100644 CommonCore/testsrc/de/steamwar/network/PacketHandlerTest.java create mode 100644 CommonCore/testsrc/de/steamwar/network/PacketTest.java create mode 100644 CommonCore/testsrc/de/steamwar/network/TestPacket.java create mode 100644 CommonCore/testsrc/de/steamwar/network/TestPacketHandler.java diff --git a/CommonCore/build.gradle.kts b/CommonCore/build.gradle.kts index 8e3456a7..a3343ba6 100644 --- a/CommonCore/build.gradle.kts +++ b/CommonCore/build.gradle.kts @@ -40,4 +40,18 @@ sourceSets { exclude("**/*.java", "**/*.kt") } } + test { + java { + srcDirs("testsrc/") + } + resources { + srcDirs("testsrc/") + exclude("**/*.java", "**/*.kt") + } + } +} + +dependencies { + compileOnly("org.projectlombok:lombok:1.18.32") + annotationProcessor("org.projectlombok:lombok:1.18.32") } diff --git a/CommonCore/src/de/steamwar/ImplementationProvider.java b/CommonCore/src/de/steamwar/ImplementationProvider.java new file mode 100644 index 00000000..e5b795e4 --- /dev/null +++ b/CommonCore/src/de/steamwar/ImplementationProvider.java @@ -0,0 +1,34 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 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; + +import java.lang.reflect.InvocationTargetException; + +public class ImplementationProvider { + private ImplementationProvider() {} + + public static T getImpl(String className) { + try { + return (T) Class.forName(className).getDeclaredConstructor().newInstance(); + } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException | ClassNotFoundException e) { + throw new SecurityException("Could not load implementation", e); + } + } +} diff --git a/CommonCore/src/de/steamwar/linkage/AllowedContexts.java b/CommonCore/src/de/steamwar/linkage/AllowedContexts.java new file mode 100644 index 00000000..175a7831 --- /dev/null +++ b/CommonCore/src/de/steamwar/linkage/AllowedContexts.java @@ -0,0 +1,36 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 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.linkage; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.ANNOTATION_TYPE) +@Retention(RetentionPolicy.CLASS) +public @interface AllowedContexts { + + /** + * The context in which this annotation is valid. + */ + Context[] value(); + +} diff --git a/CommonCore/src/de/steamwar/linkage/Context.java b/CommonCore/src/de/steamwar/linkage/Context.java new file mode 100644 index 00000000..7559bd0c --- /dev/null +++ b/CommonCore/src/de/steamwar/linkage/Context.java @@ -0,0 +1,25 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 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.linkage; + +public enum Context { + BUNGEE, + SPIGOT +} diff --git a/CommonCore/src/de/steamwar/linkage/EventMode.java b/CommonCore/src/de/steamwar/linkage/EventMode.java new file mode 100644 index 00000000..cdff4665 --- /dev/null +++ b/CommonCore/src/de/steamwar/linkage/EventMode.java @@ -0,0 +1,44 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 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.linkage; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@AllowedContexts(Context.BUNGEE) +@Retention(RetentionPolicy.SOURCE) +@Target({ElementType.TYPE}) +public @interface EventMode { + Mode value(); + + @AllArgsConstructor + enum Mode { + EventOnly(""), + NonEvent("!"); + + @Getter + private String prefix; + } +} diff --git a/CommonCore/src/de/steamwar/linkage/LinkageProcessor.java b/CommonCore/src/de/steamwar/linkage/LinkageProcessor.java new file mode 100644 index 00000000..29382a59 --- /dev/null +++ b/CommonCore/src/de/steamwar/linkage/LinkageProcessor.java @@ -0,0 +1,352 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 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.linkage; + +import de.steamwar.linkage.plan.BuildPlan; +import de.steamwar.linkage.plan.FieldBuilder; +import de.steamwar.linkage.plan.MethodBuilder; +import de.steamwar.linkage.types.Plain_GENERIC; +import lombok.Cleanup; +import lombok.Getter; +import lombok.SneakyThrows; + +import javax.annotation.processing.*; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.Modifier; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.DeclaredType; +import javax.lang.model.type.TypeMirror; +import javax.tools.Diagnostic; +import javax.tools.StandardLocation; +import java.io.*; +import java.lang.annotation.Annotation; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.*; +import java.util.function.Consumer; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +@SupportedAnnotationTypes("de.steamwar.linkage.Linked") +public class LinkageProcessor extends AbstractProcessor { + + private static Context context; + + @Getter + private static String pluginMain; + + private String name; + private String className; + + private Set disabledFeatures = new HashSet<>(); + + private Messager messager; + private boolean processed = false; + + @Override + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latestSupported(); + } + + @SneakyThrows + @Override + public synchronized void init(ProcessingEnvironment processingEnv) { + super.init(processingEnv); + + name = new File(System.getProperty("user.dir")).getName().replaceAll("[^a-zA-Z]", "").toLowerCase(); + + messager = processingEnv.getMessager(); + + className = "LinkageUtils"; + mainClass(); + disabledFeatures(); + } + + @SneakyThrows + private void mainClass() { + File file = new File(System.getProperty("user.dir")); + Optional pluginYMLFile = Files.walk(file.toPath()) + .map(Path::toFile) + .filter(File::isFile) + .filter(f -> f.getName().equals("plugin.yml") || f.getName().equals("bungee.yml")) + .findFirst(); + if (!pluginYMLFile.isPresent()) { + messager.printMessage(Diagnostic.Kind.ERROR, "Could not find plugin.yml or bungee.yml"); + return; + } + context = pluginYMLFile.get().getName().equals("bungee.yml") ? Context.BUNGEE : Context.SPIGOT; + @Cleanup BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(pluginYMLFile.get()))); + Optional mainName = reader.lines() + .filter(line -> line.startsWith("main:")) + .map(line -> line.substring(line.indexOf(':') + 1).trim()) + .findFirst(); + if (mainName.isPresent()) { + pluginMain = mainName.get(); + } else { + messager.printMessage(Diagnostic.Kind.ERROR, "Could not find main class in plugin.yml or bungee.yml"); + } + } + + @SneakyThrows + private void disabledFeatures() { + File file = new File(System.getProperty("user.dir"), "disabled-features.txt"); + if (!file.exists()) return; + @Cleanup BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file))); + reader.lines() + .map(String::trim) + .filter(line -> !line.isEmpty()) + .filter(line -> !line.startsWith("#")) + .forEach(disabledFeatures::add); + } + + @SneakyThrows + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + if (processed) return false; + processed = true; + + Writer writer = processingEnv.getFiler().createSourceFile("de.steamwar." + name + ".linkage.LinkageUtils").openWriter(); + BuildPlan buildPlan = new BuildPlan("de.steamwar." + name + ".linkage", className); + + Set disabledElements = new HashSet<>(); + + Set elements = roundEnv.getElementsAnnotatedWith(Linked.class).stream() + .filter(element -> element.getKind() == ElementKind.CLASS) + .map(TypeElement.class::cast) + .peek(element -> { + String featureName = element.getAnnotation(Linked.class).feature(); + if (featureName.isEmpty()) { + String tempName = element.getQualifiedName().toString(); + if (tempName.contains(".features.")) { + tempName = tempName.substring(tempName.indexOf(".features.") + 10); + featureName = tempName.substring(0, tempName.indexOf('.')); + } else { + tempName = tempName.substring(0, tempName.lastIndexOf('.')); + featureName = tempName.substring(tempName.lastIndexOf('.') + 1); + } + } + if (disabledFeatures.contains(featureName) || disabledFeatures.contains("*")) { + disabledElements.add(element); + } + }) + .peek(typeElement -> System.out.println("Found element: " + typeElement.getQualifiedName().toString())) + .collect(Collectors.toSet()); + + Map, List> groupedByChecks = elements.stream() + .collect(Collectors.groupingBy(element -> checks(element, buildPlan))); + + Map neededFields = new HashMap<>(); + Set fieldInjections = new HashSet<>(); + for (TypeElement typeElement : elements) { + if (getLinkagesOfType(typeElement).size() > 1) { + neededFields.put(typeElement.getQualifiedName().toString(), typeElement); + } + + List variableElements = typeElement.getEnclosedElements().stream() + .filter(e -> e.getKind() == ElementKind.FIELD) + .map(VariableElement.class::cast) + .filter(e -> e.getAnnotation(LinkedInstance.class) != null) + .collect(Collectors.toList()); + if (variableElements.isEmpty()) continue; + + for (VariableElement variableElement : variableElements) { + if (!variableElement.getModifiers().contains(Modifier.PUBLIC)) { + messager.printMessage(Diagnostic.Kind.ERROR, "Field " + variableElement.getSimpleName() + " must be public", variableElement); + continue; + } + if (variableElement.getModifiers().contains(Modifier.STATIC)) { + messager.printMessage(Diagnostic.Kind.ERROR, "Field " + variableElement.getSimpleName() + " must be non static", variableElement); + continue; + } + if (variableElement.getModifiers().contains(Modifier.FINAL)) { + messager.printMessage(Diagnostic.Kind.ERROR, "Field " + variableElement.getSimpleName() + " must be non final", variableElement); + continue; + } + TypeElement fieldType = (TypeElement) ((DeclaredType) variableElement.asType()).asElement(); + if (disabledElements.contains(fieldType)) { + continue; + } + if (disabledElements.contains(typeElement)) { + continue; + } + neededFields.put(typeElement.getQualifiedName().toString(), typeElement); + neededFields.put(fieldType.getQualifiedName().toString(), fieldType); + + fieldInjections.add(() -> { + specialElements(typeElement, buildPlan, buildPlan::addStaticLine, () -> { + buildPlan.addStaticLine(getElement(typeElement, neededFields) + "." + variableElement.getSimpleName().toString() + " = " + getElement((TypeElement) ((DeclaredType) variableElement.asType()).asElement(), neededFields) + ";"); + }); + }); + } + } + neededFields.forEach((s, typeElement) -> { + if (disabledElements.contains(typeElement)) return; + buildPlan.addImport(typeElement.getQualifiedName().toString()); + String t = typeElement.getSimpleName().toString(); + t = t.substring(0, 1).toLowerCase() + t.substring(1); + buildPlan.addField(new FieldBuilder(typeElement.getSimpleName().toString(), t)); + + String finalT = t; + specialElements(typeElement, buildPlan, buildPlan::addStaticLine, () -> { + buildPlan.addStaticLine(finalT + " = new " + typeElement.getSimpleName().toString() + "();"); + }); + }); + fieldInjections.forEach(Runnable::run); + + Map methods = new HashMap<>(); + for (Map.Entry, List> entry : groupedByChecks.entrySet()) { + Map>> groupedByMethod = new HashMap<>(); + for (TypeElement typeElement : entry.getValue()) { + for (Map.Entry> linkages : getLinkagesOfType(typeElement).entrySet()) { + groupedByMethod.computeIfAbsent(linkages.getKey(), ignored -> new HashMap<>()) + .put(typeElement, linkages.getValue()); + } + } + + for (Map.Entry>> group : groupedByMethod.entrySet()) { + MethodBuilder method = methods.computeIfAbsent(group.getKey(), s -> { + MethodBuilder methodBuilder = new MethodBuilder(s, "void"); + buildPlan.addMethod(methodBuilder); + return methodBuilder; + }); + + boolean generated = false; + for (Map.Entry> toGenerate : group.getValue().entrySet()) { + if (disabledElements.contains(toGenerate.getKey())) continue; + if (!generated && !entry.getKey().isEmpty()) { + method.addLine("if (" + String.join(" && ", entry.getKey()) + ") {"); + generated = true; + } + TypeElement typeElement = toGenerate.getKey(); + String instance = getElement(typeElement, neededFields); + if (toGenerate.getValue().size() > 1 && instance.startsWith("new ")) { + method.addLine(typeElement.getSimpleName() + " local" + typeElement.getSimpleName().toString() + " = " + instance + ";"); + instance = "local" + typeElement.getSimpleName().toString(); + } + String finalInstance = instance; + toGenerate.getValue().forEach(linkageType -> { + buildPlan.addImport(typeElement.getQualifiedName().toString()); + linkageType.generateCode(buildPlan, method, finalInstance, typeElement); + }); + } + if (generated && !entry.getKey().isEmpty()) method.addLine("}"); + } + } + + BufferedWriter bufferedWriter = new BufferedWriter(writer); + buildPlan.write(bufferedWriter); + bufferedWriter.close(); + return true; + } + + private String getElement(TypeElement typeElement, Map neededFields) { + String s = typeElement.getSimpleName().toString(); + if (neededFields.containsKey(typeElement.getQualifiedName().toString())) { + return s.substring(0, 1).toLowerCase() + s.substring(1); + } + return "new " + s + "()"; + } + + private Set checks(TypeElement typeElement, BuildPlan buildPlan) { + Set checks = new HashSet<>(); + MinVersion minVersion = typeElement.getAnnotation(MinVersion.class); + MaxVersion maxVersion = typeElement.getAnnotation(MaxVersion.class); + EventMode eventMode = typeElement.getAnnotation(EventMode.class); + PluginCheck[] pluginChecks = typeElement.getAnnotationsByType(PluginCheck.class); + if (context == Context.SPIGOT) { + errorOnNonNull(typeElement, eventMode); + if (minVersion != null) { + buildPlan.addImport("de.steamwar.core.Core"); + checks.add("Core.getVersion() >= " + minVersion.value()); + } + if (maxVersion != null) { + buildPlan.addImport("de.steamwar.core.Core"); + checks.add("Core.getVersion() <= " + maxVersion.value()); + } + if (pluginChecks.length != 0) { + buildPlan.addImport("org.bukkit.Bukkit"); + Arrays.stream(pluginChecks).map(pluginCheck -> { + return "Bukkit.getPluginManager().getPlugin(\"" + pluginCheck.value() + "\") " + (pluginCheck.has() == PluginCheck.Has.THIS ? "!" : "=") + "= null"; + }).forEach(checks::add); + } + } else { + errorOnNonNull(typeElement, minVersion, maxVersion); + if (eventMode != null) { + buildPlan.addImport("de.steamwar.bungeecore.BungeeCore"); + checks.add(eventMode.value().getPrefix() + "BungeeCore.EVENT_MODE"); + } + if (pluginChecks.length != 0) { + buildPlan.addImport("net.md_5.bungee.BungeeCord"); + Arrays.stream(pluginChecks).map(pluginCheck -> { + return "BungeeCord.getPluginManager().getPlugin(\"" + pluginCheck.value() + "\") " + (pluginCheck.has() == PluginCheck.Has.THIS ? "!" : "=") + "= null"; + }).forEach(checks::add); + } + } + return checks; + } + + private void specialElements(TypeElement typeElement, BuildPlan buildPlan, Consumer stringConsumer, Runnable inner) { + Set checks = checks(typeElement, buildPlan); + if (!checks.isEmpty()) stringConsumer.accept("if (" + String.join(" && ", checks) + ") {"); + inner.run(); + if (!checks.isEmpty()) stringConsumer.accept("}"); + } + + private void errorOnNonNull(TypeElement typeElement, Annotation... annotations) { + for (Annotation annotation : annotations) { + if (annotation != null) { + messager.printMessage(Diagnostic.Kind.ERROR, annotation.annotationType().getSimpleName() + " is not supported in " + context.name(), typeElement); + } + } + } + + private Plain_GENERIC plain_GENERIC = new Plain_GENERIC(); + + private Map> getLinkagesOfType(TypeElement typeElement) { + Map> linkages = new HashMap<>(); + Stream.concat(Stream.of(typeElement.getSuperclass()), typeElement.getInterfaces().stream()) + .map(this::resolveSingle) + .filter(Objects::nonNull) + .forEach(linkageType -> linkages.computeIfAbsent(linkageType.method(), s -> new ArrayList<>()).add(linkageType)); + if (linkages.size() == 1 && linkages.containsKey("unlink")) { + linkages.put(plain_GENERIC.method(), Collections.singletonList(plain_GENERIC)); + } + return linkages; + } + + private LinkageType resolveSingle(TypeMirror typeMirror) { + String qualifier = typeMirror.toString(); + if (qualifier.contains("<")) qualifier = qualifier.substring(0, qualifier.indexOf('<')); + qualifier = qualifier.substring(qualifier.lastIndexOf('.') + 1); + try { + return (LinkageType) Class.forName("de.steamwar.linkage.types." + qualifier + "_" + context.name()).getDeclaredConstructor().newInstance(); + } catch (Exception e) { + // Ignore + } + try { + return (LinkageType) Class.forName("de.steamwar.linkage.types." + qualifier + "_GENERIC").getDeclaredConstructor().newInstance(); + } catch (Exception e) { + // Ignore + } + return null; + } +} diff --git a/CommonCore/src/de/steamwar/linkage/LinkageType.java b/CommonCore/src/de/steamwar/linkage/LinkageType.java new file mode 100644 index 00000000..9291279b --- /dev/null +++ b/CommonCore/src/de/steamwar/linkage/LinkageType.java @@ -0,0 +1,36 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 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.linkage; + +import de.steamwar.linkage.plan.BuildPlan; +import de.steamwar.linkage.plan.MethodBuilder; + +import javax.lang.model.element.TypeElement; + +public interface LinkageType { + + default String getPluginMain() { + return LinkageProcessor.getPluginMain(); + } + + String method(); + + void generateCode(BuildPlan buildPlan, MethodBuilder method, String instance, TypeElement typeElement); +} diff --git a/CommonCore/src/de/steamwar/linkage/Linked.java b/CommonCore/src/de/steamwar/linkage/Linked.java new file mode 100644 index 00000000..dbaf0eb7 --- /dev/null +++ b/CommonCore/src/de/steamwar/linkage/Linked.java @@ -0,0 +1,28 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 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.linkage; + +import java.lang.annotation.*; + +@Retention(RetentionPolicy.SOURCE) +@Target({ElementType.TYPE}) +public @interface Linked { + String feature() default ""; +} diff --git a/CommonCore/src/de/steamwar/linkage/LinkedInstance.java b/CommonCore/src/de/steamwar/linkage/LinkedInstance.java new file mode 100644 index 00000000..9636ba52 --- /dev/null +++ b/CommonCore/src/de/steamwar/linkage/LinkedInstance.java @@ -0,0 +1,30 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 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.linkage; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.SOURCE) +@Target({ElementType.FIELD}) +public @interface LinkedInstance { +} diff --git a/CommonCore/src/de/steamwar/linkage/MaxVersion.java b/CommonCore/src/de/steamwar/linkage/MaxVersion.java new file mode 100644 index 00000000..e144b164 --- /dev/null +++ b/CommonCore/src/de/steamwar/linkage/MaxVersion.java @@ -0,0 +1,32 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 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.linkage; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@AllowedContexts(Context.SPIGOT) +@Retention(RetentionPolicy.SOURCE) +@Target({ElementType.TYPE}) +public @interface MaxVersion { + int value(); +} diff --git a/CommonCore/src/de/steamwar/linkage/MinVersion.java b/CommonCore/src/de/steamwar/linkage/MinVersion.java new file mode 100644 index 00000000..b6f5b997 --- /dev/null +++ b/CommonCore/src/de/steamwar/linkage/MinVersion.java @@ -0,0 +1,32 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 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.linkage; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@AllowedContexts(Context.SPIGOT) +@Retention(RetentionPolicy.SOURCE) +@Target({ElementType.TYPE}) +public @interface MinVersion { + int value(); +} diff --git a/CommonCore/src/de/steamwar/linkage/PluginCheck.java b/CommonCore/src/de/steamwar/linkage/PluginCheck.java new file mode 100644 index 00000000..241f19a1 --- /dev/null +++ b/CommonCore/src/de/steamwar/linkage/PluginCheck.java @@ -0,0 +1,42 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 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.linkage; + +import java.lang.annotation.*; + +@AllowedContexts({Context.BUNGEE, Context.SPIGOT}) +@Retention(RetentionPolicy.SOURCE) +@Target({ElementType.TYPE}) +@Repeatable(PluginCheck.PluginChecks.class) +public @interface PluginCheck { + Has has() default Has.THIS; + String value(); + + enum Has { + THIS, + NOT + } + + @Retention(RetentionPolicy.SOURCE) + @Target({ElementType.TYPE}) + @interface PluginChecks { + @SuppressWarnings("unused") PluginCheck[] value() default {}; + } +} diff --git a/CommonCore/src/de/steamwar/linkage/api/Disable.java b/CommonCore/src/de/steamwar/linkage/api/Disable.java new file mode 100644 index 00000000..f09b8468 --- /dev/null +++ b/CommonCore/src/de/steamwar/linkage/api/Disable.java @@ -0,0 +1,24 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 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.linkage.api; + +public interface Disable { + void disable(); +} diff --git a/CommonCore/src/de/steamwar/linkage/api/Enable.java b/CommonCore/src/de/steamwar/linkage/api/Enable.java new file mode 100644 index 00000000..5d516cd6 --- /dev/null +++ b/CommonCore/src/de/steamwar/linkage/api/Enable.java @@ -0,0 +1,24 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 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.linkage.api; + +public interface Enable { + void enable(); +} diff --git a/CommonCore/src/de/steamwar/linkage/api/Plain.java b/CommonCore/src/de/steamwar/linkage/api/Plain.java new file mode 100644 index 00000000..23901ed2 --- /dev/null +++ b/CommonCore/src/de/steamwar/linkage/api/Plain.java @@ -0,0 +1,23 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 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.linkage.api; + +public interface Plain { +} diff --git a/CommonCore/src/de/steamwar/linkage/plan/BuildPlan.java b/CommonCore/src/de/steamwar/linkage/plan/BuildPlan.java new file mode 100644 index 00000000..2fc7b8b4 --- /dev/null +++ b/CommonCore/src/de/steamwar/linkage/plan/BuildPlan.java @@ -0,0 +1,89 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 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.linkage.plan; + +import lombok.RequiredArgsConstructor; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.util.*; + +@RequiredArgsConstructor +public class BuildPlan { + + private final String packageName; + private Set imports = new HashSet<>(); + private final String className; + + private List fieldBuilders = new ArrayList<>(); + private Map methodBuilderMap = new HashMap<>(); + private List staticLines = new ArrayList<>(); + + public void addImport(String importName) { + imports.add(importName); + } + + public void addField(FieldBuilder fieldBuilder) { + fieldBuilders.add(fieldBuilder); + } + + public void addMethod(MethodBuilder methodBuilder) { + methodBuilderMap.put(methodBuilder.getMethodName(), methodBuilder); + } + + public boolean hasMethod(String methodName) { + return methodBuilderMap.containsKey(methodName); + } + + public void addStaticLine(String line) { + staticLines.add(line); + } + + public void write(BufferedWriter writer) throws IOException { + writer.write("package " + packageName + ";\n"); + if (!imports.isEmpty()) { + writer.write("\n"); + for (String importName : imports) { + writer.write("import " + importName + ";\n"); + } + } + writer.write("\n"); + writer.write("public class " + className + " {\n"); + if (!fieldBuilders.isEmpty()) { + for (FieldBuilder fieldBuilder : fieldBuilders) { + fieldBuilder.write(writer); + } + writer.write("\n"); + } + if (!staticLines.isEmpty()) { + writer.write(" static {\n"); + for (String line : staticLines) { + writer.write(" " + line + "\n"); + } + writer.write(" }\n"); + writer.write("\n"); + } + for (MethodBuilder methodBuilder : methodBuilderMap.values()) { + methodBuilder.write(writer); + writer.write("\n"); + } + writer.write("}\n"); + } +} diff --git a/CommonCore/src/de/steamwar/linkage/plan/FieldBuilder.java b/CommonCore/src/de/steamwar/linkage/plan/FieldBuilder.java new file mode 100644 index 00000000..12fa4408 --- /dev/null +++ b/CommonCore/src/de/steamwar/linkage/plan/FieldBuilder.java @@ -0,0 +1,44 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 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.linkage.plan; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +import java.io.BufferedWriter; +import java.io.IOException; + +@RequiredArgsConstructor +@AllArgsConstructor +public class FieldBuilder { + @Getter + private final String type; + private final String name; + private String initializer; + + public String getFieldName() { + return name; + } + + public void write(BufferedWriter writer) throws IOException { + writer.write(" private static " + type + " " + getFieldName() + (initializer == null ? "" : " = " + initializer) + ";\n"); + } +} diff --git a/CommonCore/src/de/steamwar/linkage/plan/MethodBuilder.java b/CommonCore/src/de/steamwar/linkage/plan/MethodBuilder.java new file mode 100644 index 00000000..6a31175a --- /dev/null +++ b/CommonCore/src/de/steamwar/linkage/plan/MethodBuilder.java @@ -0,0 +1,70 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 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.linkage.plan; + +import lombok.RequiredArgsConstructor; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +@RequiredArgsConstructor +public class MethodBuilder { + + private final String name; + private final String returnType; + private List parameters = new ArrayList<>(); + private List lines = new ArrayList<>(); + private boolean isPrivate = false; + + public void addParameter(ParameterBuilder parameterBuilder) { + parameters.add(parameterBuilder); + } + + public void addLine(String line) { + lines.add(line); + } + + public String getMethodName() { + return name; + } + + public void setPrivate(boolean isPrivate) { + this.isPrivate = isPrivate; + } + + public void write(BufferedWriter writer) throws IOException { + writer.write(" " + (isPrivate ? "private" : "public") + " static " + returnType + " " + getMethodName() + "("); + for (int i = 0; i < parameters.size(); i++) { + parameters.get(i).write(writer); + if (i < parameters.size() - 1) { + writer.write(", "); + } + } + writer.write(") {"); + for (String line : lines) { + writer.write("\n"); + writer.write(" " + line); + } + writer.write("\n"); + writer.write(" }\n"); + } +} diff --git a/CommonCore/src/de/steamwar/linkage/plan/ParameterBuilder.java b/CommonCore/src/de/steamwar/linkage/plan/ParameterBuilder.java new file mode 100644 index 00000000..d88364be --- /dev/null +++ b/CommonCore/src/de/steamwar/linkage/plan/ParameterBuilder.java @@ -0,0 +1,35 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 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.linkage.plan; + +import lombok.AllArgsConstructor; + +import java.io.BufferedWriter; +import java.io.IOException; + +@AllArgsConstructor +public class ParameterBuilder { + private String type; + private String name; + + public void write(BufferedWriter writer) throws IOException { + writer.write(type + " " + name); + } +} diff --git a/CommonCore/src/de/steamwar/linkage/types/Disable_GENERIC.java b/CommonCore/src/de/steamwar/linkage/types/Disable_GENERIC.java new file mode 100644 index 00000000..ea58c91b --- /dev/null +++ b/CommonCore/src/de/steamwar/linkage/types/Disable_GENERIC.java @@ -0,0 +1,39 @@ +/* + * 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.linkage.types; + +import de.steamwar.linkage.LinkageType; +import de.steamwar.linkage.plan.BuildPlan; +import de.steamwar.linkage.plan.MethodBuilder; + +import javax.lang.model.element.TypeElement; + +public class Disable_GENERIC implements LinkageType { + + @Override + public String method() { + return "unlink"; + } + + @Override + public void generateCode(BuildPlan buildPlan, MethodBuilder method, String instance, TypeElement typeElement) { + method.addLine(instance + ".disable();"); + } +} diff --git a/CommonCore/src/de/steamwar/linkage/types/Enable_GENERIC.java b/CommonCore/src/de/steamwar/linkage/types/Enable_GENERIC.java new file mode 100644 index 00000000..03afd570 --- /dev/null +++ b/CommonCore/src/de/steamwar/linkage/types/Enable_GENERIC.java @@ -0,0 +1,39 @@ +/* + * 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.linkage.types; + +import de.steamwar.linkage.LinkageType; +import de.steamwar.linkage.plan.BuildPlan; +import de.steamwar.linkage.plan.MethodBuilder; + +import javax.lang.model.element.TypeElement; + +public class Enable_GENERIC implements LinkageType { + + @Override + public String method() { + return "link"; + } + + @Override + public void generateCode(BuildPlan buildPlan, MethodBuilder method, String instance, TypeElement typeElement) { + method.addLine(instance + ".enable();"); + } +} diff --git a/CommonCore/src/de/steamwar/linkage/types/Listener_BUNGEE.java b/CommonCore/src/de/steamwar/linkage/types/Listener_BUNGEE.java new file mode 100644 index 00000000..327b19ad --- /dev/null +++ b/CommonCore/src/de/steamwar/linkage/types/Listener_BUNGEE.java @@ -0,0 +1,41 @@ +/* + * 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.linkage.types; + +import de.steamwar.linkage.LinkageType; +import de.steamwar.linkage.plan.BuildPlan; +import de.steamwar.linkage.plan.MethodBuilder; + +import javax.lang.model.element.TypeElement; + +public class Listener_BUNGEE implements LinkageType { + + @Override + public String method() { + return "link"; + } + + @Override + public void generateCode(BuildPlan buildPlan, MethodBuilder method, String instance, TypeElement typeElement) { + buildPlan.addImport("net.md_5.bungee.api.ProxyServer"); + buildPlan.addImport("de.steamwar.bungeecore.BungeeCore"); + method.addLine("ProxyServer.getInstance().getPluginManager().registerListener(BungeeCore.get(), " + instance + ");"); + } +} diff --git a/CommonCore/src/de/steamwar/linkage/types/Listener_SPIGOT.java b/CommonCore/src/de/steamwar/linkage/types/Listener_SPIGOT.java new file mode 100644 index 00000000..3491d6d2 --- /dev/null +++ b/CommonCore/src/de/steamwar/linkage/types/Listener_SPIGOT.java @@ -0,0 +1,105 @@ +/* + * 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.linkage.types; + +import de.steamwar.linkage.LinkageType; +import de.steamwar.linkage.plan.BuildPlan; +import de.steamwar.linkage.plan.FieldBuilder; +import de.steamwar.linkage.plan.MethodBuilder; +import de.steamwar.linkage.plan.ParameterBuilder; + +import javax.lang.model.element.*; +import javax.lang.model.type.DeclaredType; +import java.util.HashMap; +import java.util.Map; + +public class Listener_SPIGOT implements LinkageType { + + @Override + public String method() { + return "link"; + } + + @Override + public void generateCode(BuildPlan buildPlan, MethodBuilder method, String instance, TypeElement typeElement) { + Map eventClasses = new HashMap<>(); + Map eventMethods = new HashMap<>(); + + typeElement.getEnclosedElements().stream().filter(e -> e.getKind() == ElementKind.METHOD).map(ExecutableElement.class::cast).filter(e -> { + return e.getAnnotationMirrors().stream().anyMatch(annotationMirror -> { + return annotationMirror.getAnnotationType().asElement().getSimpleName().toString().equals("EventHandler"); + }); + }).forEach(e -> { + TypeElement current = ((TypeElement)((DeclaredType) e.getParameters().get(0).asType()).asElement()); + eventClasses.put(current.getQualifiedName().toString(), current); + eventMethods.put(current, e); + }); + + eventClasses.forEach((s, eventType) -> { + if (buildPlan.hasMethod(eventType.getSimpleName().toString())) return; + buildPlan.addImport("org.bukkit.event.HandlerList"); + buildPlan.addImport("org.bukkit.event.Listener"); + buildPlan.addImport("java.util.function.Consumer"); + buildPlan.addImport("org.bukkit.event.EventPriority"); + buildPlan.addImport("org.bukkit.plugin.RegisteredListener"); + buildPlan.addImport("org.bukkit.plugin.EventExecutor"); + buildPlan.addImport(s); + buildPlan.addField(new FieldBuilder("HandlerList", "handlerList" + eventType.getSimpleName())); + MethodBuilder methodBuilder = new MethodBuilder(eventType.getSimpleName().toString(), "void"); + methodBuilder.addParameter(new ParameterBuilder("Listener", "listener")); + methodBuilder.addParameter(new ParameterBuilder("Consumer<" + eventType.getSimpleName() + ">", "consumer")); + methodBuilder.addParameter(new ParameterBuilder("EventPriority", "eventPriority")); + methodBuilder.addParameter(new ParameterBuilder("boolean", "ignoreCancelled")); + methodBuilder.setPrivate(true); + methodBuilder.addLine("EventExecutor eventExecutor = (l, event) -> {"); + methodBuilder.addLine(" if (event instanceof " + eventType.getSimpleName() + ") {"); + methodBuilder.addLine(" consumer.accept((" + eventType.getSimpleName() + ") event);"); + methodBuilder.addLine(" }"); + methodBuilder.addLine("};"); + methodBuilder.addLine("handlerList" + eventType.getSimpleName() + ".register(new RegisteredListener(listener, eventExecutor, eventPriority, " + getPluginMain() + ".getInstance(), ignoreCancelled));"); + buildPlan.addMethod(methodBuilder); + method.addLine("handlerList" + eventType.getSimpleName() + " = " + eventType.getSimpleName() + ".getHandlerList();"); + }); + + String localInstance = "local" + typeElement.getSimpleName().toString(); + if (!instance.startsWith("new ")) { + localInstance = instance; + } else { + method.addLine(typeElement.getSimpleName() + " " + localInstance + " = " + instance + ";"); + } + String finalLocalInstance = localInstance; + eventMethods.forEach((type, executableElement) -> { + AnnotationMirror eventHandler = executableElement.getAnnotationMirrors().stream().filter(annotationMirror -> annotationMirror.getAnnotationType().asElement().getSimpleName().toString().equals("EventHandler")).findFirst().orElse(null); + if (eventHandler == null) { + return; + } + String priority = "NORMAL"; + String ignoreCancelled = "false"; + for (Map.Entry entry : eventHandler.getElementValues().entrySet()) { + if (entry.getKey().getSimpleName().toString().equals("priority")) { + priority = entry.getValue().getValue().toString(); + } else if (entry.getKey().getSimpleName().toString().equals("ignoreCancelled")) { + ignoreCancelled = entry.getValue().getValue().toString(); + } + } + method.addLine(type.getSimpleName().toString() + "(" + finalLocalInstance + ", " + finalLocalInstance + "::" + executableElement.getSimpleName().toString() + ", EventPriority." + priority + ", " + ignoreCancelled + ");"); + }); + } +} diff --git a/CommonCore/src/de/steamwar/linkage/types/PacketHandler_GENERIC.java b/CommonCore/src/de/steamwar/linkage/types/PacketHandler_GENERIC.java new file mode 100644 index 00000000..630f6f95 --- /dev/null +++ b/CommonCore/src/de/steamwar/linkage/types/PacketHandler_GENERIC.java @@ -0,0 +1,39 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 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.linkage.types; + +import de.steamwar.linkage.LinkageType; +import de.steamwar.linkage.plan.BuildPlan; +import de.steamwar.linkage.plan.MethodBuilder; + +import javax.lang.model.element.TypeElement; + +public class PacketHandler_GENERIC implements LinkageType { + + @Override + public String method() { + return "link"; + } + + @Override + public void generateCode(BuildPlan buildPlan, MethodBuilder method, String instance, TypeElement typeElement) { + method.addLine(instance + ".register();"); + } +} diff --git a/CommonCore/src/de/steamwar/linkage/types/Plain_GENERIC.java b/CommonCore/src/de/steamwar/linkage/types/Plain_GENERIC.java new file mode 100644 index 00000000..f066d035 --- /dev/null +++ b/CommonCore/src/de/steamwar/linkage/types/Plain_GENERIC.java @@ -0,0 +1,39 @@ +/* + * 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.linkage.types; + +import de.steamwar.linkage.LinkageType; +import de.steamwar.linkage.plan.BuildPlan; +import de.steamwar.linkage.plan.MethodBuilder; + +import javax.lang.model.element.TypeElement; + +public class Plain_GENERIC implements LinkageType { + + @Override + public String method() { + return "link"; + } + + @Override + public void generateCode(BuildPlan buildPlan, MethodBuilder method, String instance, TypeElement typeElement) { + if (instance.startsWith("new ")) method.addLine(instance + ";"); + } +} diff --git a/CommonCore/src/de/steamwar/linkage/types/SWCommand_BUNGEE.java b/CommonCore/src/de/steamwar/linkage/types/SWCommand_BUNGEE.java new file mode 100644 index 00000000..5db62c4b --- /dev/null +++ b/CommonCore/src/de/steamwar/linkage/types/SWCommand_BUNGEE.java @@ -0,0 +1,39 @@ +/* + * 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.linkage.types; + +import de.steamwar.linkage.LinkageType; +import de.steamwar.linkage.plan.BuildPlan; +import de.steamwar.linkage.plan.MethodBuilder; + +import javax.lang.model.element.TypeElement; + +public class SWCommand_BUNGEE implements LinkageType { + + @Override + public String method() { + return "link"; + } + + @Override + public void generateCode(BuildPlan buildPlan, MethodBuilder method, String instance, TypeElement typeElement) { + method.addLine(instance + ";"); + } +} diff --git a/CommonCore/src/de/steamwar/linkage/types/SWCommand_SPIGOT.java b/CommonCore/src/de/steamwar/linkage/types/SWCommand_SPIGOT.java new file mode 100644 index 00000000..96e3f770 --- /dev/null +++ b/CommonCore/src/de/steamwar/linkage/types/SWCommand_SPIGOT.java @@ -0,0 +1,39 @@ +/* + * 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.linkage.types; + +import de.steamwar.linkage.LinkageType; +import de.steamwar.linkage.plan.BuildPlan; +import de.steamwar.linkage.plan.MethodBuilder; + +import javax.lang.model.element.TypeElement; + +public class SWCommand_SPIGOT implements LinkageType { + + @Override + public String method() { + return "link"; + } + + @Override + public void generateCode(BuildPlan buildPlan, MethodBuilder method, String instance, TypeElement typeElement) { + method.addLine(instance + ".setMessage(" + getPluginMain() + ".MESSAGE);"); + } +} diff --git a/CommonCore/src/de/steamwar/network/packets/MetaInfos.java b/CommonCore/src/de/steamwar/network/packets/MetaInfos.java new file mode 100644 index 00000000..61632d7c --- /dev/null +++ b/CommonCore/src/de/steamwar/network/packets/MetaInfos.java @@ -0,0 +1,23 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 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.network.packets; + +public interface MetaInfos { +} diff --git a/CommonCore/src/de/steamwar/network/packets/NetworkPacket.java b/CommonCore/src/de/steamwar/network/packets/NetworkPacket.java new file mode 100644 index 00000000..987e1ef1 --- /dev/null +++ b/CommonCore/src/de/steamwar/network/packets/NetworkPacket.java @@ -0,0 +1,62 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 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.network.packets; + +import lombok.EqualsAndHashCode; +import lombok.SneakyThrows; + +import java.io.*; + +@EqualsAndHashCode +public abstract class NetworkPacket implements Serializable { + + private static final long serialVersionUID = -3168992457669156473L; + private transient MetaInfos metaInfos; + + public MetaInfos getMetaInfos() { + return metaInfos; + } + + @SneakyThrows + public byte[] serialize() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(this); + oos.flush(); + return baos.toByteArray(); + } + + public static void handle(byte[] data) { + PacketHandler.handlePacket(deserialize(data)); + } + + public static void handle(MetaInfos metaInfos, byte[] data) { + NetworkPacket networkPacket = deserialize(data); + networkPacket.metaInfos = metaInfos; + PacketHandler.handlePacket(networkPacket); + } + + @SneakyThrows + public static NetworkPacket deserialize(byte[] data) { + ByteArrayInputStream bais = new ByteArrayInputStream(data); + ObjectInputStream ois = new ObjectInputStream(bais); + return (NetworkPacket) ois.readObject(); + } +} diff --git a/CommonCore/src/de/steamwar/network/packets/PacketHandler.java b/CommonCore/src/de/steamwar/network/packets/PacketHandler.java new file mode 100644 index 00000000..671eb469 --- /dev/null +++ b/CommonCore/src/de/steamwar/network/packets/PacketHandler.java @@ -0,0 +1,77 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 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.network.packets; + +import lombok.SneakyThrows; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public abstract class PacketHandler { + + private static final List PACKET_HANDLERS = new ArrayList<>(); + + private final Map, Method> HANDLER_MAP = new HashMap<>(); + + public static void handlePacket(NetworkPacket packet) { + for (PacketHandler handler : PACKET_HANDLERS) { + handler.handle(packet); + } + } + + protected PacketHandler() { + Method[] methods = getClass().getMethods(); + for (Method method : methods) { + if(method.getParameterCount() != 1 || !NetworkPacket.class.isAssignableFrom(method.getParameterTypes()[0])) { + continue; + } + + if (method.isAnnotationPresent(Handler.class)) { + Class packetClass = (Class) method.getParameterTypes()[0]; + HANDLER_MAP.put(packetClass, method); + } + } + } + + public void register() { + PACKET_HANDLERS.add(this); + } + + public void unregister() { + PACKET_HANDLERS.remove(this); + } + + @SneakyThrows + public void handle(NetworkPacket packet) { + Method method = HANDLER_MAP.get(packet.getClass()); + if (method == null) { + return; + } + method.invoke(this, packet); + } + + @Retention(RetentionPolicy.RUNTIME) + protected @interface Handler {} +} diff --git a/CommonCore/src/de/steamwar/network/packets/client/ExecuteCommandPacket.java b/CommonCore/src/de/steamwar/network/packets/client/ExecuteCommandPacket.java new file mode 100644 index 00000000..9f7d000f --- /dev/null +++ b/CommonCore/src/de/steamwar/network/packets/client/ExecuteCommandPacket.java @@ -0,0 +1,37 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 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.network.packets.client; + +import de.steamwar.network.packets.NetworkPacket; +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@AllArgsConstructor +@NoArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Getter +public class ExecuteCommandPacket extends NetworkPacket { + + private static final long serialVersionUID = 6283457297487602016L; + private int playerId; + private String command; +} diff --git a/CommonCore/src/de/steamwar/network/packets/client/ImALobbyPacket.java b/CommonCore/src/de/steamwar/network/packets/client/ImALobbyPacket.java new file mode 100644 index 00000000..dcd07ddf --- /dev/null +++ b/CommonCore/src/de/steamwar/network/packets/client/ImALobbyPacket.java @@ -0,0 +1,28 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 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.network.packets.client; + +import de.steamwar.network.packets.NetworkPacket; +import lombok.EqualsAndHashCode; + +@EqualsAndHashCode(callSuper = true) +public class ImALobbyPacket extends NetworkPacket { + private static final long serialVersionUID = 8110246509205246654L; +} diff --git a/CommonCore/src/de/steamwar/network/packets/client/InventoryCallbackPacket.java b/CommonCore/src/de/steamwar/network/packets/client/InventoryCallbackPacket.java new file mode 100644 index 00000000..cfe9fbc6 --- /dev/null +++ b/CommonCore/src/de/steamwar/network/packets/client/InventoryCallbackPacket.java @@ -0,0 +1,88 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 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.network.packets.client; + +import de.steamwar.network.packets.NetworkPacket; +import lombok.*; + +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Getter +public class InventoryCallbackPacket extends NetworkPacket { + private static final long serialVersionUID = -261823209186008718L; + @Builder.Default + private int position = -1; + private int owner; + private CallbackType type; + @Builder.Default + private ClickType clickType = ClickType.UNKNOWN; + + public enum CallbackType { + CLICK, + CLOSE, + } + + public enum ClickType { + LEFT, + SHIFT_LEFT, + RIGHT, + SHIFT_RIGHT, + WINDOW_BORDER_LEFT, + WINDOW_BORDER_RIGHT, + MIDDLE, + NUMBER_KEY, + DOUBLE_CLICK, + DROP, + CONTROL_DROP, + CREATIVE, + UNKNOWN; + + public boolean isKeyboardClick() { + return this == NUMBER_KEY || this == DROP || this == CONTROL_DROP; + } + + public boolean isCreativeAction() { + return this == MIDDLE || this == CREATIVE; + } + + public boolean isRightClick() { + return this == RIGHT || this == SHIFT_RIGHT; + } + + public boolean isLeftClick() { + return this == LEFT || this == SHIFT_LEFT || this == DOUBLE_CLICK || this == CREATIVE; + } + + public boolean isShiftClick() { + return this == SHIFT_LEFT || this == SHIFT_RIGHT || this == CONTROL_DROP; + } + + public static ClickType getByName(String name) { + for (ClickType type : values()) { + if (type.name().equalsIgnoreCase(name)) { + return type; + } + } + return UNKNOWN; + } + } +} diff --git a/CommonCore/src/de/steamwar/network/packets/client/PrepareSchemPacket.java b/CommonCore/src/de/steamwar/network/packets/client/PrepareSchemPacket.java new file mode 100644 index 00000000..8f607faf --- /dev/null +++ b/CommonCore/src/de/steamwar/network/packets/client/PrepareSchemPacket.java @@ -0,0 +1,38 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 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.network.packets.client; + +import de.steamwar.network.packets.NetworkPacket; +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@AllArgsConstructor +@NoArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Getter +public class PrepareSchemPacket extends NetworkPacket { + + private static final long serialVersionUID = -4798561188105813349L; + private int player; + private int schem; + private String schemType; +} diff --git a/CommonCore/src/de/steamwar/network/packets/client/RequestSchematicSearchPacket.java b/CommonCore/src/de/steamwar/network/packets/client/RequestSchematicSearchPacket.java new file mode 100644 index 00000000..ea8420ca --- /dev/null +++ b/CommonCore/src/de/steamwar/network/packets/client/RequestSchematicSearchPacket.java @@ -0,0 +1,39 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2023 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.network.packets.client; + +import de.steamwar.network.packets.NetworkPacket; +import lombok.*; + +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Getter +public class RequestSchematicSearchPacket extends NetworkPacket { + private static final long serialVersionUID = -6525229932332581648L; + + private int playerId; + private int schematicId; + private boolean ignoreBlockData; + private boolean ignoreAir; + private boolean airAsAny; + +} diff --git a/CommonCore/src/de/steamwar/network/packets/common/FightEndsPacket.java b/CommonCore/src/de/steamwar/network/packets/common/FightEndsPacket.java new file mode 100644 index 00000000..c1d86bb6 --- /dev/null +++ b/CommonCore/src/de/steamwar/network/packets/common/FightEndsPacket.java @@ -0,0 +1,42 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 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.network.packets.common; + +import de.steamwar.network.packets.NetworkPacket; +import lombok.*; + +import java.util.List; + +@Builder +@AllArgsConstructor +@NoArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Getter +public class FightEndsPacket extends NetworkPacket { + + private static final long serialVersionUID = 1279352415549011332L; + private byte win; + private int blueSchem; + private int redSchem; + private List bluePlayers; + private List redPlayers; + private String gameMode; + private int duration; +} diff --git a/CommonCore/src/de/steamwar/network/packets/common/FightInfoPacket.java b/CommonCore/src/de/steamwar/network/packets/common/FightInfoPacket.java new file mode 100644 index 00000000..bbca8b09 --- /dev/null +++ b/CommonCore/src/de/steamwar/network/packets/common/FightInfoPacket.java @@ -0,0 +1,49 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 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.network.packets.common; + +import de.steamwar.network.packets.NetworkPacket; +import lombok.*; + +import java.util.List; + +@Builder +@AllArgsConstructor +@NoArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Getter +public class FightInfoPacket extends NetworkPacket { + + private static final long serialVersionUID = 7448644597856605853L; + private @With String serverName; + private String gameMode; + private String arena; + private String blueName; + private String redName; + private String fightState; + private int countdown; + private int blueLeader; + private int redLeader; + private int blueSchem; + private int redSchem; + private List bluePlayers; + private List redPlayers; + private List spectators; +} diff --git a/CommonCore/src/de/steamwar/network/packets/server/BaumemberUpdatePacket.java b/CommonCore/src/de/steamwar/network/packets/server/BaumemberUpdatePacket.java new file mode 100644 index 00000000..5351473a --- /dev/null +++ b/CommonCore/src/de/steamwar/network/packets/server/BaumemberUpdatePacket.java @@ -0,0 +1,29 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 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.network.packets.server; + +import de.steamwar.network.packets.NetworkPacket; +import lombok.EqualsAndHashCode; + +@EqualsAndHashCode(callSuper = true) +public class BaumemberUpdatePacket extends NetworkPacket { + private static final long serialVersionUID = 6863118892424244051L; + +} diff --git a/CommonCore/src/de/steamwar/network/packets/server/CloseInventoryPacket.java b/CommonCore/src/de/steamwar/network/packets/server/CloseInventoryPacket.java new file mode 100644 index 00000000..e30d927f --- /dev/null +++ b/CommonCore/src/de/steamwar/network/packets/server/CloseInventoryPacket.java @@ -0,0 +1,36 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 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.network.packets.server; + +import de.steamwar.network.packets.NetworkPacket; +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@AllArgsConstructor +@NoArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Getter +public class CloseInventoryPacket extends NetworkPacket { + + private static final long serialVersionUID = -2191021190060504521L; + private int playerId; +} diff --git a/CommonCore/src/de/steamwar/network/packets/server/InventoryPacket.java b/CommonCore/src/de/steamwar/network/packets/server/InventoryPacket.java new file mode 100644 index 00000000..8e7f7b37 --- /dev/null +++ b/CommonCore/src/de/steamwar/network/packets/server/InventoryPacket.java @@ -0,0 +1,41 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 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.network.packets.server; + +import de.steamwar.network.packets.NetworkPacket; +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.Map; + +@AllArgsConstructor +@NoArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Getter +public class InventoryPacket extends NetworkPacket { + + private static final long serialVersionUID = 8071052544654047316L; + private String title; + private int player; + private int size; + private Map items; +} diff --git a/CommonCore/src/de/steamwar/network/packets/server/LocaleInvalidationPacket.java b/CommonCore/src/de/steamwar/network/packets/server/LocaleInvalidationPacket.java new file mode 100644 index 00000000..1e24547d --- /dev/null +++ b/CommonCore/src/de/steamwar/network/packets/server/LocaleInvalidationPacket.java @@ -0,0 +1,35 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 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.network.packets.server; + +import de.steamwar.network.packets.NetworkPacket; +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@AllArgsConstructor +@NoArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Getter +public class LocaleInvalidationPacket extends NetworkPacket { + private static final long serialVersionUID = 1113963147008168582L; + private int playerId; +} diff --git a/CommonCore/src/de/steamwar/network/packets/server/PingPacket.java b/CommonCore/src/de/steamwar/network/packets/server/PingPacket.java new file mode 100644 index 00000000..88ac32a8 --- /dev/null +++ b/CommonCore/src/de/steamwar/network/packets/server/PingPacket.java @@ -0,0 +1,35 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 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.network.packets.server; + +import de.steamwar.network.packets.NetworkPacket; +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Getter +public class PingPacket extends NetworkPacket { + private static final long serialVersionUID = 714647343959550378L; + private int id; +} diff --git a/CommonCore/src/de/steamwar/network/packets/server/StartingServerPacket.java b/CommonCore/src/de/steamwar/network/packets/server/StartingServerPacket.java new file mode 100644 index 00000000..f536d8fe --- /dev/null +++ b/CommonCore/src/de/steamwar/network/packets/server/StartingServerPacket.java @@ -0,0 +1,35 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 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.network.packets.server; + +import de.steamwar.network.packets.NetworkPacket; +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Getter +public class StartingServerPacket extends NetworkPacket { + private static final long serialVersionUID = 2808607245898121801L; + private int user; +} diff --git a/CommonCore/src/de/steamwar/sql/BannedUserIPs.java b/CommonCore/src/de/steamwar/sql/BannedUserIPs.java new file mode 100644 index 00000000..f5828177 --- /dev/null +++ b/CommonCore/src/de/steamwar/sql/BannedUserIPs.java @@ -0,0 +1,67 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2023 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.sql; + +import de.steamwar.sql.internal.Field; +import de.steamwar.sql.internal.SelectStatement; +import de.steamwar.sql.internal.Statement; +import de.steamwar.sql.internal.Table; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.sql.Timestamp; +import java.time.Instant; +import java.util.List; + +@AllArgsConstructor +public class BannedUserIPs { + + private static final Table table = new Table<>(BannedUserIPs.class); + + private static final SelectStatement getByID = table.selectFields("UserID"); + private static final SelectStatement getByIP = new SelectStatement<>(table, "SELECT * FROM BannedUserIPs WHERE IP = ? ORDER BY Timestamp DESC"); + private static final Statement banIP = table.insertAll(); + private static final Statement unbanIPs = table.deleteFields("UserID"); + + @Getter + @Field(keys = {Table.PRIMARY}) + private final int userID; + @Getter + @Field(def = "CURRENT_TIMESTAMP") + private final Timestamp timestamp; + @Field(keys = {Table.PRIMARY}) + private final String ip; + + public static List get(int userID) { + return getByID.listSelect(userID); + } + + public static List get(String ip) { + return getByIP.listSelect(ip); + } + + public static void banIP(int userID, String ip){ + banIP.update(userID, Timestamp.from(Instant.now()), ip); + } + + public static void unbanIPs(int userID) { + unbanIPs.update(userID); + } +} diff --git a/CommonCore/src/de/steamwar/sql/BauweltMember.java b/CommonCore/src/de/steamwar/sql/BauweltMember.java new file mode 100644 index 00000000..4efd9c38 --- /dev/null +++ b/CommonCore/src/de/steamwar/sql/BauweltMember.java @@ -0,0 +1,123 @@ +/* + 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.sql; + +import de.steamwar.sql.internal.Field; +import de.steamwar.sql.internal.SelectStatement; +import de.steamwar.sql.internal.Statement; +import de.steamwar.sql.internal.Table; +import lombok.Getter; + +import java.util.*; + +public class BauweltMember { + private static final Map memberCache = new HashMap<>(); + + public static void clear() { + memberCache.clear(); + } + + private static final Table table = new Table<>(BauweltMember.class); + private static final SelectStatement getMember = table.select(Table.PRIMARY); + private static final SelectStatement getMembers = table.selectFields("BauweltID"); + private static final Statement update = table.insertAll(); + private static final Statement delete = table.delete(Table.PRIMARY); + + public static void addMember(UUID ownerID, UUID memberID) { + new BauweltMember(SteamwarUser.get(ownerID).getId(), SteamwarUser.get(memberID).getId(), false, false).updateDB(); + } + + public static BauweltMember getBauMember(UUID ownerID, UUID memberID){ + return getBauMember(SteamwarUser.get(ownerID).getId(), SteamwarUser.get(memberID).getId()); + } + + public static BauweltMember getBauMember(int ownerID, int memberID){ + BauweltMember member = memberCache.get(memberID); + if(member != null && member.bauweltID == ownerID) + return member; + return getMember.select(ownerID, memberID); + } + + public static List getMembers(UUID bauweltID){ + return getMembers(SteamwarUser.get(bauweltID).getId()); + } + + public static List getMembers(int bauweltID){ + return getMembers.listSelect(bauweltID); + } + + @Getter + @Field(keys = {Table.PRIMARY}) + private final int bauweltID; + @Getter + @Field(keys = {Table.PRIMARY}) + private final int memberID; + @Getter + @Field(def = "0") + private boolean worldEdit; + @Getter + @Field(def = "0") + private boolean world; + + public BauweltMember(int bauweltID, int memberID, boolean worldEdit, boolean world) { + this.bauweltID = bauweltID; + this.memberID = memberID; + this.worldEdit = worldEdit; + this.world = world; + memberCache.put(memberID, this); + } + + public void setWorldEdit(boolean worldEdit) { + this.worldEdit = worldEdit; + updateDB(); + } + + public void setWorld(boolean world) { + this.world = world; + updateDB(); + } + + private void updateDB(){ + update.update(bauweltID, memberID, worldEdit, world); + } + + public void remove(){ + delete.update(bauweltID, memberID); + memberCache.remove(memberID); + } + + public boolean isBuild() { + return worldEdit; + } + + public boolean isSupervisor() { + return world; + } + + public void setBuild(boolean build) { + this.worldEdit = build; + updateDB(); + } + + public void setSupervisor(boolean supervisor) { + this.world = supervisor; + updateDB(); + } +} diff --git a/CommonCore/src/de/steamwar/sql/CheckedSchematic.java b/CommonCore/src/de/steamwar/sql/CheckedSchematic.java new file mode 100644 index 00000000..e173d413 --- /dev/null +++ b/CommonCore/src/de/steamwar/sql/CheckedSchematic.java @@ -0,0 +1,86 @@ +/* + 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.sql; + +import de.steamwar.sql.internal.Field; +import de.steamwar.sql.internal.SelectStatement; +import de.steamwar.sql.internal.Statement; +import de.steamwar.sql.internal.Table; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.sql.Timestamp; +import java.util.List; + +@AllArgsConstructor +public class CheckedSchematic { + + private static final Table table = new Table<>(CheckedSchematic.class); + private static final SelectStatement statusOfNode = new SelectStatement<>(table, "SELECT * FROM CheckedSchematic WHERE NodeId = ? AND DeclineReason != 'Prüfvorgang abgebrochen' ORDER BY EndTime DESC"); + private static final SelectStatement nodeHistory = new SelectStatement<>(table, "SELECT * FROM CheckedSchematic WHERE NodeId = ? AND DeclineReason != '' AND DeclineReason != 'Prüfvorgang abgebrochen' ORDER BY EndTime DESC"); + private static final Statement insert = table.insertAll(); + + public static void create(int nodeId, String name, int owner, int validator, Timestamp startTime, Timestamp endTime, String reason){ + insert.update(nodeId, owner, name, validator, startTime, endTime, reason); + } + + public static void create(SchematicNode node, int validator, Timestamp startTime, Timestamp endTime, String reason){ + create(node.getId(), node.getName(), node.getOwner(), validator, startTime, endTime, reason); + } + + public static List getLastDeclinedOfNode(int node){ + return statusOfNode.listSelect(node); + } + + public static List previousChecks(SchematicNode node) { + return nodeHistory.listSelect(node.getId()); + } + + @Field(nullable = true) + private final Integer nodeId; + @Field + private final int nodeOwner; + @Field + private final String nodeName; + @Getter + @Field + private final int validator; + @Getter + @Field + private final Timestamp startTime; + @Getter + @Field + private final Timestamp endTime; + @Getter + @Field + private final String declineReason; + + public int getNode() { + return nodeId; + } + + public String getSchemName() { + return nodeName; + } + + public int getSchemOwner() { + return nodeOwner; + } +} diff --git a/CommonCore/src/de/steamwar/sql/Event.java b/CommonCore/src/de/steamwar/sql/Event.java new file mode 100644 index 00000000..31c220ac --- /dev/null +++ b/CommonCore/src/de/steamwar/sql/Event.java @@ -0,0 +1,109 @@ +/* + 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.sql; + +import de.steamwar.sql.internal.Field; +import de.steamwar.sql.internal.SelectStatement; +import de.steamwar.sql.internal.Table; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.sql.Timestamp; +import java.time.Instant; +import java.util.List; + +@AllArgsConstructor +public class Event { + + static { + SchematicType.Normal.name(); // Ensure SchematicType is loaded. + } + + private static final Table table = new Table<>(Event.class); + + private static final SelectStatement byCurrent = new SelectStatement<>(table, "SELECT * FROM Event WHERE Start < now() AND End > now()"); + private static final SelectStatement byId = table.select(Table.PRIMARY); + private static final SelectStatement byName = table.select("eventName"); + private static final SelectStatement byComing = new SelectStatement<>(table, "SELECT * FROM Event WHERE Start > now()"); + + private static Event current = null; + + public static Event get(){ + if(current != null && current.now()) + return current; + + current = byCurrent.select(); + return current; + } + + public static Event get(int eventID){ + return byId.select(eventID); + } + + public static Event get(String eventName) { + return byName.select(eventName); + } + + public static List getComing() { + return byComing.listSelect(); + } + + @Getter + @Field(keys = {Table.PRIMARY}, autoincrement = true) + private final int eventID; + @Getter + @Field(keys = {"eventName"}) + private final String eventName; + @Getter + @Field + private final Timestamp deadline; + @Getter + @Field + private final Timestamp start; + @Getter + @Field + private final Timestamp end; + @Getter + @Field + private final int maximumTeamMembers; + @Field(nullable = true) + private final SchematicType schemType; + @Field + private final boolean publicSchemsOnly; + @Deprecated + @Field + private final boolean spectateSystem; + + public boolean publicSchemsOnly() { + return publicSchemsOnly; + } + public boolean spectateSystem(){ + return spectateSystem; + } + + public SchematicType getSchematicType() { + return schemType; + } + + private boolean now() { + Instant now = Instant.now(); + return now.isAfter(start.toInstant()) && now.isBefore(end.toInstant()); + } +} diff --git a/CommonCore/src/de/steamwar/sql/EventFight.java b/CommonCore/src/de/steamwar/sql/EventFight.java new file mode 100644 index 00000000..623e383a --- /dev/null +++ b/CommonCore/src/de/steamwar/sql/EventFight.java @@ -0,0 +1,136 @@ +/* + 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.sql; + +import de.steamwar.sql.internal.Field; +import de.steamwar.sql.internal.SelectStatement; +import de.steamwar.sql.internal.Statement; +import de.steamwar.sql.internal.Table; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.sql.Timestamp; +import java.util.*; + +import static java.time.temporal.ChronoUnit.SECONDS; + +@AllArgsConstructor +public class EventFight implements Comparable { + + private static final Table table = new Table<>(EventFight.class); + private static final SelectStatement byId = table.select(Table.PRIMARY); + private static final SelectStatement allComing = new SelectStatement<>(table, "SELECT * FROM EventFight WHERE StartTime > now() ORDER BY StartTime ASC"); + private static final SelectStatement event = new SelectStatement<>(table, "SELECT * FROM EventFight WHERE EventID = ? ORDER BY StartTime ASC"); + private static final Statement reschedule = table.update(Table.PRIMARY, "StartTime"); + private static final Statement setResult = table.update(Table.PRIMARY, "Ergebnis"); + private static final Statement setFight = table.update(Table.PRIMARY, "Fight"); + + private static final Queue fights = new PriorityQueue<>(); + + public static EventFight get(int fightID) { + return byId.select(fightID); + } + + public static void loadAllComingFights() { + fights.clear(); + fights.addAll(allComing.listSelect()); + } + + public static List getEvent(int eventID) { + return event.listSelect(eventID); + } + + public static Queue getFights() { + return fights; + } + + @Getter + @Field + private final int eventID; + @Getter + @Field(keys = {Table.PRIMARY}, autoincrement = true) + private final int fightID; + @Getter + @Field + private Timestamp startTime; + @Getter + @Field + private final String spielmodus; + @Getter + @Field + private final String map; + @Getter + @Field + private final int teamBlue; + @Getter + @Field + private final int teamRed; + @Getter + @Field + @Deprecated + private final int kampfleiter; + @Getter + @Field + private final int spectatePort; + @Getter + @Field(def = "0") + private int ergebnis; + @Field(nullable = true) + private int fight; + + public void setErgebnis(int winner) { + this.ergebnis = winner; + setResult.update(winner, fightID); + } + + public void setFight(int fight) { + //Fight.FightID, not EventFight.FightID + this.fight = fight; + setFight.update(fight, fightID); + } + + public boolean hasFinished() { + return fight != 0 || ergebnis != 0; + } + + public void reschedule() { + startTime = Timestamp.from(new Date().toInstant().plus(30, SECONDS)); + reschedule.update(startTime, fightID); + } + + @Override + public int hashCode(){ + return fightID; + } + + @Override + public boolean equals(Object o){ + if(o == null) + return false; + if(!(o instanceof EventFight)) + return false; + return fightID == ((EventFight) o).fightID; + } + + @Override + public int compareTo(EventFight o) { + return startTime.compareTo(o.startTime); + } +} diff --git a/CommonCore/src/de/steamwar/sql/Fight.java b/CommonCore/src/de/steamwar/sql/Fight.java new file mode 100644 index 00000000..efa230d2 --- /dev/null +++ b/CommonCore/src/de/steamwar/sql/Fight.java @@ -0,0 +1,124 @@ +/* + 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.sql; + +import de.steamwar.sql.internal.Field; +import de.steamwar.sql.internal.SelectStatement; +import de.steamwar.sql.internal.Statement; +import de.steamwar.sql.internal.Table; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +@AllArgsConstructor +public class Fight { + + private static final Table table = new Table<>(Fight.class); + private static final SelectStatement getPage = new SelectStatement<>(table, "SELECT f.*, (b.NodeId IS NULL OR b.AllowReplay) AND (r.NodeId IS NULL OR r.AllowReplay) AS ReplayAllowed, (SELECT COUNT(1) FROM Replay WHERE Replay.FightID = f.FightID) as ReplayAvailable FROM Fight f LEFT OUTER JOIN SchematicNode b ON f.BlueSchem = b.NodeId LEFT OUTER JOIN SchematicNode r ON f.RedSchem = r.NodeId ORDER BY FightID DESC LIMIT ?, ?"); + private static final Statement insert = table.insertFields(true, "GameMode", "Server", "StartTime", "Duration", "BlueLeader", "RedLeader", "BlueSchem", "RedSchem", "Win", "WinCondition"); + + public static List getPage(int page, int elementsPerPage) { + List fights = getPage.listSelect(page * elementsPerPage, elementsPerPage); + + List fightPlayers = FightPlayer.batchGet(fights.stream().map(f -> f.fightID)); + for(Fight fight : fights) { + fight.initPlayers(fightPlayers); + } + + SteamwarUser.batchCache(fightPlayers.stream().map(FightPlayer::getUserID).collect(Collectors.toSet())); + return fights; + } + + public static int create(String gamemode, String server, Timestamp starttime, int duration, int blueleader, int redleader, Integer blueschem, Integer redschem, int win, String wincondition){ + return insert.insertGetKey(gamemode, server, starttime, duration, blueleader, redleader, blueschem, redschem, win, wincondition); + } + + @Getter + @Field(keys = {Table.PRIMARY}, autoincrement = true) + private final int fightID; + @Field + private final String gameMode; + @Getter + @Field + private final String server; + @Getter + @Field + private final Timestamp startTime; + @Field + private final int duration; + @Field + private final int blueLeader; + @Field + private final int redLeader; + @Field(nullable = true) + private final Integer blueSchem; + @Field(nullable = true) + private final Integer redSchem; + @Getter + @Field + private final int win; + @Field + private final String wincondition; + @Field // Virtual field for easy select + private final boolean replayAllowed; + @Field // Virtual field for easy select + private final boolean replayAvailable; + + @Getter + private final List bluePlayers = new ArrayList<>(); + @Getter + private final List redPlayers = new ArrayList<>(); + + public SchematicType getSchemType() { + return SchematicType.fromDB(gameMode); + } + + public SteamwarUser getBlueLeader() { + return SteamwarUser.get(blueLeader); + } + + public SteamwarUser getRedLeader() { + return SteamwarUser.get(redLeader); + } + + public boolean replayAllowed() { + return replayExists() && replayAllowed; + } + + public boolean replayExists() { + return getSchemType() != null && replayAvailable; + } + + private void initPlayers(List fightPlayers) { + for(FightPlayer fp : fightPlayers) { + if(fp.getFightID() != fightID) + continue; + + if(fp.getTeam() == 1) + bluePlayers.add(fp); + else + redPlayers.add(fp); + } + } +} diff --git a/CommonCore/src/de/steamwar/sql/FightPlayer.java b/CommonCore/src/de/steamwar/sql/FightPlayer.java new file mode 100644 index 00000000..57b977c6 --- /dev/null +++ b/CommonCore/src/de/steamwar/sql/FightPlayer.java @@ -0,0 +1,65 @@ +/* + 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.sql; + +import de.steamwar.sql.internal.Field; +import de.steamwar.sql.internal.SelectStatement; +import de.steamwar.sql.internal.Statement; +import de.steamwar.sql.internal.Table; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +@AllArgsConstructor +public class FightPlayer { + + private static final Table table = new Table<>(FightPlayer.class); + private static final Statement create = table.insertAll(); + private static final SelectStatement batchGet = new SelectStatement<>(table, "SELECT * FROM FightPlayer WHERE FightID IN ?"); + + @Getter + @Field(keys = {Table.PRIMARY}) + private final int fightID; + @Getter + @Field(keys = {Table.PRIMARY}) + private final int userID; + @Getter + @Field + private final int team; + @Field + private final String kit; + @Field + private final int kills; + @Field + private final boolean isOut; + + public static void create(int fightID, int userID, boolean blue, String kit, int kills, boolean isOut) { + create.update(fightID, userID, blue ? 1 : 2, kit, kills, isOut); + } + + public static List batchGet(Stream fightIds) { + try (SelectStatement batch = new SelectStatement<>(table, "SELECT * FROM FightPlayer WHERE FightID IN (" + fightIds.map(Object::toString).collect(Collectors.joining(", ")) + ")")) { + return batch.listSelect(); + } + } +} diff --git a/CommonCore/src/de/steamwar/sql/IgnoreSystem.java b/CommonCore/src/de/steamwar/sql/IgnoreSystem.java new file mode 100644 index 00000000..d6ce26aa --- /dev/null +++ b/CommonCore/src/de/steamwar/sql/IgnoreSystem.java @@ -0,0 +1,59 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2023 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.sql; + +import de.steamwar.sql.internal.Field; +import de.steamwar.sql.internal.SelectStatement; +import de.steamwar.sql.internal.Statement; +import de.steamwar.sql.internal.Table; +import lombok.AllArgsConstructor; + +import java.sql.ResultSet; +import java.util.UUID; + +@AllArgsConstructor +public class IgnoreSystem { + + private static final Table table = new Table<>(IgnoreSystem.class, "IgnoredPlayers"); + private static final SelectStatement select = table.select(Table.PRIMARY); + private static final Statement insert = table.insertAll(); + private static final Statement delete = table.delete(Table.PRIMARY); + + @Field(keys = {Table.PRIMARY}) + private final int ignorer; + @Field(keys = {Table.PRIMARY}) + private final int ignored; + + public static boolean isIgnored(UUID ignorer, UUID ignored){ + return isIgnored(SteamwarUser.get(ignorer), SteamwarUser.get(ignored)); + } + + public static boolean isIgnored(SteamwarUser ignorer, SteamwarUser ignored) { + return select.select(ResultSet::next, ignorer.getId(), ignored.getId()); + } + + public static void ignore(SteamwarUser ignorer, SteamwarUser ignored) { + insert.update(ignorer.getId(), ignored.getId()); + } + + public static void unIgnore(SteamwarUser ignorer, SteamwarUser ignored) { + delete.update(ignorer.getId(), ignored.getId()); + } +} diff --git a/CommonCore/src/de/steamwar/sql/Mod.java b/CommonCore/src/de/steamwar/sql/Mod.java new file mode 100644 index 00000000..2a4e6981 --- /dev/null +++ b/CommonCore/src/de/steamwar/sql/Mod.java @@ -0,0 +1,101 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2023 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.sql; + +import de.steamwar.sql.internal.*; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.List; + +@AllArgsConstructor +public class Mod { + + static { + SqlTypeMapper.ordinalEnumMapper(Platform.class); + SqlTypeMapper.ordinalEnumMapper(ModType.class); + } + + private static final Table table = new Table<>(Mod.class, "Mods"); + private static final SelectStatement get = table.select(Table.PRIMARY); + private static final SelectStatement findFirst = new SelectStatement<>(table, "SELECT * FROM Mods WHERE ModType = 0 LIMIT 1"); + private static final SelectStatement getPageOfType = new SelectStatement<>(table, "SELECT * FROM Mods WHERE ModType = ? ORDER BY ModName DESC LIMIT ?, ?"); + private static final Statement insert = table.insert(Table.PRIMARY); + private static final Statement set = table.update(Table.PRIMARY, "ModType"); + + public static Mod get(String name, Platform platform) { + return get.select(platform, name); + } + + public static Mod getOrCreate(String name, Platform platform) { + Mod mod = get(name, platform); + if(mod != null) + return mod; + + insert.update(platform, name); + return new Mod(platform, name, ModType.UNKLASSIFIED); + } + + public static List getAllModsFiltered(int page, int elementsPerPage, Mod.ModType filter) { + return Mod.getPageOfType.listSelect(filter, page * elementsPerPage, elementsPerPage); + } + + public static Mod findFirstMod() { + return findFirst.select(); + } + + @Getter + @Field(keys = {Table.PRIMARY}) + private final Platform platform; + @Getter + @Field(keys = {Table.PRIMARY}) + private final String modName; + @Getter + @Field(def = "0") + private ModType modType; + + public void setModType(Mod.ModType modType) { + set.update(modType, platform, modName); + this.modType = modType; + } + + public enum Platform { + FORGE, + LABYMOD, + FABRIC + } + + public enum ModType { + UNKLASSIFIED("7"), + GREEN("a"), + YELLOW("e"), + RED("c"), + YOUTUBER_ONLY("6"); + + ModType(String colorcode) { + this.colorcode = colorcode; + } + private final String colorcode; + + public String getColorCode() { + return colorcode; + } + } +} diff --git a/CommonCore/src/de/steamwar/sql/NoClipboardException.java b/CommonCore/src/de/steamwar/sql/NoClipboardException.java new file mode 100644 index 00000000..97433485 --- /dev/null +++ b/CommonCore/src/de/steamwar/sql/NoClipboardException.java @@ -0,0 +1,23 @@ +/* + 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.sql; + +public class NoClipboardException extends RuntimeException { +} diff --git a/CommonCore/src/de/steamwar/sql/NodeData.java b/CommonCore/src/de/steamwar/sql/NodeData.java new file mode 100644 index 00000000..52743811 --- /dev/null +++ b/CommonCore/src/de/steamwar/sql/NodeData.java @@ -0,0 +1,92 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2023 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.sql; + +import de.steamwar.sql.internal.*; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.io.*; +import java.sql.PreparedStatement; +import java.util.zip.GZIPInputStream; + +@AllArgsConstructor +public class NodeData { + + static { + new SqlTypeMapper<>(PipedInputStream.class, "BLOB", (rs, identifier) -> { throw new SecurityException("PipedInputStream is write only datatype"); }, PreparedStatement::setBinaryStream); + new SqlTypeMapper<>(ByteArrayInputStream.class, "BLOB", (rs, identifier) -> { throw new SecurityException("ByteArrayInputStream is write only datatype"); }, PreparedStatement::setBinaryStream); + new SqlTypeMapper<>(BufferedInputStream.class, "BLOB", (rs, identifier) -> { throw new SecurityException("BufferedInputStream is write only datatype"); }, PreparedStatement::setBinaryStream); + } + + private static final Table table = new Table<>(NodeData.class); + + private static final Statement updateDatabase = new Statement("INSERT INTO NodeData(NodeId, NodeFormat, SchemData) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE NodeFormat = VALUES(NodeFormat), SchemData = VALUES(SchemData)"); + private static final Statement selSchemData = new Statement("SELECT SchemData FROM NodeData WHERE NodeId = ?"); + + private static final SelectStatement get = table.select(Table.PRIMARY); + + public static NodeData get(SchematicNode node) { + if(node.isDir()) + throw new IllegalArgumentException("Node is a directory"); + return get.select(rs -> { + if(rs.next()) { + return new NodeData(node.getId(), rs.getBoolean("NodeFormat")); + } else { + return new NodeData(node.getId(), false); + } + }, node); + } + + @Getter + @Field(keys = {Table.PRIMARY}) + private final int nodeId; + + @Field + private boolean nodeFormat; + + public InputStream schemData() throws IOException { + try { + return selSchemData.select(rs -> { + rs.next(); + InputStream schemData = rs.getBinaryStream("SchemData"); + try { + if(rs.wasNull() || schemData.available() == 0) { + throw new SecurityException("SchemData is null"); + } + return new GZIPInputStream(schemData); + } catch (IOException e) { + throw new SecurityException("SchemData is wrong", e); + } + }, nodeId); + } catch (Exception e) { + throw new IOException(e); + } + } + + public void saveFromStream(InputStream blob, boolean newFormat) { + updateDatabase.update(nodeId, newFormat, blob); + nodeFormat = newFormat; + } + + public boolean getNodeFormat() { + return nodeFormat; + } +} diff --git a/CommonCore/src/de/steamwar/sql/NodeDownload.java b/CommonCore/src/de/steamwar/sql/NodeDownload.java new file mode 100644 index 00000000..666cf681 --- /dev/null +++ b/CommonCore/src/de/steamwar/sql/NodeDownload.java @@ -0,0 +1,69 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2021 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.sql; + +import de.steamwar.sql.internal.Field; +import de.steamwar.sql.internal.Statement; +import de.steamwar.sql.internal.Table; +import lombok.AllArgsConstructor; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.sql.Timestamp; +import java.time.Instant; + +@AllArgsConstructor +public class NodeDownload { + + private static final char[] HEX = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + private static final String LINK_BASE = "https://steamwar.de/download.php?schem="; + + private static final Table table = new Table<>(NodeDownload.class); + private static final Statement insert = table.insertFields("NodeId", "Link"); + + @Field(keys = {Table.PRIMARY}) + private final int nodeId; + @Field + private final String link; + @Field(def = "CURRENT_TIMESTAMP") + private final Timestamp timestamp; + + public static String getLink(SchematicNode schem){ + if(schem.isDir()) + throw new SecurityException("Can not Download Directorys"); + MessageDigest digest; + try { + digest = MessageDigest.getInstance("SHA-1"); + } catch (NoSuchAlgorithmException e) { + throw new SecurityException(e); + } + digest.reset(); + digest.update((Instant.now().toString() + schem.getOwner() + schem.getId()).getBytes()); + String hash = base16encode(digest.digest()); + insert.update(schem.getId(), hash); + return LINK_BASE + hash; + } + public static String base16encode(byte[] byteArray) { + StringBuilder hexBuffer = new StringBuilder(byteArray.length * 2); + for (byte b : byteArray) + hexBuffer.append(HEX[(b >>> 4) & 0xF]).append(HEX[b & 0xF]); + return hexBuffer.toString(); + } +} diff --git a/CommonCore/src/de/steamwar/sql/NodeMember.java b/CommonCore/src/de/steamwar/sql/NodeMember.java new file mode 100644 index 00000000..e25764ec --- /dev/null +++ b/CommonCore/src/de/steamwar/sql/NodeMember.java @@ -0,0 +1,91 @@ +/* + * 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.sql; + +import de.steamwar.sql.internal.Field; +import de.steamwar.sql.internal.SelectStatement; +import de.steamwar.sql.internal.Statement; +import de.steamwar.sql.internal.Table; +import lombok.AllArgsConstructor; + +import java.util.HashSet; +import java.util.Optional; +import java.util.Set; + +@AllArgsConstructor +public class NodeMember { + + public static void init() { + // enforce class initialization + } + + private static final Table table = new Table<>(NodeMember.class); + private static final SelectStatement getNodeMember = table.select(Table.PRIMARY); + private static final SelectStatement getNodeMembers = table.selectFields("NodeId"); + private static final SelectStatement getSchematics = table.selectFields("UserId"); + private static final Statement create = table.insert(Table.PRIMARY); + private static final Statement delete = table.delete(Table.PRIMARY); + private static final Statement updateParent = table.update(Table.PRIMARY, "ParentId"); + + @Field(keys = {Table.PRIMARY}) + private final int nodeId; + @Field(keys = {Table.PRIMARY}) + private final int userId; + @Field(nullable = true, def = "null") + private Integer parentId; + + public int getNode() { + return nodeId; + } + + public int getMember() { + return userId; + } + + public Optional getParent() { + return Optional.ofNullable(parentId); + } + + public void delete() { + delete.update(nodeId, userId); + } + + public static NodeMember createNodeMember(int node, int member) { + create.update(node, member); + return new NodeMember(node, member, null); + } + + public static NodeMember getNodeMember(int node, int member) { + return getNodeMember.select(node, member); + } + + public static Set getNodeMembers(int node) { + return new HashSet<>(getNodeMembers.listSelect(node)); + } + + public static Set getSchematics(int member) { + return new HashSet<>(getSchematics.listSelect(member)); + } + + public void setParentId(Integer parentId) { + this.parentId = parentId; + updateParent.update(this.parentId, nodeId, userId); + } +} diff --git a/CommonCore/src/de/steamwar/sql/PollAnswer.java b/CommonCore/src/de/steamwar/sql/PollAnswer.java new file mode 100644 index 00000000..933f2536 --- /dev/null +++ b/CommonCore/src/de/steamwar/sql/PollAnswer.java @@ -0,0 +1,77 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2023 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.sql; + +import de.steamwar.sql.internal.Field; +import de.steamwar.sql.internal.SelectStatement; +import de.steamwar.sql.internal.Statement; +import de.steamwar.sql.internal.Table; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +import java.util.HashMap; +import java.util.Map; + +@AllArgsConstructor +public class PollAnswer { + + @Getter + @Setter + private static String currentPoll; + + private static final Table table = new Table<>(PollAnswer.class); + + private static final SelectStatement get = table.select(Table.PRIMARY); + private static final Statement getResults = new Statement("SELECT Count(UserID) AS Times, Answer FROM PollAnswer WHERE Question = ? GROUP BY Answer ORDER BY Times ASC"); + private static final Statement insert = table.insertAll(); + + @Field(keys = {Table.PRIMARY}) + private final int userID; + @Field(keys = {Table.PRIMARY}) + private final String question; + @Field(def = "0") + private int answer; + + public static PollAnswer get(int userID) { + PollAnswer answer = get.select(userID, currentPoll); + if(answer == null) + return new PollAnswer(userID, currentPoll, 0); + return answer; + } + + public static Map getCurrentResults() { + return getResults.select(rs -> { + Map retMap = new HashMap<>(); + while (rs.next()) + retMap.put(rs.getInt("Answer")-1, rs.getInt("Times")); + return retMap; + }, currentPoll); + } + + public boolean hasAnswered(){ + return answer != 0; + } + + public void setAnswer(int answer){ + this.answer = answer; + insert.update(userID, question, answer); + } +} diff --git a/CommonCore/src/de/steamwar/sql/Punishment.java b/CommonCore/src/de/steamwar/sql/Punishment.java new file mode 100644 index 00000000..5960dcef --- /dev/null +++ b/CommonCore/src/de/steamwar/sql/Punishment.java @@ -0,0 +1,140 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 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.sql; + +import de.steamwar.sql.internal.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +import java.sql.Timestamp; +import java.time.Instant; +import java.time.format.DateTimeFormatter; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; +import java.util.stream.Collectors; + +@AllArgsConstructor +public class Punishment { + + static { + SqlTypeMapper.nameEnumMapper(PunishmentType.class); + } + + public static final Timestamp PERMA_TIME = Timestamp.from(Instant.ofEpochSecond(946674800)); + + private static final Table table = new Table<>(Punishment.class, "Punishments"); + private static final SelectStatement getPunishments = new SelectStatement<>(table, "SELECT * FROM Punishments WHERE PunishmentId IN (SELECT MAX(PunishmentId) FROM Punishments WHERE UserId = ? GROUP BY Type)"); + private static final SelectStatement getPunishment = new SelectStatement<>(table, "SELECT * FROM Punishments WHERE UserId = ? AND Type = ? ORDER BY PunishmentId DESC LIMIT 1"); + private static final SelectStatement getAllPunishments = new SelectStatement<>(table, "SELECT * FROM Punishments WHERE UserId = ? ORDER BY `PunishmentId` DESC"); + private static final Statement insert = table.insertFields(true, "UserId", "Punisher", "Type", "EndTime", "Perma", "Reason"); + + public static Punishment getPunishmentOfPlayer(int user, PunishmentType type) { + return getPunishment.select(user, type); + } + + public static Map getPunishmentsOfPlayer(int user) { + return getPunishments.listSelect(user).stream().collect(Collectors.toMap(Punishment::getType, punishment -> punishment)); + } + + public static List getAllPunishmentsOfPlayer(int user) { + return getAllPunishments.listSelect(user); + } + + public static boolean isPunished(SteamwarUser user, Punishment.PunishmentType type, Consumer callback) { + Punishment punishment = Punishment.getPunishmentOfPlayer(user.getId(), type); + if(punishment == null || !punishment.isCurrent()) { + return false; + } else { + callback.accept(punishment); + return true; + } + } + + public static Punishment createPunishment(int user, int executor, PunishmentType type, String reason, Timestamp endTime, boolean perma) { + if(perma && !endTime.equals(PERMA_TIME)) { + throw new IllegalArgumentException("Permanent punishments must have an end time of `Punishment.PERMA_TIME`"); + } + int punishmentId = insert.insertGetKey(user, executor, type.name(), endTime, perma, reason); + return new Punishment(punishmentId, user, executor, type, Timestamp.from(Instant.now()), endTime, perma, reason); + } + + @Field(keys = {Table.PRIMARY}, autoincrement = true) + private final int punishmentId; + @Field + @Getter + private final int userId; + @Field + @Getter + private final int punisher; + @Field + @Getter + private final PunishmentType type; + @Field + @Getter + private final Timestamp startTime; + @Field + @Getter + private final Timestamp endTime; + @Field + @Getter + private final boolean perma; + @Field + @Getter + private final String reason; + + @Deprecated // Not multiling, misleading title + public String getBantime(Timestamp endTime, boolean perma) { + if (perma) { + return "permanent"; + } else { + return endTime.toLocalDateTime().format(DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm")); + } + } + + public boolean isCurrent() { + return isPerma() || getEndTime().after(new Date()); + } + + @AllArgsConstructor + @RequiredArgsConstructor + @Getter + public enum PunishmentType { + Ban(false, "BAN_TEAM", "BAN_PERMA", "BAN_UNTIL", "UNBAN_ERROR", "UNBAN"), + Mute( false, "MUTE_TEAM", "MUTE_PERMA", "MUTE_UNTIL", "UNMUTE_ERROR", "UNMUTE"), + NoSchemReceiving(false, "NOSCHEMRECEIVING_TEAM", "NOSCHEMRECEIVING_PERMA", "NOSCHEMRECEIVING_UNTIL", "UNNOSCHEMRECEIVING_ERROR", "UNNOSCHEMRECEIVING"), + NoSchemSharing(false, "NOSCHEMSHARING_TEAM", "NOSCHEMSHARING_PERMA", "NOSCHEMSHARING_UNTIL", "UNNOSCHEMSHARING_ERROR", "UNNOSCHEMSHARING"), + NoSchemSubmitting(true, "NOSCHEMSUBMITTING_TEAM", "NOSCHEMSUBMITTING_PERMA", "NOSCHEMSUBMITTING_UNTIL", "UNNOSCHEMSUBMITTING_ERROR", "UNNOSCHEMSUBMITTING"), + NoDevServer(true, "NODEVSERVER_TEAM", "NODEVSERVER_PERMA", "NODEVSERVER_UNTIL", "UNNODEVSERVER_ERROR", "UNNODEVSERVER"), + NoFightServer(false, "NOFIGHTSERVER_TEAM", "NOFIGHTSERVER_PERMA", "NOFIGHTSERVER_UNTIL", "UNNOFIGHTSERVER_ERROR", "UNNOFIGHTSERVER"), + NoTeamServer(true, "NOTEAMSERVER_TEAM", "NOTEAMSERVER_PERMA", "NOTEAMSERVER_UNTIL", "UNNOTEAMSERVER_ERROR", "UNNOTEAMSERVER"), + Note(false, "NOTE_TEAM", null, null, null, null, true); + + private final boolean needsAdmin; + private final String teamMessage; + private final String playerMessagePerma; + private final String playerMessageUntil; + private final String usageNotPunished; + private final String unpunishmentMessage; + private boolean multi = false; + } +} diff --git a/CommonCore/src/de/steamwar/sql/Referee.java b/CommonCore/src/de/steamwar/sql/Referee.java new file mode 100644 index 00000000..281ad302 --- /dev/null +++ b/CommonCore/src/de/steamwar/sql/Referee.java @@ -0,0 +1,44 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2024 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.sql; + +import de.steamwar.sql.internal.Field; +import de.steamwar.sql.internal.SelectStatement; +import de.steamwar.sql.internal.Table; +import lombok.AllArgsConstructor; + +import java.util.Set; +import java.util.stream.Collectors; + +@AllArgsConstructor +public class Referee { + + private static final Table table = new Table<>(Referee.class); + private static final SelectStatement byEvent = table.selectFields("eventID"); + + public static Set get(int eventID) { + return byEvent.listSelect(eventID).stream().map(referee -> referee.userID).collect(Collectors.toSet()); + } + + @Field(keys = {"eventReferee"}) + private final int eventID; + @Field(keys = {"eventReferee"}) + private final int userID; +} diff --git a/CommonCore/src/de/steamwar/sql/Replay.java b/CommonCore/src/de/steamwar/sql/Replay.java new file mode 100644 index 00000000..a90e2392 --- /dev/null +++ b/CommonCore/src/de/steamwar/sql/Replay.java @@ -0,0 +1,74 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 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.sql; + +import de.steamwar.sql.internal.*; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; +import java.sql.SQLException; + +@AllArgsConstructor +public class Replay { + + static { + new SqlTypeMapper<>(File.class, "BLOB", (rs, identifier) -> { + try { + File file = File.createTempFile("replay", ".replay"); + file.deleteOnExit(); + Files.copy(rs.getBinaryStream(identifier), file.toPath(), StandardCopyOption.REPLACE_EXISTING); + return file; + } catch (IOException e) { + throw new SQLException(e); + } + }, (st, index, value) -> { + try { + st.setBinaryStream(index, new FileInputStream(value)); + } catch (FileNotFoundException e) { + throw new SQLException(e); + } + }); + } + + private static final Table table = new Table<>(Replay.class); + private static final SelectStatement get = table.select(Table.PRIMARY); + + public static final Statement insert = table.insertAll(); + + public static Replay get(int fightID) { + return get.select(fightID); + } + + public static void save(int fightID, File file) { + insert.update(fightID, file); + } + + @Field(keys = {Table.PRIMARY}) + private final int fightID; + @Getter + @Field + private final File replay; +} diff --git a/CommonCore/src/de/steamwar/sql/SQLWrapper.java b/CommonCore/src/de/steamwar/sql/SQLWrapper.java new file mode 100644 index 00000000..cff7dec9 --- /dev/null +++ b/CommonCore/src/de/steamwar/sql/SQLWrapper.java @@ -0,0 +1,33 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 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.sql; + +import de.steamwar.ImplementationProvider; + +import java.util.List; +import java.util.Map; + +public interface SQLWrapper { + SQLWrapper impl = ImplementationProvider.getImpl("de.steamwar.sql.SQLWrapperImpl"); + + void loadSchemTypes(List tmpTypes, Map tmpFromDB); + + void additionalExceptionMetadata(StringBuilder builder); +} diff --git a/CommonCore/src/de/steamwar/sql/SWException.java b/CommonCore/src/de/steamwar/sql/SWException.java new file mode 100644 index 00000000..4656804a --- /dev/null +++ b/CommonCore/src/de/steamwar/sql/SWException.java @@ -0,0 +1,68 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 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.sql; + +import de.steamwar.sql.internal.Field; +import de.steamwar.sql.internal.Statement; +import de.steamwar.sql.internal.Table; +import lombok.AllArgsConstructor; + +import java.io.File; +import java.sql.Timestamp; + +@AllArgsConstructor +public class SWException { + + public static void init() { + // force class initialialisation + } + + private static final String CWD = System.getProperty("user.dir"); + private static final String SERVER_NAME = new File(CWD).getName(); + + private static final Table table = new Table<>(SWException.class, "Exception"); + private static final Statement insert = table.insertFields(true, "server", "message", "stacktrace"); + + @Field(keys = {Table.PRIMARY}, autoincrement = true) + private final int id; + @Field(def = "CURRENT_TIMESTAMP") + private final Timestamp time; + @Field + private final String server; + @Field + private final String message; + @Field + private final String stacktrace; + + public static void log(String message, String stacktrace){ + insert.update(SERVER_NAME, generateMessage(message), stacktrace); + } + + public static int logGetId(String message, String stacktrace) { + return insert.insertGetKey(SERVER_NAME, generateMessage(message), stacktrace); + } + + private static String generateMessage(String message) { + StringBuilder msgBuilder = new StringBuilder(message); + SQLWrapper.impl.additionalExceptionMetadata(msgBuilder); + msgBuilder.append("\nCWD: ").append(CWD); + return msgBuilder.toString(); + } +} diff --git a/CommonCore/src/de/steamwar/sql/SchemElo.java b/CommonCore/src/de/steamwar/sql/SchemElo.java new file mode 100644 index 00000000..0e92cfd5 --- /dev/null +++ b/CommonCore/src/de/steamwar/sql/SchemElo.java @@ -0,0 +1,56 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 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.sql; + +import de.steamwar.sql.internal.Field; +import de.steamwar.sql.internal.SelectStatement; +import de.steamwar.sql.internal.Statement; +import de.steamwar.sql.internal.Table; +import lombok.AllArgsConstructor; + +@AllArgsConstructor +public class SchemElo { + private static final int ELO_DEFAULT = 1000; + + private static final Table table = new Table<>(SchemElo.class); + private static final SelectStatement select = table.select(Table.PRIMARY); + private static final Statement setElo = table.insertAll(); + + public static int getElo(SchematicNode node, int season) { + SchemElo elo = select.select(node, season); + return elo != null ? elo.elo : 0; + } + + public static int getCurrentElo(int schemID) { + SchemElo elo = select.select(schemID, Season.getSeason()); + return elo != null ? elo.elo : ELO_DEFAULT; + } + + public static void setElo(int schemID, int elo) { + setElo.update(schemID, elo, Season.getSeason()); + } + + @Field(keys = {Table.PRIMARY}) + private final int schemId; + @Field + private final int elo; + @Field(keys = {Table.PRIMARY}) + private final int season; +} diff --git a/CommonCore/src/de/steamwar/sql/SchematicNode.java b/CommonCore/src/de/steamwar/sql/SchematicNode.java new file mode 100644 index 00000000..b432a709 --- /dev/null +++ b/CommonCore/src/de/steamwar/sql/SchematicNode.java @@ -0,0 +1,559 @@ +/* + * 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.sql; + +import de.steamwar.sql.internal.*; +import lombok.Getter; + +import java.sql.Timestamp; +import java.time.Instant; +import java.util.*; +import java.util.function.Predicate; + +public class SchematicNode { + + static { + SchematicType.Normal.name(); // Ensure SchematicType is loaded. + new SqlTypeMapper<>(SchematicNode.class, null, (rs, identifier) -> { throw new SecurityException("SchematicNode cannot be used as type (recursive select)"); }, (st, index, value) -> st.setInt(index, value.nodeId)); + } + + private static final Map>> TAB_CACHE = new HashMap<>(); + public static void clear() { + TAB_CACHE.clear(); + } + + private static final String nodeSelector = "SELECT NodeId, NodeOwner, NodeOwner AS EffectiveOwner, NodeName, ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, ReplaceColor, AllowReplay FROM SchematicNode "; + + private static final Table table = new Table<>(SchematicNode.class); + private static final Statement create = table.insertFields(true, "NodeOwner", "NodeName", "ParentNode", "NodeItem", "NodeType"); + private static final Statement update = table.update(Table.PRIMARY, "NodeName", "ParentNode", "NodeItem", "NodeType", "NodeRank", "ReplaceColor", "AllowReplay"); + private static final Statement delete = table.delete(Table.PRIMARY); + + private static final SelectStatement byId = new SelectStatement<>(table, nodeSelector + "WHERE NodeId = ?"); + private static final SelectStatement byOwnerNameParent = new SelectStatement<>(table, nodeSelector + "WHERE NodeOwner = ? AND NodeName = ? AND ParentNode " + Statement.NULL_SAFE_EQUALS + "?"); + private static final SelectStatement byParent = new SelectStatement<>(table, nodeSelector + "WHERE ParentNode" + Statement.NULL_SAFE_EQUALS + "? ORDER BY NodeName"); + private static final SelectStatement dirsByParent = new SelectStatement<>(table, nodeSelector + "WHERE ParentNode" + Statement.NULL_SAFE_EQUALS + "? AND NodeType is NULL ORDER BY NodeName"); + private static final SelectStatement byOwnerType = new SelectStatement<>(table, nodeSelector + "WHERE NodeOwner = ? AND NodeType = ? ORDER BY NodeName"); + private static final SelectStatement byType = new SelectStatement<>(table, nodeSelector + "WHERE NodeType = ? ORDER BY NodeName"); + private static final SelectStatement all = new SelectStatement<>(table, "SELECT * FROM EffectiveSchematicNode WHERE EffectiveOwner = ? ORDER BY NodeName"); + private static final SelectStatement list = new SelectStatement<>(table, "SELECT SchematicNode.NodeId, NodeOwner, ? AS EffectiveOwner, NodeName, NM.ParentId AS ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, ReplaceColor, AllowReplay FROM SchematicNode INNER JOIN NodeMember NM on SchematicNode.NodeId = NM.NodeId WHERE NM.ParentId " + Statement.NULL_SAFE_EQUALS + "? AND NM.UserId = ? UNION ALL SELECT SchematicNode.NodeId, NodeOwner, ? AS EffectiveOwner, NodeName, ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, ReplaceColor, AllowReplay FROM SchematicNode WHERE (? IS NULL AND ParentNode IS NULL AND NodeOwner = ?) OR (? IS NOT NULL AND ParentNode = ?) ORDER BY NodeName"); + private static final SelectStatement byParentName = new SelectStatement<>(table, "SELECT SchematicNode.NodeId, NodeOwner, ? AS EffectiveOwner, NodeName, NM.ParentId AS ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, ReplaceColor, AllowReplay FROM SchematicNode INNER JOIN NodeMember NM on SchematicNode.NodeId = NM.NodeId WHERE NM.ParentId " + Statement.NULL_SAFE_EQUALS + "? AND NM.UserId = ? AND SchematicNode.NodeName = ? UNION ALL SELECT SchematicNode.NodeId, NodeOwner, ? AS EffectiveOwner, NodeName, ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, ReplaceColor, AllowReplay FROM SchematicNode WHERE ((? IS NULL AND ParentNode IS NULL AND NodeOwner = ?) OR (? IS NOT NULL AND ParentNode = ?)) AND NodeName = ?"); + private static final SelectStatement schematicAccessibleForUser = new SelectStatement<>(table, "SELECT COUNT(DISTINCT NodeId) FROM EffectiveSchematicNode WHERE EffectiveOwner = ? AND NodeId = ?"); + private static final SelectStatement accessibleByUserTypeInParent = new SelectStatement<>(table, "WITH RECURSIVE RSASN AS(WITH RECURSIVE RSAN AS (WITH RSANH AS (WITH RECURSIVE RSA AS (SELECT SN.NodeId, NM.ParentId FROM SchematicNode SN LEFT JOIN NodeMember NM on SN.NodeId = NM.NodeId WHERE NM.UserId = ? UNION SELECT SN.NodeId, SN.ParentNode FROM SchematicNode SN INNER JOIN RSA ON RSA.NodeId = SN.ParentNode) SELECT * FROM RSA UNION SELECT NodeId, ParentNode FROM SchematicNode WHERE NodeOwner = ?) SELECT * FROM RSANH UNION SELECT SN.NodeId, SN.ParentNode FROM RSANH JOIN SchematicNode SN ON SN.ParentNode = RSANH.NodeId) SELECT RSAN.NodeId, RSAN.ParentId FROM RSAN JOIN SchematicNode SN ON SN.NodeId = RSAN.NodeId WHERE NodeType = ? UNION SELECT SN.NodeId, SN.ParentNode FROM SchematicNode SN JOIN RSASN ON SN.NodeId = RSASN.ParentId) SELECT SN.*, ? as EffectiveOwner, RSASN.ParentId AS ParentNode FROM RSASN JOIN SchematicNode SN ON SN.NodeId = RSASN.NodeId WHERE RSASN.ParentId" + Statement.NULL_SAFE_EQUALS + "? ORDER BY NodeName"); + private static final SelectStatement accessibleByUserType = new SelectStatement<>(table, "WITH RECURSIVE Nodes AS (SELECT NodeId, ParentId as ParentNode FROM NodeMember WHERE UserId = ? UNION SELECT NodeId, ParentNode FROM SchematicNode WHERE NodeOwner = ?), RSN AS ( SELECT NodeId, ParentNode FROM Nodes UNION SELECT SN.NodeId, SN.ParentNode FROM SchematicNode SN, RSN WHERE SN.ParentNode = RSN.NodeId ) SELECT SN.*, ? AS EffectiveOwner FROM RSN INNER JOIN SchematicNode SN ON RSN.NodeId = SN.NodeId WHERE NodeType = ?"); + private static final SelectStatement byIdAndUser = new SelectStatement<>(table, "SELECT NodeId, NodeOwner, ? AS EffectiveOwner, NodeName, ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, ReplaceColor, AllowReplay FROM SchematicNode WHERE NodeId = ?"); + private static final SelectStatement allParentsOfNode = new SelectStatement<>(table, "WITH RECURSIVE R AS (SELECT NodeId, ParentNode FROM EffectiveSchematicNode WHERE NodeId = ? AND EffectiveOwner = ? UNION SELECT E.NodeId, E.ParentNode FROM R, EffectiveSchematicNode E WHERE R.ParentNode = E.NodeId AND E.EffectiveOwner = ?) SELECT SN.NodeId, SN.NodeOwner, ? AS EffectiveOwner, SN.NodeName, R.ParentNode, SN.LastUpdate, SN.NodeItem, SN.NodeType, SN.NodeRank, SN.ReplaceColor, SN.AllowReplay FROM R INNER JOIN SchematicNode SN ON SN.NodeId = R.NodeId"); + + static { + NodeMember.init(); + } + + @Field(keys = {Table.PRIMARY}, autoincrement = true) + private final int nodeId; + @Field(keys = {"OwnerNameParent"}) + private final int nodeOwner; + @Field(def = "0") + @Getter + private final int effectiveOwner; + @Field(keys = {"OwnerNameParent"}) + private String nodeName; + @Field(keys = {"OwnerNameParent"}, nullable = true) + private Integer parentNode; + @Field(def = "CURRENT_TIMESTAMP") + private Timestamp lastUpdate; + @Field(def = "''") + private String nodeItem; + @Field(def = "'normal'", nullable = true) + private SchematicType nodeType; + @Field(def = "0") + private int nodeRank; + @Field(def = "1") + private boolean replaceColor; + @Field(def = "1") + private boolean allowReplay; + + private String brCache; + + public SchematicNode( + int nodeId, + int nodeOwner, + int effectiveOwner, + String nodeName, + Integer parentNode, + Timestamp lastUpdate, + String nodeItem, + SchematicType nodeType, + int nodeRank, + boolean replaceColor, + boolean allowReplay + ) { + this.nodeId = nodeId; + this.nodeOwner = nodeOwner; + this.effectiveOwner = effectiveOwner; + this.nodeName = nodeName; + this.parentNode = parentNode; + this.nodeItem = nodeItem; + this.nodeType = nodeType; + this.lastUpdate = lastUpdate; + this.nodeRank = nodeRank; + this.replaceColor = replaceColor; + this.allowReplay = allowReplay; + } + + public static List getAll(SteamwarUser user) { + return all.listSelect(user); + } + + public static Map> getAllMap(SteamwarUser user) { + return map(getAll(user)); + } + + public static List list(SteamwarUser user, Integer schematicId) { + return list.listSelect(user, schematicId, user, user, schematicId, user, schematicId, schematicId); + } + + public static SchematicNode byParentName(SteamwarUser user, Integer schematicId, String name) { + return byParentName.select(user, schematicId, user, name, user, schematicId, user, schematicId, schematicId, name); + } + + public static List accessibleByUserType(SteamwarUser user, SchematicType type) { + return accessibleByUserType.listSelect(user, user, user, type); + } + + public static Map> accessibleByUserTypeMap(SteamwarUser user, SchematicType type) { + return map(accessibleByUserType(user, type)); + } + + public static boolean schematicAccessibleForUser(SteamwarUser user, Integer schematicId) { + return schematicAccessibleForUser.select(user, schematicId) != null; + } + + public static List accessibleByUserTypeParent(SteamwarUser user, SchematicType type, Integer parentId) { + return accessibleByUserTypeInParent.listSelect(user, user, type, user, parentId); + } + + public static SchematicNode byIdAndUser(SteamwarUser user, Integer id) { + return byIdAndUser.select(user, id); + } + + public static List parentsOfNode(SteamwarUser user, Integer id) { + return allParentsOfNode.listSelect(id, user, user, user); + } + + private static Map> map(List in) { + Map> map = new HashMap<>(); + for (SchematicNode effectiveSchematicNode : in) { + map.computeIfAbsent(effectiveSchematicNode.getOptionalParent().orElse(0), k -> new ArrayList<>()).add(effectiveSchematicNode); + } + return map; + } + + public static SchematicNode createSchematic(int owner, String name, Integer parent) { + return createSchematicNode(owner, name, parent, SchematicType.Normal.toDB(), ""); + } + + public static SchematicNode createSchematicDirectory(int owner, String name, Integer parent) { + return createSchematicNode(owner, name, parent, null, ""); + } + + public static SchematicNode createSchematicNode(int owner, String name, Integer parent, String type, String item) { + if (parent != null && parent == 0) + parent = null; + int nodeId = create.insertGetKey(owner, name, parent, item, type); + return getSchematicNode(nodeId); + } + + public static SchematicNode getSchematicNode(int owner, String name, SchematicNode parent) { + return getSchematicNode(owner, name, parent.getId()); + } + + public static SchematicNode getSchematicNode(int owner, String name, Integer parent) { + return byOwnerNameParent.select(owner, name, parent); + } + + public static List getSchematicNodeInNode(SchematicNode parent) { + return getSchematicNodeInNode(parent.getId()); + } + + public static List getSchematicNodeInNode(Integer parent) { + return byParent.listSelect(parent); + } + + public static List getSchematicDirectoryInNode(Integer parent) { + return dirsByParent.listSelect(parent); + } + + @Deprecated + public static SchematicNode getSchematicDirectory(String name, SchematicNode parent) { + return getSchematicNode(name, parent.getId()); + } + + @Deprecated + public static SchematicNode getSchematicDirectory(String name, Integer parent) { + return getSchematicNode(name, parent); + } + + public static SchematicNode getSchematicNode(String name, Integer parent) { + return byParentName.select(name, parent); + } + + public static SchematicNode getSchematicNode(int id) { + return byId.select(id); + } + + public static List getAccessibleSchematicsOfTypeInParent(int owner, String schemType, Integer parent) { + return accessibleByUserTypeParent(SteamwarUser.get(owner), SchematicType.fromDB(schemType), parent); + } + + public static List getAllAccessibleSchematicsOfType(int user, String schemType) { + return accessibleByUserType(SteamwarUser.get(user), SchematicType.fromDB(schemType)); + } + + public static List getAllSchematicsOfType(int owner, String schemType) { + return byOwnerType.listSelect(owner, schemType); + } + + @Deprecated + public static List getAllSchematicsOfType(String schemType) { + return byType.listSelect(schemType); + } + + public static List getAllSchematicsOfType(SchematicType schemType) { + return byType.listSelect(schemType); + } + + public static List deepGet(Integer parent, Predicate filter) { + List finalList = new ArrayList<>(); + List nodes = SchematicNode.getSchematicNodeInNode(parent); + nodes.forEach(node -> { + if (node.isDir()) { + finalList.addAll(deepGet(node.getId(), filter)); + } else { + if (filter.test(node)) + finalList.add(node); + } + }); + return finalList; + } + + @Deprecated + public static List getSchematicsAccessibleByUser(int user, Integer parent) { + return list(SteamwarUser.get(user), parent); + } + + @Deprecated + public static List getAllSchematicsAccessibleByUser(int user) { + return getAll(SteamwarUser.get(user)); + } + + public static List getAllParentsOfNode(SchematicNode node) { + return getAllParentsOfNode(node.getId()); + } + + public static List getAllParentsOfNode(int node) { + return allParentsOfNode.listSelect(node); + } + + public static SchematicNode getNodeFromPath(SteamwarUser user, String s) { + if (s.startsWith("/")) { + s = s.substring(1); + } + if (s.endsWith("/")) { + s = s.substring(0, s.length() - 1); + } + if (s.isEmpty()) { + return null; + } + if (s.contains("/")) { + String[] layers = s.split("/"); + Optional currentNode = Optional.ofNullable(SchematicNode.byParentName(user, null, layers[0])); + for (int i = 1; i < layers.length; i++) { + int finalI = i; + Optional node = currentNode.map(effectiveSchematicNode -> SchematicNode.byParentName(user, effectiveSchematicNode.getId(), layers[finalI])); + if (!node.isPresent()) { + return null; + } else { + currentNode = node; + if (!currentNode.map(SchematicNode::isDir).orElse(false) && i != layers.length - 1) { + return null; + } + } + } + return currentNode.orElse(null); + } else { + return SchematicNode.byParentName(user, null, s); + } + } + + public static List filterSchems(int user, Predicate filter) { + List finalList = new ArrayList<>(); + List nodes = getSchematicsAccessibleByUser(user, null); + nodes.forEach(node -> { + if (node.isDir()) { + finalList.addAll(deepGet(node.getId(), filter)); + } else { + if (filter.test(node)) + finalList.add(node); + } + }); + return finalList; + } + + public int getId() { + return nodeId; + } + + public int getOwner() { + return nodeOwner; + } + + public String getName() { + return nodeName; + } + + public void setName(String name) { + this.nodeName = name; + updateDB(); + } + + public Integer getParent() { + return parentNode; + } + + public Optional getOptionalParent() { + return Optional.ofNullable(parentNode); + } + + public void setParent(Integer parent) { + this.parentNode = parent; + updateDB(); + } + + public String getItem() { + if (nodeItem.isEmpty()) { + return isDir() ? "CHEST" : "CAULDRON_ITEM"; + } + return nodeItem; + } + + public void setItem(String item) { + this.nodeItem = item; + updateDB(); + } + + @Deprecated + public String getType() { + return nodeType.name(); + } + + @Deprecated + public void setType(String type) { + if(isDir()) + throw new SecurityException("Node is Directory"); + this.nodeType = SchematicType.fromDB(type); + updateDB(); + } + + public boolean isDir() { + return nodeType == null; + } + + @Deprecated + public boolean getSchemFormat() { + if(isDir()) + throw new SecurityException("Node is Directory"); + return NodeData.get(this).getNodeFormat(); + } + + public int getRank() { + if(isDir()) + throw new SecurityException("Node is Directory"); + return nodeRank; + } + + @Deprecated + public int getRankUnsafe() { + return nodeRank; + } + + public void setRank(int rank) { + if(isDir()) + throw new SecurityException("Node is Directory"); + this.nodeRank = rank; + } + + public SchematicType getSchemtype() { + if(isDir()) + throw new SecurityException("Is Directory"); + return nodeType; + } + + public void setSchemtype(SchematicType type) { + if(isDir()) + throw new SecurityException("Is Directory"); + this.nodeType = type; + updateDB(); + } + + public boolean replaceColor() { + return replaceColor; + } + + public void setReplaceColor(boolean replaceColor) { + if(isDir()) + throw new SecurityException("Is Directory"); + this.replaceColor = replaceColor; + updateDB(); + } + + public boolean allowReplay() { + return allowReplay; + } + + public void setAllowReplay(boolean allowReplay) { + if(isDir()) + throw new SecurityException("Is Directory"); + this.allowReplay = allowReplay; + updateDB(); + } + + public SchematicNode getParentNode() { + if(parentNode == null) return null; + return SchematicNode.getSchematicNode(parentNode); + } + + public int getElo(int season) { + return SchemElo.getElo(this, season); + } + + public boolean accessibleByUser(int user) { + return NodeMember.getNodeMember(nodeId, user) != null; + } + + public Set getMembers() { + return NodeMember.getNodeMembers(nodeId); + } + + public Timestamp getLastUpdate() { + return lastUpdate; + } + + private void updateDB() { + this.lastUpdate = Timestamp.from(Instant.now()); + update.update(nodeName, parentNode, nodeItem, nodeType, nodeRank, replaceColor, allowReplay, nodeId); + TAB_CACHE.clear(); + } + + public void delete() { + delete.update(nodeId); + } + + @Override + public int hashCode() { + return nodeId; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof SchematicNode)) + return false; + + return ((SchematicNode) obj).getId() == nodeId; + } + + public String generateBreadcrumbs(SteamwarUser user) { + return byIdAndUser(user, nodeId).generateBreadcrumbs(); + } + + public String generateBreadcrumbs(String split, SteamwarUser user) { + return byIdAndUser(user, nodeId).generateBreadcrumbs(split); + } + + public String generateBreadcrumbs() { + if(brCache == null) { + brCache = generateBreadcrumbs("/"); + } + return brCache; + } + + public String generateBreadcrumbs(String split) { + StringBuilder builder = new StringBuilder(getName()); + Optional currentNode = Optional.of(this); + if(currentNode.map(SchematicNode::isDir).orElse(false)) { + builder.append(split); + } + while (currentNode.isPresent()) { + currentNode = currentNode.flatMap(schematicNode -> Optional.ofNullable(NodeMember.getNodeMember(schematicNode.getId(), effectiveOwner)).map(NodeMember::getParent).orElse(schematicNode.getOptionalParent())).map(SchematicNode::getSchematicNode); + currentNode.ifPresent(node -> builder.insert(0, split).insert(0, node.getName())); + } + return builder.toString(); + } + + private static final List FORBIDDEN_NAMES = Collections.unmodifiableList(Arrays.asList("public")); + public static boolean invalidSchemName(String[] layers) { + for (String layer : layers) { + if (layer.isEmpty()) { + return true; + } + if (layer.contains("/") || + layer.contains("\\") || + layer.contains("<") || + layer.contains(">") || + layer.contains("^") || + layer.contains("°") || + layer.contains("'") || + layer.contains("\"") || + layer.contains(" ")) { + return true; + } + if(FORBIDDEN_NAMES.contains(layer.toLowerCase())) { + return true; + } + } + return false; + } + + public static List getNodeTabcomplete(SteamwarUser user, String s) { + boolean sws = s.startsWith("/"); + if (sws) { + s = s.substring(1); + } + int index = s.lastIndexOf("/"); + String cacheKey = index == -1 ? "" : s.substring(0, index); + if(TAB_CACHE.containsKey(user.getId()) && TAB_CACHE.get(user.getId()).containsKey(cacheKey)) { + return new ArrayList<>(TAB_CACHE.get(user.getId()).get(cacheKey)); + } + List list = new ArrayList<>(); + if (s.contains("/")) { + String preTab = s.substring(0, s.lastIndexOf("/") + 1); + SchematicNode pa = SchematicNode.getNodeFromPath(user, preTab); + if (pa == null) return new ArrayList<>(); + List nodes = SchematicNode.list(user, pa.getId()); + String br = pa.generateBreadcrumbs(); + nodes.forEach(node -> list.add((sws ? "/" : "") + br + node.getName() + (node.isDir() ? "/" : ""))); + } else { + List nodes = SchematicNode.list(user, null); + nodes.forEach(node -> list.add((sws ? "/" : "") + node.getName() + (node.isDir() ? "/" : ""))); + } + list.remove("//copy"); + TAB_CACHE.computeIfAbsent(user.getId(), integer -> new HashMap<>()).putIfAbsent(cacheKey, list); + return list; + } +} diff --git a/CommonCore/src/de/steamwar/sql/SchematicType.java b/CommonCore/src/de/steamwar/sql/SchematicType.java new file mode 100644 index 00000000..0ee483a8 --- /dev/null +++ b/CommonCore/src/de/steamwar/sql/SchematicType.java @@ -0,0 +1,124 @@ +/* + 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.sql; + +import de.steamwar.sql.internal.SqlTypeMapper; +import lombok.Getter; + +import java.util.*; + +public class SchematicType { + + public static final SchematicType Normal = new SchematicType("Normal", "", Type.NORMAL, null, "STONE_BUTTON", false); + + private static final Map fromDB; + private static final List types; + + static { + List tmpTypes = new LinkedList<>(); + Map tmpFromDB = new HashMap<>(); + + tmpTypes.add(Normal); + tmpFromDB.put(Normal.name().toLowerCase(), Normal); + + SQLWrapper.impl.loadSchemTypes(tmpTypes, tmpFromDB); + + fromDB = Collections.unmodifiableMap(tmpFromDB); + types = Collections.unmodifiableList(tmpTypes); + } + + static { + new SqlTypeMapper<>(SchematicType.class, "VARCHAR(16)", (rs, identifier) -> { + String t = rs.getString(identifier); + return t != null ? fromDB.get(t) : null; + }, (st, index, value) -> st.setString(index, value.toDB())); + } + + private final String name; + @Getter + private final String kuerzel; + private final Type type; + private final SchematicType checkType; + @Getter + private final String material; + @Getter + private final Date deadline; + @Getter + private final boolean manualCheck; + + SchematicType(String name, String kuerzel, Type type, SchematicType checkType, String material, boolean manualCheck){ + this(name, kuerzel, type, checkType, material, null, manualCheck); + } + + SchematicType(String name, String kuerzel, Type type, SchematicType checkType, String material, Date deadline, boolean manualCheck){ + this.name = name; + this.kuerzel = kuerzel; + this.type = type; + this.checkType = checkType; + this.material = material; + this.deadline = deadline; + this.manualCheck = manualCheck; + } + + public boolean isAssignable(){ + return type == Type.NORMAL || (type == Type.FIGHT_TYPE && checkType != null) || !manualCheck; + } + + public SchematicType checkType(){ + if (!manualCheck) { + return this; + } + return checkType; + } + + public boolean check(){ + return type == Type.CHECK_TYPE; + } + + public boolean fightType(){ + return type == Type.FIGHT_TYPE; + } + + public boolean writeable(){ + return type == Type.NORMAL; + } + + public String name(){ + return name; + } + + public String toDB(){ + return name.toLowerCase(); + } + + public static SchematicType fromDB(String input){ + return fromDB.get(input.toLowerCase()); + } + + public static List values(){ + return types; + } + + enum Type{ + NORMAL, + CHECK_TYPE, + FIGHT_TYPE + } +} diff --git a/CommonCore/src/de/steamwar/sql/Script.java b/CommonCore/src/de/steamwar/sql/Script.java new file mode 100644 index 00000000..9691c439 --- /dev/null +++ b/CommonCore/src/de/steamwar/sql/Script.java @@ -0,0 +1,84 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2023 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.sql; + +import de.steamwar.sql.internal.Field; +import de.steamwar.sql.internal.SelectStatement; +import de.steamwar.sql.internal.Statement; +import de.steamwar.sql.internal.Table; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.List; + +@AllArgsConstructor +@Getter +public class Script { + + private static final Table