diff --git a/src/de/steamwar/bungeecore/BungeeCore.java b/src/de/steamwar/bungeecore/BungeeCore.java index f2bd01f..65fd3ce 100644 --- a/src/de/steamwar/bungeecore/BungeeCore.java +++ b/src/de/steamwar/bungeecore/BungeeCore.java @@ -24,14 +24,14 @@ import de.steamwar.bungeecore.bot.config.SteamwarDiscordBotConfig; import de.steamwar.bungeecore.commands.*; import de.steamwar.bungeecore.comms.SpigotReceiver; import de.steamwar.bungeecore.listeners.*; -import de.steamwar.bungeecore.listeners.mods.ModLoaderBlocker; import de.steamwar.bungeecore.listeners.mods.Forge; import de.steamwar.bungeecore.listeners.mods.LabyMod; +import de.steamwar.bungeecore.listeners.mods.ModLoaderBlocker; import de.steamwar.bungeecore.listeners.mods.WorldDownloader; -import de.steamwar.bungeecore.sql.SQL; +import de.steamwar.bungeecore.sql.Punishment; +import de.steamwar.bungeecore.sql.Statement; import de.steamwar.bungeecore.sql.SteamwarUser; import de.steamwar.bungeecore.sql.Team; -import net.dv8tion.jda.api.JDA; import net.md_5.bungee.api.ChatMessageType; import net.md_5.bungee.api.CommandSender; import net.md_5.bungee.api.ProxyServer; @@ -71,6 +71,8 @@ public class BungeeCore extends Plugin { public static final Map serverPermissions = new HashMap<>(); public static final Map commands = new HashMap<>(); + private ErrorLogger errorLogger; + @Override public void onEnable(){ getProxy().registerChannel("sw:bridge"); @@ -78,7 +80,7 @@ public class BungeeCore extends Plugin { setInstance(this); loadConfig(); - new ErrorLogger(); + errorLogger = new ErrorLogger(); new ConnectionListener(); new Forge(); new LabyMod(); @@ -89,9 +91,10 @@ public class BungeeCore extends Plugin { new WorldDownloader(); new BrandListener(); - commands.put("/b", null); - commands.put("/gs", null); - commands.put("/bau", null); + new Node.LocalNode(); + //new Node.RemoteNode("lx"); + //new Node.RemoteNode("az"); + commands.put("/tp", null); commands.put("/bc", null); commands.put("/bauchat", null); @@ -106,8 +109,6 @@ public class BungeeCore extends Plugin { new JoinmeCommand(); new TpCommand(); new HelpCommand(); - new BanCommand(); - new UnbanCommand(); new DenyCommand("watchcat", "wc"); new TeamCommand(); new ServerTeamchatCommand(); @@ -116,7 +117,6 @@ public class BungeeCore extends Plugin { new EventreloadCommand(); new EventRescheduleCommand(); new PollCommand(); - new MuteCommand(); new BugCommand(); new WhoisCommand(); new RegelnCommand(); @@ -129,7 +129,16 @@ public class BungeeCore extends Plugin { new StatCommand(); new VerifyCommand(); + // Punishment Commands: + new PunishmentCommand("ban", Punishment.PunishmentType.Ban); + new PunishmentCommand("mute", Punishment.PunishmentType.Mute); + new PunishmentCommand("noschemreceiving", Punishment.PunishmentType.NoSchemReceiving); + new PunishmentCommand("noschemsharing", Punishment.PunishmentType.NoSchemSharing); + new PunishmentCommand("noschemsubmitting", Punishment.PunishmentType.NoSchemSubmitting); + new PunishmentCommand("nodev", Punishment.PunishmentType.NoDevServer); + if(!EVENT_MODE){ + new BauCommand(); new WebregisterCommand(); new FightCommand(); new ChallengeCommand(); @@ -145,25 +154,32 @@ public class BungeeCore extends Plugin { new EventStarter(); new SessionManager(); new SpigotReceiver(); - new SteamwarDiscordBot(); new TablistManager(); getProxy().getScheduler().schedule(this, () -> { SteamwarUser.clearCache(); Team.clearCache(); }, 1, 1, TimeUnit.HOURS); + + if (SteamwarDiscordBotConfig.loaded) { + try { + new SteamwarDiscordBot(); + } catch (Throwable e) { + getLogger().log(Level.SEVERE, "Could not initialize discord bot", e); + } + } } @Override public void onDisable(){ - ErrorLogger.stop(); - SQL.close(); try { - SteamwarDiscordBot.instance().getJda().shutdownNow(); - SteamwarDiscordBot.instance().getJda().awaitStatus(JDA.Status.SHUTDOWN); - } catch (Exception e) { - // Ignored + SteamwarDiscordBot.instance().getJda().shutdown(); + } catch (Throwable e) { + getLogger().log(Level.SEVERE, "Could not shutdown discord bot", e); } + + errorLogger.unregister(); + Statement.close(); } public static BungeeCore get() { @@ -258,14 +274,16 @@ public class BungeeCore extends Plugin { Persistent.setChatPrefix(CHAT_PREFIX); Persistent.setLobbyServer(LOBBY_SERVER); - SQL.connect( + Statement.connect( config.getString("db.url"), config.getString("db.username"), config.getString("db.password") ); ArenaMode.init(config.getSection("games")); - SteamwarDiscordBotConfig.loadConfig(config.getSection("discord")); + if (config.getSection("discord") != null) { + SteamwarDiscordBotConfig.loadConfig(config.getSection("discord")); + } final Configuration servers = config.getSection("servers"); for(final String serverName : servers.getKeys()){ diff --git a/src/de/steamwar/bungeecore/ErrorLogger.java b/src/de/steamwar/bungeecore/ErrorLogger.java index 5f4ab53..80b417f 100644 --- a/src/de/steamwar/bungeecore/ErrorLogger.java +++ b/src/de/steamwar/bungeecore/ErrorLogger.java @@ -20,83 +20,55 @@ package de.steamwar.bungeecore; import de.steamwar.bungeecore.sql.SWException; -import net.md_5.bungee.api.ProxyServer; +import de.steamwar.bungeecore.sql.Statement; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; import java.text.MessageFormat; -import java.util.logging.Filter; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import java.util.logging.Handler; import java.util.logging.Level; import java.util.logging.LogRecord; +import java.util.logging.Logger; -public class ErrorLogger extends Handler implements Filter { - private static ErrorLogger instance; +public class ErrorLogger extends Handler { private int ddosRate = 0; ErrorLogger(){ - ProxyServer.getInstance().getLogger().addHandler(this); - ProxyServer.getInstance().getLogger().setFilter(this); - instance = this; + Logger.getLogger("").addHandler(this); } - static void stop(){ - ProxyServer.getInstance().getLogger().removeHandler(instance); + void unregister(){ + Logger.getLogger("").removeHandler(this); } @Override - public boolean isLoggable(LogRecord record) { - if(record.getLevel() != Level.SEVERE) - return true; + public void publish(LogRecord logRecord) { + if(logRecord.getLevel().intValue() < Level.WARNING.intValue()) + return; - StringBuilder stacktrace = new StringBuilder(record.getSourceClassName() + "\n" + record.getSourceMethodName()); - Throwable thrown = record.getThrown(); - while(thrown != null){ - stacktrace.append("\nCaused by ").append(thrown.getMessage()); + String message = MessageFormat.format(logRecord.getMessage(), logRecord.getParameters()); + for(String reason : ignoreContains) + if(message.contains(reason)) + return; - for(StackTraceElement ste : thrown.getStackTrace()) - stacktrace.append("\n").append(ste.toString()); - - thrown = thrown.getCause(); - } - - String stacktraceString = stacktrace.toString(); - if(stacktraceString.contains("Cannot request protocol")){ - ddosRate++; - if(ddosRate % 1000 == 0){ + ByteArrayOutputStream stacktraceOutput = new ByteArrayOutputStream(); + if(logRecord.getThrown() != null) + logRecord.getThrown().printStackTrace(new PrintStream(stacktraceOutput)); + String stacktrace = stacktraceOutput.toString(); + if(stacktrace.contains("Cannot request protocol")) { + if(++ddosRate % 1000 == 0) { SWException.log("Bungee", "DDOS", ddosRate + ""); } - return false; - } - return true; - } - - @Override - public void publish(LogRecord record) { - if(record.getLevel() != Level.SEVERE && record.getLevel() != Level.WARNING) return; - - StringBuilder stacktrace = new StringBuilder(record.getSourceClassName() + "\n" + record.getSourceMethodName()); - Throwable thrown = record.getThrown(); - while(thrown != null){ - stacktrace.append("\nCaused by ").append(thrown.getMessage()); - - for(StackTraceElement ste : thrown.getStackTrace()) - stacktrace.append("\n").append(ste.toString()); - - thrown = thrown.getCause(); + } else if (!Statement.connectionStable()) { + return; } - String stacktraceString = stacktrace.toString(); - String message = MessageFormat.format(record.getMessage(), record.getParameters()); - if(message.contains("ServerConnector") - || message.contains("InitialHandler") - || message.contains("UpstreamBridge") - || message.contains("DownstreamBridge") - || message.contains(" took ") - || message.contains("No client connected for pending server!")) - return; - - SWException.log("Bungee", message, stacktraceString); + SWException.log("Bungee", message, stacktrace); } @Override @@ -108,4 +80,17 @@ public class ErrorLogger extends Handler implements Filter { public void close() { //ignored } + + private static final List ignoreContains; + + static { + List contains = new ArrayList<>(); + contains.add("ServerConnector"); + contains.add("InitialHandler"); + contains.add("UpstreamBridge"); + contains.add("DownstreamBridge"); + contains.add(" took "); + contains.add("No client connected for pending server!"); + ignoreContains = Collections.unmodifiableList(contains); + } } diff --git a/src/de/steamwar/bungeecore/LoadEvaluation.java b/src/de/steamwar/bungeecore/LoadEvaluation.java deleted file mode 100644 index 59fda6c..0000000 --- a/src/de/steamwar/bungeecore/LoadEvaluation.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * 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.bungeecore; - -import java.io.*; - -public class LoadEvaluation { - private LoadEvaluation(){} - - private static final File meminfo = new File("/proc/meminfo"); - - public static double getRamPercentage() { - try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(meminfo)))) { - String memTotal = bufferedReader.readLine().replaceAll(" +", " "); - bufferedReader.readLine(); - String memAvailable = bufferedReader.readLine().replaceAll(" +", " "); - - long memTotalLong = getNumber(memTotal); - long memAvailableLong = getNumber(memAvailable); - return (memTotalLong - memAvailableLong) / (double) memTotalLong; - } catch (IOException e) { - return 1D; - } - } - - public static double getRemoteRamPercentage(String remote) { - try { - // Attention: - // memInfo.sh needs to contain: cat /proc/meminfo - Process process = new ProcessBuilder("ssh", remote, "\"./memInfo.sh\"").start(); - process.waitFor(); - BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream())); - String memTotal = bufferedReader.readLine().replaceAll(" +", " "); - bufferedReader.readLine(); - String memAvailable = bufferedReader.readLine().replaceAll(" +", " "); - - long memTotalLong = getNumber(memTotal); - long memAvailableLong = getNumber(memAvailable); - return (memTotalLong - memAvailableLong) / (double) memTotalLong; - } catch (IOException e) { - return 1D; - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - return 1D; - } - } - - public static double getCPULoad() { - try { - Process process = new ProcessBuilder("bash", "-c", "cat <(grep 'cpu ' /proc/stat) <(sleep 1 && grep 'cpu ' /proc/stat) | awk -v RS=\"\" '{printf \"%.2f\\n\", ($13-$2+$15-$4)*100/($13-$2+$15-$4+$16-$5)}'").start(); - process.waitFor(); - return Double.parseDouble(new BufferedReader(new InputStreamReader(process.getInputStream())).readLine()) / 100.0; - } catch (IOException e) { - return 1D; - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - return 1D; - } - } - - public static double getRemoteCPULoad(String remote) { - try { - // Attention: - // cpuLoad.sh needs to contain: cat <(grep 'cpu ' /proc/stat) <(sleep 1 && grep 'cpu ' /proc/stat) | awk -v RS="" '{printf "%.2f\n", ($13-$2+$15-$4)*100/($13-$2+$15-$4+$16-$5)}' - Process process = new ProcessBuilder("ssh", remote, "\"./cpuLoad.sh\"").start(); - process.waitFor(); - return Double.parseDouble(new BufferedReader(new InputStreamReader(process.getInputStream())).readLine()) / 100.0; - } catch (IOException e) { - return 1D; - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - return 1D; - } - } - - private static long getNumber(String s) { - return Long.parseLong(s.split(" ")[1]); - } -} diff --git a/src/de/steamwar/bungeecore/Node.java b/src/de/steamwar/bungeecore/Node.java new file mode 100644 index 0000000..9c714c6 --- /dev/null +++ b/src/de/steamwar/bungeecore/Node.java @@ -0,0 +1,263 @@ +/* + 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.bungeecore; + +import net.md_5.bungee.api.ProxyServer; + +import java.io.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; +import java.util.logging.Level; + +public abstract class Node { + + private static final List OPENJDK8_ARGS = Arrays.asList("-Dlog4j.configurationFile=log4j2.xml", "-server", "-Xms128M", "-XX:+UseCompressedOops", "-XX:+TieredCompilation", "-XX:TargetSurvivorRatio=90", "-XX:SurvivorRatio=8", "-XX:MaxTenuringThreshold=15", "-XX:+UnlockExperimentalVMOptions", "-XX:+UseBiasedLocking", "-XX:UseSSE=3", "-XX:+UseCodeCacheFlushing", "-XX:+UseThreadPriorities", "-XX:+AggressiveOpts", "-XX:+ReduceSignalUsage", "-XX:+UseInterpreter", "-XX:+UseSharedSpaces", "-XX:AllocatePrefetchStyle=1", "-XX:+AlwaysCompileLoopMethods", "-XX:+UseConcMarkSweepGC", "-XX:+RewriteFrequentPairs", "-XX:+OptimizeStringConcat", "-XX:+CMSCleanOnEnter", "-XX:+UseInlineCaches", "-XX:ThreadPriorityPolicy=42", "-XX:SharedReadOnlySize=30m", "-XX:+UseFastEmptyMethods", "-XX:+UseFastAccessorMethods"); + private static final List OPENJ9_ARGS = Arrays.asList("-Xgc:excessiveGCratio=80", "-Xsyslog:none", "-Xtrace:none", "-Xdisableexplicitgc", "-XX:+AlwaysPreTouch", "-XX:+CompactStrings", "-XX:-HeapDumpOnOutOfMemory", "-XX:+ExitOnOutOfMemoryError", "-Dlog4j.configurationFile=log4j2.xml"); + private static final double MIN_FREE_MEM = 4.0 * 1024 * 1024; // 4 GiB + + private static final List nodes = new ArrayList<>(); + public static Node local = null; + + public static Node getNode() { + Node node = local; + double minLoad = local.getLoad(); + if(minLoad < 0.5) + return local; + + synchronized (nodes) { + Iterator it = nodes.iterator(); + while(it.hasNext()) { + Node n = it.next(); + double load = n.getLoad(); + if (load < minLoad) { + minLoad = load; + node = n; + } else if (load == Double.POSITIVE_INFINITY) { + BungeeCore.get().getLogger().log(Level.SEVERE, "Removing " + n.getName() + " due to infinite load!"); + it.remove(); + } + } + } + return node; + } + + public static void forEach(Consumer consumer) { + consumer.accept(local); + synchronized (nodes) { + nodes.forEach(consumer); + } + } + + public abstract ProcessBuilder startServer(String serverJar, File directory, String worldDir, String levelName, int port, String xmx, String... dParams); + public abstract void execute(String... command); + public abstract String getName(); + public abstract double getLoad(); + + protected void constructServerstart(File directory, List cmd, String serverJar, String worldDir, String levelName, int port, String xmx, String... dParams) { + boolean openjdk8 = !serverJar.contains("1.8.9") && !serverJar.contains("1.15.2"); + if(openjdk8) + cmd.add("java"); + else + cmd.add("/usr/lib/jvm/java-16-openj9-amd64/bin/java"); + + for(String param : dParams){ + cmd.add("-D" + param); + } + cmd.add("-Xmx" + xmx); + if(openjdk8) + cmd.addAll(OPENJDK8_ARGS); + else { + cmd.add("-Xshareclasses:nonfatal,name=" + directory.getName()); + cmd.addAll(OPENJ9_ARGS); + } + cmd.add("-jar"); + cmd.add("/binarys/" + serverJar); + cmd.add("--log-strip-color"); + cmd.add("--world-dir"); + cmd.add(worldDir); + cmd.add("--level-name"); + cmd.add(levelName); + cmd.add("--port"); + cmd.add(String.valueOf(port)); + cmd.add("nogui"); + } + + protected void execute(ProcessBuilder builder) { + try { + builder.start().waitFor(); + } catch (IOException e) { + throw new SecurityException("Could not execute command", e); + } catch (InterruptedException e) { + ProxyServer.getInstance().getLogger().log(Level.SEVERE, "Interrupted during execution", e); + Thread.currentThread().interrupt(); + } + } + + public static class LocalNode extends Node { + private static final File meminfo = new File("/proc/meminfo"); + private static final File loadavg = new File("/proc/loadavg"); + + private final int cores; + + public LocalNode() { + this.cores = Runtime.getRuntime().availableProcessors(); + local = this; + } + + @Override + public ProcessBuilder startServer(String serverJar, File directory, String worldDir, String levelName, int port, String xmx, String... dParams) { + List cmd = new ArrayList<>(); + constructServerstart(directory, cmd, serverJar, worldDir, levelName, port, xmx, dParams); + ProcessBuilder builder = new ProcessBuilder(cmd); + builder.directory(directory); + return builder; + } + + @Override + public void execute(String... command) { + execute(new ProcessBuilder(command)); + } + + @Override + public String getName() { + return "local"; + } + + @Override + public double getLoad() { + double totalMem; + double freeMem; + try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(meminfo)))) { + totalMem = Double.parseDouble(bufferedReader.readLine().replaceAll(" +", " ").split(" ")[1]); + bufferedReader.readLine(); + freeMem = Double.parseDouble(bufferedReader.readLine().replaceAll(" +", " ").split(" ")[1]); + } catch (IOException e) { + throw new SecurityException("Could not read local memory", e); + } + + double cpuLoad; + try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(loadavg)))) { + cpuLoad = Double.parseDouble(bufferedReader.readLine().split(" ")[0]); + } catch (IOException e) { + throw new SecurityException("Could not read local cpu", e); + } + + return cpuLoad / cores + (freeMem > MIN_FREE_MEM ? 0 : ((totalMem - freeMem) / totalMem)); + } + } + + public static class RemoteNode extends Node { + private final int cores; + private final String remote; + + public RemoteNode(String remote) { + this.remote = remote; + + //Determine core count + Process process; + try { + process = new ProcessBuilder("ssh", remote, "nproc").start(); + if(!process.waitFor(5, TimeUnit.SECONDS)) + throw new IOException("Timeout of " + remote + " on init"); + } catch (IOException e) { + BungeeCore.get().getLogger().log(Level.SEVERE, "Could not initialize " + remote); + cores = 1; + return; + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + cores = 1; + return; + } + + int c; + try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()))) { + c = Integer.parseInt(bufferedReader.readLine()); + } catch (IOException | NumberFormatException e) { + BungeeCore.get().getLogger().log(Level.SEVERE, "Could not read cores of" + remote, e); + c = 1; + } + cores = c; + BungeeCore.get().getLogger().log(Level.INFO, "Adding node " + remote + " with " + cores + " cores."); + + synchronized (nodes) { + nodes.add(this); + } + } + + @Override + public ProcessBuilder startServer(String serverJar, File directory, String worldDir, String levelName, int port, String xmx, String... dParams) { + List cmd = new ArrayList<>(); + cmd.add("ssh"); + cmd.add("-L"); + cmd.add(port + ":localhost:" + port); + cmd.add(remote); + cmd.add("cd"); + cmd.add(directory.getPath()); + cmd.add(";"); + constructServerstart(directory, cmd, serverJar, worldDir, levelName, port, xmx, dParams); + return new ProcessBuilder(cmd); + } + + @Override + public void execute(String... command) { + List cmd = new ArrayList<>(); + cmd.add("ssh"); + cmd.add(remote); + cmd.addAll(Arrays.asList(command)); + execute(new ProcessBuilder(cmd)); + } + + @Override + public String getName() { + return remote; + } + + @Override + public double getLoad() { + Process process; + try { + process = new ProcessBuilder("ssh", remote, "cat /proc/loadavg;cat /proc/meminfo").start(); + if(!process.waitFor(1, TimeUnit.SECONDS)) + return Double.POSITIVE_INFINITY; + } catch (IOException e) { + BungeeCore.get().getLogger().log(Level.SEVERE, "Could starting process to read load", e); + return Double.POSITIVE_INFINITY; + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + return Double.POSITIVE_INFINITY; + } + + try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()))) { + double cpuLoad = Double.parseDouble(bufferedReader.readLine().split(" ")[0]); + double totalMem = Double.parseDouble(bufferedReader.readLine().replaceAll(" +", " ").split(" ")[1]); + bufferedReader.readLine(); + double freeMem = Double.parseDouble(bufferedReader.readLine().replaceAll(" +", " ").split(" ")[1]); + return cpuLoad / cores + (freeMem > MIN_FREE_MEM ? 0 : ((totalMem - freeMem) / totalMem)); + } catch (IOException e) { + BungeeCore.get().getLogger().log(Level.SEVERE, "Could read load", e); + return Double.POSITIVE_INFINITY; + } + } + } +} diff --git a/src/de/steamwar/bungeecore/SubserverSystem.java b/src/de/steamwar/bungeecore/SubserverSystem.java index d5e85b0..9e08df5 100644 --- a/src/de/steamwar/bungeecore/SubserverSystem.java +++ b/src/de/steamwar/bungeecore/SubserverSystem.java @@ -27,30 +27,23 @@ import net.md_5.bungee.api.chat.ClickEvent; import net.md_5.bungee.api.connection.ProxiedPlayer; import java.io.File; -import java.io.IOException; import java.net.InetSocketAddress; import java.time.format.DateTimeFormatter; -import java.util.*; -import java.util.logging.Level; +import java.util.Set; +import java.util.UUID; +import java.util.stream.Collectors; public class SubserverSystem { private SubserverSystem(){} - private static final String BACKBONE = "/home/minecraft/backbone/"; - private static final List JVM_ARGS = Arrays.asList("-Dlog4j.configurationFile=log4j2.xml", "-server", "-Xms128M", "-XX:+UseCompressedOops", "-XX:+TieredCompilation", "-XX:TargetSurvivorRatio=90", "-XX:SurvivorRatio=8", "-XX:MaxTenuringThreshold=15", "-XX:+UnlockExperimentalVMOptions", "-XX:+UseBiasedLocking", "-XX:UseSSE=3", "-XX:+UseCodeCacheFlushing", "-XX:+UseThreadPriorities", "-XX:+AggressiveOpts", "-XX:+ReduceSignalUsage", "-XX:+UseInterpreter", "-XX:+UseSharedSpaces", "-XX:AllocatePrefetchStyle=1", "-XX:+AlwaysCompileLoopMethods", "-XX:+UseConcMarkSweepGC", "-XX:+RewriteFrequentPairs", "-XX:+OptimizeStringConcat", "-XX:+CMSCleanOnEnter", "-XX:+UseInlineCaches"); - private static final List JVM8_ARGS = Arrays.asList("-XX:ThreadPriorityPolicy=42", "-XX:SharedReadOnlySize=30m", "-XX:+UseFastEmptyMethods", "-XX:+UseFastAccessorMethods"); + private static final String BACKBONE = "/home/minecraft/"; private static final String ARENA_PATH = BACKBONE + "arenaserver/"; private static final String SERVER_PATH = BACKBONE + "server/"; private static final String EVENT_PATH = BACKBONE + "event/"; - private static final int FIRST_ARENA_PORT; - - static { - if(BungeeCore.EVENT_MODE) - FIRST_ARENA_PORT = 6000; - else - FIRST_ARENA_PORT = 2500; - } + private static final boolean MAIN_SERVER = ProxyServer.getInstance().getConfig().getListeners().stream().anyMatch(info -> ((InetSocketAddress) info.getSocketAddress()).getPort() == 25565); + private static final Portrange bauPorts = MAIN_SERVER ? new Portrange(10100, 20000) : new Portrange(2100, 2200); + private static final Portrange arenaPorts = MAIN_SERVER ? new Portrange(3000, 3100) : (BungeeCore.EVENT_MODE ? new Portrange(4000, 5000) : bauPorts); /** * This function starts every arena (even test- and eventarenas). @@ -91,13 +84,14 @@ public class SubserverSystem { */ public static synchronized Subserver startArena(ArenaMode modus, String map, int eventFightID, int checkSchemID, int prepareSchemID, String serverName, String mapName, UUID player1, UUID player2, boolean ranked){ //Generate missing parameters - int port = freePort(FIRST_ARENA_PORT); + Node node = eventFightID > 0 ? Node.local : Node.getNode(); + int port = arenaPorts.freePort(); if(serverName == null){ if(ranked) - serverName = "Ranked" + (port - FIRST_ARENA_PORT); + serverName = "Ranked" + (port - arenaPorts.start); else - serverName = modus.getDisplayName() + (port - FIRST_ARENA_PORT); + serverName = modus.getDisplayName() + (port - arenaPorts.start); } if(mapName == null) mapName = serverName; @@ -109,56 +103,31 @@ public class SubserverSystem { worldDir = ARENA_PATH; //Copy world - try { - new ProcessBuilder("cp", "-r", SERVER_PATH + modus.getFolder() + "/arenas/" + map, worldDir + mapName).start().waitFor(); - } catch (IOException e) { - throw new SecurityException("Could not copy folder", e); - } catch (InterruptedException e) { - ProxyServer.getInstance().getLogger().log(Level.SEVERE, "Interrupted while copying folder", e); - Thread.currentThread().interrupt(); - } + node.execute("cp", "-r", SERVER_PATH + modus.getFolder() + "/arenas/" + map, worldDir + mapName); File directory = new File(SERVER_PATH, modus.getFolder()); - List cmd = serverStartCommand( - modus.serverJar(), - directory, - worldDir, - mapName, - port, - "2G", - "logPath=" + mapName, - "config="+modus.getConfig(), - "fightID=" + eventFightID, - "ranked=" + ranked, - "checkSchemID=" + checkSchemID, - "prepareSchemID=" + prepareSchemID, + ProcessBuilder builder = node.startServer( + modus.serverJar(), directory, worldDir, mapName, port, "768M", + "logPath=" + mapName, "config=" + modus.getConfig(), + "fightID=" + eventFightID, "ranked=" + ranked, + "checkSchemID=" + checkSchemID, "prepareSchemID=" + prepareSchemID, player1 != null && eventFightID != -1 ? "blueLeader=" + player1 : null, - player2 != null ? "redLeader=" + player2 : null); - - //Start server - ProcessBuilder process = new ProcessBuilder(cmd); - process.directory(directory); + player2 != null ? "redLeader=" + player2 : null + ); String finalMapName = mapName; if(eventFightID == -1) - return new Bauserver(serverName, player1, port, process, () -> deleteFolder(ARENA_PATH + finalMapName)); + return new Bauserver(serverName, player1, port, builder, () -> deleteFolder(node, ARENA_PATH + finalMapName)); else - return new Subserver(Servertype.ARENA, serverName, port, process, () -> { + return new Subserver(Servertype.ARENA, serverName, port, builder, () -> { if(eventFightID > 0) return; - deleteFolder(ARENA_PATH + finalMapName); + deleteFolder(node, ARENA_PATH + finalMapName); }); } - public static void deleteFolder(String worldName){ - try { - new ProcessBuilder("rm", "-r", worldName).start().waitFor(); - } catch (IOException e) { - throw new SecurityException("Could not clean up folder", e); - } catch (InterruptedException e) { - ProxyServer.getInstance().getLogger().log(Level.SEVERE, "Interrupted while deleting folder", e); - Thread.currentThread().interrupt(); - } + public static void deleteFolder(Node node, String worldName){ + node.execute("rm", "-r", worldName); } public static Subserver startEventArena(EventFight eventFight, String serverName){ @@ -183,25 +152,15 @@ public class SubserverSystem { if(bauRunning(p, owner)) return; + copyBauweltIfRequired(prototype, worldFolder + worldName); SteamwarUser user = SteamwarUser.get(owner); - copyBauweltIfRequired(p, prototype, worldFolder + worldName); - int port = freePort(4000); - File directory = new File(SERVER_PATH, serverName); - List cmd = serverStartCommand( - serverJar, - directory, - worldDir, - worldName, - port, - xmx, - "logPath=" + worldName); + Node node = Node.getNode(); + int port = bauPorts.freePort(); - //Start server - ProcessBuilder process = new ProcessBuilder(cmd); - process.directory(directory); - - new Bauserver(user.getUserName() + "s Bau", owner, port, process, () -> {}).sendPlayer(p); + new Bauserver(user.getUserName() + "s Bau", owner, port, node.startServer( + serverJar, directory, worldDir, worldName, port, xmx, "logPath=" + worldName + ), () -> {}).sendPlayer(p); } public static void sendToBauServer(ProxiedPlayer p, UUID owner){ @@ -210,7 +169,7 @@ public class SubserverSystem { private static void sendToBau15(ProxiedPlayer p, UUID owner, String serverJar){ SteamwarUser user = SteamwarUser.get(owner); - sendToBau(p, owner, BungeeCore.BAUWELT15, BungeeCore.USERWORLDS15, serverJar, "/home/minecraft/userworlds15", String.valueOf(user.getId()), "512M", "Bau15"); + sendToBau(p, owner, BungeeCore.BAUWELT15, BungeeCore.USERWORLDS15, serverJar, "/home/minecraft/userworlds15", String.valueOf(user.getId()), "768M", "Bau15"); } public static void sendToBau15(ProxiedPlayer p, UUID owner){ @@ -235,63 +194,6 @@ public class SubserverSystem { new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/bau addmember " + p.getName())); } - private static List serverStartCommand(String serverJar, File directory, String worldDir, String levelName, int port, String xmx, String... dParams){ - List cmd = new ArrayList<>(); - boolean jdk11 = serverJar.contains("1.15.2"); - - boolean fallback = false; - if (!steamwarStartAvailable()) { - cmd.add("ssh"); - cmd.add("-L"); - cmd.add(port + ":localhost:" + port); - if (remoteStartAvailable("lx")) { - cmd.add("lx"); - } else if (remoteStartAvailable("az")) { - cmd.add("az"); - } else { - fallback = true; - } - cmd.add("cd"); - cmd.add(directory.getPath()); - cmd.add(";"); - } - if (fallback) { - cmd.clear(); - } - - if(jdk11) - cmd.add("/usr/lib/jvm/java-11-openjdk-amd64/bin/java"); - else - cmd.add("java"); - - for(String param : dParams){ - cmd.add("-D" + param); - } - cmd.add("-Xmx" + xmx); - cmd.addAll(JVM_ARGS); - if(!jdk11) - cmd.addAll(JVM8_ARGS); - cmd.add("-jar"); - cmd.add("/binarys/" + serverJar); - cmd.add("--log-strip-color"); - cmd.add("--world-dir"); - cmd.add(worldDir); - cmd.add("--level-name"); - cmd.add(levelName); - cmd.add("--port"); - cmd.add(String.valueOf(port)); - - return cmd; - } - - private static boolean steamwarStartAvailable(){ - return LoadEvaluation.getCPULoad() < 0.7 && LoadEvaluation.getRamPercentage() < 0.8; - } - - private static boolean remoteStartAvailable(String remote) { - return LoadEvaluation.getRemoteCPULoad(remote) < 0.7 && LoadEvaluation.getRemoteRamPercentage(remote) < 0.8; - } - private static boolean bauRunning(ProxiedPlayer p, UUID owner){ for(Subserver subserver : Subserver.getServerList()){ if(subserver.getType() == Servertype.BAUSERVER && ((Bauserver)subserver).getOwner().equals(owner)){ @@ -302,37 +204,46 @@ public class SubserverSystem { return false; } - private static void copyBauweltIfRequired(ProxiedPlayer p, String sourcePath, String targetPath){ + private static void copyBauweltIfRequired(String sourcePath, String targetPath){ File w = new File(targetPath); - if (!w.exists() || !w.isDirectory()){ - try { - new ProcessBuilder("cp", "-r", sourcePath, targetPath).start().waitFor(); - } catch (IOException e) { - Message.send("SERVER_WORLD_ERROR", p); - throw new SecurityException("Could not create Bauwelt", e); - } catch (InterruptedException e){ - BungeeCore.log("Could not create Bauwelt", e); - Message.send("SERVER_WORLD_ERROR", p); - Thread.currentThread().interrupt(); - } - } + if (!w.exists() || !w.isDirectory()) + Node.local.execute("cp", "-r", sourcePath, targetPath); } - private static int freePort(int start){ - synchronized (Subserver.getServerList()){ - int port = start; - boolean isFree = false; - while(!isFree){ - port++; - isFree = true; - for(Subserver server : Subserver.getServerList()){ - if(((InetSocketAddress)server.getServer().getSocketAddress()).getPort() == port){ - isFree = false; - break; - } - } + + private static class Portrange { + + private final int start; + private final int end; + private int current; + + private Portrange(int start, int end) { + this.start = start; + this.end = end; + current = start; + } + + private void increment() { + current++; + + if(current == end) + current = start; + } + + private synchronized int freePort() { + Set usedPorts; + + synchronized (Subserver.getServerList()) { + usedPorts = Subserver.getServerList().stream().map(server -> ((InetSocketAddress) server.getServer().getSocketAddress()).getPort()).collect(Collectors.toSet()); } - return port; + + while(usedPorts.contains(current)) { + increment(); + } + + int result = current; + increment(); + return result; } } } diff --git a/src/de/steamwar/bungeecore/bot/AuthManager.java b/src/de/steamwar/bungeecore/bot/AuthManager.java index 1502b68..ac4f553 100644 --- a/src/de/steamwar/bungeecore/bot/AuthManager.java +++ b/src/de/steamwar/bungeecore/bot/AuthManager.java @@ -27,7 +27,6 @@ import net.dv8tion.jda.api.entities.Emoji; import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.interactions.components.ActionRow; import net.dv8tion.jda.api.interactions.components.Button; -import net.md_5.bungee.api.scheduler.ScheduledTask; import java.util.*; import java.util.concurrent.TimeUnit; @@ -48,11 +47,7 @@ public class AuthManager { TOKENS.put(code, member.getIdLong()); BungeeCore.log("Created Discord Auth-Token: " + code + " for: " + member.getUser().getAsTag()); - ScheduledTask[] task = new ScheduledTask[1]; - task[0] = BungeeCore.get().getProxy().getScheduler().schedule(BungeeCore.get(), () -> { - TOKENS.remove(code); - task[0].cancel(); - }, 10, 10, TimeUnit.MINUTES); + BungeeCore.get().getProxy().getScheduler().schedule(BungeeCore.get(), () -> TOKENS.remove(code), 10, TimeUnit.MINUTES); return code; } @@ -60,16 +55,16 @@ public class AuthManager { if (TOKENS.containsKey(code)) { Member member = SteamwarDiscordBot.instance().getJda().getGuildById(SteamwarDiscordBotConfig.GUILD).retrieveMemberById(TOKENS.get(code).longValue()).complete(); if(member == null) return null; - user.setDiscordId(member.getId()); + user.setDiscordId(member.getIdLong()); MessageBuilder builder = new MessageBuilder(); builder.setContent(":white_check_mark: Dein Discord Konto wurde mit **" + user.getUserName() + "** verknüpft"); builder.setActionRows(ActionRow.of(Button.success("tada", Emoji.fromUnicode("U+1F389")), Button.danger("invalid", "Ich war das nicht"))); try { - member.getUser().openPrivateChannel().complete().sendMessage(builder.build()).complete(); + member.getUser().openPrivateChannel().queue(privateChannel -> privateChannel.sendMessage(builder.build()).queue()); if (member.getNickname() == null) { try { - member.getGuild().modifyNickname(member, user.getUserName()).complete(); + member.getGuild().modifyNickname(member, user.getUserName()).queue(); } catch (Exception e) { // Ignored } diff --git a/src/de/steamwar/bungeecore/bot/SteamwarDiscordBot.java b/src/de/steamwar/bungeecore/bot/SteamwarDiscordBot.java index 7c5f1db..e614c5e 100644 --- a/src/de/steamwar/bungeecore/bot/SteamwarDiscordBot.java +++ b/src/de/steamwar/bungeecore/bot/SteamwarDiscordBot.java @@ -44,6 +44,7 @@ import javax.security.auth.login.LoginException; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; +import java.util.logging.Level; public class SteamwarDiscordBot { @@ -54,13 +55,13 @@ public class SteamwarDiscordBot { } @Getter - private AnnouncementListener announcementListener; + private volatile AnnouncementListener announcementListener; @Getter - private IngameChatListener ingameChatListener; + private volatile IngameChatListener ingameChatListener; @Getter - private ServerTeamChatListener serverTeamChatListener; + private volatile ServerTeamChatListener serverTeamChatListener; @Getter private final JDA jda; @@ -78,43 +79,48 @@ public class SteamwarDiscordBot { } catch (LoginException e) { throw new SecurityException("Could not Login: " + SteamwarDiscordBotConfig.TOKEN, e); } - try { - jda.awaitReady(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - activity(); - EventManager.update(); - SchematicsManager.update(); - ProxyServer.getInstance().getScheduler().schedule(BungeeCore.get(), () -> { - activity(); + ProxyServer.getInstance().getScheduler().runAsync(BungeeCore.get(), () -> { + try { + jda.awaitReady(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + try { + activity(); + } catch (Exception e) { + BungeeCore.get().getLogger().log(Level.SEVERE, "Could not set initial activity to discord", e); + } EventManager.update(); SchematicsManager.update(); - }, 30, 30, TimeUnit.SECONDS); - DiscordRolesMessage.sendMessage(); - DiscordRulesMessage.sendMessage(); - DiscordTicketMessage.sendMessage(); + ProxyServer.getInstance().getScheduler().schedule(BungeeCore.get(), () -> { + activity(); + EventManager.update(); + SchematicsManager.update(); + }, 30, 30, TimeUnit.SECONDS); + DiscordRolesMessage.sendMessage(); + DiscordRulesMessage.sendMessage(); + DiscordTicketMessage.sendMessage(); + new RolesInteractionButtonListener(); + new DiscordTicketListener(); + new DiscordAuthListener(); + new DiscordEventListener(); + announcementListener = new AnnouncementListener(); + ingameChatListener = new IngameChatListener(); + serverTeamChatListener = new ServerTeamChatListener(); + new SlashCommandListener(); + jda.retrieveCommands().complete().forEach(command -> jda.deleteCommandById(command.getId()).queue()); - new RolesInteractionButtonListener(); - new DiscordTicketListener(); - new DiscordAuthListener(); - announcementListener = new AnnouncementListener(); - ingameChatListener = new IngameChatListener(); - serverTeamChatListener = new ServerTeamChatListener(); - new SlashCommandListener(); - - jda.retrieveCommands().complete().forEach(command -> jda.deleteCommandById(command.getId()).complete()); - - Guild guild = jda.getGuildById(SteamwarDiscordBotConfig.GUILD); - guild.retrieveCommands().complete().forEach(command -> guild.deleteCommandById(command.getId()).complete()); - CommandListUpdateAction commands = jda.getGuildById(SteamwarDiscordBotConfig.GUILD).updateCommands(); - addCommand(commands, new MuteCommand()); - addCommand(commands, new BanCommand()); - addCommand(commands, new WhoisCommand()); - addCommand(commands, new TeamCommand()); - addCommand(commands, new ListCommand()); - addCommand(commands, new UnbanCommand()); - commands.complete(); + Guild guild = jda.getGuildById(SteamwarDiscordBotConfig.GUILD); + guild.retrieveCommands().complete().forEach(command -> guild.deleteCommandById(command.getId()).complete()); + CommandListUpdateAction commands = jda.getGuildById(SteamwarDiscordBotConfig.GUILD).updateCommands(); + addCommand(commands, new MuteCommand()); + addCommand(commands, new BanCommand()); + addCommand(commands, new WhoisCommand()); + addCommand(commands, new TeamCommand()); + addCommand(commands, new ListCommand()); + addCommand(commands, new UnbanCommand()); + commands.complete(); + }); } private void addCommand(CommandListUpdateAction commands, BasicDiscordCommand basicDiscordCommand) { diff --git a/src/de/steamwar/bungeecore/bot/commands/BanCommand.java b/src/de/steamwar/bungeecore/bot/commands/BanCommand.java index 7d3772f..e328997 100644 --- a/src/de/steamwar/bungeecore/bot/commands/BanCommand.java +++ b/src/de/steamwar/bungeecore/bot/commands/BanCommand.java @@ -20,6 +20,8 @@ package de.steamwar.bungeecore.bot.commands; import de.steamwar.bungeecore.Message; +import de.steamwar.bungeecore.commands.PunishmentCommand; +import de.steamwar.bungeecore.sql.Punishment; import de.steamwar.bungeecore.sql.SteamwarUser; import net.dv8tion.jda.api.events.interaction.SlashCommandEvent; import net.dv8tion.jda.api.interactions.commands.OptionType; @@ -45,21 +47,21 @@ public class BanCommand extends BasicDiscordCommand { SteamwarUser sender = SteamwarUser.get(event.getMember().getIdLong()); SteamwarUser target = SteamwarUser.getOrCreateOfflinePlayer(event.getOption("user").getAsString()); if (target == null) { - event.reply("Angegebener User invalide").setEphemeral(true).complete(); + event.reply("Angegebener User invalide").setEphemeral(true).queue(); return; } - Timestamp time = de.steamwar.bungeecore.commands.BanCommand.parseTime(null, event.getOption("time").getAsString()); + Timestamp time = PunishmentCommand.parseTime(null, event.getOption("time").getAsString()); if (time == null) { - event.reply("Angegebene Zeit invalide").setEphemeral(true).complete(); + event.reply("Angegebene Zeit invalide").setEphemeral(true).queue(); return; } String msg = event.getOption("reason").getAsString(); boolean isPerma = event.getOption("time").getAsString().equals("perma"); - target.ban(time, msg, sender.getId(), isPerma); - Message.team("BAN_TEAM_BANNED", new Message("PREFIX"), target.getUserName(), sender.getUserName(), new Message((isPerma ? "BAN_PERMA" : "BAN_UNTIL"), time), msg); - event.reply("Erfolgreich " + target.getUserName() + (isPerma ? " permanent" : " bis " + time) + " gebannt").setEphemeral(true).complete(); + target.punish(Punishment.PunishmentType.Ban, time, msg, sender.getId(), isPerma); + Message.team("BAN_TEAM", new Message("PREFIX"), target.getUserName(), sender.getUserName(), new Message((isPerma ? "BAN_PERMA" : "BAN_UNTIL"), time), msg); + event.reply("Erfolgreich " + target.getUserName() + (isPerma ? " permanent" : " bis " + time) + " gebannt").setEphemeral(true).queue(); } } diff --git a/src/de/steamwar/bungeecore/bot/commands/BasicDiscordCommand.java b/src/de/steamwar/bungeecore/bot/commands/BasicDiscordCommand.java index a767eba..29bbe85 100644 --- a/src/de/steamwar/bungeecore/bot/commands/BasicDiscordCommand.java +++ b/src/de/steamwar/bungeecore/bot/commands/BasicDiscordCommand.java @@ -46,7 +46,7 @@ public abstract class BasicDiscordCommand extends CommandData { Member member = event.getMember(); SteamwarUser steamwarUser = SteamwarUser.get(member.getIdLong()); if (steamwarUser == null || (!steamwarUser.getUserGroup().isTeamGroup() && steamwarUser.getUserGroup() != UserGroup.Builder)) { - event.reply("Du hast für " + event.getName() + " keine Rechte oder es existiert keine Verknüpfung für dich.").setEphemeral(true).complete(); + event.reply("Du hast für " + event.getName() + " keine Rechte oder es existiert keine Verknüpfung für dich.").setEphemeral(true).queue(); return false; } return true; diff --git a/src/de/steamwar/bungeecore/bot/commands/ListCommand.java b/src/de/steamwar/bungeecore/bot/commands/ListCommand.java index 2050180..746bb02 100644 --- a/src/de/steamwar/bungeecore/bot/commands/ListCommand.java +++ b/src/de/steamwar/bungeecore/bot/commands/ListCommand.java @@ -32,12 +32,12 @@ public class ListCommand extends BasicDiscordCommand { @Override public void run(SlashCommandEvent event) { - de.steamwar.bungeecore.commands.ListCommand.updateCustomTablist(); + de.steamwar.bungeecore.commands.ListCommand.getCustomTablist(); EmbedBuilder embedBuilder = new EmbedBuilder(); embedBuilder.setTitle("List"); - de.steamwar.bungeecore.commands.ListCommand.getPlayerMap().forEach((s, proxiedPlayers) -> { + de.steamwar.bungeecore.commands.ListCommand.getCustomTablist().forEach((s, proxiedPlayers) -> { embedBuilder.addField(s, proxiedPlayers.stream().map(player -> "`" + player.getName() + "`").collect(Collectors.joining(", ")), true); }); - event.replyEmbeds(embedBuilder.build()).setEphemeral(true).complete(); + event.replyEmbeds(embedBuilder.build()).setEphemeral(true).queue(); } } diff --git a/src/de/steamwar/bungeecore/bot/commands/MuteCommand.java b/src/de/steamwar/bungeecore/bot/commands/MuteCommand.java index 700baac..086cf77 100644 --- a/src/de/steamwar/bungeecore/bot/commands/MuteCommand.java +++ b/src/de/steamwar/bungeecore/bot/commands/MuteCommand.java @@ -20,7 +20,8 @@ package de.steamwar.bungeecore.bot.commands; import de.steamwar.bungeecore.Message; -import de.steamwar.bungeecore.commands.BanCommand; +import de.steamwar.bungeecore.commands.PunishmentCommand; +import de.steamwar.bungeecore.sql.Punishment; import de.steamwar.bungeecore.sql.SteamwarUser; import net.dv8tion.jda.api.events.interaction.SlashCommandEvent; import net.dv8tion.jda.api.interactions.commands.OptionType; @@ -50,7 +51,7 @@ public class MuteCommand extends BasicDiscordCommand { return; } - Timestamp time = BanCommand.parseTime(null, event.getOption("time").getAsString()); + Timestamp time = PunishmentCommand.parseTime(null, event.getOption("time").getAsString()); if (time == null) { event.reply("Angegebene Zeit invalide").setEphemeral(true).complete(); return; @@ -59,8 +60,8 @@ public class MuteCommand extends BasicDiscordCommand { String msg = event.getOption("reason").getAsString(); boolean isPerma = event.getOption("time").getAsString().equals("perma"); - target.mute(time, msg, sender.getId(), isPerma); - Message.team("MUTE_TEAM_MUTED", new Message("PREFIX"), target.getUserName(), sender.getUserName(), new Message((isPerma ? "BAN_PERMA" : "BAN_UNTIL"), time), msg); - event.reply("Erfolgreich " + target.getUserName() + (isPerma ? " permanent" : " bis " + time) + " gemutet").setEphemeral(true).complete(); + target.punish(Punishment.PunishmentType.Mute, time, msg, sender.getId(), isPerma); + Message.team("MUTE_TEAM", new Message("PREFIX"), target.getUserName(), sender.getUserName(), new Message((isPerma ? "BAN_PERMA" : "BAN_UNTIL"), time), msg); + event.reply("Erfolgreich " + target.getUserName() + (isPerma ? " permanent" : " bis " + time) + " gemutet").setEphemeral(true).queue(); } } diff --git a/src/de/steamwar/bungeecore/bot/commands/TeamCommand.java b/src/de/steamwar/bungeecore/bot/commands/TeamCommand.java index 53d7039..e0b3545 100644 --- a/src/de/steamwar/bungeecore/bot/commands/TeamCommand.java +++ b/src/de/steamwar/bungeecore/bot/commands/TeamCommand.java @@ -58,11 +58,11 @@ public class TeamCommand extends BasicDiscordCommand { Team team; if (optionMapping == null) { if (steamwarUser == null) { - event.reply("Dein Discord ist nicht verknüpft").setEphemeral(true).complete(); + event.reply("Dein Discord ist nicht verknüpft").setEphemeral(true).queue(); return; } if (steamwarUser.getTeam() == 0) { - event.reply("Du bist in keinem Team").setEphemeral(true).complete(); + event.reply("Du bist in keinem Team").setEphemeral(true).queue(); return; } team = Team.get(steamwarUser.getTeam()); @@ -70,7 +70,7 @@ public class TeamCommand extends BasicDiscordCommand { team = Team.get(optionMapping.getAsString()); } if (team == null) { - event.reply("Unbekanntes Team").setEphemeral(true).complete(); + event.reply("Unbekanntes Team").setEphemeral(true).queue(); return; } EmbedBuilder embedBuilder = new EmbedBuilder(); @@ -81,10 +81,10 @@ public class TeamCommand extends BasicDiscordCommand { embedBuilder.addField("Leader", members.stream().filter(SteamwarUser::isLeader).map(user -> "`" + (isOnline(user) ? emoji.getAsMention() : "") + user.getUserName() + "`").collect(Collectors.joining(" ")), false); embedBuilder.addField("Member", members.stream().filter(user -> !user.isLeader()).map(user -> "`" + (isOnline(user) ? emoji.getAsMention() : "") + user.getUserName() + "`").collect(Collectors.joining(" ")), false); embedBuilder.addField("Events", "`" + TeamTeilnahme.getEvents(team.getTeamId()).stream().map(Event::getEventName).collect(Collectors.joining("` `")) + "`", false); - event.replyEmbeds(embedBuilder.build()).setEphemeral(true).complete(); + event.replyEmbeds(embedBuilder.build()).setEphemeral(true).queue(); return; default: - event.reply("Unbekannter Befehl").setEphemeral(true).complete(); + event.reply("Unbekannter Befehl").setEphemeral(true).queue(); return; } } diff --git a/src/de/steamwar/bungeecore/bot/commands/UnbanCommand.java b/src/de/steamwar/bungeecore/bot/commands/UnbanCommand.java index 7147108..f8d6185 100644 --- a/src/de/steamwar/bungeecore/bot/commands/UnbanCommand.java +++ b/src/de/steamwar/bungeecore/bot/commands/UnbanCommand.java @@ -19,7 +19,7 @@ package de.steamwar.bungeecore.bot.commands; -import de.steamwar.bungeecore.Message; +import de.steamwar.bungeecore.sql.Punishment; import de.steamwar.bungeecore.sql.SteamwarUser; import net.dv8tion.jda.api.events.interaction.SlashCommandEvent; import net.dv8tion.jda.api.interactions.commands.OptionType; @@ -44,16 +44,16 @@ public class UnbanCommand extends BasicDiscordCommand { SteamwarUser sender = SteamwarUser.get(event.getMember().getIdLong()); SteamwarUser target = SteamwarUser.getOrCreateOfflinePlayer(event.getOption("user").getAsString()); if (target == null) { - event.reply("Angegebener User invalide").setEphemeral(true).complete(); + event.reply("Angegebener User invalide").setEphemeral(true).queue(); return; } - if (!target.isBanned()) { - event.reply("Angegebener User ist nicht gebannt").setEphemeral(true).complete(); + if (!target.isPunished(Punishment.PunishmentType.Ban)) { + event.reply("Angegebener User ist nicht gebannt").setEphemeral(true).queue(); return; } - target.ban(Timestamp.from(new Date().toInstant()), "Unban", sender.getId(), false); - event.reply("Erfolgreich " + target.getUserName() + " entbannt").setEphemeral(true).complete(); + target.punish(Punishment.PunishmentType.Ban, Timestamp.from(new Date().toInstant()), "Unban", sender.getId(), false); + event.reply("Erfolgreich " + target.getUserName() + " entbannt").setEphemeral(true).queue(); } } diff --git a/src/de/steamwar/bungeecore/bot/commands/WhoisCommand.java b/src/de/steamwar/bungeecore/bot/commands/WhoisCommand.java index b40c049..8608047 100644 --- a/src/de/steamwar/bungeecore/bot/commands/WhoisCommand.java +++ b/src/de/steamwar/bungeecore/bot/commands/WhoisCommand.java @@ -89,6 +89,6 @@ public class WhoisCommand extends BasicDiscordCommand { embedBuilder.addField(punishment.getType().name() + " von " + SteamwarUser.get(punishment.getPunisher()).getUserName(), "Von: " + punishment.getBantime(punishment.getStartTime(), false) + "\nBis: " + punishment.getBantime(punishment.getEndTime(), punishment.isPerma()) + "\nGrund: " + punishment.getReason(), true); } - event.replyEmbeds(embedBuilder.build()).setEphemeral(true).complete(); + event.replyEmbeds(embedBuilder.build()).setEphemeral(true).queue(); } } diff --git a/src/de/steamwar/bungeecore/bot/config/SteamwarDiscordBotConfig.java b/src/de/steamwar/bungeecore/bot/config/SteamwarDiscordBotConfig.java index f69a3ac..34c65e8 100644 --- a/src/de/steamwar/bungeecore/bot/config/SteamwarDiscordBotConfig.java +++ b/src/de/steamwar/bungeecore/bot/config/SteamwarDiscordBotConfig.java @@ -29,6 +29,7 @@ import java.util.Map; public class SteamwarDiscordBotConfig { + public static boolean loaded = false; public static String TOKEN; public static String GUILD; public static String ANNOUNCEMENTS_CHANNEL; @@ -110,5 +111,6 @@ public class SteamwarDiscordBotConfig { for (String type : ranksSections.getKeys()) { RANKS.put(UserGroup.getUsergroup(type), ranksSections.getString(type)); } + loaded = true; } } diff --git a/src/de/steamwar/bungeecore/bot/events/EventManager.java b/src/de/steamwar/bungeecore/bot/events/EventManager.java index 56f982c..79ef2e3 100644 --- a/src/de/steamwar/bungeecore/bot/events/EventManager.java +++ b/src/de/steamwar/bungeecore/bot/events/EventManager.java @@ -28,13 +28,17 @@ import de.steamwar.bungeecore.sql.TeamTeilnahme; import lombok.experimental.UtilityClass; import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.MessageBuilder; +import net.dv8tion.jda.api.entities.Emoji; import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.entities.TextChannel; +import net.dv8tion.jda.api.interactions.components.ActionRow; +import net.dv8tion.jda.api.interactions.components.selections.SelectionMenu; import java.awt.*; import java.sql.Timestamp; import java.time.Instant; import java.time.temporal.ChronoUnit; +import java.util.List; import java.util.stream.Collectors; @UtilityClass @@ -66,7 +70,12 @@ public class EventManager { embedBuilder.setAuthor("SteamWar", "https://www.steamwar.de"); Timestamp now = Timestamp.from(Instant.now()); - Event.getComing().forEach(event -> { + SelectionMenu.Builder menuBuilder = SelectionMenu.create("eventName"); + menuBuilder.setPlaceholder("Wähle ein Event aus!") + .setMinValues(1) + .setMaxValues(1); + List events = Event.getComing(); + events.forEach(event -> { StringBuilder st = new StringBuilder(); if (event.getDeadline().after(now)) { st.append("Deadline: \n"); @@ -77,10 +86,16 @@ public class EventManager { st.append("\nAngemeldete Teams: ").append(teilname); } embedBuilder.addField(event.getEventName(), st.toString(), false); + if(event.getDeadline().after(Timestamp.from(Instant.now()))) { + menuBuilder.addOption(event.getEventName(), event.getEventID() + "", "An " + event.getEventName() + " teilnehmen", Emoji.fromUnicode("U+1F4DD")); + } }); MessageBuilder messageBuilder = new MessageBuilder(); messageBuilder.setEmbeds(embedBuilder.build()); + if(events.stream().anyMatch(event -> event.getDeadline().after(Timestamp.from(Instant.now())))) { + messageBuilder.setActionRows(ActionRow.of(menuBuilder.build())); + } if (message == null) { message = textChannel.sendMessage(messageBuilder.build()).complete(); } else { @@ -119,7 +134,7 @@ public class EventManager { MessageBuilder messageBuilder = new MessageBuilder(); messageBuilder.setEmbeds(embedBuilder.build()); if (message == null) { - message = textChannel.sendMessage(messageBuilder.build()).complete(); + textChannel.sendMessage(messageBuilder.build()).queue(message1 -> message = message1); } else { message.editMessage(messageBuilder.build()).complete(); } diff --git a/src/de/steamwar/bungeecore/bot/events/SchematicsManager.java b/src/de/steamwar/bungeecore/bot/events/SchematicsManager.java index 64809e1..82a8370 100644 --- a/src/de/steamwar/bungeecore/bot/events/SchematicsManager.java +++ b/src/de/steamwar/bungeecore/bot/events/SchematicsManager.java @@ -65,7 +65,7 @@ public class SchematicsManager { MessageBuilder messageBuilder = new MessageBuilder(); messageBuilder.setEmbeds(embedBuilder.build()); if (message == null) { - message = textChannel.sendMessage(messageBuilder.build()).complete(); + textChannel.sendMessage(messageBuilder.build()).queue(message1 -> message = message1); } else { message.editMessage(messageBuilder.build()).queue(); } diff --git a/src/de/steamwar/bungeecore/bot/listeners/AnnouncementListener.java b/src/de/steamwar/bungeecore/bot/listeners/AnnouncementListener.java index 2877fbd..ab4be19 100644 --- a/src/de/steamwar/bungeecore/bot/listeners/AnnouncementListener.java +++ b/src/de/steamwar/bungeecore/bot/listeners/AnnouncementListener.java @@ -45,6 +45,6 @@ public class AnnouncementListener extends BasicDiscordListener { assert textChannel != null; MessageBuilder messageBuilder = new MessageBuilder(); messageBuilder.append(message.replace("&", "")); - textChannel.sendMessage(messageBuilder.build()).complete(); + textChannel.sendMessage(messageBuilder.build()).queue(); } } diff --git a/src/de/steamwar/bungeecore/bot/listeners/DiscordAuthListener.java b/src/de/steamwar/bungeecore/bot/listeners/DiscordAuthListener.java index 514b193..8ad3428 100644 --- a/src/de/steamwar/bungeecore/bot/listeners/DiscordAuthListener.java +++ b/src/de/steamwar/bungeecore/bot/listeners/DiscordAuthListener.java @@ -35,23 +35,23 @@ public class DiscordAuthListener extends BasicDiscordListener { if(event.getChannel().getId().equals(SteamwarDiscordBotConfig.RULES_CHANNEL) && event.getComponentId().equals("auth")) { String authMessage = AuthManager.createDiscordAuthToken(event.getMember()); if(authMessage != null) { - event.reply("Gebe innerhalb der nächsten 10 Minuten ``/verify " + authMessage + "`` auf dem Minecraft Server ein").setEphemeral(true).complete(); + event.reply("Gebe innerhalb der nächsten 10 Minuten ``/verify " + authMessage + "`` auf dem Minecraft Server ein").setEphemeral(true).queue(); } else { - event.reply("Du hast bereits einen Code am laufen").setEphemeral(true).complete(); + event.reply("Du hast bereits einen Code am laufen").setEphemeral(true).queue(); } } if(event.getComponentId().equals("tada") && event.getChannelType() == ChannelType.PRIVATE) { - event.reply(":tada:").setEphemeral(false).complete(); + event.reply(":tada:").setEphemeral(false).queue(); } if(event.getComponentId().equals("invalid") && event.getChannelType() == ChannelType.PRIVATE) { SteamwarUser user = SteamwarUser.get(event.getUser().getIdLong()); if(user == null) { - event.reply(":question: Da ist keine verknüpfung?").setEphemeral(false).complete(); + event.reply(":question: Da ist keine verknüpfung?").setEphemeral(false).queue(); } else { user.setDiscordId(null); - event.reply(":x: Die Verknüpfung wurde beendet").setEphemeral(false).complete(); + event.reply(":x: Die Verknüpfung wurde beendet").setEphemeral(false).queue(); } } } diff --git a/src/de/steamwar/bungeecore/bot/listeners/DiscordEventListener.java b/src/de/steamwar/bungeecore/bot/listeners/DiscordEventListener.java new file mode 100644 index 0000000..a08f74d --- /dev/null +++ b/src/de/steamwar/bungeecore/bot/listeners/DiscordEventListener.java @@ -0,0 +1,93 @@ +/* + 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.bungeecore.bot.listeners; + +import de.steamwar.bungeecore.bot.config.SteamwarDiscordBotConfig; +import de.steamwar.bungeecore.bot.events.EventManager; +import de.steamwar.bungeecore.sql.Event; +import de.steamwar.bungeecore.sql.SteamwarUser; +import de.steamwar.bungeecore.sql.Team; +import de.steamwar.bungeecore.sql.TeamTeilnahme; +import net.dv8tion.jda.api.events.interaction.SelectionMenuEvent; +import net.dv8tion.jda.api.interactions.components.Component; +import org.jetbrains.annotations.NotNull; + +import java.time.Instant; + +public class DiscordEventListener extends BasicDiscordListener { + + + @Override + public void onSelectionMenu(@NotNull SelectionMenuEvent event) { + if(event.getChannel().getId().equals(SteamwarDiscordBotConfig.EVENTS_CHANNEL) && event.getComponentType() == Component.Type.SELECTION_MENU) { + if(event.getSelectedOptions().isEmpty()) { + event.deferReply(true).queue(); + return; + } + if(event.getSelectedOptions().get(0).getValue().matches("([0-9]+)")) { + SteamwarUser user = SteamwarUser.get(event.getUser().getIdLong()); + if(user == null) { + event.reply("Du hast dein Minecraft nicht verknüpft").setEphemeral(true).queue(); + return; + } + + if(user.getTeam() == 0) { + event.reply("Du bist in keinem Team").setEphemeral(true).queue(); + return; + } + + if(!user.isLeader()) { + event.reply("Du bist kein Leader in deinem Team").setEphemeral(true).queue(); + return; + } + + if(Event.get() != null) { + event.reply("Du kannst dich nicht während einem Event an einem Event anmelden").setEphemeral(true).queue(); + return; + } + + Event swEvent = Event.get(Integer.decode(event.getSelectedOptions().get(0).getValue())); + if(swEvent == null){ + event.reply("Das Event gibt es nicht").setEphemeral(true).queue(); + return; + } + + if(Instant.now().isAfter(swEvent.getDeadline().toInstant())){ + event.reply("Du kannst dich nicht mehr an diesen Event anmelden").setEphemeral(true).queue(); + return; + } + + Team team = Team.get(user.getTeam()); + + if(TeamTeilnahme.nimmtTeil(team.getTeamId(), swEvent.getEventID())){ + TeamTeilnahme.notTeilnehmen(team.getTeamId(), swEvent.getEventID()); + event.reply("Dein Team **" + team.getTeamName() + "** nimmt nun nicht mehr an **" + swEvent.getEventName() + "** teil!").setEphemeral(true).queue(); + }else{ + TeamTeilnahme.teilnehmen(team.getTeamId(), swEvent.getEventID()); + event.reply("Dein Team **" + team.getTeamName() + "** nimmt nun an **" + swEvent.getEventName() + "** teil!").setEphemeral(true).queue(); + } + + EventManager.update(); + } else { + event.reply("Lefuq?").setEphemeral(true).queue(); + } + } + } +} diff --git a/src/de/steamwar/bungeecore/bot/listeners/DiscordTicketListener.java b/src/de/steamwar/bungeecore/bot/listeners/DiscordTicketListener.java index 1ac4920..f7a2fa2 100644 --- a/src/de/steamwar/bungeecore/bot/listeners/DiscordTicketListener.java +++ b/src/de/steamwar/bungeecore/bot/listeners/DiscordTicketListener.java @@ -75,29 +75,40 @@ public class DiscordTicketListener extends BasicDiscordListener { } else if(event.getComponentId().startsWith("close-")) { TextChannel logChannel = event.getGuild().getTextChannelById(SteamwarDiscordBotConfig.TICKET_LOG); - MessageBuilder builder = new MessageBuilder(); - StringBuilder stringBuilder = new StringBuilder(); + LinkedList stringBuilders = new LinkedList<>(); + stringBuilders.add(new StringBuilder()); new LinkedList<>(event.getTextChannel().getIterableHistory().complete()).descendingIterator().forEachRemaining(message -> { if(message.getAuthor().isSystem() || message.getAuthor().isBot()) return; - stringBuilder.append(" ") + StringBuilder currentBuilder = new StringBuilder(); + currentBuilder.append(" ") .append("**") .append(message.getAuthor().getName()) .append("**: ") .append(message.getContentRaw()); if(!message.getAttachments().isEmpty()) { - stringBuilder.append("\n") + currentBuilder.append("\n") .append("Files: ").append("\n"); - message.getAttachments().forEach(attachment -> stringBuilder.append(attachment.getUrl()).append("\n")); + message.getAttachments().forEach(attachment -> currentBuilder.append(attachment.getUrl()).append("\n")); } - stringBuilder.append("\n"); + currentBuilder.append("\n"); + if(currentBuilder.length() >= 4096) { + stringBuilders.getLast().append(currentBuilder.substring(0, 4090)); + stringBuilders.add(new StringBuilder(currentBuilder.substring(4090, currentBuilder.length() - 1))); + } else if (currentBuilder.length() + stringBuilders.getLast().length() >= 4096) { + stringBuilders.add(new StringBuilder(currentBuilder.toString())); + } else { + stringBuilders.getLast().append(currentBuilder); + } }); - stringBuilder.append("\n"); - stringBuilder.append(" ") - .append("**").append(event.getUser().getName()).append("**: ") - .append("Ticket geschlossen"); + String footer = " **" + event.getUser().getName() + "**: Ticket geschlossen"; + if(stringBuilders.getLast().length() + footer.length() > 4090) { + stringBuilders.add(new StringBuilder(footer)); + } else { + stringBuilders.getLast().append(footer); + } EmbedBuilder embedBuilder = new EmbedBuilder(); embedBuilder.setColor(Color.GREEN); @@ -107,14 +118,16 @@ public class DiscordTicketListener extends BasicDiscordListener { embedBuilder.setAuthor(user.getName(), swuser==null?"https://steamwar.de/":("https://steamwar.de/users/" + swuser.getUserName().toLowerCase() + "/"), user.getAvatarUrl()); embedBuilder.setTimestamp(Instant.now()); embedBuilder.setTitle(event.getTextChannel().getName()); - embedBuilder.setDescription(stringBuilder); + stringBuilders.forEach(stringBuilder -> { + embedBuilder.setDescription(stringBuilder.toString()); + MessageBuilder builder = new MessageBuilder(); + builder.setEmbeds(embedBuilder.build()); - builder.setEmbeds(embedBuilder.build()); - - logChannel.sendMessage(builder.build()).complete(); + logChannel.sendMessage(builder.build()).queue(); + }); Message.team("DISCORD_TICKET_CLOSED", event.getTextChannel().getName()); - event.getTextChannel().delete().reason("Closed").complete(); + event.getTextChannel().delete().reason("Closed").queue(); } } } @@ -126,16 +139,15 @@ public class DiscordTicketListener extends BasicDiscordListener { BungeeCore.get().getProxy().getPlayers().forEach(player -> { if(event.getAuthor().isBot() || event.getAuthor().isSystem()) return; SteamwarUser user = SteamwarUser.get(player); + boolean sendMessage; if(user.getDiscordId() == null) { - if(user.getUserGroup().isTeamGroup()) { - Message.sendPrefixless("DISCORD_TICKET_MESSAGE", player, "Zur nachricht", new ClickEvent(ClickEvent.Action.OPEN_URL, event.getMessage().getJumpUrl()), event.getChannel().getName(), event.getAuthor().getName(), event.getMessage().getContentRaw()); - } + sendMessage = user.getUserGroup().isCheckSchematics(); } else { if(event.getAuthor().getId().equals(user.getDiscordId())) return; - Member member = event.getGuild().retrieveMemberById(user.getDiscordId()).complete(); - if(member.hasPermission(event.getChannel().getManager().getChannel(), Permission.MESSAGE_WRITE)) { - Message.sendPrefixless("DISCORD_TICKET_MESSAGE", player, "Zur nachricht", new ClickEvent(ClickEvent.Action.OPEN_URL, event.getMessage().getJumpUrl()), event.getChannel().getName(), event.getAuthor().getName(), event.getMessage().getContentRaw()); - } + sendMessage = user.getDiscordId().equals(event.getChannel().getTopic()) || user.getUserGroup().isCheckSchematics(); + } + if(sendMessage) { + Message.sendPrefixless("DISCORD_TICKET_MESSAGE", player, "Zur nachricht", new ClickEvent(ClickEvent.Action.OPEN_URL, event.getMessage().getJumpUrl()), event.getChannel().getName(), event.getAuthor().getName(), event.getMessage().getContentRaw()); } }); } diff --git a/src/de/steamwar/bungeecore/bot/listeners/IngameChatListener.java b/src/de/steamwar/bungeecore/bot/listeners/IngameChatListener.java index ce635f3..e7b709d 100644 --- a/src/de/steamwar/bungeecore/bot/listeners/IngameChatListener.java +++ b/src/de/steamwar/bungeecore/bot/listeners/IngameChatListener.java @@ -22,6 +22,7 @@ package de.steamwar.bungeecore.bot.listeners; import de.steamwar.bungeecore.bot.SteamwarDiscordBot; import de.steamwar.bungeecore.bot.config.SteamwarDiscordBotConfig; import de.steamwar.bungeecore.listeners.ChatListener; +import de.steamwar.bungeecore.sql.Punishment; import de.steamwar.bungeecore.sql.SteamwarUser; import de.steamwar.bungeecore.sql.UserGroup; import net.dv8tion.jda.api.MessageBuilder; @@ -43,15 +44,15 @@ public class IngameChatListener extends BasicDiscordListener { Member member = event.getMember(); SteamwarUser steamwarUser = SteamwarUser.get(member.getIdLong()); if (steamwarUser == null || event.getMessage().getContentRaw().length() > 250) { - event.getMessage().delete().complete(); + event.getMessage().delete().queue(); } else { String s = event.getMessage().getContentDisplay(); if (steamwarUser.getUserGroup() == UserGroup.Member && (s.contains("http") || s.contains("www"))) { - event.getMessage().delete().complete(); + event.getMessage().delete().queue(); return; } - if (steamwarUser.isMuted() || steamwarUser.isBanned()) { - event.getMessage().delete().complete(); + if (steamwarUser.isPunished(Punishment.PunishmentType.Mute) || steamwarUser.isPunished(Punishment.PunishmentType.Ban)) { + event.getMessage().delete().queue(); return; } ChatListener.discordChat(steamwarUser, event.getMessage().getContentDisplay().replaceAll("§[a-f0-9]", "").replace('\n', ' ')); diff --git a/src/de/steamwar/bungeecore/bot/listeners/RolesInteractionButtonListener.java b/src/de/steamwar/bungeecore/bot/listeners/RolesInteractionButtonListener.java index 035cd77..ae0e44d 100644 --- a/src/de/steamwar/bungeecore/bot/listeners/RolesInteractionButtonListener.java +++ b/src/de/steamwar/bungeecore/bot/listeners/RolesInteractionButtonListener.java @@ -32,10 +32,10 @@ public class RolesInteractionButtonListener extends BasicDiscordListener { if(event.getType() == InteractionType.COMPONENT && event.getChannelType() == ChannelType.TEXT && event.getTextChannel().getId().equals(SteamwarDiscordBotConfig.ROLES_CHANNEL) && SteamwarDiscordBotConfig.ROLES.stream().anyMatch(discordRole -> discordRole.getRoleId().equals(event.getComponentId()))) { if (event.getMember().getRoles().stream().anyMatch(role -> role.getId().equals(event.getComponentId()))) { event.getGuild().removeRoleFromMember(event.getMember(), event.getGuild().getRoleById(event.getComponentId())).complete(); - event.reply(SteamwarDiscordBotConfig.ROLES_REMOVED.replace("%role%", event.getGuild().getRoleById(event.getComponentId()).getAsMention())).setEphemeral(true).complete(); + event.reply(SteamwarDiscordBotConfig.ROLES_REMOVED.replace("%role%", event.getGuild().getRoleById(event.getComponentId()).getAsMention())).setEphemeral(true).queue(); } else { event.getGuild().addRoleToMember(event.getMember(), event.getGuild().getRoleById(event.getComponentId())).complete(); - event.reply(SteamwarDiscordBotConfig.ROLES_ADDED.replace("%role%", event.getGuild().getRoleById(event.getComponentId()).getAsMention())).setEphemeral(true).complete(); + event.reply(SteamwarDiscordBotConfig.ROLES_ADDED.replace("%role%", event.getGuild().getRoleById(event.getComponentId()).getAsMention())).setEphemeral(true).queue(); } } } diff --git a/src/de/steamwar/bungeecore/bot/listeners/ServerTeamChatListener.java b/src/de/steamwar/bungeecore/bot/listeners/ServerTeamChatListener.java index 0f82673..816da82 100644 --- a/src/de/steamwar/bungeecore/bot/listeners/ServerTeamChatListener.java +++ b/src/de/steamwar/bungeecore/bot/listeners/ServerTeamChatListener.java @@ -22,7 +22,6 @@ package de.steamwar.bungeecore.bot.listeners; import de.steamwar.bungeecore.bot.SteamwarDiscordBot; import de.steamwar.bungeecore.bot.config.SteamwarDiscordBotConfig; import de.steamwar.bungeecore.commands.ServerTeamchatCommand; -import de.steamwar.bungeecore.listeners.ChatListener; import de.steamwar.bungeecore.sql.SteamwarUser; import net.dv8tion.jda.api.MessageBuilder; import net.dv8tion.jda.api.entities.Member; diff --git a/src/de/steamwar/bungeecore/bot/util/DiscordRanks.java b/src/de/steamwar/bungeecore/bot/util/DiscordRanks.java index dedf0a5..7224576 100644 --- a/src/de/steamwar/bungeecore/bot/util/DiscordRanks.java +++ b/src/de/steamwar/bungeecore/bot/util/DiscordRanks.java @@ -22,13 +22,11 @@ package de.steamwar.bungeecore.bot.util; import de.steamwar.bungeecore.bot.SteamwarDiscordBot; import de.steamwar.bungeecore.bot.config.SteamwarDiscordBotConfig; import de.steamwar.bungeecore.sql.SteamwarUser; -import de.steamwar.bungeecore.sql.UserGroup; import lombok.experimental.UtilityClass; import net.dv8tion.jda.api.entities.Guild; -import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Role; +import net.dv8tion.jda.api.exceptions.ErrorResponseException; -import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -41,27 +39,31 @@ public class DiscordRanks { return; } Guild guild = SteamwarDiscordBot.instance().getJda().getGuildById(SteamwarDiscordBotConfig.GUILD); - Member member = guild.retrieveMemberById(steamwarUser.getDiscordId()).complete(); - if (member == null) { - return; - } - - List roleList = member.getRoles(); - Set strings = new HashSet<>(SteamwarDiscordBotConfig.RANKS.values()); - String needed = SteamwarDiscordBotConfig.RANKS.get(steamwarUser.getUserGroup()); - for (Role role : roleList) { - if (!strings.contains(role.getId())) { - continue; + guild.retrieveMemberById(steamwarUser.getDiscordId()).queue(member -> { + List roleList = member.getRoles(); + Set strings = new HashSet<>(SteamwarDiscordBotConfig.RANKS.values()); + String needed = SteamwarDiscordBotConfig.RANKS.get(steamwarUser.getUserGroup()); + for (Role role : roleList) { + if (!strings.contains(role.getId())) { + continue; + } + if (role.getId().equals(needed)) { + needed = ""; + continue; + } + guild.removeRoleFromMember(member, role).complete(); } - if (role.getId().equals(needed)) { - needed = ""; - continue; - } - guild.removeRoleFromMember(member, role).complete(); - } - if (needed != null && !needed.isEmpty()) { - guild.addRoleToMember(member, guild.getRoleById(needed)).complete(); - } + if (needed != null && !needed.isEmpty()) { + guild.addRoleToMember(member, guild.getRoleById(needed)).complete(); + } + }, throwable -> { + if(throwable instanceof ErrorResponseException) { + ErrorResponseException e = (ErrorResponseException) throwable; + if(e.getErrorCode() == 10007) { + steamwarUser.setDiscordId(null); + } + } + }); } } diff --git a/src/de/steamwar/bungeecore/bot/util/DiscordRolesMessage.java b/src/de/steamwar/bungeecore/bot/util/DiscordRolesMessage.java index baa8801..1486deb 100644 --- a/src/de/steamwar/bungeecore/bot/util/DiscordRolesMessage.java +++ b/src/de/steamwar/bungeecore/bot/util/DiscordRolesMessage.java @@ -38,10 +38,6 @@ public class DiscordRolesMessage { public void sendMessage() { TextChannel channel = SteamwarDiscordBot.instance().getJda().getGuildById(SteamwarDiscordBotConfig.GUILD).getTextChannelById(SteamwarDiscordBotConfig.ROLES_CHANNEL); assert channel != null; - Message message = null; - if(channel.hasLatestMessage()) { - message = channel.getIterableHistory().complete().stream().filter(m -> m.getAuthor().isBot()).findFirst().orElse(null); - } MessageBuilder builder = new MessageBuilder(); builder.setContent(SteamwarDiscordBotConfig.ROLES_BASE_MESSAGE); @@ -49,10 +45,17 @@ public class DiscordRolesMessage { SteamwarDiscordBotConfig.ROLES.forEach(discordRole -> buttons.add(discordRole.toButton())); builder.setActionRows(ActionRow.of(buttons)); - if (message != null) { - message.editMessage(builder.build()).complete(); + if(channel.hasLatestMessage()) { + channel.getIterableHistory().queue(messages -> { + Message message = messages.stream().filter(m -> m.getAuthor().isBot()).findFirst().orElse(null); + if (message != null) { + message.editMessage(builder.build()).queue(); + } else { + channel.sendMessage(builder.build()).queue(); + } + }); } else { - channel.sendMessage(builder.build()).complete(); + channel.sendMessage(builder.build()).queue(); } } } diff --git a/src/de/steamwar/bungeecore/bot/util/DiscordRulesMessage.java b/src/de/steamwar/bungeecore/bot/util/DiscordRulesMessage.java index a1cb6fb..a061d66 100644 --- a/src/de/steamwar/bungeecore/bot/util/DiscordRulesMessage.java +++ b/src/de/steamwar/bungeecore/bot/util/DiscordRulesMessage.java @@ -60,9 +60,9 @@ public class DiscordRulesMessage { messageBuilder.setEmbeds(builder.build()); messageBuilder.setActionRows(ActionRow.of(buttons), ActionRow.of(authButton)); if (message != null) { - message.editMessage(messageBuilder.build()).complete(); + message.editMessage(messageBuilder.build()).queue(); } else { - channel.sendMessage(messageBuilder.build()).complete(); + channel.sendMessage(messageBuilder.build()).queue(); } } } diff --git a/src/de/steamwar/bungeecore/bot/util/DiscordTicketMessage.java b/src/de/steamwar/bungeecore/bot/util/DiscordTicketMessage.java index ab93000..ea6cea3 100644 --- a/src/de/steamwar/bungeecore/bot/util/DiscordTicketMessage.java +++ b/src/de/steamwar/bungeecore/bot/util/DiscordTicketMessage.java @@ -56,9 +56,9 @@ public class DiscordTicketMessage { messageBuilder.setEmbeds(builder.build()); messageBuilder.setActionRows(ActionRow.of(buttons)); if (message != null) { - message.editMessage(messageBuilder.build()).complete(); + message.editMessage(messageBuilder.build()).queue(); } else { - channel.sendMessage(messageBuilder.build()).complete(); + channel.sendMessage(messageBuilder.build()).queue(); } } } diff --git a/src/de/steamwar/bungeecore/commands/BanCommand.java b/src/de/steamwar/bungeecore/commands/BanCommand.java deleted file mode 100644 index 1b3f38d..0000000 --- a/src/de/steamwar/bungeecore/commands/BanCommand.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - 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.bungeecore.commands; - -import de.steamwar.bungeecore.Message; -import de.steamwar.bungeecore.sql.SteamwarUser; -import net.md_5.bungee.api.CommandSender; - -import java.sql.Timestamp; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.time.Instant; -import java.util.Date; - -public class BanCommand extends BasicCommand { - - public BanCommand() { - super("ban", "bungeecore.ban"); - } - - @Override - public void execute(CommandSender sender, String[] args) { - if(args.length < 3){ - Message.send("USAGE_BAN", sender); - return; - } - - SteamwarUser target = unsafeUser(sender, args[0]); - if(target == null) - return; - - Timestamp banTime = parseTime(sender, args[1]); - if(banTime == null) - return; - - StringBuilder banReason = new StringBuilder(); - for (int i = 2; i < args.length; i++){ - banReason.append(args[i]).append(" "); - } - boolean isPerma = args[1].equalsIgnoreCase("perma"); - String msg = banReason.toString(); - target.ban(banTime, msg, SteamwarUser.get(sender.getName()).getId(), isPerma); - Message.team("BAN_TEAM_BANNED", new Message("PREFIX"), target.getUserName(), sender.getName(), new Message((isPerma?"BAN_PERMA":"BAN_UNTIL"), banTime), msg); - } - - public static Timestamp parseTime(CommandSender sender, String arg){ - if(arg.equalsIgnoreCase("perma")) { - return Timestamp.from(Instant.ofEpochSecond(946674800)); - }else{ - SimpleDateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy_HH:mm"); - try{ - Date parsedDate = dateFormat.parse(arg); - return new java.sql.Timestamp(parsedDate.getTime()); - }catch(ParseException e){ - dateFormat = new SimpleDateFormat("dd.MM.yyyy"); - try{ - Date parsedDate = dateFormat.parse(arg.split("_")[0]); - return new java.sql.Timestamp(parsedDate.getTime()); - }catch(ParseException exception){ - if (sender != null) { - Message.send("INVALID_TIME", sender); - } - return null; - } - } - } - } -} diff --git a/src/de/steamwar/bungeecore/commands/BauCommand.java b/src/de/steamwar/bungeecore/commands/BauCommand.java index 43944d7..b555494 100644 --- a/src/de/steamwar/bungeecore/commands/BauCommand.java +++ b/src/de/steamwar/bungeecore/commands/BauCommand.java @@ -20,38 +20,39 @@ package de.steamwar.bungeecore.commands; import de.steamwar.bungeecore.*; +import de.steamwar.bungeecore.comms.packets.BaumemberUpdatePacket; import de.steamwar.bungeecore.inventory.SWInventory; import de.steamwar.bungeecore.inventory.SWItem; import de.steamwar.bungeecore.sql.BauweltMember; import de.steamwar.bungeecore.sql.SteamwarUser; +import net.md_5.bungee.api.CommandSender; import net.md_5.bungee.api.ProxyServer; +import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.api.connection.ProxiedPlayer; -import net.md_5.bungee.api.event.ChatEvent; -public class BauCommand { +public class BauCommand extends BasicCommand { - private BauCommand(){} + public BauCommand(){ + super("bau", null, "b", "gs"); + } - public static void onBau(ChatEvent e, String[] command){ - if(BungeeCore.EVENT_MODE) + @Override + public void execute(CommandSender sender, String[] args) { + if(!(sender instanceof ProxiedPlayer)) { return; + } - ProxiedPlayer p = (ProxiedPlayer) e.getSender(); - Subserver server = Subserver.getSubserver(p); - Bauserver bau = (server != null && server.getType() == Servertype.BAUSERVER) ? (Bauserver)server : null; - boolean ownBau = bau != null && bau.getOwner().equals(p.getUniqueId()); - e.setCancelled(true); - BungeeCore.log(p, e.getMessage()); + ProxiedPlayer p = (ProxiedPlayer) sender; - if(command.length == 1){ - if(bau15(p, command, 1)) + if(args.length == 0){ + if(bau15(p, args, 0)) SubserverSystem.sendToBau15(p, p.getUniqueId()); else SubserverSystem.sendToBauServer(p, p.getUniqueId()); return; } - switch(command[1].toLowerCase()){ + switch(args[0].toLowerCase()){ case "ws": case "warship": case "12": @@ -72,52 +73,44 @@ public class BauCommand { SubserverSystem.sendToBau15paper(p, p.getUniqueId()); break; case "addmember": - addmember(p, command); + addmember(p, args); break; case "tp": case "teleport": - teleport(p, command); + teleport(p, args); break; case "info": - if (bau != null) { - e.setCancelled(false); - } + p.chat("/bauinfo"); break; case "togglewe": - if(ownBau && command.length > 2) - e.setCancelled(false); - else - togglewe(p, command); + togglewe(p, args); break; case "toggleworld": - if(ownBau && command.length > 2) - e.setCancelled(false); - else - toggleworld(p, command); + toggleworld(p, args); break; case "delmember": - delmember(p, command); + delmember(p, args); break; case "resetall": case "delete": - delete(p, command); + delete(p, args); break; case "testarena": case "test": - testarena(p, command); + testarena(p, args); break; default: HelpCommand.sendBauHelp(p); } } - private static void addmember(ProxiedPlayer p, String[] command){ - if (command.length == 2) { + private static void addmember(ProxiedPlayer p, String[] args){ + if (args.length == 1) { Message.send("BAU_ADDMEMBER_USAGE", p); return; } - SteamwarUser target = SteamwarUser.get(command[2]); + SteamwarUser target = SteamwarUser.get(args[1]); if (target == null) { Message.send("UNKNOWN_PLAYER", p); return; @@ -137,13 +130,13 @@ public class BauCommand { Message.send("BAU_ADDMEMBER_ADDED_TARGET", z, p.getName()); } - private static void teleport(ProxiedPlayer p, String[] command){ - if (command.length == 2) { + private static void teleport(ProxiedPlayer p, String[] args){ + if (args.length == 1) { Message.send("BAU_TP_USAGE", p); return; } - SteamwarUser worldOwner = SteamwarUser.get(command[2]); + SteamwarUser worldOwner = SteamwarUser.get(args[1]); if (worldOwner == null) { Message.send("UNKNOWN_PLAYER", p); return; @@ -153,7 +146,7 @@ public class BauCommand { return; } - if(bau15(p, command, 3)) + if(bau15(p, args, 2)) SubserverSystem.sendToBau15(p, worldOwner.getUuid()); else SubserverSystem.sendToBauServer(p, worldOwner.getUuid()); @@ -183,31 +176,43 @@ public class BauCommand { } } - private static void togglewe(ProxiedPlayer p, String[] command){ - BauweltMember target = toggle(p, command, "togglewe"); + private static void togglewe(ProxiedPlayer p, String[] args){ + BauweltMember target = toggle(p, args, "togglewe"); if(target == null) return; target.setWorldEdit(!target.isWorldEdit()); + clearMembercache(p); isAllowedTo(target.isWorldEdit(), p, target, "WorldEdit verwenden"); } - private static void toggleworld(ProxiedPlayer p, String[] command){ - BauweltMember target = toggle(p, command, "toggleworld"); + private static void toggleworld(ProxiedPlayer p, String[] args){ + BauweltMember target = toggle(p, args, "toggleworld"); if(target == null) return; target.setWorld(!target.isWorld()); + clearMembercache(p); isAllowedTo(target.isWorld(), p, target, "Einstellungen vornehmen"); } - private static void delmember(ProxiedPlayer p, String[] command){ - if (command.length == 2) { + private static void clearMembercache(ProxiedPlayer p){ + for(ServerInfo info : ProxyServer.getInstance().getServers().values()){ + Subserver server = Subserver.getSubserver(info); + if(server != null && server.getType() == Servertype.BAUSERVER && ((Bauserver)server).getOwner().equals(p.getUniqueId())){ + info.getPlayers().stream().findAny().ifPresent(player -> new BaumemberUpdatePacket().send(player)); + break; + } + } + } + + private static void delmember(ProxiedPlayer p, String[] args){ + if (args.length == 1) { Message.send("BAU_DELMEMBER_USAGE", p); return; } - BauweltMember target = member(p, SteamwarUser.get(command[2])); + BauweltMember target = member(p, SteamwarUser.get(args[1])); if(target == null) return; @@ -228,13 +233,13 @@ public class BauCommand { Message.send("BAU_DELMEMBER_DELETED", p); } - private static void delete(ProxiedPlayer p, String[] command){ + private static void delete(ProxiedPlayer p, String[] args){ SWInventory inventory = new SWInventory(p, 9, Message.parse("BAU_DELETE_GUI_NAME", p)); inventory.addItem(8, new SWItem(Message.parse("BAU_DELETE_GUI_CANCEL", p), 1), click -> inventory.close() ); inventory.addItem(0, new SWItem(Message.parse("BAU_DELETE_GUI_DELETE", p), 10), click -> { - if(bau15(p, command, 2)){ + if(bau15(p, args, 1)){ SteamwarUser user = SteamwarUser.get(p.getUniqueId()); deleteWorld(p, BungeeCore.USERWORLDS15 + user.getId()); }else{ @@ -253,16 +258,16 @@ public class BauCommand { break; } } - SubserverSystem.deleteFolder(world); + SubserverSystem.deleteFolder(Node.local, world); }); } - public static void stopBauserver(ProxiedPlayer p){ + public static boolean stopBauserver(ProxiedPlayer p){ for (Subserver subserver : Subserver.getServerList()) { if (subserver.getType() == Servertype.BAUSERVER && ((Bauserver) subserver).getOwner().equals(p.getUniqueId())) { - if(subserver.getServer().getPlayers().isEmpty()){ + if(!subserver.hasStarted()){ Message.send("BAU_START_ALREADY", p); - return; + return false; } subserver.stop(); try { @@ -273,12 +278,13 @@ public class BauCommand { break; } } + return true; } - private static void testarena(ProxiedPlayer p, String[] command){ - FightCommand.createArena(p, "/bau testarena ", command, 2, false, (player, mode, map) -> ProxyServer.getInstance().getScheduler().runAsync(BungeeCore.get(), () -> { - stopBauserver(p); - SubserverSystem.startTestServer(p, mode, map, 0, 0); + private static void testarena(ProxiedPlayer p, String[] args){ + FightCommand.createArena(p, "/bau testarena ", args, 1, false, (player, mode, map) -> ProxyServer.getInstance().getScheduler().runAsync(BungeeCore.get(), () -> { + if(stopBauserver(p)) + SubserverSystem.startTestServer(p, mode, map, 0, 0); })); } @@ -296,13 +302,13 @@ public class BauCommand { return target; } - private static BauweltMember toggle(ProxiedPlayer p, String[] command, String subcommand){ - if (command.length == 2) { + private static BauweltMember toggle(ProxiedPlayer p, String[] args, String subcommand){ + if (args.length == 1) { Message.send("BAU_MEMBER_TOGGLE_USAGE", p, subcommand); return null; } - SteamwarUser member = SteamwarUser.get(command[2]); + SteamwarUser member = SteamwarUser.get(args[1]); return member(p, member); } diff --git a/src/de/steamwar/bungeecore/commands/ChallengeCommand.java b/src/de/steamwar/bungeecore/commands/ChallengeCommand.java index 3d4150d..1025eea 100644 --- a/src/de/steamwar/bungeecore/commands/ChallengeCommand.java +++ b/src/de/steamwar/bungeecore/commands/ChallengeCommand.java @@ -27,7 +27,8 @@ import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.chat.ClickEvent; import net.md_5.bungee.api.connection.ProxiedPlayer; -import java.util.*; +import java.util.ArrayList; +import java.util.LinkedList; import static de.steamwar.bungeecore.Storage.challenges; diff --git a/src/de/steamwar/bungeecore/commands/CheckCommand.java b/src/de/steamwar/bungeecore/commands/CheckCommand.java index dde381b..bbfd55f 100644 --- a/src/de/steamwar/bungeecore/commands/CheckCommand.java +++ b/src/de/steamwar/bungeecore/commands/CheckCommand.java @@ -234,7 +234,10 @@ public class CheckCommand extends BasicCommand { this.checkList = checkQuestions.get(schematic.getSchemtype()).listIterator(); ProxyServer.getInstance().getScheduler().runAsync(BungeeCore.get(), () -> { - BauCommand.stopBauserver(checker); + if(!BauCommand.stopBauserver(checker)){ + remove(); + return; + } ArenaMode mode = ArenaMode.getBySchemType(schematic.getSchemtype()); SubserverSystem.startTestServer(checker, mode, FightCommand.getMap(checker, mode, "Random"), schematic.getId(), 0); @@ -324,7 +327,7 @@ public class CheckCommand extends BasicCommand { private void stop(){ currentCheckers.remove(checker.getUniqueId()); - currentSchems.remove(schematic.getId()); + currentSchems.remove(schematic.getSchemID()); ProxyServer.getInstance().getScheduler().runAsync(BungeeCore.get(), () -> { for (Subserver subserver : Subserver.getServerList()) { if (subserver.getType() == Servertype.BAUSERVER && ((Bauserver) subserver).getOwner().equals(checker.getUniqueId())) { @@ -334,5 +337,10 @@ public class CheckCommand extends BasicCommand { } }); } + + private void remove() { + currentCheckers.remove(checker.getUniqueId()); + currentSchems.remove(schematic.getSchemID()); + } } } diff --git a/src/de/steamwar/bungeecore/commands/DevCommand.java b/src/de/steamwar/bungeecore/commands/DevCommand.java index dcc4b7f..ce05e13 100644 --- a/src/de/steamwar/bungeecore/commands/DevCommand.java +++ b/src/de/steamwar/bungeecore/commands/DevCommand.java @@ -20,6 +20,8 @@ package de.steamwar.bungeecore.commands; import de.steamwar.bungeecore.Message; +import de.steamwar.bungeecore.sql.Punishment; +import de.steamwar.bungeecore.sql.SteamwarUser; import net.md_5.bungee.api.CommandSender; import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.config.ServerInfo; @@ -27,14 +29,15 @@ import net.md_5.bungee.api.connection.ProxiedPlayer; import java.io.File; import java.net.InetSocketAddress; -import java.util.Arrays; import java.util.Collections; -import java.util.function.Predicate; +import java.util.HashMap; +import java.util.Map; import java.util.stream.Collectors; public class DevCommand extends BasicCommand { - private final File DevServerDir = new File("/configs/DevServer"); + private final File devServerDir = new File("/configs/DevServer"); + private final Map devServers = new HashMap<>(); public DevCommand() { super("dev", ""); @@ -42,56 +45,79 @@ public class DevCommand extends BasicCommand { @Override public void execute(CommandSender sender, String[] args) { - if (!(sender instanceof ProxiedPlayer)) { + if (!(sender instanceof ProxiedPlayer)) + return; + ProxiedPlayer player = (ProxiedPlayer) sender; + + SteamwarUser steamwarUser = SteamwarUser.get(player); + if (steamwarUser.isPunishedWithMessage(player, Punishment.PunishmentType.NoDevServer)) { return; } - String[] devServer = DevServerDir.list(); - if (devServer == null || devServer.length == 0) { + + updateDevServers(); + if(devServers.isEmpty()) { Message.send("DEV_NO_SERVER", sender); - } else if (devServer.length == 1) { - String[] server = devServer[0].split("\\."); - sendToServer((ProxiedPlayer) sender, server[0], Integer.parseInt(server[1])); + } else if (devServers.size() == 1) { + player.connect(devServers.values().stream().findAny().get()); + } else if (args.length == 0) { + ServerInfo info = devServers.get(player.getName().toLowerCase()); + if (info == null) { + Message.send("DEV_UNKNOWN_SERVER", player); + return; + } + + player.connect(info); } else { - if (args.length == 0) { - send(devServer, (ProxiedPlayer) sender, s -> s.equalsIgnoreCase(sender.getName()), () -> Message.send("DEV_UNKNOWN_SERVER", sender)); - } else { - send(devServer, (ProxiedPlayer) sender, args[0]::equalsIgnoreCase, () -> Message.send("DEV_NO_SERVER", sender)); + ServerInfo info = devServers.get(args[0].toLowerCase()); + if (info == null) { + Message.send("DEV_NO_SERVER", player); + return; } - } - } - private void send(String[] devServer, ProxiedPlayer sender, Predicate test, Runnable error) { - for (String s : devServer) { - String[] server = s.split("\\."); - if (test.test(server[0])) { - sendToServer(sender, server[0], Integer.parseInt(server[1])); - break; - } + player.connect(info); } - error.run(); - } - - private void sendToServer(ProxiedPlayer proxiedPlayer, String name, int port) { - InetSocketAddress address = new InetSocketAddress("127.0.0.1", port); - ServerInfo serverInfo = ProxyServer.getInstance().constructServerInfo("Dev-" + name, address, "SteamWar.de - Subserver", false); - proxiedPlayer.connect(serverInfo); } @Override public Iterable onTabComplete(CommandSender sender, String[] args) { - if (!(sender instanceof ProxiedPlayer)) { + if (!(sender instanceof ProxiedPlayer) || args.length > 1) { return Collections.emptyList(); } - String[] devSever = DevServerDir.list(); - if (devSever == null) { - return Collections.emptyList(); - } - if (args.length > 1) { - return Collections.emptyList(); - } - return Arrays.stream(devSever).map(s -> s.split("\\.")).map(s -> s[0]).filter(s -> { + + updateDevServers(); + return devServers.keySet().stream().filter(s -> { if (args.length == 0) return true; - return s.startsWith(args[0]); + return s.startsWith(args[0].toLowerCase()); }).collect(Collectors.toList()); } + + private void updateDevServers() { + String[] serverFiles = devServerDir.list(); + + Map devServerFiles = new HashMap<>(); + if(serverFiles != null) { + for(String serverFile : serverFiles) { + String[] server = serverFile.split("\\."); + devServerFiles.put(server[0], Integer.parseInt(server[1])); + } + } + + devServers.entrySet().removeIf(entry -> { + if(!devServerFiles.containsKey(entry.getKey())) { + ProxyServer.getInstance().getServers().remove(entry.getValue().getName()); + return true; + } + return false; + }); + + devServerFiles.forEach((key, value) -> { + if (devServers.containsKey(key)) + return; + + SteamwarUser user = SteamwarUser.get(key); + ServerInfo info = ProxyServer.getInstance().constructServerInfo("Dev " + user.getUserName(), new InetSocketAddress("127.0.0.1", value), "SteamWar.de - Subserver", false); + ProxyServer.getInstance().getServers().put(info.getName(), info); + devServers.put(user.getUserName().toLowerCase(), info); + }); + } } diff --git a/src/de/steamwar/bungeecore/commands/HistoricCommand.java b/src/de/steamwar/bungeecore/commands/HistoricCommand.java index ebf9312..0ddfef2 100644 --- a/src/de/steamwar/bungeecore/commands/HistoricCommand.java +++ b/src/de/steamwar/bungeecore/commands/HistoricCommand.java @@ -19,7 +19,10 @@ package de.steamwar.bungeecore.commands; -import de.steamwar.bungeecore.*; +import de.steamwar.bungeecore.ArenaMode; +import de.steamwar.bungeecore.Message; +import de.steamwar.bungeecore.Subserver; +import de.steamwar.bungeecore.SubserverSystem; import net.md_5.bungee.api.CommandSender; import net.md_5.bungee.api.chat.ClickEvent; diff --git a/src/de/steamwar/bungeecore/commands/ListCommand.java b/src/de/steamwar/bungeecore/commands/ListCommand.java index b7a4a63..cb2de64 100644 --- a/src/de/steamwar/bungeecore/commands/ListCommand.java +++ b/src/de/steamwar/bungeecore/commands/ListCommand.java @@ -22,7 +22,6 @@ package de.steamwar.bungeecore.commands; import de.steamwar.bungeecore.Message; import de.steamwar.bungeecore.Servertype; import de.steamwar.bungeecore.Subserver; -import lombok.Getter; import net.md_5.bungee.api.CommandSender; import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.config.ServerInfo; @@ -40,12 +39,8 @@ public class ListCommand extends BasicCommand { super("list", ""); } - @Getter - private static final TreeMap> playerMap = new TreeMap<>(); - - public static synchronized void updateCustomTablist(){ - //Calculate server-player-map - playerMap.clear(); + public static synchronized TreeMap> getCustomTablist(){ + TreeMap> playerMap = new TreeMap<>(); for (ProxiedPlayer player : ProxyServer.getInstance().getPlayers()) { Server pserver = player.getServer(); if (pserver == null) //Happens temporarily @@ -62,11 +57,12 @@ public class ListCommand extends BasicCommand { } } playerMap.forEach((server, players) -> players.sort((proxiedPlayer, t1) -> proxiedPlayer.getName().compareToIgnoreCase(t1.getName()))); + return playerMap; } @Override public void execute(CommandSender commandSender, String[] strings) { - updateCustomTablist(); + TreeMap> playerMap = getCustomTablist(); for (String server : playerMap.navigableKeySet()) { if (server.equals("Bau")) { server = Message.parse("TABLIST_BAU", commandSender); diff --git a/src/de/steamwar/bungeecore/commands/MsgCommand.java b/src/de/steamwar/bungeecore/commands/MsgCommand.java index 8ec0d38..67f7013 100644 --- a/src/de/steamwar/bungeecore/commands/MsgCommand.java +++ b/src/de/steamwar/bungeecore/commands/MsgCommand.java @@ -22,6 +22,7 @@ package de.steamwar.bungeecore.commands; import de.steamwar.bungeecore.BungeeCore; import de.steamwar.bungeecore.Message; import de.steamwar.bungeecore.sql.IgnoreSystem; +import de.steamwar.bungeecore.sql.Punishment; import de.steamwar.bungeecore.sql.SteamwarUser; import net.md_5.bungee.api.CommandSender; import net.md_5.bungee.api.ProxyServer; @@ -48,8 +49,7 @@ public class MsgCommand extends BasicCommand { } SteamwarUser user = SteamwarUser.get(player); - if(user.isMuted()){ - sender.sendMessage(user.muteMessage(player)); + if (user.isPunishedWithMessage(player, Punishment.PunishmentType.Mute)) { return; } diff --git a/src/de/steamwar/bungeecore/commands/MuteCommand.java b/src/de/steamwar/bungeecore/commands/MuteCommand.java deleted file mode 100644 index 9ecfde1..0000000 --- a/src/de/steamwar/bungeecore/commands/MuteCommand.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - 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.bungeecore.commands; - -import de.steamwar.bungeecore.Message; -import de.steamwar.bungeecore.sql.SteamwarUser; -import net.md_5.bungee.api.CommandSender; - -import java.sql.Timestamp; - -public class MuteCommand extends BasicCommand { - - public MuteCommand() { - super("mute", "bungeecore.ban"); - } - - @Override - public void execute(CommandSender sender, String[] args) { - if(args.length < 3){ - Message.send("USAGE_MUTE", sender); - return; - } - - SteamwarUser target = unsafeUser(sender, args[0]); - if(target == null) - return; - - Timestamp muteTime = BanCommand.parseTime(sender, args[1]); - if(muteTime == null) - return; - - StringBuilder muteReason = new StringBuilder(); - for (int i = 2; i < args.length; i++){ - muteReason.append(args[i]).append(" "); - } - String msg = muteReason.toString(); - target.mute(muteTime, msg, SteamwarUser.get(sender.getName()).getId(), args[1].equalsIgnoreCase("perma")); - Message.team("MUTE_TEAM_MUTED", new Message("PREFIX"), target.getUserName(), sender.getName(), new Message((args[1].equalsIgnoreCase("perma")?"BAN_PERMA":"BAN_UNTIL"), muteTime), msg); - } -} diff --git a/src/de/steamwar/bungeecore/commands/PollresultCommand.java b/src/de/steamwar/bungeecore/commands/PollresultCommand.java index 1d39e9e..cfebd66 100644 --- a/src/de/steamwar/bungeecore/commands/PollresultCommand.java +++ b/src/de/steamwar/bungeecore/commands/PollresultCommand.java @@ -46,7 +46,7 @@ public class PollresultCommand extends BasicCommand { ProxiedPlayer player = (ProxiedPlayer) sender; Map voted = PollAnswer.getCurrentResults(); - Message.send("POLLRESULT_HEADER", player, PollAnswer.getAllAnswered(), PollSystem.getQuestion()); + Message.send("POLLRESULT_HEADER", player, voted.values().stream().reduce(Integer::sum), PollSystem.getQuestion()); for (Map.Entry e: voted.entrySet()) { Message.send("POLLRESULT_LIST", sender, e.getKey(), e.getValue()); } diff --git a/src/de/steamwar/bungeecore/commands/PunishmentCommand.java b/src/de/steamwar/bungeecore/commands/PunishmentCommand.java new file mode 100644 index 0000000..eda5c8b --- /dev/null +++ b/src/de/steamwar/bungeecore/commands/PunishmentCommand.java @@ -0,0 +1,115 @@ +/* + * 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.bungeecore.commands; + +import de.steamwar.bungeecore.Message; +import de.steamwar.bungeecore.sql.Punishment; +import de.steamwar.bungeecore.sql.SteamwarUser; +import net.md_5.bungee.api.CommandSender; +import net.md_5.bungee.api.connection.ProxiedPlayer; + +import java.sql.Timestamp; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.time.Instant; +import java.util.Date; + +public class PunishmentCommand { + + public PunishmentCommand(String command, Punishment.PunishmentType punishmentType) { + new BasicCommand(command, "bungeecore.ban") { + @Override + public void execute(CommandSender sender, String[] args) { + if (punishmentType.isNeedsAdmin() && !SteamwarUser.get((ProxiedPlayer) sender).getUserGroup().isAdminGroup()) { + return; + } + if (args.length < 3) { + Message.send("PUNISHMENT_USAGE", sender, command); + return; + } + + SteamwarUser target = unsafeUser(sender, args[0]); + if (target == null) + return; + + Timestamp banTime = parseTime(sender, args[1]); + if (banTime == null) + return; + + StringBuilder reason = new StringBuilder(); + for (int i = 2; i < args.length; i++) { + reason.append(args[i]).append(" "); + } + boolean isPerma = args[1].equalsIgnoreCase("perma"); + String msg = reason.toString(); + target.punish(punishmentType, banTime, msg, SteamwarUser.get(sender.getName()).getId(), isPerma); + Message.team(punishmentType.getTeamMessage(), new Message("PREFIX"), target.getUserName(), sender.getName(), new Message((isPerma ? "PUNISHMENT_PERMA" : "PUNISHMENT_UNTIL"), banTime), msg); + } + }; + String antiCommand = "un" + command; + new BasicCommand(antiCommand, "bungeecore.ban") { + @Override + public void execute(CommandSender sender, String[] args) { + if (punishmentType.isNeedsAdmin() && !SteamwarUser.get((ProxiedPlayer) sender).getUserGroup().isAdminGroup()) { + return; + } + if (args.length < 1) { + Message.send("UNPUNISHMENT_USAGE", sender, antiCommand); + return; + } + + SteamwarUser target = existingUser(sender, args[0]); + if (target == null) + return; + + if (!target.isPunished(punishmentType)) { + Message.send(punishmentType.getUsageNotPunished(), sender); + return; + } + + Message.send(punishmentType.getUnpunishmentMessage(), sender, target.getUserName()); + target.punish(punishmentType, Timestamp.from(new Date().toInstant()), antiCommand, SteamwarUser.get(sender.getName()).getId(), false); + } + }; + } + + public static Timestamp parseTime(CommandSender sender, String arg) { + if (arg.equalsIgnoreCase("perma")) { + return Timestamp.from(Instant.ofEpochSecond(946674800)); + } else { + SimpleDateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy_HH:mm"); + try { + Date parsedDate = dateFormat.parse(arg); + return new java.sql.Timestamp(parsedDate.getTime()); + } catch (ParseException e) { + dateFormat = new SimpleDateFormat("dd.MM.yyyy"); + try { + Date parsedDate = dateFormat.parse(arg.split("_")[0]); + return new java.sql.Timestamp(parsedDate.getTime()); + } catch (ParseException exception) { + if (sender != null) { + Message.send("INVALID_TIME", sender); + } + return null; + } + } + } + } +} diff --git a/src/de/steamwar/bungeecore/commands/RCommand.java b/src/de/steamwar/bungeecore/commands/RCommand.java index fef0031..c9d70dd 100644 --- a/src/de/steamwar/bungeecore/commands/RCommand.java +++ b/src/de/steamwar/bungeecore/commands/RCommand.java @@ -22,6 +22,7 @@ package de.steamwar.bungeecore.commands; import de.steamwar.bungeecore.BungeeCore; import de.steamwar.bungeecore.Message; import de.steamwar.bungeecore.sql.IgnoreSystem; +import de.steamwar.bungeecore.sql.Punishment; import de.steamwar.bungeecore.sql.SteamwarUser; import net.md_5.bungee.api.CommandSender; import net.md_5.bungee.api.connection.ProxiedPlayer; @@ -44,8 +45,7 @@ public class RCommand extends BasicCommand { } SteamwarUser user = SteamwarUser.get(player); - if(user.isMuted()){ - sender.sendMessage(user.muteMessage(player)); + if (user.isPunishedWithMessage(player, Punishment.PunishmentType.Mute)) { return; } diff --git a/src/de/steamwar/bungeecore/commands/RankedCommand.java b/src/de/steamwar/bungeecore/commands/RankedCommand.java index 1a978b5..f1649cb 100644 --- a/src/de/steamwar/bungeecore/commands/RankedCommand.java +++ b/src/de/steamwar/bungeecore/commands/RankedCommand.java @@ -49,11 +49,14 @@ public class RankedCommand extends BasicCommand { @Override public void execute(CommandSender sender, String[] args) { + if(!(sender instanceof ProxiedPlayer)) { + return; + } + if(args.length < 1){ getModes(sender, "/ranked "); return; - }else if(!(sender instanceof ProxiedPlayer)) - return; + } ArenaMode mode = FightCommand.getMode(sender, args[0]); if(mode == null) diff --git a/src/de/steamwar/bungeecore/commands/ServerTeamchatCommand.java b/src/de/steamwar/bungeecore/commands/ServerTeamchatCommand.java index b9b0ab1..f9c589b 100644 --- a/src/de/steamwar/bungeecore/commands/ServerTeamchatCommand.java +++ b/src/de/steamwar/bungeecore/commands/ServerTeamchatCommand.java @@ -19,6 +19,7 @@ package de.steamwar.bungeecore.commands; +import de.steamwar.bungeecore.BungeeCore; import de.steamwar.bungeecore.Message; import de.steamwar.bungeecore.bot.SteamwarDiscordBot; import de.steamwar.bungeecore.listeners.ChatListener; @@ -28,6 +29,8 @@ import net.md_5.bungee.api.CommandSender; import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.connection.ProxiedPlayer; +import java.util.logging.Level; + public class ServerTeamchatCommand extends BasicCommand { public ServerTeamchatCommand() { @@ -51,7 +54,11 @@ public class ServerTeamchatCommand extends BasicCommand { String msg = msgBuilder.toString(); msg = ChatColor.translateAlternateColorCodes('&', msg); - SteamwarDiscordBot.instance().getServerTeamChatListener().send(" " + (player.getName() + "» " + msg).replaceAll("§[a-f0-9r]", "")); + try { + SteamwarDiscordBot.instance().getServerTeamChatListener().send(" " + (player.getName() + "» " + msg).replaceAll("§[a-f0-9r]", "")); + } catch (Exception e) { + BungeeCore.get().getLogger().log(Level.SEVERE, "Could not send stc message to discord", e); + } sendToTeam(msg, player); } } diff --git a/src/de/steamwar/bungeecore/commands/StatCommand.java b/src/de/steamwar/bungeecore/commands/StatCommand.java index 1488dbf..b633fb5 100644 --- a/src/de/steamwar/bungeecore/commands/StatCommand.java +++ b/src/de/steamwar/bungeecore/commands/StatCommand.java @@ -19,8 +19,8 @@ package de.steamwar.bungeecore.commands; -import de.steamwar.bungeecore.LoadEvaluation; import de.steamwar.bungeecore.Message; +import de.steamwar.bungeecore.Node; import net.md_5.bungee.api.CommandSender; import java.io.BufferedReader; @@ -36,34 +36,22 @@ public class StatCommand extends BasicCommand { @Override public void execute(CommandSender sender, String[] args) { + Map serverCount = new HashMap<>(); try { Process process = new ProcessBuilder("ps", "x").start(); - process.waitFor(); - BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream())); - Map serverCounts = new HashMap<>(); - bufferedReader.lines().forEach(s -> { - if (!s.contains("--port")) { + new BufferedReader(new InputStreamReader(process.getInputStream())).lines().forEach(s -> { + if (!s.contains("--port")) return; - } - String server = "SW"; - if (s.contains("ssh -L")) { - server = s.substring(s.indexOf("ssh -L") + 6).split(" ")[2]; - } - serverCounts.put(server, serverCounts.computeIfAbsent(server, s1 -> 0) + 1); + serverCount.compute( + s.contains("ssh -L") ? s.substring(s.indexOf("ssh -L") + 6).split(" ")[2] : "local", + (server, count) -> (count != null ? count : 0) + 1 + ); }); - serverCounts.forEach((s, integer) -> { - if (s.equals("SW")) { - Message.send("STAT_SERVER", sender, s, LoadEvaluation.getRamPercentage(), LoadEvaluation.getCPULoad(), integer); - } else { - Message.send("STAT_SERVER", sender, s.toUpperCase(), LoadEvaluation.getRemoteRamPercentage(s), LoadEvaluation.getRemoteCPULoad(s), integer); - } - }); - if (serverCounts.isEmpty()) { - Message.send("NO_STATS", sender); - } } catch (Exception e) { throw new SecurityException(e.getMessage(), e); } + + Node.forEach(node -> Message.send("STAT_SERVER", sender, node.getName(), node.getLoad(), serverCount.getOrDefault(node.getName(), 0))); } } diff --git a/src/de/steamwar/bungeecore/commands/TeamCommand.java b/src/de/steamwar/bungeecore/commands/TeamCommand.java index af3a84b..58a3c35 100644 --- a/src/de/steamwar/bungeecore/commands/TeamCommand.java +++ b/src/de/steamwar/bungeecore/commands/TeamCommand.java @@ -177,7 +177,7 @@ public class TeamCommand extends BasicCommand { if(checkTeamName(player, team, args[2])) return; - Team.create(args[1], args[2], user); + Team.create(args[1], args[2]); user.setTeam(Team.get(args[1]).getTeamId()); user.setLeader(true); Message.send("TEAM_CREATE_CREATED", player, args[2]); @@ -441,10 +441,7 @@ public class TeamCommand extends BasicCommand { Set events = TeamTeilnahme.getEvents(team.getTeamId()); if(!events.isEmpty()){ - StringBuilder sb = new StringBuilder(); - for(Event e : events) - sb.append(e.getEventName()).append(" "); - Message.sendPrefixless("TEAM_INFO_EVENTS", player, sb.toString()); + Message.sendPrefixless("TEAM_INFO_EVENTS", player, events.stream().map(Event::getEventName).collect(Collectors.joining(", "))); } } diff --git a/src/de/steamwar/bungeecore/commands/UnbanCommand.java b/src/de/steamwar/bungeecore/commands/UnbanCommand.java deleted file mode 100644 index 176029a..0000000 --- a/src/de/steamwar/bungeecore/commands/UnbanCommand.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - 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.bungeecore.commands; - -import de.steamwar.bungeecore.Message; -import de.steamwar.bungeecore.sql.SteamwarUser; -import net.md_5.bungee.api.CommandSender; - -import java.sql.Timestamp; -import java.util.Date; - -public class UnbanCommand extends BasicCommand { - - public UnbanCommand() { - super("unban", "bungeecore.ban"); - } - - @Override - public void execute(CommandSender sender, String[] args) { - if(args.length < 1){ - Message.send("UNBAN_USAGE", sender); - return; - } - - SteamwarUser target = existingUser(sender, args[0]); - if(target == null) - return; - - if(!target.isBanned()) { - Message.send("UNBAN_NOT_BANNED", sender); - return; - } - - Message.send("UNBAN_UNBANNED", sender, target.getUserName()); - target.ban(Timestamp.from(new Date().toInstant()), "Unban", SteamwarUser.get(sender.getName()).getId(), false); - } -} diff --git a/src/de/steamwar/bungeecore/comms/PacketIdManager.java b/src/de/steamwar/bungeecore/comms/PacketIdManager.java index 8376d59..01d474a 100644 --- a/src/de/steamwar/bungeecore/comms/PacketIdManager.java +++ b/src/de/steamwar/bungeecore/comms/PacketIdManager.java @@ -25,9 +25,14 @@ public class PacketIdManager { public static final byte PING_PACKET = 0x01; public static final byte TABLIST_NAME = 0x02; public static final byte PREPARE_SCHEM = 0x03; + public static final byte BAUMEMBER_UPDATE = 0x04; //0x1(X) Bungee Inventory public static final byte INVENTORY_PACKET = 0x10; public static final byte INVENTORY_CALLBACK_PACKET = 0x11; public static final byte INVENTORY_CLOSE_PACKET = 0x12; + + //0x2(X) Server Information System + public static final byte I_AM_A_LOBBY = 0x20; + public static final byte FIGHT_INFO = 0x21; } diff --git a/src/de/steamwar/bungeecore/comms/SpigotHandler.java b/src/de/steamwar/bungeecore/comms/SpigotHandler.java index 5c0f118..574e9a2 100644 --- a/src/de/steamwar/bungeecore/comms/SpigotHandler.java +++ b/src/de/steamwar/bungeecore/comms/SpigotHandler.java @@ -20,8 +20,9 @@ package de.steamwar.bungeecore.comms; import com.google.common.io.ByteArrayDataInput; +import net.md_5.bungee.api.config.ServerInfo; public interface SpigotHandler { - void handle(ByteArrayDataInput byteArrayDataInput); + void handle(ByteArrayDataInput in, ServerInfo info); } diff --git a/src/de/steamwar/bungeecore/comms/SpigotReceiver.java b/src/de/steamwar/bungeecore/comms/SpigotReceiver.java index f87646f..ab6d246 100644 --- a/src/de/steamwar/bungeecore/comms/SpigotReceiver.java +++ b/src/de/steamwar/bungeecore/comms/SpigotReceiver.java @@ -21,10 +21,9 @@ package de.steamwar.bungeecore.comms; import com.google.common.io.ByteArrayDataInput; import com.google.common.io.ByteStreams; -import de.steamwar.bungeecore.comms.handlers.InventoryCallbackHandler; -import de.steamwar.bungeecore.comms.handlers.PrepareSchemHandler; -import de.steamwar.bungeecore.comms.handlers.TablistNameHandler; +import de.steamwar.bungeecore.comms.handlers.*; import de.steamwar.bungeecore.listeners.BasicListener; +import net.md_5.bungee.api.connection.Server; import net.md_5.bungee.api.event.PluginMessageEvent; import net.md_5.bungee.event.EventHandler; @@ -39,14 +38,14 @@ public class SpigotReceiver extends BasicListener { public void onPluginMessage(PluginMessageEvent event) { if(!event.getTag().equalsIgnoreCase("sw:bridge")) return; - if(!event.getSender().getAddress().getHostName().equals("localhost")){ - event.setCancelled(true); + + event.setCancelled(true); + if(!(event.getSender() instanceof Server)) return; - } + ByteArrayDataInput in = ByteStreams.newDataInput(event.getData()); Byte handler = in.readByte(); - handlerMap.get(handler).handle(in); - event.setCancelled(true); + handlerMap.get(handler).handle(in, ((Server) event.getSender()).getInfo()); } public static void registerHandler(Byte id, SpigotHandler handler) { @@ -55,7 +54,9 @@ public class SpigotReceiver extends BasicListener { static { registerHandler(PacketIdManager.INVENTORY_CALLBACK_PACKET, new InventoryCallbackHandler()); - registerHandler(PacketIdManager.TABLIST_NAME, new TablistNameHandler()); + registerHandler(PacketIdManager.TABLIST_NAME, (in, info) -> {}); registerHandler(PacketIdManager.PREPARE_SCHEM, new PrepareSchemHandler()); + registerHandler(PacketIdManager.I_AM_A_LOBBY, new ImALobbyHandler()); + registerHandler(PacketIdManager.FIGHT_INFO, new FightInfoHandler()); } } diff --git a/src/de/steamwar/bungeecore/comms/handlers/FightInfoHandler.java b/src/de/steamwar/bungeecore/comms/handlers/FightInfoHandler.java new file mode 100644 index 0000000..998e53e --- /dev/null +++ b/src/de/steamwar/bungeecore/comms/handlers/FightInfoHandler.java @@ -0,0 +1,60 @@ +/* + 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.bungeecore.comms.handlers; + +import com.google.common.io.ByteArrayDataInput; +import de.steamwar.bungeecore.comms.SpigotHandler; +import de.steamwar.bungeecore.comms.packets.FightInfoPacket; +import de.steamwar.bungeecore.listeners.TablistManager; +import net.md_5.bungee.api.config.ServerInfo; +import net.md_5.bungee.api.connection.ProxiedPlayer; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +public class FightInfoHandler implements SpigotHandler { + + private static final Set lobbys = new HashSet<>(); + + public static void addLobby(ServerInfo lobby) { + lobbys.add(lobby); + } + + @Override + public void handle(ByteArrayDataInput in, ServerInfo info) { + FightInfoPacket packet = new FightInfoPacket(in); + packet.setServerName(info.getName()); + + TablistManager.newFightInfo(info, packet); + + Iterator lobbyIt = lobbys.iterator(); + while(lobbyIt.hasNext()) { + ServerInfo lobby = lobbyIt.next(); + Iterator it = lobby.getPlayers().iterator(); + if(!it.hasNext()){ + lobbyIt.remove(); + continue; + } + + packet.send(it.next()); + } + } +} diff --git a/src/de/steamwar/bungeecore/comms/handlers/ImALobbyHandler.java b/src/de/steamwar/bungeecore/comms/handlers/ImALobbyHandler.java new file mode 100644 index 0000000..8d2013d --- /dev/null +++ b/src/de/steamwar/bungeecore/comms/handlers/ImALobbyHandler.java @@ -0,0 +1,32 @@ +/* + 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.bungeecore.comms.handlers; + +import com.google.common.io.ByteArrayDataInput; +import de.steamwar.bungeecore.comms.SpigotHandler; +import net.md_5.bungee.api.config.ServerInfo; + +public class ImALobbyHandler implements SpigotHandler { + + @Override + public void handle(ByteArrayDataInput in, ServerInfo info) { + FightInfoHandler.addLobby(info); + } +} diff --git a/src/de/steamwar/bungeecore/comms/handlers/InventoryCallbackHandler.java b/src/de/steamwar/bungeecore/comms/handlers/InventoryCallbackHandler.java index 07d37b7..0fd90a6 100644 --- a/src/de/steamwar/bungeecore/comms/handlers/InventoryCallbackHandler.java +++ b/src/de/steamwar/bungeecore/comms/handlers/InventoryCallbackHandler.java @@ -27,6 +27,7 @@ import de.steamwar.bungeecore.inventory.InvCallback; import de.steamwar.bungeecore.inventory.SWInventory; import de.steamwar.bungeecore.sql.SteamwarUser; import net.md_5.bungee.api.ProxyServer; +import net.md_5.bungee.api.config.ServerInfo; import java.util.HashMap; import java.util.Map; @@ -36,9 +37,9 @@ public class InventoryCallbackHandler implements SpigotHandler { public static final Map inventoryHashMap = new HashMap<>(); @Override - public void handle(ByteArrayDataInput byteArrayDataInput) { - SteamwarUser owner = SteamwarUser.get(byteArrayDataInput.readInt()); - CallbackType type = CallbackType.valueOf(byteArrayDataInput.readUTF()); + public void handle(ByteArrayDataInput in, ServerInfo info) { + SteamwarUser owner = SteamwarUser.get(in.readInt()); + CallbackType type = CallbackType.valueOf(in.readUTF()); if(!inventoryHashMap.containsKey(owner.getId())) { BungeeCore.send(ProxyServer.getInstance().getPlayer(owner.getUuid()), BungeeCore.CHAT_PREFIX + "§cBitte erneut versuchen. Durch ein Softwareupdate konnte die übliche Aktion nicht durchgeführt werden."); if(type == CallbackType.CLICK) { @@ -47,8 +48,8 @@ public class InventoryCallbackHandler implements SpigotHandler { return; } if(type == CallbackType.CLICK) { - int pos = byteArrayDataInput.readInt(); - InvCallback.ClickType clickType = InvCallback.ClickType.valueOf(byteArrayDataInput.readUTF()); + int pos = in.readInt(); + InvCallback.ClickType clickType = InvCallback.ClickType.valueOf(in.readUTF()); inventoryHashMap.get(owner.getId()).handleCallback(clickType, pos); }else if(type == CallbackType.CLOSE) { if(inventoryHashMap.get(owner.getId()).isNext()) { diff --git a/src/de/steamwar/bungeecore/comms/handlers/PrepareSchemHandler.java b/src/de/steamwar/bungeecore/comms/handlers/PrepareSchemHandler.java index 46d1a03..14171c5 100644 --- a/src/de/steamwar/bungeecore/comms/handlers/PrepareSchemHandler.java +++ b/src/de/steamwar/bungeecore/comms/handlers/PrepareSchemHandler.java @@ -27,14 +27,15 @@ import de.steamwar.bungeecore.comms.SpigotHandler; import de.steamwar.bungeecore.sql.SchematicType; import de.steamwar.bungeecore.sql.SteamwarUser; import net.md_5.bungee.api.ProxyServer; +import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.api.connection.ProxiedPlayer; public class PrepareSchemHandler implements SpigotHandler { @Override - public void handle(ByteArrayDataInput byteArrayDataInput) { - ProxiedPlayer player = ProxyServer.getInstance().getPlayer(SteamwarUser.get(byteArrayDataInput.readInt()).getUuid()); - int schematicID = byteArrayDataInput.readInt(); - ArenaMode mode = ArenaMode.getBySchemType(SchematicType.fromDB(byteArrayDataInput.readUTF())); + public void handle(ByteArrayDataInput in, ServerInfo info) { + ProxiedPlayer player = ProxyServer.getInstance().getPlayer(SteamwarUser.get(in.readInt()).getUuid()); + int schematicID = in.readInt(); + ArenaMode mode = ArenaMode.getBySchemType(SchematicType.fromDB(in.readUTF())); BauCommand.stopBauserver(player); SubserverSystem.startTestServer(player, mode, mode.getRandomMap(), 0, schematicID); diff --git a/src/de/steamwar/bungeecore/comms/handlers/TablistNameHandler.java b/src/de/steamwar/bungeecore/comms/handlers/TablistNameHandler.java deleted file mode 100644 index 678d930..0000000 --- a/src/de/steamwar/bungeecore/comms/handlers/TablistNameHandler.java +++ /dev/null @@ -1,20 +0,0 @@ -package de.steamwar.bungeecore.comms.handlers; - -import com.google.common.io.ByteArrayDataInput; -import de.steamwar.bungeecore.Subserver; -import de.steamwar.bungeecore.comms.SpigotHandler; -import de.steamwar.bungeecore.sql.SteamwarUser; -import net.md_5.bungee.api.ProxyServer; -import net.md_5.bungee.api.connection.ProxiedPlayer; - -public class TablistNameHandler implements SpigotHandler { - - @Override - public void handle(ByteArrayDataInput byteArrayDataInput) { - ProxiedPlayer player = ProxyServer.getInstance().getPlayer(SteamwarUser.get(byteArrayDataInput.readInt()).getUuid()); - Subserver subserver = Subserver.getSubserver(player.getServer().getInfo()); - if(subserver == null) - return; - subserver.getTablistNames().put(player, byteArrayDataInput.readUTF()); - } -} diff --git a/src/de/steamwar/bungeecore/comms/packets/BaumemberUpdatePacket.java b/src/de/steamwar/bungeecore/comms/packets/BaumemberUpdatePacket.java new file mode 100644 index 0000000..ddb4021 --- /dev/null +++ b/src/de/steamwar/bungeecore/comms/packets/BaumemberUpdatePacket.java @@ -0,0 +1,36 @@ +/* + 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.bungeecore.comms.packets; + +import com.google.common.io.ByteArrayDataOutput; +import de.steamwar.bungeecore.comms.BungeePacket; +import de.steamwar.bungeecore.comms.PacketIdManager; + +public class BaumemberUpdatePacket extends BungeePacket { + @Override + public int getId() { + return PacketIdManager.BAUMEMBER_UPDATE; + } + + @Override + public void writeVars(ByteArrayDataOutput byteArrayDataOutput) { + // empty + } +} diff --git a/src/de/steamwar/bungeecore/comms/packets/FightInfoPacket.java b/src/de/steamwar/bungeecore/comms/packets/FightInfoPacket.java new file mode 100644 index 0000000..34f120a --- /dev/null +++ b/src/de/steamwar/bungeecore/comms/packets/FightInfoPacket.java @@ -0,0 +1,183 @@ +/* + 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.bungeecore.comms.packets; + +import com.google.common.io.ByteArrayDataInput; +import com.google.common.io.ByteArrayDataOutput; +import de.steamwar.bungeecore.comms.BungeePacket; +import de.steamwar.bungeecore.comms.PacketIdManager; + +import java.util.ArrayList; +import java.util.List; + +public class FightInfoPacket extends BungeePacket { + + private String serverName; // Name of the Server + private final String gameMode; // GameMode aka Schematictype (if known, else "") + private final String arena; // Name of the arena + private final String blueName; // Name of the blue team, expected to begin with "§a" colorcode + private final String redName; // Name of the red team, expected to begin with "§a" colorcode + private final String fightState; // Fight state (technical term) (if known, else "") + private final int countdown; // Countdown state in seconds (if known, else 0) + private final int blueLeader; // SWUserID of the blue team leader (if known, else 0) + private final int redLeader; // SWUserID of the red team leader (if known, else 0) + private final int blueSchem; // Blue SchemID (if known, else 0) + private final int redSchem; // Red SchemID (if known, else 0) + private final List bluePlayers; // List of Blue SWUserIDs + private final List redPlayers; // List of Red SWUserIDs + private final List spectators; // List of Spectator SWUserIDs + + public FightInfoPacket(String serverName, String gameMode, String arena, String blueName, String redName, String fightState, int countdown, int blueLeader, int redLeader, int blueSchem, int redSchem, List bluePlayers, List redPlayers, List spectators) { + this.serverName = serverName; + this.gameMode = gameMode; + this.arena = arena; + this.blueName = blueName; + this.redName = redName; + this.fightState = fightState; + this.countdown = countdown; + this.blueLeader = blueLeader; + this.redLeader = redLeader; + this.blueSchem = blueSchem; + this.redSchem = redSchem; + this.bluePlayers = bluePlayers; + this.redPlayers = redPlayers; + this.spectators = spectators; + } + + public FightInfoPacket(ByteArrayDataInput in) { + this.serverName = in.readUTF(); + this.gameMode = in.readUTF(); + this.arena = in.readUTF(); + this.blueName = in.readUTF(); + this.redName = in.readUTF(); + this.fightState = in.readUTF(); + this.countdown = in.readInt(); + this.blueLeader = in.readInt(); + this.redLeader = in.readInt(); + this.blueSchem = in.readInt(); + this.redSchem = in.readInt(); + this.bluePlayers = readPlayerList(in); + this.redPlayers = readPlayerList(in); + this.spectators = readPlayerList(in); + } + + @Override + public int getId() { + return PacketIdManager.FIGHT_INFO; + } + + @Override + public void writeVars(ByteArrayDataOutput out) { + out.writeUTF(serverName); + out.writeUTF(gameMode); + out.writeUTF(arena); + out.writeUTF(blueName); + out.writeUTF(redName); + out.writeUTF(fightState); + out.writeInt(countdown); + out.writeInt(blueLeader); + out.writeInt(redLeader); + out.writeInt(blueSchem); + out.writeInt(redSchem); + writePlayerList(out, bluePlayers); + writePlayerList(out, redPlayers); + writePlayerList(out, spectators); + } + + public String getServerName() { + return serverName; + } + + public void setServerName(String serverName) { + this.serverName = serverName; + } + + public String getGameMode() { + return gameMode; + } + + public String getArena() { + return arena; + } + + public String getBlueName() { + return blueName; + } + + public String getRedName() { + return redName; + } + + public String getFightState() { + return fightState; + } + + public int getCountdown() { + return countdown; + } + + public int getBlueLeader() { + return blueLeader; + } + + public int getRedLeader() { + return redLeader; + } + + public int getBlueSchem() { + return blueSchem; + } + + public int getRedSchem() { + return redSchem; + } + + public List getBluePlayers() { + return bluePlayers; + } + + public List getRedPlayers() { + return redPlayers; + } + + public List getSpectators() { + return spectators; + } + + public int playerSize(){ + return bluePlayers.size() + redPlayers.size() + spectators.size(); + } + + private static List readPlayerList(ByteArrayDataInput in) { + int length = in.readInt(); + List players = new ArrayList<>(length); + for(int i = 0; i < length; i++) { + players.add(in.readInt()); + } + return players; + } + + private void writePlayerList(ByteArrayDataOutput out, List players) { + out.writeInt(players.size()); + for(Integer player : players) { + out.writeInt(player); + } + } +} diff --git a/src/de/steamwar/bungeecore/listeners/BanListener.java b/src/de/steamwar/bungeecore/listeners/BanListener.java index 2daabde..195cc19 100644 --- a/src/de/steamwar/bungeecore/listeners/BanListener.java +++ b/src/de/steamwar/bungeecore/listeners/BanListener.java @@ -41,10 +41,10 @@ public class BanListener extends BasicListener { @EventHandler public void onLogin(LoginEvent event) { SteamwarUser user = SteamwarUser.getOrCreate(event.getConnection()); - if(user.isBanned()) { + if (user.isPunished(Punishment.PunishmentType.Ban)) { user.updateBanIP(event.getConnection().getAddress().getAddress().getHostAddress()); event.setCancelled(true); - event.setCancelReason(user.banMessage(ProxyServer.getInstance().getPlayer(event.getConnection().getUniqueId()))); + event.setCancelReason(user.punishmentMessage(Punishment.PunishmentType.Ban, ProxyServer.getInstance().getPlayer(event.getConnection().getUniqueId()))); return; } @@ -55,7 +55,7 @@ public class BanListener extends BasicListener { boolean perma = false; for(BannedUserIPs banned : ips) { SteamwarUser bannedUser = SteamwarUser.get(banned.getUserID()); - if(bannedUser.isBanned()) { + if (bannedUser.isPunished(Punishment.PunishmentType.Ban)) { Punishment ban = bannedUser.getPunishment(Punishment.PunishmentType.Ban); if(ban.isPerma()) { perma = true; diff --git a/src/de/steamwar/bungeecore/listeners/ChatListener.java b/src/de/steamwar/bungeecore/listeners/ChatListener.java index 34de79c..697bd84 100644 --- a/src/de/steamwar/bungeecore/listeners/ChatListener.java +++ b/src/de/steamwar/bungeecore/listeners/ChatListener.java @@ -21,10 +21,9 @@ package de.steamwar.bungeecore.listeners; import de.steamwar.bungeecore.*; import de.steamwar.bungeecore.bot.SteamwarDiscordBot; -import de.steamwar.bungeecore.bot.listeners.IngameChatListener; -import de.steamwar.bungeecore.commands.BauCommand; import de.steamwar.bungeecore.commands.TpCommand; import de.steamwar.bungeecore.comms.packets.PingPacket; +import de.steamwar.bungeecore.sql.Punishment; import de.steamwar.bungeecore.sql.SteamwarUser; import de.steamwar.bungeecore.sql.Team; import de.steamwar.bungeecore.sql.UserGroup; @@ -39,6 +38,7 @@ import net.md_5.bungee.event.EventHandler; import java.util.List; import java.util.concurrent.TimeUnit; +import java.util.logging.Level; public class ChatListener extends BasicListener { @@ -82,11 +82,6 @@ public class ChatListener extends BasicListener { } switch(command[0].toLowerCase()){ - case "/bau": - case "/b": - case "/gs": - BauCommand.onBau(e, command); - break; case "/bc": case "/bauchat": case "/local": @@ -151,13 +146,12 @@ public class ChatListener extends BasicListener { } SteamwarUser user = SteamwarUser.get(sender); - if(user.isMuted()){ - sender.sendMessage(user.muteMessage(sender)); + if (user.isPunishedWithMessage(sender, Punishment.PunishmentType.Mute)) { e.setCancelled(true); return; } - if(!sender.hasPermission(ConnectionListener.TEAM_GROUP) && (e.getMessage().contains("http") || e.getMessage().contains("www"))){ + if(!sender.hasPermission(ConnectionListener.TEAM_GROUP) && (e.getMessage().contains("http:") || e.getMessage().contains("https:") || e.getMessage().contains("www."))){ Message.send("CHAT_NO_LINKS", sender); e.setCancelled(true); return; @@ -210,7 +204,11 @@ public class ChatListener extends BasicListener { msg = "§" + team.getTeamColor() + team.getTeamKuerzel() + " §r" + msg; } - SteamwarDiscordBot.instance().getIngameChatListener().send(" " + msg.replaceAll("§[a-f0-9r]", "")); + try { + SteamwarDiscordBot.instance().getIngameChatListener().send(" " + msg.replaceAll("§[a-f0-9r]", "")); + } catch (Exception e) { + BungeeCore.get().getLogger().log(Level.SEVERE, "Could not send chat message to discord", e); + } for(ProxiedPlayer target : ProxyServer.getInstance().getPlayers()){ Subserver targetServer = Subserver.getSubserver(target); if(!(targetServer == null || targetServer.getType() != Servertype.ARENA || targetServer.getServer() != target.getServer().getInfo())) continue; @@ -230,8 +228,7 @@ public class ChatListener extends BasicListener { } SteamwarUser user = SteamwarUser.get(sender); - if(user.isMuted()){ - sender.sendMessage(user.muteMessage(sender)); + if (user.isPunishedWithMessage(sender, Punishment.PunishmentType.Mute)) { e.setCancelled(true); return; } diff --git a/src/de/steamwar/bungeecore/listeners/TablistManager.java b/src/de/steamwar/bungeecore/listeners/TablistManager.java index 7c92736..59f44bf 100644 --- a/src/de/steamwar/bungeecore/listeners/TablistManager.java +++ b/src/de/steamwar/bungeecore/listeners/TablistManager.java @@ -26,13 +26,12 @@ import de.steamwar.bungeecore.BungeeCore; import de.steamwar.bungeecore.Message; import de.steamwar.bungeecore.Servertype; import de.steamwar.bungeecore.Subserver; +import de.steamwar.bungeecore.comms.packets.FightInfoPacket; import de.steamwar.bungeecore.sql.SteamwarUser; -import de.steamwar.bungeecore.sql.Team; import de.steamwar.bungeecore.sql.UserGroup; import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.api.connection.ProxiedPlayer; -import net.md_5.bungee.api.connection.Server; import net.md_5.bungee.api.event.PlayerDisconnectEvent; import net.md_5.bungee.api.event.PostLoginEvent; import net.md_5.bungee.event.EventHandler; @@ -42,69 +41,11 @@ import java.io.File; import java.io.IOException; import java.util.*; import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; public class TablistManager extends BasicListener { private static final Map tablists = new HashMap<>(); - private int seconds = 0; - private Icon darkGray; - private Icon gray; - - private int size; - private final TreeMap> playerMap = new TreeMap<>(); - - public TablistManager(){ - ProxyServer.getInstance().getScheduler().schedule(BungeeCore.get(), this::updateCustomTablist, 1, 1, TimeUnit.SECONDS); - try{ - BungeeTabListPlusAPI.createIcon(ImageIO.read(new File("/configs/BungeeTabListPlus/heads/colors/dark_gray.png")), (icon) -> darkGray = icon); - BungeeTabListPlusAPI.createIcon(ImageIO.read(new File("/configs/BungeeTabListPlus/heads/colors/gray.png")), (icon) -> gray = icon); - }catch(IOException e){ - throw new SecurityException("Could not load icons", e); - } - - for(ProxiedPlayer p : ProxyServer.getInstance().getPlayers()){ - tablists.put(p, new Tablist(p)); - } - } - - private void calculateSize() { - size = -1; - size += playerMap.size() * 2 + ProxyServer.getInstance().getPlayers().size(); - size = (size + 19) / 20; - if(size > 5) size = 5; - } - - private synchronized void updateCustomTablist(){ - //Calculate server-player-map - playerMap.clear(); - for (ProxiedPlayer player : ProxyServer.getInstance().getPlayers()) { - Server pserver = player.getServer(); - if (pserver == null) //Happens temporarily - continue; - - ServerInfo server = pserver.getInfo(); - String serverName = server.getName(); - - Subserver subserver = Subserver.getSubserver(server); - if (subserver != null && subserver.getType() == Servertype.BAUSERVER) { - playerMap.computeIfAbsent("Bau", s -> new ArrayList<>()).add(player); - } else { - playerMap.computeIfAbsent(serverName, s -> new ArrayList<>()).add(player); - } - } - playerMap.forEach((server, players) -> players.sort((proxiedPlayer, t1) -> proxiedPlayer.getName().compareToIgnoreCase(t1.getName()))); - - //Set size - calculateSize(); - - for(Tablist tablist : tablists.values()) - tablist.refresh(); - - seconds++; - } - @EventHandler public synchronized void onJoin(PostLoginEvent e){ tablists.put(e.getPlayer(), new Tablist(e.getPlayer())); @@ -115,15 +56,68 @@ public class TablistManager extends BasicListener { tablists.remove(e.getPlayer()); } + + private static final Map fightInfos = new HashMap<>(); + + public static synchronized void newFightInfo(ServerInfo info, FightInfoPacket packet) { + fightInfos.put(info, packet); + fightInfos.keySet().removeIf(serverInfo -> serverInfo.getPlayers().isEmpty()); + } + + + private static Icon darkGray; + private static Icon gray; + + private int seconds = 0; + private int size; + private TablistGroup tablist; + + public TablistManager(){ + ProxyServer.getInstance().getScheduler().schedule(BungeeCore.get(), this::updateTablist, 1, 1, TimeUnit.SECONDS); + try{ + BungeeTabListPlusAPI.createIcon(ImageIO.read(new File("/configs/BungeeTabListPlus/heads/colors/dark_gray.png")), (icon) -> darkGray = icon); + BungeeTabListPlusAPI.createIcon(ImageIO.read(new File("/configs/BungeeTabListPlus/heads/colors/gray.png")), (icon) -> gray = icon); + }catch(IOException e){ + throw new SecurityException("Could not load icons", e); + } + + ProxyServer.getInstance().getPlayers().forEach(p -> tablists.put(p, new Tablist(p))); + } + + private synchronized void updateTablist(){ + //Calculate server-player-map + tablist = new TablistGroup(true, ""); + TablistGroup bau = new TablistGroup(false, "Bau"); + for (ServerInfo server : ProxyServer.getInstance().getServersCopy().values()){ + if(server.getPlayers().isEmpty()) + continue; + + Subserver subserver = Subserver.getSubserver(server); + if(subserver != null && subserver.getType() == Servertype.BAUSERVER) + bau.addSubTablist(new TablistServer(server)); + else if(fightInfos.containsKey(server)) + tablist.addSubTablist(new TablistServer(server, fightInfos.get(server))); + else + tablist.addSubTablist(new TablistServer(server)); + } + if(bau.size() > 0) + tablist.addSubTablist(bau); + + size = (int) Math.ceil(tablist.size() / 20.0); + tablists.values().forEach(Tablist::refresh); + seconds++; + } + private class Tablist extends DefaultCustomTablist { private final ProxiedPlayer player; + private int pos = 0; private Tablist(ProxiedPlayer player){ this.player = player; BungeeTabListPlusAPI.setCustomTabList(player, this); } - private String calcHeader(ProxiedPlayer player){ + private String header(){ int phase = (seconds % 16) / 3; switch(phase){ case 0: @@ -136,7 +130,7 @@ public class TablistManager extends BasicListener { } } - private String getPing(){ + private String ping(){ int ping = player.getPing(); if(ping < 50){ return "§a" + ping; @@ -151,126 +145,164 @@ public class TablistManager extends BasicListener { if (player.getServer() == null) { return; } - ServerInfo currentServer = player.getServer().getInfo(); - setHeader(calcHeader(player)); - // TABLIST_FOOTER=§e{0} {1}§8ms §eSpieler§8: §7{2} - setFooter("§e" + currentServer.getName() + " " + getPing() + "§8ms §eSpieler§8: §7" + ProxyServer.getInstance().getPlayers().size()); - setSize(size, 20); + pos = 0; + setHeader(header()); + setFooter("§e" + player.getServer().getInfo().getName() + " " + ping() + "§8ms §eSpieler§8: §7" + ProxyServer.getInstance().getPlayers().size()); + int currentSize = size > 4 ? tablist.slimSize(player) : size; + setSize(currentSize, 20); - if (size >= 5) { - refreshSlim(currentServer); + tablist.print(this, size > 4); + + while (pos < currentSize*20){ + setSlot(darkGray, "", 1000); + } + } + + private void setSlot(Icon icon, String name, int ping){ + if(pos / 20 >= getColumns()) return; - } - try { - int i = 0; - for (String server : playerMap.navigableKeySet()) { - if (i > 0){ - setSlot(i%20, i/20, darkGray, "", 1000); - i++; - } - if(server.equals("Bau")) - server = Message.parse("TABLIST_BAU", player); - setSlot(i%20, i/20, gray, "§7§l" + server, 1000); - i++; - i = update(currentServer, playerMap.get(server), i); - } + setSlot(pos % 20, pos / 20, icon, name, ping); + pos++; + } + } - finish(i); - }catch(IndexOutOfBoundsException | NullPointerException e){ - //Ignore IndexOutOfBoundsException - //Ignore NPE, happens sometimes (only 1s long) when somebody is joining, server switching or disconnecting - } + private interface TablistPart { + int size(); + int slimSize(ProxiedPlayer viewer); + String name(); + void print(Tablist viewer, boolean slim); + } + + private static class TablistGroup implements TablistPart { + + private final boolean withHeaders; + private final String orderName; + private final List subTablists = new ArrayList<>(); + + private TablistGroup(boolean withHeaders, String orderName) { + this.withHeaders = withHeaders; + this.orderName = orderName; } - private void refreshSlim(ServerInfo currentServer) { - try { - int i = 0; - boolean spacer = true; - for (String server : playerMap.navigableKeySet()) { - if (i > 0 && spacer) { - setSlot(i%20, i/20, darkGray, "", 1000); - i++; - } - spacer = true; - Team team = getTeam(player); - List players = playerMap.get(server) - .stream() - .filter(p -> (p.getServer() != null && p.getServer().getInfo() == currentServer) || SteamwarUser.get(p).getUserGroup() != UserGroup.Member || (team != null && team == getTeam(p))) - .collect(Collectors.toList()); - - Subserver subserver = Subserver.getSubserver(player); - if (server.equals("Bau")) { - if (subserver != null && subserver.getType() == Servertype.BAUSERVER) { - players = playerMap.get(server); - } - server = Message.parse("TABLIST_BAU", player); - } - if (subserver != null && subserver.getType() == Servertype.ARENA && playerMap.get(server).size() == 1) { - players = playerMap.get(server); - } - - int increment = playerMap.get(server).size() - players.size(); - if (players.isEmpty()) { - server += " §7(" + increment + ")"; - spacer = false; - } else if (increment != 0) { - server += " §7(+" + increment + ")"; - } - - setSlot(i%20, i/20, gray, "§7§l" + server, 1000); - i++; - i = update(currentServer, players, i); - } - - finish(i); - }catch(IndexOutOfBoundsException | NullPointerException e){ - //Ignore IndexOutOfBoundsException - //Ignore NPE, happens sometimes (only 1s long) when somebody is joining, server switching or disconnecting - } + private void addSubTablist(TablistPart tablist){ + subTablists.add(tablist); + subTablists.sort((t1, t2) -> t1.name().compareToIgnoreCase(t2.name())); } - private int update(ServerInfo currentServer, List players, int i) { - for (ProxiedPlayer p : players){ - boolean sameServer = currentServer == p.getServer().getInfo(); - setSlot(i % 20, i / 20, BungeeTabListPlusAPI.getIconFromPlayer(p), getTablistName(p), (sameServer ? 1 : 500)); - i++; - } - return i; + @Override + public int size() { + return slimSize(null); } - private void finish(int i) { - while (i < size*20){ - setSlot(i%20, i/20, darkGray, "", 1000); - i++; - } + @Override + public int slimSize(ProxiedPlayer viewer) { + int size = subTablists.stream().mapToInt(tPart -> viewer == null ? tPart.size() : tPart.slimSize(viewer)).sum(); + if(withHeaders) + size += subTablists.size() * 2; + return size; } - private Team getTeam(ProxiedPlayer p) { - Team team = Team.get(SteamwarUser.get(p).getTeam()); - return team.getTeamId() <= 0 ? null : team; + @Override + public String name() { + return orderName; } - private String getTablistName(ProxiedPlayer p) { - Subserver server = Subserver.getSubserver(p); - if(server != null){ - String tablistName = server.getTablistNames().get(p); - if(tablistName != null) - return tablistName; + @Override + public void print(Tablist viewer, boolean slim) { + subTablists.forEach(tPart -> { + if(withHeaders) + viewer.setSlot(gray, "§7§l" + tPart.name(), 1000); + tPart.print(viewer, slim); + if(withHeaders) + viewer.setSlot(darkGray, "", 1000); + }); + } + } + + private static class TablistServer implements TablistPart { + private static class TablistPlayer { + private final ProxiedPlayer player; + private final String defaultName; + + private TablistPlayer(ProxiedPlayer player, String defaultName) { + this.player = player; + this.defaultName = defaultName; } + } + private final List players = new ArrayList<>(); + private final ServerInfo info; + private final Subserver subserver; - StringBuilder st = new StringBuilder(); - UserGroup group = SteamwarUser.get(p).getUserGroup(); + private TablistServer(ServerInfo info, FightInfoPacket packet){ + this.info = info; + subserver = Subserver.getSubserver(info); + Collection onlinePlayers = info.getPlayers(); + addPlayers(packet.getBlueName().substring(0, 2), packet.getBluePlayers(), onlinePlayers); + addPlayers(packet.getRedName().substring(0, 2), packet.getRedPlayers(), onlinePlayers); + addPlayers("§7", packet.getSpectators(), onlinePlayers); + } - if (group == UserGroup.Member) { - Team team = getTeam(player); - if (team != null && team == getTeam(p)) st.append("§f"); - else st.append("§7"); - } else { - st.append(group.getColorCode()); + private void addPlayers(String prefix, List teamPlayers, Collection onlinePlayers){ + teamPlayers.stream().map(SteamwarUser::get).map( + user -> onlinePlayers.stream().filter(player -> player.getUniqueId().equals(user.getUuid())).findAny() + ).filter(Optional::isPresent).map(Optional::get).sorted( + (p1, p2) -> p1.getName().compareToIgnoreCase(p2.getName()) + ).forEachOrdered(player -> players.add(new TablistPlayer(player, prefix + player.getName()))); + } + + private TablistServer(ServerInfo info) { + this.info = info; + subserver = Subserver.getSubserver(info); + info.getPlayers().forEach(player -> players.add(new TablistPlayer(player, SteamwarUser.get(player.getUniqueId()).getUserGroup().getColorCode() + player.getName()))); + players.sort((tp1, tp2) -> tp1.player.getName().compareToIgnoreCase(tp2.player.getName())); + } + + private boolean displaySlim(ProxiedPlayer viewer, ProxiedPlayer player){ + if(viewer.getServer().getInfo() == info) + return true; + + if(subserver != null && subserver.getType() == Servertype.ARENA && info.getPlayers().size() == 1) + return true; + + SteamwarUser user = SteamwarUser.get(player); + if(user.getUserGroup() != UserGroup.Member) + return true; + + return user.getTeam() != 0 && SteamwarUser.get(viewer).getTeam() == user.getTeam(); + } + + @Override + public int size() { + return players.size(); + } + + @Override + public int slimSize(ProxiedPlayer viewer) { + if(viewer.getServer().getInfo() == info) + return size(); + + return players.stream().mapToInt(player -> displaySlim(viewer, player.player) ? 1 : 0).sum(); + } + + @Override + public String name() { + return info.getName(); + } + + @Override + public void print(Tablist viewer, boolean slim) { + boolean sameServer = viewer.player.getServer().getInfo() == info; + + SteamwarUser user = SteamwarUser.get(viewer.player.getUniqueId()); + for(TablistPlayer player : players){ + if(slim && !displaySlim(viewer.player, player.player)) + continue; + + int ping = sameServer ? 1 : 500; + String name = player.defaultName.startsWith("§7") && user.getTeam() != 0 && user.getTeam() == SteamwarUser.get(player.player.getUniqueId()).getTeam() ? "§f" + player.player.getName() : player.defaultName; + viewer.setSlot(BungeeTabListPlusAPI.getIconFromPlayer(player.player), name, ping); } - - return st.append(p.getName()).toString(); } } } diff --git a/src/de/steamwar/bungeecore/listeners/mods/Utils.java b/src/de/steamwar/bungeecore/listeners/mods/Utils.java index e6907c5..9ed160a 100644 --- a/src/de/steamwar/bungeecore/listeners/mods/Utils.java +++ b/src/de/steamwar/bungeecore/listeners/mods/Utils.java @@ -23,6 +23,7 @@ import de.steamwar.bungeecore.BungeeCore; import de.steamwar.bungeecore.Message; import de.steamwar.bungeecore.sql.Mod; import de.steamwar.bungeecore.sql.Mod.ModType; +import de.steamwar.bungeecore.sql.Punishment; import de.steamwar.bungeecore.sql.SteamwarUser; import net.md_5.bungee.api.connection.ProxiedPlayer; @@ -75,7 +76,7 @@ class Utils { if(max == ModType.YELLOW) player.disconnect(BungeeCore.stringToText(Message.parse("MOD_YELLOW_SING", player, mods.get(0).getModName()))); else{ - user.ban(Timestamp.from(Instant.now().plus(7, ChronoUnit.DAYS)), Message.parse("MOD_RED_SING", player, mods.get(0).getModName()), 0, false); + user.punish(Punishment.PunishmentType.Ban, Timestamp.from(Instant.now().plus(7, ChronoUnit.DAYS)), Message.parse("MOD_RED_SING", player, mods.get(0).getModName()), 0, false); BungeeCore.log(Level.SEVERE, user.getUserName() + " " + user.getId() + " wurde automatisch wegen des Mods " + mods.get(0).getModName() + " gebannt."); } }else{ @@ -85,7 +86,7 @@ class Utils { if(max == ModType.YELLOW) player.disconnect(BungeeCore.stringToText(Message.parse("MOD_YELLOW_PLUR", player, sb.toString()))); else{ - user.ban(Timestamp.from(Instant.now().plus(7, ChronoUnit.DAYS)), Message.parse("MOD_RED_PLUR", player, sb.toString()), 0, false); + user.punish(Punishment.PunishmentType.Ban, Timestamp.from(Instant.now().plus(7, ChronoUnit.DAYS)), Message.parse("MOD_RED_PLUR", player, sb.toString()), 0, false); BungeeCore.log(Level.SEVERE, user.getUserName() + " " + user.getId() + " wurde automatisch wegen der Mods " + sb.toString() + " gebannt."); } } diff --git a/src/de/steamwar/bungeecore/sql/BannedUserIPs.java b/src/de/steamwar/bungeecore/sql/BannedUserIPs.java index 6b371cc..4a75484 100644 --- a/src/de/steamwar/bungeecore/sql/BannedUserIPs.java +++ b/src/de/steamwar/bungeecore/sql/BannedUserIPs.java @@ -19,18 +19,18 @@ package de.steamwar.bungeecore.sql; -import de.steamwar.bungeecore.BungeeCore; - -import java.sql.ResultSet; -import java.sql.SQLException; import java.sql.Timestamp; import java.util.ArrayList; import java.util.List; public class BannedUserIPs { - private int userID; - private Timestamp timestamp; + private static final Statement getByID = new Statement("SELECT * FROM BannedUserIPs WHERE UserID = ? ORDER BY Timestamp ASC"); + private static final Statement getByIP = new Statement("SELECT * FROM BannedUserIPs WHERE IP = ? ORDER BY Timestamp DESC"); + private static final Statement banIP = new Statement("INSERT INTO BannedUserIPs (UserID, Timestamp, IP) VALUES (?, NOW(), ?) ON DUPLICATE KEY UPDATE Timestamp=NOW()"); + + private final int userID; + private final Timestamp timestamp; private BannedUserIPs(int userID, Timestamp timestamp){ this.userID = userID; @@ -38,37 +38,31 @@ public class BannedUserIPs { } public static List get(int userID){ - List userIPs = new ArrayList<>(); - ResultSet dbentry = SQL.select("SELECT * FROM BannedUserIPs WHERE UserID = ? ORDER BY Timestamp ASC", userID); - try { - while(dbentry.next()){ + return getByID.select(rs -> { + List userIPs = new ArrayList<>(); + while(rs.next()) { userIPs.add(new BannedUserIPs( userID, - dbentry.getTimestamp("Timestamp"))); + rs.getTimestamp("Timestamp"))); } - } catch (SQLException e) { - BungeeCore.log("Get BannedUserIPs failed", e); - } - return userIPs; + return userIPs; + }, userID); } public static List get(String ip){ - List userIDs = new ArrayList<>(); - ResultSet dbentry = SQL.select("SELECT * FROM BannedUserIPs WHERE IP = ? ORDER BY Timestamp DESC", ip); - try { - while(dbentry.next()){ + return getByIP.select(rs -> { + List userIDs = new ArrayList<>(); + while(rs.next()) { userIDs.add(new BannedUserIPs( - dbentry.getInt("UserID"), - dbentry.getTimestamp("Timestamp"))); + rs.getInt("UserID"), + rs.getTimestamp("Timestamp"))); } - } catch (SQLException e) { - BungeeCore.log("Get BannedUserIPs failed", e); - } - return userIDs; + return userIDs; + }, ip); } static void banIP(SteamwarUser user, String ip){ - SQL.update("INSERT INTO BannedUserIPs (UserID, Timestamp, IP) VALUES (?, NOW(), ?) ON DUPLICATE KEY UPDATE Timestamp=NOW()", user.getId(), ip); + banIP.update(user.getId(), ip); } public int getUserID() { diff --git a/src/de/steamwar/bungeecore/sql/BauweltMember.java b/src/de/steamwar/bungeecore/sql/BauweltMember.java index f05cab2..f89650e 100644 --- a/src/de/steamwar/bungeecore/sql/BauweltMember.java +++ b/src/de/steamwar/bungeecore/sql/BauweltMember.java @@ -19,15 +19,17 @@ package de.steamwar.bungeecore.sql; -import de.steamwar.bungeecore.BungeeCore; - -import java.sql.ResultSet; -import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import java.util.UUID; public class BauweltMember{ + + private static final Statement delete = new Statement("DELETE FROM BauweltMember WHERE BauweltID = ? AND MemberID = ?"); + private static final Statement update = new Statement("INSERT INTO BauweltMember (BauweltID, MemberID, WorldEdit, World) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE WorldEdit = VALUES(WorldEdit), World = VALUES(World)"); + private static final Statement getMember = new Statement("SELECT * FROM BauweltMember WHERE BauweltID = ? AND MemberID = ?"); + private static final Statement getMembers = new Statement("SELECT * FROM BauweltMember WHERE BauweltID = ?"); + private final int bauweltID; private final int memberID; private boolean worldEdit; @@ -52,12 +54,11 @@ public class BauweltMember{ } public void remove(){ - SQL.update("DELETE FROM BauweltMember WHERE BauweltID = " + bauweltID + " AND MemberID = " + memberID); + delete.update(bauweltID, memberID); } private void updateDB(){ - SQL.update("INSERT INTO BauweltMember (BauweltID, MemberID, WorldEdit, World) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE WorldEdit = VALUES(WorldEdit), World = VALUES(World)", - bauweltID, memberID, worldEdit, world); + update.update(bauweltID, memberID, worldEdit, world); } public static BauweltMember getBauMember(UUID ownerID, UUID memberID){ @@ -65,18 +66,12 @@ public class BauweltMember{ } public static BauweltMember getBauMember(int ownerID, int memberID){ - ResultSet member = SQL.select("SELECT * FROM BauweltMember WHERE BauweltID = ? AND MemberID = ?", ownerID, memberID); - try { - if(member == null || !member.next()){ + return getMember.select(rs -> { + if(!rs.next()) return null; - } - boolean worldEdit = member.getBoolean("WorldEdit"); - boolean world = member.getBoolean("World"); - return new BauweltMember(ownerID, memberID, worldEdit, world, false); - } catch (SQLException e) { - BungeeCore.log("Could not load BauweltMember", e); - } - return null; + + return new BauweltMember(ownerID, memberID, rs.getBoolean("WorldEdit"), rs.getBoolean("World"), false); + }, ownerID, memberID); } public static List getMembers(UUID bauweltID){ @@ -84,20 +79,13 @@ public class BauweltMember{ } public static List getMembers(int bauweltID){ - try{ - ResultSet memberlist = SQL.select("SELECT * FROM BauweltMember WHERE BauweltID = ?", bauweltID); + return getMembers.select(rs -> { List members = new ArrayList<>(); - while(memberlist.next()){ - int memberID = memberlist.getInt("MemberID"); - boolean worldEdit = memberlist.getBoolean("WorldEdit"); - boolean world = memberlist.getBoolean("World"); - members.add(new BauweltMember(bauweltID, memberID, worldEdit, world, false)); + while(rs.next()){ + members.add(new BauweltMember(bauweltID, rs.getInt("MemberID"), rs.getBoolean("WorldEdit"), rs.getBoolean("World"), false)); } return members; - }catch(SQLException e){ - BungeeCore.log("Could not load BauweltMembers", e); - } - return new ArrayList<>(); + }, bauweltID); } public int getBauweltID() { diff --git a/src/de/steamwar/bungeecore/sql/CheckedSchematic.java b/src/de/steamwar/bungeecore/sql/CheckedSchematic.java index ed2160c..499a2f0 100644 --- a/src/de/steamwar/bungeecore/sql/CheckedSchematic.java +++ b/src/de/steamwar/bungeecore/sql/CheckedSchematic.java @@ -27,7 +27,11 @@ import java.util.List; public class CheckedSchematic { - private final int nodeId; + private static final Statement create = new Statement("INSERT INTO CheckedSchematic (SchemName, SchemOwner, Validator, StartTime, EndTime, DeclineReason) VALUES (?, ?, ?, ?, ?, ?)"); + private static final Statement previous = new Statement("SELECT * FROM CheckedSchematic WHERE SchemName = ? AND SchemOwner = ? ORDER BY EndTime ASC"); + + private final String schemName; + private final int schemOwner; private final int validator; private final Timestamp startTime; @@ -42,21 +46,19 @@ public class CheckedSchematic { reason = rs.getString("DeclineReason"); } - public static void create(int nodeId, int validator, Timestamp startTime, Timestamp endTime, String reason){ - SQL.update("INSERT INTO CheckedSchematic (NodeId, Validator, StartTime, EndTime, DeclineReason) VALUES (?, ?, ?, ?, ?)", - nodeId, validator, startTime, endTime, reason); + public static void create(String schemName, int schemOwner, int validator, Timestamp startTime, Timestamp endTime, String reason){ + SQL.update("INSERT INTO CheckedSchematic (SchemName, SchemOwner, Validator, StartTime, EndTime, DeclineReason) VALUES (?, ?, ?, ?, ?, ?)", + schemName, schemOwner, validator, startTime, endTime, reason); } - public static List previousChecks(int nodeId){ - ResultSet rs = SQL.select("SELECT * FROM CheckedSchematic WHERE NodeId = ? ORDER BY EndTime ASC", nodeId); + public static List previousChecks(String schemName, int schemOwner){ + ResultSet rs = SQL.select("SELECT * FROM CheckedSchematic WHERE SchemName = ? AND SchemOwner = ? ORDER BY EndTime ASC", schemName, schemOwner); List schematics = new ArrayList<>(); try { while(rs.next()) schematics.add(new CheckedSchematic(rs)); - } catch (SQLException e) { - throw new SecurityException("Could not load previous checks", e); - } - return schematics; + return schematics; + }, schemName, schemOwner); } public int getValidator() { diff --git a/src/de/steamwar/bungeecore/sql/Elo.java b/src/de/steamwar/bungeecore/sql/Elo.java index 07a95c2..b61c8a3 100644 --- a/src/de/steamwar/bungeecore/sql/Elo.java +++ b/src/de/steamwar/bungeecore/sql/Elo.java @@ -19,33 +19,26 @@ package de.steamwar.bungeecore.sql; -import java.sql.ResultSet; -import java.sql.SQLException; - public class Elo { + + private static final Statement elo = new Statement("SELECT Elo FROM Elo WHERE UserID = ? AND GameMode = ?"); + private static final Statement place = new Statement("SELECT COUNT(*) AS Place FROM Elo WHERE GameMode = ? AND Elo > ?"); + private Elo(){} public static int getElo(int userID, String gameMode){ - ResultSet rs = SQL.select("SELECT Elo FROM Elo WHERE UserID = ? AND GameMode = ?", userID, gameMode); - int elo = 1000; - try { + return elo.select(rs -> { if(rs.next()) - elo = rs.getInt("Elo"); - } catch (SQLException e) { - throw new SecurityException("Could not get Elo", e); - } - return elo; + return rs.getInt("Elo"); + return 1000; + }, userID, gameMode); } public static int getPlacement(int elo, String gameMode){ - ResultSet rs = SQL.select("SELECT COUNT(*) AS Place FROM Elo WHERE GameMode = ? AND Elo > ?", gameMode, elo); - try{ - if(!rs.next()) - return -1; - - return rs.getInt("Place"); - }catch(SQLException e){ - throw new SecurityException("Could not get place", e); - } + return place.select(rs -> { + if(rs.next()) + return rs.getInt("Place"); + return -1; + }, gameMode, elo); } } diff --git a/src/de/steamwar/bungeecore/sql/Event.java b/src/de/steamwar/bungeecore/sql/Event.java index 72db065..93fd211 100644 --- a/src/de/steamwar/bungeecore/sql/Event.java +++ b/src/de/steamwar/bungeecore/sql/Event.java @@ -19,17 +19,20 @@ package de.steamwar.bungeecore.sql; -import de.steamwar.bungeecore.BungeeCore; - import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Timestamp; import java.time.Instant; -import java.util.LinkedList; +import java.util.ArrayList; import java.util.List; public class Event { + private static final Statement byCurrent = new Statement("SELECT * FROM Event WHERE Start < now() AND End > now()"); + private static final Statement byId = new Statement("SELECT * FROM Event WHERE EventID = ?"); + private static final Statement byName = new Statement("SELECT * FROM Event WHERE lower(EventName) = ?"); + private static final Statement byComing = new Statement("SELECT * FROM Event WHERE Start > now()"); + private final int eventID; private final String eventName; private final Timestamp start; @@ -56,57 +59,39 @@ public class Event { if(current != null && current.now()) return current; - ResultSet rs = SQL.select("SELECT * FROM Event WHERE Start < now() AND End > now()"); - try{ - if(!rs.next()){ + return byCurrent.select(rs -> { + if(rs.next()) + current = new Event(rs); + else current = null; - return null; - } - - current = new Event(rs); return current; - }catch (SQLException e){ - BungeeCore.log("Failed to load current Event", e); - throw new SecurityException(); - } + }); } public static Event get(int eventID){ - ResultSet rs = SQL.select("SELECT * FROM Event WHERE EventID = " + eventID); - try{ + return byId.select(rs -> { if(!rs.next()) - throw new IllegalArgumentException(); - + throw new SQLException("Couldn't find event " + eventID); return new Event(rs); - }catch (SQLException e){ - BungeeCore.log("Failed to load Event", e); - throw new SecurityException(); - } + }, eventID); } public static Event get(String eventName){ - ResultSet rs = SQL.select("SELECT * FROM Event WHERE lower(EventName) = ?", eventName.toLowerCase()); - try{ + return byName.select(rs -> { if(!rs.next()) return null; return new Event(rs); - }catch (SQLException e){ - BungeeCore.log("Failed to load Event by name", e); - throw new SecurityException(); - } + }, eventName.toLowerCase()); } public static List getComing(){ - List events = new LinkedList<>(); - ResultSet rs = SQL.select("SELECT * FROM Event WHERE Start > now()"); - try{ + return byComing.select(rs -> { + List events = new ArrayList<>(); while(rs.next()) events.add(new Event(rs)); - }catch (SQLException e){ - BungeeCore.log("Failed to load Events", e); - } - return events; + return events; + }); } private boolean now(){ diff --git a/src/de/steamwar/bungeecore/sql/EventFight.java b/src/de/steamwar/bungeecore/sql/EventFight.java index c86b145..ffcbe6f 100644 --- a/src/de/steamwar/bungeecore/sql/EventFight.java +++ b/src/de/steamwar/bungeecore/sql/EventFight.java @@ -20,7 +20,6 @@ package de.steamwar.bungeecore.sql; import de.steamwar.bungeecore.ArenaMode; -import de.steamwar.bungeecore.BungeeCore; import java.sql.ResultSet; import java.sql.SQLException; @@ -31,7 +30,11 @@ import static java.time.temporal.ChronoUnit.SECONDS; public class EventFight implements Comparable { - private static Queue fights = new PriorityQueue<>(); + private static final Statement reschedule = new Statement("UPDATE EventFight SET StartTime = ? WHERE EventID = ? AND FightID = ?"); + private static final Statement allComing = new Statement("SELECT * FROM EventFight WHERE StartTime > now() ORDER BY `StartTime` ASC"); + private static final Statement event = new Statement("SELECT * FROM EventFight WHERE EventID = ? ORDER BY `StartTime` ASC"); + + private static final Queue fights = new PriorityQueue<>(); private final int eventID; private final int fightID; @@ -57,31 +60,26 @@ public class EventFight implements Comparable { public void reschedule(){ startTime = Timestamp.from(new Date().toInstant().plus(30, SECONDS)); - SQL.update("UPDATE EventFight SET StartTime = ? WHERE EventID = ? AND FightID = ?", startTime, eventID, fightID); + reschedule.update(startTime, eventID, fightID); } public static void loadAllComingFights(){ - ResultSet rs = SQL.select("SELECT * FROM EventFight WHERE StartTime > now() ORDER BY `StartTime` ASC"); - fights.clear(); - try{ + allComing.select(rs -> { + fights.clear(); while(rs.next()){ - fights.add(new EventFight(rs)); + fights.add(new EventFight(rs)); } - }catch (SQLException e){ - BungeeCore.log("Failed to load EventFights", e); - } + return null; + }); } public static List getEvent(int eventID){ - ResultSet rs = SQL.select("SELECT * FROM EventFight WHERE EventID = ? ORDER BY `StartTime` ASC", eventID); - List fights = new LinkedList<>(); - try{ + return event.select(rs -> { + List fights = new LinkedList<>(); while(rs.next()) fights.add(new EventFight(rs)); - }catch (SQLException e){ - BungeeCore.log("Failed to load EventFights", e); - } - return fights; + return fights; + }, eventID); } public static Queue getFights() { diff --git a/src/de/steamwar/bungeecore/sql/IgnoreSystem.java b/src/de/steamwar/bungeecore/sql/IgnoreSystem.java index 73c1500..7309f8a 100644 --- a/src/de/steamwar/bungeecore/sql/IgnoreSystem.java +++ b/src/de/steamwar/bungeecore/sql/IgnoreSystem.java @@ -22,9 +22,13 @@ package de.steamwar.bungeecore.sql; import net.md_5.bungee.api.connection.ProxiedPlayer; import java.sql.ResultSet; -import java.sql.SQLException; public class IgnoreSystem{ + + private static final Statement select = new Statement("SELECT * FROM IgnoredPlayers WHERE Ignorer = ? AND Ignored = ?"); + private static final Statement insert = new Statement("INSERT INTO IgnoredPlayers (Ignorer, Ignored) VALUES (?, ?)"); + private static final Statement delete = new Statement("DELETE FROM IgnoredPlayers WHERE Ignorer = ? AND Ignored = ?"); + private IgnoreSystem(){} public static boolean isIgnored(ProxiedPlayer ignorer, ProxiedPlayer ignored){ @@ -34,22 +38,14 @@ public class IgnoreSystem{ } public static boolean isIgnored(SteamwarUser ignorer, SteamwarUser ignored) { - try { - ResultSet rs = SQL.select("SELECT COUNT(*) AS blocked FROM IgnoredPlayers WHERE Ignorer = ? AND Ignored = ?", ignorer.getId(), ignored.getId()); - if(!rs.next()) - return false; - - return rs.getInt("blocked") > 0; - } catch (SQLException e) { - throw new SecurityException("Could not check if ignored", e); - } + return select.select(ResultSet::next, ignorer.getId(), ignored.getId()); } public static void ignore(SteamwarUser ignorer, SteamwarUser ignored) { - SQL.update("INSERT INTO IgnoredPlayers (Ignorer, Ignored) VALUES (?, ?)", ignorer.getId(), ignored.getId()); + insert.update(ignorer.getId(), ignored.getId()); } public static void unIgnore(SteamwarUser ignorer, SteamwarUser ignored) { - SQL.update("DELETE FROM IgnoredPlayers WHERE Ignorer = ? AND Ignored = ?", ignorer.getId(), ignored.getId()); + delete.update(ignorer.getId(), ignored.getId()); } } diff --git a/src/de/steamwar/bungeecore/sql/Mod.java b/src/de/steamwar/bungeecore/sql/Mod.java index 98034bb..9aad08b 100644 --- a/src/de/steamwar/bungeecore/sql/Mod.java +++ b/src/de/steamwar/bungeecore/sql/Mod.java @@ -19,12 +19,11 @@ package de.steamwar.bungeecore.sql; -import de.steamwar.bungeecore.BungeeCore; - -import java.sql.ResultSet; -import java.sql.SQLException; - public class Mod { + + private static final Statement get = new Statement("SELECT * FROM Mods WHERE ModName = ? AND Platform = ?"); + private static final Statement insert = new Statement("INSERT INTO Mods (ModName, Platform) VALUES (?, ?)"); + private final String modName; private final Platform platform; private final ModType modType; @@ -36,15 +35,15 @@ public class Mod { } public static Mod get(String modName, Platform platform){ - ResultSet rs = SQL.select("SELECT * FROM Mods WHERE ModName = ? AND Platform = ?", modName, platform.value); - try{ + Mod mod = get.select(rs -> { if(rs.next()) return new Mod(modName, platform, ModType.valueOf(rs.getInt("ModType"))); - }catch (SQLException e){ - BungeeCore.log("Failed to load Mod", e); - throw new SecurityException(); - } - SQL.update("INSERT INTO Mods (ModName, Platform) VALUES (?, ?)", modName, platform.value); + return null; + }, modName, platform.value); + if(mod != null) + return mod; + + insert.update(modName, platform.value); return new Mod(modName, platform, ModType.UNKLASSIFIED); } diff --git a/src/de/steamwar/bungeecore/sql/PollAnswer.java b/src/de/steamwar/bungeecore/sql/PollAnswer.java index 62fcee0..7d23c38 100644 --- a/src/de/steamwar/bungeecore/sql/PollAnswer.java +++ b/src/de/steamwar/bungeecore/sql/PollAnswer.java @@ -19,7 +19,6 @@ package de.steamwar.bungeecore.sql; -import de.steamwar.bungeecore.BungeeCore; import de.steamwar.bungeecore.listeners.PollSystem; import java.sql.ResultSet; @@ -29,6 +28,10 @@ import java.util.Map; public class PollAnswer { + private static final Statement get = new Statement("SELECT * FROM PollAnswer WHERE UserID = ? AND Question = ?"); + 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 = new Statement("INSERT INTO PollAnswer (UserID, Question, Answer) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE Answer = VALUES(Answer)"); + private final int userID; private final String question; private int answer; @@ -44,38 +47,20 @@ public class PollAnswer { } public static PollAnswer get(int userID){ - ResultSet rs = SQL.select("SELECT * FROM PollAnswer WHERE UserID = ? AND Question = ?", userID, PollSystem.getQuestion()); - try { - if(!rs.next()) - return new PollAnswer(userID, PollSystem.getQuestion()); - return new PollAnswer(rs); - } catch (SQLException e) { - throw new SecurityException("Unable to get PollAnswer", e); - } + return get.select(rs -> { + if(rs.next()) + return new PollAnswer(rs); + return new PollAnswer(userID, PollSystem.getQuestion()); + }, userID, PollSystem.getQuestion()); } public static Map getCurrentResults() { - ResultSet set = SQL.select("SELECT Count(UserID) AS Times, Answer FROM PollAnswer WHERE Question = ? GROUP BY Answer ORDER BY `Times` ASC", PollSystem.getQuestion()); - try { + return getResults.select(rs -> { Map retMap = new HashMap<>(); - while (set.next()) { - retMap.put(PollSystem.getAnswer(set.getInt("Answer")), set.getInt("Times")); - } + while (rs.next()) + retMap.put(PollSystem.getAnswer(rs.getInt("Answer")), rs.getInt("Times")); return retMap; - }catch (SQLException e) { - throw new SecurityException("Unable to get PollAnswer", e); - } - } - - public static Integer getAllAnswered() { - ResultSet set = SQL.select("SELECT Count(UserID) AS Times FROM PollAnswer WHERE Question = ?", PollSystem.getQuestion()); - try { - if(!set.next()) - throw new SecurityException("Could not get PollAnswers"); - return set.getInt("Times"); - }catch (SQLException e) { - throw new SecurityException("Unable to get PollAnswer", e); - } + }, PollSystem.getQuestion()); } public boolean hasAnswered(){ @@ -84,6 +69,6 @@ public class PollAnswer { public void setAnswer(int answer){ this.answer = answer; - SQL.update("INSERT INTO PollAnswer (UserID, Question, Answer) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE Answer = VALUES(Answer)", userID, question, answer); + insert.update(userID, question, answer); } } diff --git a/src/de/steamwar/bungeecore/sql/Punishment.java b/src/de/steamwar/bungeecore/sql/Punishment.java index e4d9034..7f9a24e 100644 --- a/src/de/steamwar/bungeecore/sql/Punishment.java +++ b/src/de/steamwar/bungeecore/sql/Punishment.java @@ -19,9 +19,8 @@ package de.steamwar.bungeecore.sql; -import de.steamwar.bungeecore.BungeeCore; -import de.steamwar.bungeecore.Message; -import net.md_5.bungee.api.connection.ProxiedPlayer; +import lombok.AllArgsConstructor; +import lombok.Getter; import java.sql.ResultSet; import java.sql.SQLException; @@ -31,45 +30,39 @@ import java.util.*; public class Punishment { + private static final Statement getPunishment = new Statement("SELECT * FROM Punishments WHERE UserId = ? AND Type = ? ORDER BY PunishmentId DESC LIMIT 1"); + private static final Statement getPunishments = new Statement("SELECT * FROM Punishments WHERE PunishmentId IN (SELECT MAX(PunishmentId) FROM Punishments WHERE UserId = ? GROUP BY Type)"); + private static final Statement getAllPunishments = new Statement("SELECT * FROM Punishments WHERE UserId = ? ORDER BY `PunishmentId` DESC"); + private static final Statement insert = new Statement("INSERT INTO Punishments (UserId, Punisher, Type, Reason, EndTime, Perma) VALUES (?, ?, ?, ?, ?, ?)"); + public static Punishment getPunishmentOfPlayer(int user, PunishmentType type) { - ResultSet set = SQL.select("SELECT * FROM Punishments WHERE UserId = ? AND Type = ? ORDER BY PunishmentId DESC LIMIT 1", user, type.name()); - try { - if(!set.next()) - return null; - return new Punishment(set); - } catch (SQLException e) { - throw new SecurityException("Could not Load Punishments", e); - } + return getPunishment.select(rs -> { + if (rs.next()) + return new Punishment(rs); + return null; + }, user, type.name()); } public static Map getPunishmentsOfPlayer(int user) { - ResultSet set = SQL.select("SELECT * FROM Punishments WHERE PunishmentId IN (SELECT MAX(PunishmentId) FROM Punishments WHERE UserId = ? GROUP BY Type)", user); - try { + return getPunishments.select(rs -> { Map punishments = new HashMap<>(); - while (set.next()) - punishments.put(PunishmentType.valueOf(set.getString("Type")), new Punishment(set)); + while (rs.next()) + punishments.put(PunishmentType.valueOf(rs.getString("Type")), new Punishment(rs)); return punishments; - } catch (SQLException e) { - throw new SecurityException("Could not Load Punishments", e); - } + }, user); } public static List getAllPunishmentsOfPlayer(int user) { - ResultSet set = SQL.select("SELECT * FROM Punishments WHERE UserId = ? ORDER BY `PunishmentId` DESC", user); - try { + return getAllPunishments.select(rs -> { List punishments = new ArrayList<>(); - while (set.next()) { - punishments.add(new Punishment(set)); - } + while (rs.next()) + punishments.add(new Punishment(rs)); return punishments; - } catch (SQLException e) { - throw new SecurityException("Could not Load all Punishments", e); - } + }, user); } public static Punishment createPunishment(int user, int executor, PunishmentType type, String reason, Timestamp endTime, boolean perma) { - SQL.update("INSERT INTO Punishments (UserId, Punisher, Type, Reason, EndTime, Perma) VALUES (?, ?, ?, ?, ?, ?)", - user, executor, type.name(), reason, endTime, perma); + insert.update(user, executor, type.name(), reason, endTime, perma); return getPunishmentOfPlayer(user, type); } @@ -121,35 +114,33 @@ public class Punishment { return perma; } - public void updateEndTime(int from, String newreason, Timestamp newUpdate, boolean perma) { - if(newreason.equals(reason) && newUpdate.equals(endTime) && perma == perma) - return; - ProxiedPlayer player = BungeeCore.get().getProxy().getPlayer(SteamwarUser.get(from).getUuid()); - String newReason = Message.parse("BAN_CHANGED", player, reason, - SteamwarUser.get(from).getUserName(), - getBantime(endTime, this.perma), - getBantime(newUpdate, perma), - newreason); - - SQL.update("UPDATE Punishments SET EndTime = ?, Reason = ?, Perma = ? WHERE PunishmentId = ?", newUpdate, newReason, perma, id); - this.reason = newReason; - this.perma = perma; - this.endTime = newUpdate; - } - public String getBantime(Timestamp endTime, boolean perma) { - if(perma) + if (perma) { return "permanent"; - else + } else { return endTime.toLocalDateTime().format(DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm")); + } } public boolean isCurrent() { return isPerma() || getEndTime().after(new Date()); } + @AllArgsConstructor + @Getter public enum PunishmentType { - Ban, - Mute; + 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"); + + private final boolean needsAdmin; + private final String teamMessage; + private final String playerMessagePerma; + private final String playerMessageUntil; + private final String usageNotPunished; + private final String unpunishmentMessage; } } diff --git a/src/de/steamwar/bungeecore/sql/SQL.java b/src/de/steamwar/bungeecore/sql/SQL.java deleted file mode 100644 index 947e2b6..0000000 --- a/src/de/steamwar/bungeecore/sql/SQL.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - 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.bungeecore.sql; - -import de.steamwar.bungeecore.BungeeCore; -import net.md_5.bungee.api.ProxyServer; - -import java.sql.*; - - -public class SQL { - private SQL(){} - - private static Connection con; - private static String url; - private static String user; - private static String password; - - public static void connect(String url, String user, String password) { - SQL.url = url; - SQL.user = user; - SQL.password = password; - try { - con = DriverManager.getConnection(url + "?autoreconnect=true", user, password); - }catch (SQLException e) { - ProxyServer.getInstance().stop(); - throw new SecurityException("Could not start SQL-Exception", e); - } - } - - public static void close() { - try { - if(con != null) - con.close(); - }catch (SQLException e) { - BungeeCore.log("Could not close SQL-Connection", e); - } - } - - static void update(String qry, Object... objects) { - try { - prepare(con, qry, objects).executeUpdate(); - } catch (SQLException e) { - sqlException(); - try (PreparedStatement st = con.prepareStatement(qry)) { - st.executeUpdate(); - } catch (SQLException ex) { - throw new SecurityException("Could not execute update statement", ex); - } - } - } - - static ResultSet select(String qry, Object... objects){ - try{ - return prepare(con, qry, objects).executeQuery(); - } catch (SQLException e) { - sqlException(); - try { - return prepare(con, qry, objects).executeQuery(); - } catch (SQLException ex) { - throw new SecurityException("Could not run Select-Statement", ex); - } - } - } - - private static PreparedStatement prepare(Connection connection, String qry, Object... objects) throws SQLException{ - PreparedStatement st = connection.prepareStatement(qry); - for(int i = 0; i < objects.length; i++){ - st.setObject(i+1, objects[i]); - } - return st; - } - - private static void sqlException(){ - close(); - connect(url, user, password); - } -} diff --git a/src/de/steamwar/bungeecore/sql/SWException.java b/src/de/steamwar/bungeecore/sql/SWException.java index 44a43ca..8a2c2e1 100644 --- a/src/de/steamwar/bungeecore/sql/SWException.java +++ b/src/de/steamwar/bungeecore/sql/SWException.java @@ -22,7 +22,9 @@ package de.steamwar.bungeecore.sql; public class SWException { private SWException(){} + private static final Statement insert = new Statement("INSERT INTO Exception (server, message, stacktrace) VALUES (?, ?, ?)"); + public static void log(String server, String message, String stacktrace){ - SQL.update("INSERT INTO Exception (server, message, stacktrace) VALUES (?, ?, ?)", server, message, stacktrace); + insert.update(server, message, stacktrace); } } diff --git a/src/de/steamwar/bungeecore/sql/Session.java b/src/de/steamwar/bungeecore/sql/Session.java index 7f48659..9793c35 100644 --- a/src/de/steamwar/bungeecore/sql/Session.java +++ b/src/de/steamwar/bungeecore/sql/Session.java @@ -22,9 +22,12 @@ package de.steamwar.bungeecore.sql; import java.sql.Timestamp; public class Session { + + private static final Statement insert = new Statement("INSERT INTO Session (UserID, StartTime, EndTime) VALUES (?, ?, NOW())"); + private Session(){} public static void insertSession(int userID, Timestamp startTime){ - SQL.update("INSERT INTO Session (UserID, StartTime, EndTime) VALUES (?, ?, NOW())", userID, startTime); + insert.update(userID, startTime); } } diff --git a/src/de/steamwar/bungeecore/sql/Statement.java b/src/de/steamwar/bungeecore/sql/Statement.java new file mode 100644 index 0000000..9b1628c --- /dev/null +++ b/src/de/steamwar/bungeecore/sql/Statement.java @@ -0,0 +1,145 @@ +/* + 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.bungeecore.sql; + +import de.steamwar.bungeecore.BungeeCore; +import net.md_5.bungee.api.ProxyServer; + +import java.sql.*; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; + +public class Statement { + private static final List statements = new ArrayList<>(); + + private static Connection con; + private static String url; + private static String user; + private static String password; + + public static void connect(String url, String user, String password) { + Statement.url = url; + Statement.user = user; + Statement.password = password; + try { + con = DriverManager.getConnection(url + "?autoReconnect=true&useServerPrepStmts=true", user, password); + } catch (SQLException e) { + ProxyServer.getInstance().stop(); + throw new SecurityException("Could not start SQL-Connection", e); + } + } + + private static void reset() { + close(); + connect(url, user, password); + try { + for (Statement statement : statements) { + statement.init(); + } + } catch (SQLException e) { + throw new SecurityException("Could not reprepare SQL statements", e); + } + } + + public static void close() { + synchronized (statements) { + for (Statement statement : statements) { + try { + statement.st.close(); + } catch (SQLException e) { + BungeeCore.get().getLogger().log(Level.INFO, "Could not close statement", e); + } + } + + try { + con.close(); + } catch (SQLException e) { + BungeeCore.get().getLogger().log(Level.INFO, "Could not close SQL connection", e); + } + } + } + + public static boolean connectionStable() { + try { + return !con.isClosed(); + } catch (SQLException e) { + return false; + } + } + + private final String sql; + private PreparedStatement st; + + Statement(String sql) { + this.sql = sql; + statements.add(this); + try { + init(); + } catch (SQLException e) { + throw new SecurityException("Could not init SQL statement", e); + } + } + + private void init() throws SQLException { + st = con.prepareStatement(sql); + } + + T select(ResultSetUser user, Object... objects) { + synchronized (statements) { + return prepare(() -> { + ResultSet rs = st.executeQuery(); + T result = user.use(rs); + rs.close(); + return result; + }, objects); + } + } + + void update(Object... objects) { + synchronized (statements) { + prepare(st::executeUpdate, objects); + } + } + + private T prepare(SQLRunnable runnable, Object... objects) { + try { + setObjects(objects); + return runnable.run(); + } catch (SQLException e) { + reset(); + throw new SecurityException("Could not execute SQL statement", e); + } + } + + private void setObjects(Object... objects) throws SQLException { + for (int i = 0; i < objects.length; i++) { + st.setObject(i + 1, objects[i]); + } + } + + interface ResultSetUser { + T use(ResultSet rs) throws SQLException; + } + + private interface SQLRunnable { + T run() throws SQLException; + } +} diff --git a/src/de/steamwar/bungeecore/sql/SteamwarUser.java b/src/de/steamwar/bungeecore/sql/SteamwarUser.java index 00fd221..ccc174e 100644 --- a/src/de/steamwar/bungeecore/sql/SteamwarUser.java +++ b/src/de/steamwar/bungeecore/sql/SteamwarUser.java @@ -24,44 +24,56 @@ import de.steamwar.bungeecore.BungeeCore; import de.steamwar.bungeecore.Message; import de.steamwar.bungeecore.commands.WebregisterCommand; import de.steamwar.bungeecore.listeners.ConnectionListener; -import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.Scanner; import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.chat.TextComponent; import net.md_5.bungee.api.connection.PendingConnection; import net.md_5.bungee.api.connection.ProxiedPlayer; +import java.io.IOException; import java.net.InetAddress; +import java.net.URL; import java.net.UnknownHostException; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Timestamp; import java.time.format.DateTimeFormatter; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; +import java.util.*; +import java.util.logging.Level; public class SteamwarUser { - private final int id; - private final UUID uuid; - private String userName; - private UserGroup userGroup; - private int team; - private boolean leader; - private Map punishments; - private String discordId; + + private static final Statement updateName = new Statement("UPDATE UserData SET UserName = ? WHERE id = ?"); + private static final Statement updateBedrock = new Statement("UPDATE UserData SET Bedrock = ? WHERE id = ?"); + private static final Statement insert = new Statement("INSERT INTO UserData (UUID, UserName, UserGroup) VALUES (?, ?, 'Member')"); + private static final Statement byUUID = new Statement("SELECT * FROM UserData WHERE UUID = ?"); + private static final Statement byName = new Statement("SELECT * FROM UserData WHERE lower(UserName) = ?"); + private static final Statement byID = new Statement("SELECT * FROM UserData WHERE id = ?"); + private static final Statement byDiscord = new Statement("SELECT * FROM UserData WHERE DiscordId = ?"); + private static final Statement updateTeam = new Statement("Update UserData SET Team = ? WHERE id = ?"); + private static final Statement updateDiscord = new Statement("Update UserData SET DiscordId = ? WHERE id = ?"); + private static final Statement deleteIPs = new Statement("DELETE FROM BannedUserIPs WHERE UserID = ?"); + private static final Statement updateLeader = new Statement("Update UserData SET Leader = ? WHERE id = ?"); + private static final Statement getPlaytime = new Statement("SELECT SUM(UNIX_TIMESTAMP(EndTime) - UNIX_TIMESTAMP(StartTime)) as Playtime FROM Session WHERE UserID = ?"); + private static final Statement getFirstjoin = new Statement("SELECT MIN(StartTime) AS FirstJoin FROM Session WHERE UserID = ?"); private static final Map usersByName = new HashMap<>(); private static final Map usersByUUID = new HashMap<>(); private static final Map usersById = new HashMap<>(); - private static final Map usersByDiscord = new HashMap<>(); + private static final Map usersByDiscord = new HashMap<>(); private static final InetAddress LIXFEL_DE; private static final String API_URL = "https://api.mojang.com/users/profiles/minecraft/"; private static final JsonParser jsonParser = new JsonParser(); + private final int id; + private final UUID uuid; + private String userName; + private final UserGroup userGroup; + private int team; + private boolean leader; + private final Map punishments; + private Long discordId; + static { try { LIXFEL_DE = InetAddress.getByAddress(new byte[]{(byte) 195, (byte) 201, (byte) 242, 43}); @@ -78,44 +90,49 @@ public class SteamwarUser { userGroup = UserGroup.getUsergroup(rs.getString("UserGroup")); team = rs.getInt("Team"); leader = rs.getBoolean("Leader"); - discordId = rs.getString("DiscordId"); + discordId = rs.getLong("DiscordId"); + if(rs.wasNull()) { + discordId = null; + } usersById.put(id, this); usersByName.put(userName.toLowerCase(), this); usersByUUID.put(uuid, this); - if(discordId != null) + if (discordId != null) { usersByDiscord.put(discordId, this); + } punishments = Punishment.getPunishmentsOfPlayer(id); } - public static SteamwarUser getOrCreate(PendingConnection connection){ + public static SteamwarUser getOrCreate(PendingConnection connection) { SteamwarUser user = SteamwarUser.get(connection.getUniqueId()); - if(user != null){ + if (user != null) { String userName = connection.getName(); - if(!user.userName.equals(userName)){ - SQL.update("UPDATE UserData SET UserName = ? WHERE id = ?", userName, user.id); + if (!user.userName.equals(userName)) { + updateName.update(userName, user.id); WebregisterCommand.changeUsername(user.userName, userName); user.userName = userName; } - }else{ + } else { user = SteamwarUser.createUserInDatabase(connection.getUniqueId(), connection.getName()); - if(user == null) + if (user == null) { throw new SecurityException("user == null"); + } ConnectionListener.newPlayer(user.uuid); } boolean bedrock = connection.getAddress().getAddress().equals(LIXFEL_DE); - SQL.update("UPDATE UserData SET Bedrock = ? WHERE id = ?", bedrock, user.id); + updateBedrock.update(bedrock, user.id); return user; } - public static SteamwarUser getOrCreateOfflinePlayer(String name){ + public static SteamwarUser getOrCreateOfflinePlayer(String name) { SteamwarUser user = SteamwarUser.get(name); if (user != null) { return user; } - UUID uuid = SteamwarUser.loadUUID(name); + UUID uuid = SteamwarUser.getUUIDofOfflinePlayer(name); if (uuid == null) { return null; } @@ -124,65 +141,78 @@ public class SteamwarUser { } private static SteamwarUser createUserInDatabase(UUID uuid, String name) { - SQL.update("INSERT INTO UserData (UUID, UserName, UserGroup) VALUES (?, ?, 'Member')", uuid.toString(), name); - return dbInit(SQL.select("SELECT * FROM UserData WHERE UUID = ?", uuid.toString())); + insert.update(uuid.toString(), name); + return get(uuid); } - public static SteamwarUser get(String userName){ + public static SteamwarUser get(String userName) { userName = userName.toLowerCase(); - if(usersByName.containsKey(userName)) + if (usersByName.containsKey(userName)) { return usersByName.get(userName); - return dbInit(SQL.select("SELECT * FROM UserData WHERE lower(UserName) = ?", userName)); + } + return byName.select(rs -> { + if (rs.next()) + return new SteamwarUser(rs); + return null; + }, userName); } - public static SteamwarUser get(UUID uuid){ - if(usersByUUID.containsKey(uuid)) + public static SteamwarUser get(UUID uuid) { + if (usersByUUID.containsKey(uuid)) { return usersByUUID.get(uuid); - return dbInit(SQL.select("SELECT * FROM UserData WHERE UUID = ?", uuid.toString())); + } + return byUUID.select(rs -> { + if (rs.next()) + return new SteamwarUser(rs); + return null; + }, uuid.toString()); } - public static SteamwarUser get(ProxiedPlayer player){ + public static SteamwarUser get(ProxiedPlayer player) { return get(player.getUniqueId()); } - public static SteamwarUser get(int id){ - if(usersById.containsKey(id)) + public static SteamwarUser get(int id) { + if (usersById.containsKey(id)) { return usersById.get(id); - return dbInit(SQL.select("SELECT * FROM UserData WHERE id = ?", id)); + } + return byID.select(rs -> { + rs.next(); + return new SteamwarUser(rs); + }, id); } public static SteamwarUser get(Long discordId) { - if(usersByDiscord.containsKey(discordId.toString())) - return usersByDiscord.get(discordId.toString()); - return dbInit(SQL.select("SELECT * FROM UserData WHERE DiscordId = ?", discordId)); + if(usersByDiscord.containsKey(discordId)) + return usersByDiscord.get(discordId); + return byDiscord.select(rs -> { + if (rs.next()) + return new SteamwarUser(rs); + return null; + }, discordId); } - public static void clearCache(){ + public static void clearCache() { usersById.clear(); usersByName.clear(); usersByUUID.clear(); usersByDiscord.clear(); } - public static UUID loadUUID(String playerName) { + private static UUID getUUIDofOfflinePlayer(String playerName) { try { final URL url = new URL(API_URL + playerName); - return getUniqueIdFromString(jsonParser.parse(new Scanner(url.openConnection().getInputStream()).nextLine()).getAsJsonObject().get("id").getAsString()); - } catch (MalformedURLException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); + String uuid = jsonParser.parse(new Scanner(url.openConnection().getInputStream()).nextLine()).getAsJsonObject().get("id").getAsString(); + return UUID.fromString(uuid.replaceFirst("(\\w{8})(\\w{4})(\\w{4})(\\w{4})(\\w{12})", "$1-$2-$3-$4-$5")); + } catch (NoSuchElementException | IOException e) { + BungeeCore.get().getLogger().log(Level.SEVERE, "Could not get offline player UUID " + playerName, e); + return null; } - return null; } - private static UUID getUniqueIdFromString(String uuid) { - return UUID.fromString(uuid.replaceFirst("(\\w{8})(\\w{4})(\\w{4})(\\w{4})(\\w{12})", "$1-$2-$3-$4-$5")); - } - - public void setTeam(int team){ + public void setTeam(int team) { this.team = team; - SQL.update("Update UserData SET Team = ? WHERE id = ?", team, id); + updateTeam.update(team, id); setLeader(false); } @@ -202,7 +232,7 @@ public class SteamwarUser { return userGroup; } - public int getTeam(){ + public int getTeam() { return team; } @@ -210,126 +240,91 @@ public class SteamwarUser { return punishments.getOrDefault(type, null); } - public String getDiscordId() { + public Long getDiscordId() { return discordId; } - public void setDiscordId(String discordId) { + public void setDiscordId(Long discordId) { usersByDiscord.remove(this.discordId); this.discordId = discordId; - SQL.update("Update UserData SET DiscordId = ? WHERE id = ?", discordId, id); - if(discordId != null) { + updateDiscord.update(discordId, id); + if (discordId != null) { usersByDiscord.put(discordId, this); } } - public boolean isBanned() { - if(!punishments.containsKey(Punishment.PunishmentType.Ban)) + public boolean isPunished(Punishment.PunishmentType punishment) { + if (!punishments.containsKey(punishment)) { return false; - if(!punishments.get(Punishment.PunishmentType.Ban).isCurrent()) { - SQL.update("DELETE FROM BannedUserIPs WHERE UserID = ?", id); - punishments.remove(Punishment.PunishmentType.Ban); + } + if (!punishments.get(punishment).isCurrent()) { + if (punishment == Punishment.PunishmentType.Ban) { + deleteIPs.update(id); + } + punishments.remove(punishment); return false; } return true; } - public boolean isMuted(){ - if(!punishments.containsKey(Punishment.PunishmentType.Mute)) - return false; - if(!punishments.get(Punishment.PunishmentType.Mute).isCurrent()) { - punishments.remove(Punishment.PunishmentType.Mute); + public boolean isPunishedWithMessage(ProxiedPlayer player, Punishment.PunishmentType punishment) { + if (!isPunished(punishment)) { return false; } + player.sendMessage(punishmentMessage(punishment, player)); return true; } - public TextComponent banMessage(ProxiedPlayer player){ - Punishment punishment = punishments.get(Punishment.PunishmentType.Ban); - if (punishment.isPerma()) { - return BungeeCore.stringToText(Message.parsePrefixed("BANNED_MESSAGE_PERMA", player, punishment.getReason())); + public void punish(Punishment.PunishmentType punishment, Timestamp time, String banReason, int from, boolean perma) { + punishments.remove(punishment); + punishments.put(punishment, Punishment.createPunishment(id, from, punishment, banReason, time, perma)); + + if (punishment != Punishment.PunishmentType.Ban) { + return; + } + + ProxiedPlayer player = ProxyServer.getInstance().getPlayer(uuid); + if (player != null) { + updateBanIP(player.getAddress().getAddress().getHostAddress()); + player.disconnect(punishmentMessage(punishment, player)); + for (BannedUserIPs banned : BannedUserIPs.get(player.getAddress().getAddress().getHostAddress())) { + SteamwarUser bannedUser = SteamwarUser.get(banned.getUserID()); + if (isPunished(punishment) && banned.getTimestamp().before(time)) { + bannedUser.punish(punishment, time, banReason, from, perma); + } + } } else { - return BungeeCore.stringToText(Message.parsePrefixed("BANNED_MESSAGE_UNTIL", player, punishment.getEndTime().toLocalDateTime().format(DateTimeFormatter.ofPattern(Message.parse("TIMEFORMAT", player))), - punishment.getReason())); + updateBanIP(""); } } - public TextComponent muteMessage(ProxiedPlayer player){ - Punishment punishment = punishments.get(Punishment.PunishmentType.Mute); - if (punishment.isPerma()) { - return BungeeCore.stringToText(Message.parsePrefixed("MUTED_MESSAGE_PERMA", player, punishment.getReason())); + public TextComponent punishmentMessage(Punishment.PunishmentType punishment, ProxiedPlayer player) { + Punishment currentPunishment = punishments.get(punishment); + if (currentPunishment.isPerma()) { + return BungeeCore.stringToText(Message.parsePrefixed(punishment.getPlayerMessagePerma(), player, currentPunishment.getReason())); } else { - return BungeeCore.stringToText(Message.parsePrefixed("MUTED_MESSAGE_UNTIL", player, punishment.getEndTime().toLocalDateTime().format(DateTimeFormatter.ofPattern(Message.parse("TIMEFORMAT", player))), punishment.getReason())); + return BungeeCore.stringToText(Message.parsePrefixed(punishment.getPlayerMessageUntil(), player, currentPunishment.getEndTime().toLocalDateTime().format(DateTimeFormatter.ofPattern(Message.parse("TIMEFORMAT", player))), currentPunishment.getReason())); } } - public void updateBanIP(String ip){ + public void updateBanIP(String ip) { BannedUserIPs.banIP(this, ip); } - public void ban(Timestamp time, String banReason, int from, boolean perma){ - if(isBanned()) { - punishments.get(Punishment.PunishmentType.Ban).updateEndTime(from, banReason, time, perma); - return; - } - punishments.remove(Punishment.PunishmentType.Ban); - punishments.put(Punishment.PunishmentType.Ban, Punishment.createPunishment(id, from, Punishment.PunishmentType.Ban, banReason, time, perma)); - - ProxiedPlayer player = ProxyServer.getInstance().getPlayer(uuid); - if(player != null){ - updateBanIP(player.getAddress().getAddress().getHostAddress()); - player.disconnect(banMessage(player)); - for (BannedUserIPs banned: - BannedUserIPs.get(player.getAddress().getAddress().getHostAddress())) { - SteamwarUser bannedUser = SteamwarUser.get(banned.getUserID()); - if(bannedUser.isBanned() && banned.getTimestamp().before(time)) - bannedUser.ban(time, banReason, from, perma); - } - }else - updateBanIP(""); - } - - public void mute(Timestamp time, String muteReason, int from, boolean perma){ - if(isMuted()) { - punishments.get(Punishment.PunishmentType.Mute).updateEndTime(from, muteReason, time, perma); - return; - } - punishments.remove(Punishment.PunishmentType.Mute); - punishments.put(Punishment.PunishmentType.Mute, Punishment.createPunishment(id, from, Punishment.PunishmentType.Mute, muteReason, time, perma)); - } - - private static SteamwarUser dbInit(ResultSet rs){ - try { - if(!rs.next()) - return null; - return new SteamwarUser(rs); - } catch (SQLException e) { - throw new SecurityException(e); - } - } - public double getOnlinetime() { - ResultSet set = SQL.select("SELECT SUM(UNIX_TIMESTAMP(EndTime) - UNIX_TIMESTAMP(StartTime)) as Playtime FROM Session WHERE UserID = ?", id); - try { - if(!set.next()) - return 0; - return set.getBigDecimal("Playtime").doubleValue(); - } catch (SQLException throwables) { - throw new SecurityException("Could not load Online Time", throwables); - } catch (NullPointerException e) { //When no Sessions are recorded - return 0; - } + return getPlaytime.select(rs -> { + if (rs.next() && rs.getBigDecimal("Playtime") != null) + return rs.getBigDecimal("Playtime").doubleValue(); + return 0.0; + }, id); } public Timestamp getFirstjoin() { - ResultSet set = SQL.select("SELECT MIN(StartTime) AS FirstJoin FROM Session WHERE UserID = ?", id); - try { - if(!set.next()) - return null; - return set.getTimestamp("FirstJoin"); - } catch (SQLException throwables) { - throw new SecurityException("Could not load First Join"); - } + return getFirstjoin.select(rs -> { + if (rs.next()) + return rs.getTimestamp("FirstJoin"); + return null; + }, id); } public boolean isLeader() { @@ -338,6 +333,6 @@ public class SteamwarUser { public void setLeader(boolean leader) { this.leader = leader; - SQL.update("Update UserData SET Leader = ? WHERE id = ?", leader, id); + updateLeader.update(leader, id); } } diff --git a/src/de/steamwar/bungeecore/sql/Team.java b/src/de/steamwar/bungeecore/sql/Team.java index b5c083b..f721fa5 100644 --- a/src/de/steamwar/bungeecore/sql/Team.java +++ b/src/de/steamwar/bungeecore/sql/Team.java @@ -19,25 +19,31 @@ package de.steamwar.bungeecore.sql; -import de.steamwar.bungeecore.BungeeCore; - import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; -import static de.steamwar.bungeecore.sql.SQL.select; - public class Team { + + private static final Statement insert = new Statement("INSERT INTO Team (TeamKuerzel, TeamName) VALUES (?, ?)"); + private static final Statement delete = new Statement("UPDATE Team SET TeamDeleted = 1 WHERE TeamID = ?"); + private static final Statement update = new Statement("INSERT INTO Team (TeamID, TeamKuerzel, TeamName, TeamColor) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE TeamName = VALUES(TeamName), TeamKuerzel = VALUES(TeamKuerzel), TeamColor = VALUES(TeamColor)"); + private static final Statement getSize = new Statement("SELECT COUNT(id) FROM UserData WHERE Team = ?"); + private static final Statement getMembers = new Statement("SELECT id FROM UserData WHERE Team = ?"); + private static final Statement byId = new Statement("SELECT * FROM Team WHERE TeamID = ?"); + private static final Statement byName = new Statement("SELECT * FROM Team WHERE (lower(TeamName) = ? OR lower(TeamKuerzel) = ?) AND NOT TeamDeleted"); + private static final Statement all = new Statement("SELECT * FROM Team WHERE NOT TeamDeleted"); + + private static final List teamCache = new LinkedList<>(); + private static final Team pub = new Team(0, "PUB", "Öffentlich", "8"); + private final int teamId; private String teamKuerzel; private String teamName; private String teamColor; - private static final List teamCache = new LinkedList<>(); - private static final Team pub = new Team(0, "PUB", "Öffentlich", "8"); - private Team(int id, String kuerzel, String name, String color){ teamId = id; teamKuerzel = kuerzel; @@ -52,8 +58,8 @@ public class Team { this(rs.getInt("TeamID"), rs.getString("TeamKuerzel"), rs.getString("TeamName"), rs.getString("TeamColor")); } - public static void create(String kuerzel, String name, SteamwarUser user){ - SQL.update("INSERT INTO Team (TeamKuerzel, TeamName) VALUES (?, ?)", kuerzel, name); + public static void create(String kuerzel, String name){ + insert.update(kuerzel, name); } public static Team get(int id){ @@ -64,51 +70,38 @@ public class Team { for(Team team : teamCache) if(team.teamId == id) return team; - return load(select("SELECT * FROM Team WHERE TeamID = ?", id)); + return byId.select(rs -> { + rs.next(); + return new Team(rs); + }, id); } public static Team get(String name){ for(Team team : teamCache) - if(team.teamName.equalsIgnoreCase(name)) + if(team.teamName.equalsIgnoreCase(name) || team.teamKuerzel.equalsIgnoreCase(name)) return team; - for(Team team : teamCache) - if(team.teamKuerzel.equalsIgnoreCase(name)) - return team; - return load(select("SELECT * FROM Team WHERE (lower(TeamName) = ? OR lower(TeamKuerzel) = ?) AND NOT TeamDeleted", name.toLowerCase(), name.toLowerCase())); + return byName.select(rs -> { + if(rs.next()) + return new Team(rs); + return null; + }, name.toLowerCase(), name.toLowerCase()); } public static List getAll(){ clearCache(); - try{ - ResultSet rs = select("SELECT * FROM Team WHERE NOT TeamDeleted"); - if(rs == null) - return teamCache; - + return all.select(rs -> { while(rs.next()) new Team(rs); - } catch (SQLException e) { - BungeeCore.log("Could not get all Teams", e); - } - return teamCache; + return teamCache; + }); } public static void clearCache(){ teamCache.clear(); } - private static Team load(ResultSet dbteam){ - try { - if(!dbteam.next()) - return null; - return new Team(dbteam); - } catch (SQLException e) { - BungeeCore.log("Could not load Team", e); - return null; - } - } - private void updateDB(){ - SQL.update("INSERT INTO Team (TeamID, TeamKuerzel, TeamName, TeamColor) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE TeamName = VALUES(TeamName), TeamKuerzel = VALUES(TeamKuerzel), TeamColor = VALUES(TeamColor)", teamId, teamKuerzel, teamName, teamColor); + update.update(teamId, teamKuerzel, teamName, teamColor); } public int getTeamId() { @@ -143,33 +136,24 @@ public class Team { } public int size(){ - ResultSet rs = select("SELECT COUNT(id) FROM UserData WHERE Team = ?", teamId); - try { + return getSize.select(rs -> { rs.next(); return rs.getInt("COUNT(id)"); - }catch (SQLException e) { - BungeeCore.log("Could not get Teamsize", e); - return 1000; - } + }, teamId); } public void disband(SteamwarUser user){ user.setLeader(false); - SQL.update("UPDATE Team SET TeamDeleted = 1 WHERE TeamID = ?", teamId); + delete.update(teamId); teamCache.remove(this); } public List getMembers(){ - try{ - ResultSet memberlist = select("SELECT id FROM UserData WHERE Team = ?", teamId); + return getMembers.select(rs -> { List members = new ArrayList<>(); - while(memberlist.next()){ - members.add(memberlist.getInt("id")); - } + while(rs.next()) + members.add(rs.getInt("id")); return members; - }catch(SQLException e){ - BungeeCore.log("Could not get Teammembers", e); - } - return new ArrayList<>(); + }, teamId); } } diff --git a/src/de/steamwar/bungeecore/sql/TeamTeilnahme.java b/src/de/steamwar/bungeecore/sql/TeamTeilnahme.java index 2da396b..68b1192 100644 --- a/src/de/steamwar/bungeecore/sql/TeamTeilnahme.java +++ b/src/de/steamwar/bungeecore/sql/TeamTeilnahme.java @@ -19,55 +19,46 @@ package de.steamwar.bungeecore.sql; -import de.steamwar.bungeecore.BungeeCore; - import java.sql.ResultSet; -import java.sql.SQLException; import java.util.HashSet; import java.util.Set; public class TeamTeilnahme { private TeamTeilnahme(){} + private static final Statement insert = new Statement("INSERT INTO TeamTeilnahme (TeamID, EventID) VALUES (?, ?)"); + private static final Statement delete = new Statement("DELETE FROM TeamTeilnahme WHERE TeamID = ? AND EventID = ?"); + private static final Statement byEventTeam = new Statement("SELECT * FROM TeamTeilnahme WHERE TeamID = ? AND EventID = ?"); + private static final Statement byEvent = new Statement("SELECT * FROM TeamTeilnahme WHERE EventID = ?"); + private static final Statement byTeam = new Statement("SELECT * FROM TeamTeilnahme WHERE TeamID = ?"); + public static void teilnehmen(int teamID, int eventID){ - SQL.update("INSERT INTO TeamTeilnahme (TeamID, EventID) VALUES (?, ?)", teamID, eventID); + insert.update(teamID, eventID); } public static void notTeilnehmen(int teamID, int eventID){ - SQL.update("DELETE FROM TeamTeilnahme WHERE TeamID = ? AND EventID = ?", teamID, eventID); + delete.update(teamID, eventID); } public static boolean nimmtTeil(int teamID, int eventID){ - ResultSet rs = SQL.select("SELECT * FROM TeamTeilnahme WHERE TeamID = ? AND EventID = ?", teamID, eventID); - try{ - return rs.next(); - }catch (SQLException e){ - BungeeCore.log("Failed to load TeamTeilnahme", e); - throw new SecurityException(); - } + return byEventTeam.select(ResultSet::next, teamID, eventID); } public static Set getTeams(int eventID){ - Set teams = new HashSet<>(); - ResultSet rs = SQL.select("SELECT * FROM TeamTeilnahme WHERE EventID = ?", eventID); - try{ + return byEvent.select(rs -> { + Set teams = new HashSet<>(); while(rs.next()) teams.add(Team.get(rs.getInt("TeamID"))); - }catch (SQLException e){ - BungeeCore.log("Failed to load TeamTeilnahmen", e); - } - return teams; + return teams; + }, eventID); } public static Set getEvents(int teamID){ - Set events = new HashSet<>(); - ResultSet rs = SQL.select("SELECT * FROM TeamTeilnahme WHERE TeamID = ?", teamID); - try{ + return byTeam.select(rs -> { + Set events = new HashSet<>(); while(rs.next()) events.add(Event.get(rs.getInt("EventID"))); - }catch (SQLException e){ - BungeeCore.log("Failed to load TeamTeilnahmen", e); - } - return events; + return events; + }, teamID); } } diff --git a/src/de/steamwar/messages/BungeeCore.properties b/src/de/steamwar/messages/BungeeCore.properties index 31cb6cc..cc7d8af 100644 --- a/src/de/steamwar/messages/BungeeCore.properties +++ b/src/de/steamwar/messages/BungeeCore.properties @@ -95,8 +95,6 @@ HELP_BAU_TESTARENA_HOVER=§eTestarena starten #Usage description of various commands USAGE_ALERT=§8/§7alert §8[§eNachricht§8] -USAGE_BAN=§8/§7ban §8[§eSpieler§8] [§edd§8.§emm§8.§eyyyy §7oder §edd§8.§emm§8.§eyyyy§8_§ehh§8:§emm §7oder §eperma§8] [§eGrund§8] -USAGE_MUTE=§8/§7mute §8[§eSpieler§8] [§edd§8.§emm§8.§eyyyy §7oder §edd§8.§emm§8.§eyyyy§8_§ehh§8:§emm §7oder §eperma§8] [§eGrund§8] USAGE_IGNORE=§8/§7ignore §8[§eSpieler§8] #ModListener @@ -107,25 +105,59 @@ MOD_YELLOW_PLUR=§7Deaktiviere die Mods\n§e{0}\n§7um weiter auf §eSteam§8War #Various commands ALERT=§f{0} -STAT_SERVER=§7Server §f{0} - §7Ram §f{1} §7CPU §f{2} §7Server Count §f{3} -NO_STATS=§7Kein Bau oder Fight Server gestartet +STAT_SERVER=§7Server §e{0}§8: §7Load §e{1} §7Serveranzahl §e{2} #Ban&Mute-Command -BAN_TEAM_BANNED={0} §c{1} wurde von {2} {3} gebannt. §f§lGrund: §f{4} -BANNED_MESSAGE_PERMA=§cDu bist permanent gebannt. §r§lGrund§r: §c{0} -BANNED_MESSAGE_UNTIL=§cDu bist bis zum {0} gebannt. §r§lGrund§r: §c{1} -MUTE_TEAM_MUTED={0} §c{1} wurde von {2} {3} gemuted. §f§lGrund: §f{4} -MUTED_MESSAGE_PERMA=§cDu bist permanent gemuted. §r§lGrund§r: §c{0} -MUTED_MESSAGE_UNTIL=§cDu bist bis zum {0} gemuted. §r§lGrund§r: §c{1} -BAN_CHANGED={0}verändert von {1} von {2} auf {3} wegen {4} -BAN_PERMA=permanent -BAN_UNTIL=bis zum {0} +PUNISHMENT_USAGE=§8/§7{0} §8[§eSpieler§8] [§edd§8.§emm§8.§eyyyy §7oder §edd§8.§emm§8.§eyyyy§8_§ehh§8:§emm §7oder §eperma§8] [§eGrund§8] +UNPUNISHMENT_USAGE=§8/§7{0} §8[§eSpieler§8] + +PUNISHMENT_UNTIL=bis zum {0} +PUNISHMENT_PERMA=permanent + +BAN_TEAM={0} §e{1} §7wurde von §e{2} {3} §e§lgebannt§8. §7Grund§8: §f{4} +BAN_PERMA=§7Du bist §epermanent §e§lgebannt§8. §7Grund§8: §e{0} +BAN_UNTIL=§7Du bist §ebis zum {0} §e§lgebannt§8. §7Grund§8: §e{1} +UNBAN_ERROR=§cDer Spieler ist nicht gebannt. +UNBAN=§7Du hast §e{0} §e§lentbannt. + BAN_AVOIDING_ALERT=§cMögliche Bannumgehung durch §r{0}§c: §c BAN_AVOIDING_LIST={0} §e{1} §c BAN_AVOIDING_BAN_HOVER=§cBanne Spieler wegen Bannumgehung +MUTE_TEAM={0} §e{1} §7wurde von §e{2} {3} §e§lgemuted§8. §7Grund§8: §f{4} +MUTE_PERMA=§7Du bist §epermanent §e§lgemuted§8. §7Grund§8: §e{0} +MUTE_UNTIL=§7Du bist §ebis zum {0} §e§lgemuted§8. §7Grund§8: §e{1} +UNMUTE_ERROR=§cDer Spieler ist nicht gemuted. +UNMUTE=§7Du hast §e{0} §e§lentmuted. + +NOSCHEMRECEIVING_TEAM={0} §e{1} §7wurde von §e{2} {3} §7vom §e§lSchematicerhalten ausgeschlossen§8. §7Grund§8: §f{4} +NOSCHEMRECEIVING_PERMA=§7Du bist §epermanent §7vom Erhalten von §e§lSchematics ausgeschlossen§8. §7Grund§8: §e{0} +NOSCHEMRECEIVING_UNTIL=§7Du bist §ebis zum {0} §7vom Erhalten von §e§lSchematics ausgeschlossen§8. §7Grund§8: §e{1} +UNNOSCHEMRECEIVING_ERROR=§cDer Spieler ist nicht vom Erhalten von Schematics ausgeschlossen. +UNNOSCHEMRECEIVING=§e{0} §7darf nun wieder §e§lSchematics erhalten§8. + +NOSCHEMSHARING_TEAM={0} §e{1} §7wurde von §e{2} {3} §7vom §e§lSchematicverteilen ausgeschlossen§8. §7Grund§8: §f{4} +NOSCHEMSHARING_PERMA=§7Du bist §epermanent §7vom §e§lVerteilen von Schematics§7 ausgeschlossen§8. §7Grund§8: §e{0} +NOSCHEMSHARING_UNTIL=§7Du bist §ebis zum {0} §7vom §e§lVerteilen von Schematics§7 ausgeschlossen§8. §7Grund§8: §e{1} +UNNOSCHEMSHARING_ERROR=§cDer Spieler ist nicht vom Verteilen von Schematics ausgeschlossen. +UNNOSCHEMSHARING=§e{0} §7darf nun wieder §e§lSchematics verteilen§8. + +NOSCHEMSUBMITTING_TEAM={0} §e{1} §7wurde von §e{2} {3} §7vom §e§lSchematiceinsenden ausgeschlossen§8. §7Grund§8: §f{4} +NOSCHEMSUBMITTING_PERMA=§7Du bist §epermanent §7vom §e§lEinsenden von Schematics§7 ausgeschlossen§8. §7Grund§8: §e{0} +NOSCHEMSUBMITTING_UNTIL=§7Du bist §ebis zum {0} §7vom §e§lEinsenden von Schematics§7 ausgeschlossen§8. §7Grund§8: §e{1} +UNNOSCHEMSUBMITTING_ERROR=§cDer Spieler ist nicht vom Einsenden von Schematics ausgeschlossen. +UNNOSCHEMSUBMITTING=§e{0} §7darf nun wieder §e§lSchematis einsenden§8. + +NODEVSERVER_TEAM={0} §e{1} §7hat §e{2} §7mit Grund §f{4}§7 zu generft und hat daher §e§lDevserververbot §7erhalten§8, §e{3} +NODEVSERVER_PERMA=§7Du bist §epermanent §7vom §e§lDevserver §7ausgeschlossen§8. §7Grund§8: §e{0} +NODEVSERVER_UNTIL=§7Du bist §ebis zum {0} §7vom §e§lDevserver §7ausgeschlossen§8. §7Grund§8: §e{1} +UNNODEVSERVER_ERROR=§cDer Spieler ist nicht vom Devserver ausgeschlossen. +UNNODEVSERVER=§e{0} §7darf nun wieder dem §e§lDevserver beitreten§8. + +#BugCommand BUG_MESSAGE=§7Dein Bugreport wurde gespeichert. +#IgnoreCommand IGNORE_YOURSELF=§cWie willst du dich selber ignorieren? IGNORE_ALREADY=§cDu ignorierst diesen Spieler bereits. IGNORE_MESSAGE=§7Du ignorierst nun §e{0}§8. @@ -424,11 +456,6 @@ TP_USAGE=§8/§7tp §8[§eSpieler§8] TP_USAGE_EVENT=§8/§7tp §8[§eSpieler §7oder §eTeam§8] TP_NOT_FOUND=§cKonnte das angegebene Ziel nicht finden. -#UnbanCommand -UNBAN_USAGE=§8/§7unban §8[§eSpieler§8] -UNBAN_NOT_BANNED=§cDer Spieler ist nicht gebannt. -UNBAN_UNBANNED=Du hast {0} entbannt. - #UnignoreCommand UNIGNORE_USAGE=§8/§7unignore §8[§eSpieler§8] UNIGNORE_NOT_PLAYER=§cDiesen Spieler gibt es nicht! diff --git a/steamwarci.yml b/steamwarci.yml new file mode 100644 index 0000000..432a095 --- /dev/null +++ b/steamwarci.yml @@ -0,0 +1,6 @@ +build: + - "ln -s /home/gitea/lib" + - "mvn package -B" + +artifacts: + "/binarys/bungeecore.jar": "target/bungeecore.jar"