SteamWar/BungeeCore
Archiviert
13
2

Merge branch 'master' into long_discord
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful

Dieser Commit ist enthalten in:
Lixfel 2021-09-27 16:28:46 +02:00
Commit 1d8966865f
10 geänderte Dateien mit 384 neuen und 342 gelöschten Zeilen

Datei anzeigen

@ -89,9 +89,10 @@ public class BungeeCore extends Plugin {
new WorldDownloader(); new WorldDownloader();
new BrandListener(); new BrandListener();
commands.put("/b", null); new Node.LocalNode();
commands.put("/gs", null); new Node.RemoteNode("lx");
commands.put("/bau", null); new Node.RemoteNode("az");
commands.put("/tp", null); commands.put("/tp", null);
commands.put("/bc", null); commands.put("/bc", null);
commands.put("/bauchat", null); commands.put("/bauchat", null);
@ -158,14 +159,13 @@ public class BungeeCore extends Plugin {
@Override @Override
public void onDisable(){ public void onDisable(){
ErrorLogger.stop();
Statement.close();
try { try {
SteamwarDiscordBot.instance().getJda().shutdownNow(); SteamwarDiscordBot.instance().getJda().shutdownNow();
SteamwarDiscordBot.instance().getJda().awaitStatus(JDA.Status.SHUTDOWN); SteamwarDiscordBot.instance().getJda().awaitStatus(JDA.Status.SHUTDOWN);
} catch (Exception e) { } catch (InterruptedException e) {
// Ignored Thread.currentThread().interrupt();
} }
Statement.close();
} }
public static BungeeCore get() { public static BungeeCore get() {

Datei anzeigen

@ -20,83 +20,51 @@
package de.steamwar.bungeecore; package de.steamwar.bungeecore;
import de.steamwar.bungeecore.sql.SWException; 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.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.Handler;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.LogRecord; import java.util.logging.LogRecord;
import java.util.logging.Logger;
public class ErrorLogger extends Handler implements Filter { public class ErrorLogger extends Handler {
private static ErrorLogger instance;
private int ddosRate = 0; private int ddosRate = 0;
ErrorLogger(){ ErrorLogger(){
ProxyServer.getInstance().getLogger().addHandler(this); Logger.getLogger("").addHandler(this);
ProxyServer.getInstance().getLogger().setFilter(this);
instance = this;
}
static void stop(){
ProxyServer.getInstance().getLogger().removeHandler(instance);
} }
@Override @Override
public boolean isLoggable(LogRecord record) { public void publish(LogRecord logRecord) {
if(record.getLevel() != Level.SEVERE) if(logRecord.getLevel().intValue() < Level.WARNING.intValue())
return true; return;
StringBuilder stacktrace = new StringBuilder(record.getSourceClassName() + "\n" + record.getSourceMethodName()); String message = MessageFormat.format(logRecord.getMessage(), logRecord.getParameters());
Throwable thrown = record.getThrown(); for(String reason : ignoreContains)
while(thrown != null){ if(message.contains(reason))
stacktrace.append("\nCaused by ").append(thrown.getMessage()); return;
for(StackTraceElement ste : thrown.getStackTrace()) ByteArrayOutputStream stacktraceOutput = new ByteArrayOutputStream();
stacktrace.append("\n").append(ste.toString()); if(logRecord.getThrown() != null)
logRecord.getThrown().printStackTrace(new PrintStream(stacktraceOutput));
thrown = thrown.getCause(); String stacktrace = stacktraceOutput.toString();
} if(stacktrace.contains("Cannot request protocol")) {
if(++ddosRate % 1000 == 0) {
String stacktraceString = stacktrace.toString();
if(stacktraceString.contains("Cannot request protocol")){
ddosRate++;
if(ddosRate % 1000 == 0){
SWException.log("Bungee", "DDOS", ddosRate + ""); 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; return;
} else if (!Statement.connectionStable()) {
StringBuilder stacktrace = new StringBuilder(record.getSourceClassName() + "\n" + record.getSourceMethodName()); return;
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();
} }
String stacktraceString = stacktrace.toString();
String message = MessageFormat.format(record.getMessage(), record.getParameters());
if(message.contains("ServerConnector") SWException.log("Bungee", message, stacktrace);
|| 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);
} }
@Override @Override
@ -108,4 +76,17 @@ public class ErrorLogger extends Handler implements Filter {
public void close() { public void close() {
//ignored //ignored
} }
private static final List<String> ignoreContains;
static {
List<String> 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);
}
} }

Datei anzeigen

@ -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 <https://www.gnu.org/licenses/>.
*/
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]);
}
}

Datei anzeigen

@ -0,0 +1,261 @@
/*
This file is a part of the SteamWar software.
Copyright (C) 2020 SteamWar.de-Serverteam
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.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<String> 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<String> JVM8_ARGS = Arrays.asList("-XX:ThreadPriorityPolicy=42", "-XX:SharedReadOnlySize=30m", "-XX:+UseFastEmptyMethods", "-XX:+UseFastAccessorMethods");
private static final double MIN_FREE_MEM = 4.0 * 1024 * 1024; // 4 GiB
private static final List<Node> 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<Node> 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<Node> 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(List<String> cmd, String serverJar, String worldDir, String levelName, int port, String xmx, String... dParams) {
boolean jdk11 = serverJar.contains("1.15.2");
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));
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<String> cmd = new ArrayList<>();
constructServerstart(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;
//Determin 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 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<String> 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(cmd, serverJar, worldDir, levelName, port, xmx, dParams);
return new ProcessBuilder(cmd);
}
@Override
public void execute(String... command) {
List<String> 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;
}
}
}
}

Datei anzeigen

@ -27,18 +27,14 @@ import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.*; import java.util.UUID;
import java.util.logging.Level;
public class SubserverSystem { public class SubserverSystem {
private SubserverSystem(){} private SubserverSystem(){}
private static final String BACKBONE = "/home/minecraft/backbone/"; private static final String BACKBONE = "/home/minecraft/";
private static final List<String> 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<String> JVM8_ARGS = Arrays.asList("-XX:ThreadPriorityPolicy=42", "-XX:SharedReadOnlySize=30m", "-XX:+UseFastEmptyMethods", "-XX:+UseFastAccessorMethods");
private static final String ARENA_PATH = BACKBONE + "arenaserver/"; private static final String ARENA_PATH = BACKBONE + "arenaserver/";
private static final String SERVER_PATH = BACKBONE + "server/"; private static final String SERVER_PATH = BACKBONE + "server/";
private static final String EVENT_PATH = BACKBONE + "event/"; private static final String EVENT_PATH = BACKBONE + "event/";
@ -91,6 +87,7 @@ 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){ 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 //Generate missing parameters
Node node = eventFightID > 0 ? Node.local : Node.getNode();
int port = freePort(FIRST_ARENA_PORT); int port = freePort(FIRST_ARENA_PORT);
if(serverName == null){ if(serverName == null){
@ -109,56 +106,31 @@ public class SubserverSystem {
worldDir = ARENA_PATH; worldDir = ARENA_PATH;
//Copy world //Copy world
try { node.execute("cp", "-r", SERVER_PATH + modus.getFolder() + "/arenas/" + map, worldDir + mapName);
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();
}
File directory = new File(SERVER_PATH, modus.getFolder()); File directory = new File(SERVER_PATH, modus.getFolder());
List<String> cmd = serverStartCommand( ProcessBuilder builder = node.startServer(
modus.serverJar(), modus.serverJar(), directory, worldDir, mapName, port, "2G",
directory, "logPath=" + mapName, "config=" + modus.getConfig(),
worldDir, "fightID=" + eventFightID, "ranked=" + ranked,
mapName, "checkSchemID=" + checkSchemID, "prepareSchemID=" + prepareSchemID,
port,
"2G",
"logPath=" + mapName,
"config="+modus.getConfig(),
"fightID=" + eventFightID,
"ranked=" + ranked,
"checkSchemID=" + checkSchemID,
"prepareSchemID=" + prepareSchemID,
player1 != null && eventFightID != -1 ? "blueLeader=" + player1 : null, player1 != null && eventFightID != -1 ? "blueLeader=" + player1 : null,
player2 != null ? "redLeader=" + player2 : null); player2 != null ? "redLeader=" + player2 : null
);
//Start server
ProcessBuilder process = new ProcessBuilder(cmd);
process.directory(directory);
String finalMapName = mapName; String finalMapName = mapName;
if(eventFightID == -1) 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 else
return new Subserver(Servertype.ARENA, serverName, port, process, () -> { return new Subserver(Servertype.ARENA, serverName, port, builder, () -> {
if(eventFightID > 0) if(eventFightID > 0)
return; return;
deleteFolder(ARENA_PATH + finalMapName); deleteFolder(node, ARENA_PATH + finalMapName);
}); });
} }
public static void deleteFolder(String worldName){ public static void deleteFolder(Node node, String worldName){
try { node.execute("rm", "-r", worldName);
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 Subserver startEventArena(EventFight eventFight, String serverName){ public static Subserver startEventArena(EventFight eventFight, String serverName){
@ -183,25 +155,15 @@ public class SubserverSystem {
if(bauRunning(p, owner)) if(bauRunning(p, owner))
return; return;
copyBauweltIfRequired(prototype, worldFolder + worldName);
SteamwarUser user = SteamwarUser.get(owner); SteamwarUser user = SteamwarUser.get(owner);
copyBauweltIfRequired(p, prototype, worldFolder + worldName); File directory = new File(SERVER_PATH, serverName);
Node node = Node.getNode();
int port = freePort(4000); int port = freePort(4000);
File directory = new File(SERVER_PATH, serverName); new Bauserver(user.getUserName() + "s Bau", owner, port, node.startServer(
List<String> cmd = serverStartCommand( serverJar, directory, worldDir, worldName, port, xmx, "logPath=" + worldName
serverJar, ), () -> {}).sendPlayer(p);
directory,
worldDir,
worldName,
port,
xmx,
"logPath=" + worldName);
//Start server
ProcessBuilder process = new ProcessBuilder(cmd);
process.directory(directory);
new Bauserver(user.getUserName() + "s Bau", owner, port, process, () -> {}).sendPlayer(p);
} }
public static void sendToBauServer(ProxiedPlayer p, UUID owner){ public static void sendToBauServer(ProxiedPlayer p, UUID owner){
@ -235,63 +197,6 @@ public class SubserverSystem {
new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/bau addmember " + p.getName())); new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/bau addmember " + p.getName()));
} }
private static List<String> serverStartCommand(String serverJar, File directory, String worldDir, String levelName, int port, String xmx, String... dParams){
List<String> 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){ private static boolean bauRunning(ProxiedPlayer p, UUID owner){
for(Subserver subserver : Subserver.getServerList()){ for(Subserver subserver : Subserver.getServerList()){
if(subserver.getType() == Servertype.BAUSERVER && ((Bauserver)subserver).getOwner().equals(owner)){ if(subserver.getType() == Servertype.BAUSERVER && ((Bauserver)subserver).getOwner().equals(owner)){
@ -302,20 +207,10 @@ public class SubserverSystem {
return false; 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); File w = new File(targetPath);
if (!w.exists() || !w.isDirectory()){ if (!w.exists() || !w.isDirectory())
try { Node.local.execute("cp", "-r", sourcePath, targetPath);
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();
}
}
} }
private static int freePort(int start){ private static int freePort(int start){

Datei anzeigen

@ -257,7 +257,7 @@ public class BauCommand extends BasicCommand {
break; break;
} }
} }
SubserverSystem.deleteFolder(world); SubserverSystem.deleteFolder(Node.local, world);
}); });
} }

Datei anzeigen

@ -19,8 +19,8 @@
package de.steamwar.bungeecore.commands; package de.steamwar.bungeecore.commands;
import de.steamwar.bungeecore.LoadEvaluation;
import de.steamwar.bungeecore.Message; import de.steamwar.bungeecore.Message;
import de.steamwar.bungeecore.Node;
import net.md_5.bungee.api.CommandSender; import net.md_5.bungee.api.CommandSender;
import java.io.BufferedReader; import java.io.BufferedReader;
@ -36,34 +36,22 @@ public class StatCommand extends BasicCommand {
@Override @Override
public void execute(CommandSender sender, String[] args) { public void execute(CommandSender sender, String[] args) {
Map<String, Integer> serverCount = new HashMap<>();
try { try {
Process process = new ProcessBuilder("ps", "x").start(); Process process = new ProcessBuilder("ps", "x").start();
process.waitFor(); new BufferedReader(new InputStreamReader(process.getInputStream())).lines().forEach(s -> {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream())); if (!s.contains("--port"))
Map<String, Integer> serverCounts = new HashMap<>();
bufferedReader.lines().forEach(s -> {
if (!s.contains("--port")) {
return; return;
} serverCount.compute(
String server = "SW"; s.contains("ssh -L") ? s.substring(s.indexOf("ssh -L") + 6).split(" ")[2] : "local",
if (s.contains("ssh -L")) { (server, count) -> (count != null ? count : 0) + 1
server = s.substring(s.indexOf("ssh -L") + 6).split(" ")[2]; );
}
serverCounts.put(server, serverCounts.computeIfAbsent(server, s1 -> 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) { } catch (Exception e) {
throw new SecurityException(e.getMessage(), e); throw new SecurityException(e.getMessage(), e);
} }
Node.forEach(node -> Message.send("STAT_SERVER", sender, node.getName(), node.getLoad(), serverCount.getOrDefault(node.getName(), 0)));
} }
} }

Datei anzeigen

@ -40,27 +40,27 @@ public class Statement {
Statement.user = user; Statement.user = user;
Statement.password = password; Statement.password = password;
try { try {
con = DriverManager.getConnection(url + "?autoreconnect=true", user, password); con = DriverManager.getConnection(url + "?autoreconnect=true&useServerPrepStmts=true", user, password);
} catch (SQLException e) { } catch (SQLException e) {
ProxyServer.getInstance().stop(); ProxyServer.getInstance().stop();
throw new SecurityException("Could not start SQL-Connection", e); throw new SecurityException("Could not start SQL-Connection", e);
} }
} }
private static void reset(SQLException e) { private static void reset() {
BungeeCore.get().getLogger().log(Level.WARNING, "SQL Exception thrown", e);
close(); close();
connect(url, user, password); connect(url, user, password);
try { try {
for (Statement statement : statements) { for (Statement statement : statements) {
statement.init(); statement.init();
} }
} catch (SQLException ex) { } catch (SQLException e) {
throw new SecurityException("Could not reprepare SQL Statements", ex); throw new SecurityException("Could not reprepare SQL statements", e);
} }
} }
public static void close() { public static void close() {
synchronized (statements) {
for (Statement statement : statements) { for (Statement statement : statements) {
try { try {
statement.st.close(); statement.st.close();
@ -72,7 +72,16 @@ public class Statement {
try { try {
con.close(); con.close();
} catch (SQLException e) { } catch (SQLException e) {
BungeeCore.log("Could not close SQL-Connection", 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;
} }
} }
@ -85,15 +94,16 @@ public class Statement {
try { try {
init(); init();
} catch (SQLException e) { } catch (SQLException e) {
reset(e); throw new SecurityException("Could not init SQL statement", e);
} }
} }
private synchronized void init() throws SQLException { private void init() throws SQLException {
st = con.prepareStatement(sql); st = con.prepareStatement(sql);
} }
<T> T select(ResultSetUser<T> user, Object... objects) { <T> T select(ResultSetUser<T> user, Object... objects) {
synchronized (statements) {
return prepare(() -> { return prepare(() -> {
ResultSet rs = st.executeQuery(); ResultSet rs = st.executeQuery();
T result = user.use(rs); T result = user.use(rs);
@ -101,23 +111,21 @@ public class Statement {
return result; return result;
}, objects); }, objects);
} }
void update(Object... objects) {
prepare(st::executeUpdate, objects);
} }
private synchronized <T> T prepare(SQLRunnable<T> runnable, Object... objects) { void update(Object... objects) {
synchronized (statements) {
prepare(st::executeUpdate, objects);
}
}
private <T> T prepare(SQLRunnable<T> runnable, Object... objects) {
try { try {
setObjects(objects); setObjects(objects);
return runnable.run(); return runnable.run();
} catch (SQLException e) { } catch (SQLException e) {
reset(e); reset();
try { throw new SecurityException("Could not execute SQL statement", e);
setObjects(objects);
return runnable.run();
} catch (SQLException ex) {
throw new SecurityException("Could not execute SQL statement", ex);
}
} }
} }

Datei anzeigen

@ -107,8 +107,7 @@ MOD_YELLOW_PLUR=§7Deaktiviere die Mods\n§e{0}\n§7um weiter auf §eSteam§8War
#Various commands #Various commands
ALERT=§f{0} ALERT=§f{0}
STAT_SERVER=§7Server §f{0} - §7Ram §f{1} §7CPU §f{2} §7Server Count §f{3} STAT_SERVER=§7Server §e{0}§8: §7Load §e{1} §7Serveranzahl §e{2}
NO_STATS=§7Kein Bau oder Fight Server gestartet
#Ban&Mute-Command #Ban&Mute-Command
BAN_TEAM_BANNED={0} §c{1} wurde von {2} {3} gebannt. §f§lGrund: §f{4} BAN_TEAM_BANNED={0} §c{1} wurde von {2} {3} gebannt. §f§lGrund: §f{4}

6
steamwarci.yml Normale Datei
Datei anzeigen

@ -0,0 +1,6 @@
build:
- "ln -s /home/gitea/lib"
- "mvn package -B"
artifacts:
"/binarys/bungeecore.jar": "target/bungeecore.jar"