geforkt von SteamWar/BungeeCore
Merge pull request 'Overload protection' (#429) from overloadProtection into master
Reviewed-on: SteamWar/BungeeCore#429 Reviewed-by: YoyoNow <jwsteam@nidido.de>
Dieser Commit ist enthalten in:
Commit
150cf78607
@ -69,6 +69,7 @@ public class BungeeCore extends Plugin {
|
|||||||
public static final Map<String, String> serverPermissions = new HashMap<>();
|
public static final Map<String, String> serverPermissions = new HashMap<>();
|
||||||
public static final Map<String, String> commands = new HashMap<>();
|
public static final Map<String, String> commands = new HashMap<>();
|
||||||
|
|
||||||
|
public static Node local;
|
||||||
private ErrorLogger errorLogger;
|
private ErrorLogger errorLogger;
|
||||||
private TablistManager tablistManager;
|
private TablistManager tablistManager;
|
||||||
|
|
||||||
@ -110,9 +111,8 @@ public class BungeeCore extends Plugin {
|
|||||||
new Fabric();
|
new Fabric();
|
||||||
new SubserverProtocolFixer();
|
new SubserverProtocolFixer();
|
||||||
|
|
||||||
new Node.LocalNode();
|
local = new Node.LocalNode();
|
||||||
//new Node.RemoteNode("lx");
|
//new Node.RemoteNode("lx");
|
||||||
//new Node.RemoteNode("az");
|
|
||||||
|
|
||||||
commands.put("/tp", null);
|
commands.put("/tp", null);
|
||||||
commands.put("/bc", null);
|
commands.put("/bc", null);
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
package de.steamwar.bungeecore;
|
package de.steamwar.bungeecore;
|
||||||
|
|
||||||
|
import net.md_5.bungee.BungeeCord;
|
||||||
import net.md_5.bungee.api.ProxyServer;
|
import net.md_5.bungee.api.ProxyServer;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
@ -30,7 +31,6 @@ import java.util.logging.Level;
|
|||||||
public abstract class Node {
|
public abstract class Node {
|
||||||
|
|
||||||
private static final List<String> 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 List<String> 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 Set<String> JAVA_8 = new HashSet<>();
|
private static final Set<String> JAVA_8 = new HashSet<>();
|
||||||
static {
|
static {
|
||||||
JAVA_8.add("paper-1.8.8.jar");
|
JAVA_8.add("paper-1.8.8.jar");
|
||||||
@ -40,43 +40,57 @@ public abstract class Node {
|
|||||||
JAVA_8.add("spigot-1.10.2.jar");
|
JAVA_8.add("spigot-1.10.2.jar");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final long MIN_FREE_MEM = 4 * 1024 * 1024L; // 4 GiB
|
||||||
|
private static final double MAX_LOAD = 0.8;
|
||||||
|
|
||||||
private static final List<Node> nodes = new ArrayList<>();
|
private static final List<Node> nodes = new ArrayList<>();
|
||||||
public static Node local = null;
|
|
||||||
|
|
||||||
public static Node getNode() {
|
public static Node getNode() {
|
||||||
Node node = local;
|
for(Node node : nodes) {
|
||||||
double minLoad = local.getLoad();
|
if(node.belowLoadLimit)
|
||||||
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;
|
return node;
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public static void forEach(Consumer<Node> consumer) {
|
public static void forEach(Consumer<Node> consumer) {
|
||||||
consumer.accept(local);
|
|
||||||
synchronized (nodes) {
|
|
||||||
nodes.forEach(consumer);
|
nodes.forEach(consumer);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public abstract ProcessBuilder startServer(String serverJar, File directory, String worldDir, String levelName, int port, String xmx, String... dParams);
|
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();
|
protected abstract ProcessBuilder prepareExecution(String... command);
|
||||||
public abstract double getLoad();
|
protected abstract void calcLoadLimit();
|
||||||
|
|
||||||
|
protected final String hostname;
|
||||||
|
protected volatile boolean belowLoadLimit = true;
|
||||||
|
|
||||||
|
private long previousCpuLoaded = 0;
|
||||||
|
private long previousCpuTotal = 0;
|
||||||
|
|
||||||
|
protected Node(String hostname) {
|
||||||
|
this.hostname = hostname;
|
||||||
|
nodes.add(this);
|
||||||
|
BungeeCord.getInstance().getScheduler().schedule(BungeeCore.get(), this::calcLoadLimit, 1, 2, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void execute(String... command) {
|
||||||
|
try {
|
||||||
|
prepareExecution(command).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 boolean belowLoadLimit() {
|
||||||
|
return belowLoadLimit;
|
||||||
|
}
|
||||||
|
public String getName() {
|
||||||
|
return hostname;
|
||||||
|
}
|
||||||
|
|
||||||
protected void constructServerstart(File directory, List<String> cmd, String serverJar, String worldDir, String levelName, int port, String xmx, String... dParams) {
|
protected void constructServerstart(File directory, List<String> cmd, String serverJar, String worldDir, String levelName, int port, String xmx, String... dParams) {
|
||||||
if (JAVA_8.contains(serverJar))
|
if (JAVA_8.contains(serverJar))
|
||||||
@ -106,26 +120,31 @@ public abstract class Node {
|
|||||||
cmd.add("nogui");
|
cmd.add("nogui");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void execute(ProcessBuilder builder) {
|
protected void calcLoadLimit(BufferedReader stat, BufferedReader meminfo) throws IOException {
|
||||||
try {
|
String[] cpuline = stat.readLine().split(" "); // 0-1: prefix, 2: user, 3: nice, 4: system, 5: idle, 6: iowait, 7: irq, 8: softirq, 9: steal, 10: guest, 11: guest_nice
|
||||||
builder.start().waitFor();
|
long cpuLoaded = Long.parseLong(cpuline[2]) + Long.parseLong(cpuline[4]) + Long.parseLong(cpuline[6]) + Long.parseLong(cpuline[7]) + Long.parseLong(cpuline[8]) + Long.parseLong(cpuline[9]) + Long.parseLong(cpuline[10]) + Long.parseLong(cpuline[11]);
|
||||||
} catch (IOException e) {
|
long cpuTotal = cpuLoaded + Long.parseLong(cpuline[3]) + Long.parseLong(cpuline[5]);
|
||||||
throw new SecurityException("Could not execute command", e);
|
|
||||||
} catch (InterruptedException e) {
|
cpuLoaded -= previousCpuLoaded;
|
||||||
ProxyServer.getInstance().getLogger().log(Level.SEVERE, "Interrupted during execution", e);
|
cpuTotal -= previousCpuTotal;
|
||||||
Thread.currentThread().interrupt();
|
previousCpuLoaded += cpuLoaded;
|
||||||
|
previousCpuTotal += cpuTotal;
|
||||||
|
|
||||||
|
String line = meminfo.readLine();
|
||||||
|
while(!line.startsWith("MemAvailable")) {
|
||||||
|
line = meminfo.readLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
long availableMem = Long.parseLong(line.replaceAll(" +", " ").split(" ")[1]);
|
||||||
|
belowLoadLimit = cpuLoaded / (double)cpuTotal <= MAX_LOAD && availableMem >= MIN_FREE_MEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class LocalNode extends Node {
|
public static class LocalNode extends Node {
|
||||||
private static final File meminfo = new File("/proc/meminfo");
|
private static final File MEMINFO = new File("/proc/meminfo");
|
||||||
private static final File loadavg = new File("/proc/loadavg");
|
private static final File STAT = new File("/proc/stat");
|
||||||
|
|
||||||
private final int cores;
|
|
||||||
|
|
||||||
public LocalNode() {
|
public LocalNode() {
|
||||||
this.cores = Runtime.getRuntime().availableProcessors();
|
super("sw");
|
||||||
local = this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -138,74 +157,28 @@ public abstract class Node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(String... command) {
|
protected void calcLoadLimit() {
|
||||||
execute(new ProcessBuilder(command));
|
try (BufferedReader loadavg = new BufferedReader(new InputStreamReader(new FileInputStream(STAT)))) {
|
||||||
|
try (BufferedReader meminfo = new BufferedReader(new InputStreamReader(new FileInputStream(MEMINFO)))) {
|
||||||
|
calcLoadLimit(loadavg, meminfo);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
BungeeCore.get().getLogger().log(Level.SEVERE, "Could not read local load", e);
|
||||||
|
belowLoadLimit = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
protected ProcessBuilder prepareExecution(String... command) {
|
||||||
return "local";
|
return new ProcessBuilder(command);
|
||||||
}
|
|
||||||
|
|
||||||
@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 {
|
public static class RemoteNode extends Node {
|
||||||
private final int cores;
|
|
||||||
private final String remote;
|
|
||||||
|
|
||||||
public RemoteNode(String remote) {
|
public RemoteNode(String hostname) {
|
||||||
this.remote = remote;
|
super(hostname);
|
||||||
|
BungeeCore.get().getLogger().log(Level.INFO, "Added node " + hostname);
|
||||||
//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
|
@Override
|
||||||
@ -214,7 +187,7 @@ public abstract class Node {
|
|||||||
cmd.add("ssh");
|
cmd.add("ssh");
|
||||||
cmd.add("-L");
|
cmd.add("-L");
|
||||||
cmd.add(port + ":localhost:" + port);
|
cmd.add(port + ":localhost:" + port);
|
||||||
cmd.add(remote);
|
cmd.add(hostname);
|
||||||
cmd.add("cd");
|
cmd.add("cd");
|
||||||
cmd.add(directory.getPath());
|
cmd.add(directory.getPath());
|
||||||
cmd.add(";");
|
cmd.add(";");
|
||||||
@ -223,43 +196,30 @@ public abstract class Node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(String... command) {
|
protected ProcessBuilder prepareExecution(String... command) {
|
||||||
List<String> cmd = new ArrayList<>();
|
List<String> cmd = new ArrayList<>();
|
||||||
cmd.add("ssh");
|
cmd.add("ssh");
|
||||||
cmd.add(remote);
|
cmd.add(hostname);
|
||||||
cmd.addAll(Arrays.asList(command));
|
cmd.addAll(Arrays.asList(command));
|
||||||
execute(new ProcessBuilder(cmd));
|
return new ProcessBuilder(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
protected void calcLoadLimit() {
|
||||||
return remote;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public double getLoad() {
|
|
||||||
Process process;
|
|
||||||
try {
|
try {
|
||||||
process = new ProcessBuilder("ssh", remote, "cat /proc/loadavg;cat /proc/meminfo").start();
|
Process process = prepareExecution("cat /proc/stat /proc/meminfo").start();
|
||||||
if(!process.waitFor(1, TimeUnit.SECONDS))
|
if(process.waitFor(1, TimeUnit.SECONDS))
|
||||||
return Double.POSITIVE_INFINITY;
|
throw new IOException(hostname + " timeout");
|
||||||
|
try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
|
||||||
|
calcLoadLimit(reader, reader);
|
||||||
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
BungeeCore.get().getLogger().log(Level.SEVERE, "Could starting process to read load", e);
|
if(belowLoadLimit)
|
||||||
return Double.POSITIVE_INFINITY;
|
BungeeCore.get().getLogger().log(Level.SEVERE, "Could read remote load", e);
|
||||||
|
belowLoadLimit = false;
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
return Double.POSITIVE_INFINITY;
|
belowLoadLimit = false;
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import de.steamwar.bungeecore.sql.EventFight;
|
|||||||
import de.steamwar.bungeecore.sql.SteamwarUser;
|
import de.steamwar.bungeecore.sql.SteamwarUser;
|
||||||
import de.steamwar.bungeecore.sql.Team;
|
import de.steamwar.bungeecore.sql.Team;
|
||||||
import de.steamwar.bungeecore.sql.Tutorial;
|
import de.steamwar.bungeecore.sql.Tutorial;
|
||||||
|
import de.steamwar.messages.ChatSender;
|
||||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -67,7 +68,7 @@ public class ServerStarter {
|
|||||||
|
|
||||||
public ServerStarter event(EventFight eventFight) {
|
public ServerStarter event(EventFight eventFight) {
|
||||||
arena(eventFight.getSpielmodus(), eventFight.getMap());
|
arena(eventFight.getSpielmodus(), eventFight.getMap());
|
||||||
node = Node.local;
|
node = BungeeCore.local;
|
||||||
worldDir = EVENT_PATH;
|
worldDir = EVENT_PATH;
|
||||||
worldCleanup = () -> {};
|
worldCleanup = () -> {};
|
||||||
arguments.put("fightID", String.valueOf(eventFight.getFightID()));
|
arguments.put("fightID", String.valueOf(eventFight.getFightID()));
|
||||||
@ -246,8 +247,15 @@ public class ServerStarter {
|
|||||||
int port = portrange.freePort();
|
int port = portrange.freePort();
|
||||||
String serverName = serverNameProvider.apply(port);
|
String serverName = serverNameProvider.apply(port);
|
||||||
|
|
||||||
if(node == null)
|
if(node == null) {
|
||||||
node = Node.getNode();
|
node = Node.getNode();
|
||||||
|
if(node == null) {
|
||||||
|
for (ProxiedPlayer p : playersToSend)
|
||||||
|
ChatSender.of(p).system("SERVER_START_OVERLOAD");
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
if(worldName == null)
|
if(worldName == null)
|
||||||
worldName = serverToWorldName(serverName);
|
worldName = serverToWorldName(serverName);
|
||||||
|
|
||||||
|
@ -261,7 +261,7 @@ public class BauCommand extends BasicCommand {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SubserverSystem.deleteFolder(Node.local, world);
|
SubserverSystem.deleteFolder(BungeeCore.local, world);
|
||||||
Message.send("BAU_DELETE_DELETED", player);
|
Message.send("BAU_DELETE_DELETED", player);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -20,21 +20,13 @@
|
|||||||
package de.steamwar.bungeecore.commands;
|
package de.steamwar.bungeecore.commands;
|
||||||
|
|
||||||
import de.steamwar.bungeecore.*;
|
import de.steamwar.bungeecore.*;
|
||||||
import de.steamwar.bungeecore.listeners.mods.ModLoaderBlocker;
|
|
||||||
import de.steamwar.bungeecore.sql.IgnoreSystem;
|
import de.steamwar.bungeecore.sql.IgnoreSystem;
|
||||||
import de.steamwar.command.SWCommand;
|
import de.steamwar.command.SWCommand;
|
||||||
import de.steamwar.command.TypeMapper;
|
|
||||||
import de.steamwar.command.TypeValidator;
|
import de.steamwar.command.TypeValidator;
|
||||||
import net.md_5.bungee.BungeeCord;
|
|
||||||
import net.md_5.bungee.api.CommandSender;
|
|
||||||
import net.md_5.bungee.api.ProxyServer;
|
|
||||||
import net.md_5.bungee.api.chat.ClickEvent;
|
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.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import static de.steamwar.bungeecore.Storage.challenges;
|
import static de.steamwar.bungeecore.Storage.challenges;
|
||||||
|
|
||||||
@ -52,8 +44,10 @@ public class ChallengeCommand extends SWCommand {
|
|||||||
challenges.remove(p);
|
challenges.remove(p);
|
||||||
|
|
||||||
Subserver arena = new ServerStarter().arena(mode, map).blueLeader(player).redLeader(target).start();
|
Subserver arena = new ServerStarter().arena(mode, map).blueLeader(player).redLeader(target).start();
|
||||||
|
if(arena != null) {
|
||||||
Message.broadcast("CHALLENGE_BROADCAST", "CHALLENGE_BROADCAST_HOVER",
|
Message.broadcast("CHALLENGE_BROADCAST", "CHALLENGE_BROADCAST_HOVER",
|
||||||
new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/arena " + arena.getServer().getName()), mode.getDisplayName(), p.getName(), target.getName());
|
new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/arena " + arena.getServer().getName()), mode.getDisplayName(), p.getName(), target.getName());
|
||||||
|
}
|
||||||
}else{
|
}else{
|
||||||
if(!challenges.containsKey(p)){
|
if(!challenges.containsKey(p)){
|
||||||
challenges.put(p, new LinkedList<>());
|
challenges.put(p, new LinkedList<>());
|
||||||
|
@ -97,7 +97,7 @@ public class FightCommand extends SWCommand {
|
|||||||
String command = precommand + mode.getChatName() + " Random";
|
String command = precommand + mode.getChatName() + " Random";
|
||||||
start.setBold(true);
|
start.setBold(true);
|
||||||
start.setColor(ChatColor.GRAY);
|
start.setColor(ChatColor.GRAY);
|
||||||
start.setText(sender.parseToLegacy("FIGHT_ARENA_RANDOM") + " ");
|
start.setText(sender.parseToPlain("FIGHT_ARENA_RANDOM") + " ");
|
||||||
start.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text("§e" + command)));
|
start.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text("§e" + command)));
|
||||||
start.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, command));
|
start.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, command));
|
||||||
current = new TextComponent();
|
current = new TextComponent();
|
||||||
@ -245,11 +245,13 @@ public class FightCommand extends SWCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Register
|
@Register
|
||||||
public void challenge(@Validator("arenaPlayer") ProxiedPlayer player, @Mapper("nonHistoricArenaMode") @OptionalValue("") @AllowNull ArenaMode arenaMode, @Mapper("arenaMap") @OptionalValue("") @AllowNull String map) {
|
public void fight(@Validator("arenaPlayer") ProxiedPlayer player, @Mapper("nonHistoricArenaMode") @OptionalValue("") @AllowNull ArenaMode arenaMode, @Mapper("arenaMap") @OptionalValue("") @AllowNull String map) {
|
||||||
createArena(player, "/fight ", true, arenaMode, map, false, (p, mode, m) -> {
|
createArena(player, "/fight ", true, arenaMode, map, false, (p, mode, m) -> {
|
||||||
Subserver arena = new ServerStarter().arena(mode, m).blueLeader(p).start();
|
Subserver arena = new ServerStarter().arena(mode, m).blueLeader(p).start();
|
||||||
|
if(arena != null) {
|
||||||
Message.broadcast("FIGHT_BROADCAST", "FIGHT_BROADCAST_HOVER"
|
Message.broadcast("FIGHT_BROADCAST", "FIGHT_BROADCAST_HOVER"
|
||||||
, new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/arena " + arena.getServer().getName()), mode.getDisplayName(), p.getName());
|
, new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/arena " + arena.getServer().getName()), mode.getDisplayName(), p.getName());
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,11 +33,13 @@ public class HistoricCommand extends SWCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Register
|
@Register
|
||||||
public void challenge(@Validator("arenaPlayer") ProxiedPlayer player, @Mapper("nonHistoricArenaMode") @OptionalValue("") @AllowNull ArenaMode arenaMode, @Mapper("arenaMap") @OptionalValue("") @AllowNull String map) {
|
public void historic(@Validator("arenaPlayer") ProxiedPlayer player, @Mapper("nonHistoricArenaMode") @OptionalValue("") @AllowNull ArenaMode arenaMode, @Mapper("arenaMap") @OptionalValue("") @AllowNull String map) {
|
||||||
FightCommand.createArena(player, "/historic ", true, arenaMode, map, true, (p, mode, m) -> {
|
FightCommand.createArena(player, "/historic ", true, arenaMode, map, true, (p, mode, m) -> {
|
||||||
Subserver arena = new ServerStarter().arena(mode, m).blueLeader(p).start();
|
Subserver arena = new ServerStarter().arena(mode, m).blueLeader(p).start();
|
||||||
|
if(arena != null) {
|
||||||
Message.broadcast("HISTORIC_BROADCAST", "HISTORIC_BROADCAST_HOVER",
|
Message.broadcast("HISTORIC_BROADCAST", "HISTORIC_BROADCAST_HOVER",
|
||||||
new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/arena " + arena.getServer().getName()), mode.getDisplayName(), p.getName());
|
new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/arena " + arena.getServer().getName()), mode.getDisplayName(), p.getName());
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,6 +52,6 @@ public class StatCommand extends SWCommand {
|
|||||||
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)));
|
Node.forEach(node -> Message.send("STAT_SERVER", sender, node.getName(), node.belowLoadLimit(), serverCount.getOrDefault(node.getName(), 0)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -156,8 +156,8 @@ public class TutorialCommand extends SWCommand {
|
|||||||
File tutorialWorld = tutorial.world();
|
File tutorialWorld = tutorial.world();
|
||||||
|
|
||||||
if (tutorialWorld.exists())
|
if (tutorialWorld.exists())
|
||||||
SubserverSystem.deleteFolder(Node.local, tutorialWorld.getPath());
|
SubserverSystem.deleteFolder(BungeeCore.local, tutorialWorld.getPath());
|
||||||
ServerStarter.copyWorld(Node.local, tempWorld.getPath(), tutorialWorld.getPath());
|
ServerStarter.copyWorld(BungeeCore.local, tempWorld.getPath(), tutorialWorld.getPath());
|
||||||
Message.send("TUTORIAL_CREATED", player);
|
Message.send("TUTORIAL_CREATED", player);
|
||||||
}, 1, TimeUnit.SECONDS);
|
}, 1, TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
package de.steamwar.bungeecore.sql;
|
package de.steamwar.bungeecore.sql;
|
||||||
|
|
||||||
import de.steamwar.bungeecore.Node;
|
import de.steamwar.bungeecore.BungeeCore;
|
||||||
import de.steamwar.bungeecore.ServerStarter;
|
import de.steamwar.bungeecore.ServerStarter;
|
||||||
import de.steamwar.bungeecore.SubserverSystem;
|
import de.steamwar.bungeecore.SubserverSystem;
|
||||||
|
|
||||||
@ -124,7 +124,7 @@ public class Tutorial {
|
|||||||
|
|
||||||
public void delete() {
|
public void delete() {
|
||||||
delete.update(id);
|
delete.update(id);
|
||||||
SubserverSystem.deleteFolder(Node.local, world().getPath());
|
SubserverSystem.deleteFolder(BungeeCore.local, world().getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
public File world() {
|
public File world() {
|
||||||
|
@ -18,6 +18,8 @@ DEV_UNKNOWN_SERVER=§cPlease specify a dev server.
|
|||||||
|
|
||||||
DISABLED=§cCurrently disabled.
|
DISABLED=§cCurrently disabled.
|
||||||
|
|
||||||
|
SERVER_START_OVERLOAD=§cServer start cancelled due to overload. Please try again later.
|
||||||
|
|
||||||
#ModLoader blocker
|
#ModLoader blocker
|
||||||
MODLOADER_INSTALLED=§7You play with §e{0} §7client. Therefore you can't join arenas.
|
MODLOADER_INSTALLED=§7You play with §e{0} §7client. Therefore you can't join arenas.
|
||||||
MODLOADER_INSTALLED_FABRIC=§7You play with §e{0} §7client. You can join arenas only with the FabricModSender https://steamwar.de/downloads installed.
|
MODLOADER_INSTALLED_FABRIC=§7You play with §e{0} §7client. You can join arenas only with the FabricModSender https://steamwar.de/downloads installed.
|
||||||
@ -112,7 +114,7 @@ MOD_YELLOW_PLUR=§7Deactivate the mods\n§e{0}\n§7to continue playing on §eSte
|
|||||||
|
|
||||||
#Various commands
|
#Various commands
|
||||||
ALERT=§f{0}
|
ALERT=§f{0}
|
||||||
STAT_SERVER=§7Server §e{0}§8: §7Load §e{1} §7Server count §e{2}
|
STAT_SERVER=§7Server §e{0}§8: §7Below limit §e{1} §7Server count §e{2}
|
||||||
|
|
||||||
#Ban&Mute-Command
|
#Ban&Mute-Command
|
||||||
PUNISHMENT_USAGE=§8/§7{0} §8[§eplayer§8] [§edd§8.§emm§8.§eyyyy §7or §edd§8.§emm§8.§eyyyy§8_§ehh§8:§emm §7or §eperma§8] [§ereason§8]
|
PUNISHMENT_USAGE=§8/§7{0} §8[§eplayer§8] [§edd§8.§emm§8.§eyyyy §7or §edd§8.§emm§8.§eyyyy§8_§ehh§8:§emm §7or §eperma§8] [§ereason§8]
|
||||||
|
@ -14,6 +14,8 @@ DEV_UNKNOWN_SERVER=§cBitte gib einen DevServer an.
|
|||||||
|
|
||||||
DISABLED=§cDerzeit deaktiviert.
|
DISABLED=§cDerzeit deaktiviert.
|
||||||
|
|
||||||
|
SERVER_START_OVERLOAD=§cDer Serverstart wurde aufgrund von Überlastung abgebrochen. Versuche es später erneut.
|
||||||
|
|
||||||
#ModLoader blocker
|
#ModLoader blocker
|
||||||
MODLOADER_INSTALLED=§7Du spielst mit §e{0} §7Client. Daher kannst du keinen Arenen beitreten.
|
MODLOADER_INSTALLED=§7Du spielst mit §e{0} §7Client. Daher kannst du keinen Arenen beitreten.
|
||||||
MODLOADER_INSTALLED_FABRIC=§7Du spielst mit §e{0} §7Client. Nur mit dem FabricModSender https://steamwar.de/downloads kannst du Arenen beitreten.
|
MODLOADER_INSTALLED_FABRIC=§7Du spielst mit §e{0} §7Client. Nur mit dem FabricModSender https://steamwar.de/downloads kannst du Arenen beitreten.
|
||||||
@ -97,7 +99,7 @@ MOD_YELLOW_SING=§7Deaktiviere den Mod §e{0}§7, um weiter auf §eSteam§8War
|
|||||||
MOD_YELLOW_PLUR=§7Deaktiviere die Mods\n§e{0}\n§7um weiter auf §eSteam§8War §7spielen zu können.
|
MOD_YELLOW_PLUR=§7Deaktiviere die Mods\n§e{0}\n§7um weiter auf §eSteam§8War §7spielen zu können.
|
||||||
|
|
||||||
#Various commands
|
#Various commands
|
||||||
STAT_SERVER=§7Server §e{0}§8: §7Load §e{1} §7Serveranzahl §e{2}
|
STAT_SERVER=§7Server §e{0}§8: §7Startfähig §e{1} §7Serveranzahl §e{2}
|
||||||
|
|
||||||
#Ban&Mute-Command
|
#Ban&Mute-Command
|
||||||
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]
|
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]
|
||||||
|
@ -107,6 +107,14 @@ public interface ChatSender {
|
|||||||
return new TextComponent(parse(prefixed, message));
|
return new TextComponent(parse(prefixed, message));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default String parseToPlain(String format, Object... params) {
|
||||||
|
return parseToPlain(new Message(format, params));
|
||||||
|
}
|
||||||
|
|
||||||
|
default String parseToPlain(Message message) {
|
||||||
|
return parseToComponent(false, message).toPlainText();
|
||||||
|
}
|
||||||
|
|
||||||
default String parseToLegacy(String format, Object... params) {
|
default String parseToLegacy(String format, Object... params) {
|
||||||
return parseToLegacy(new Message(format, params));
|
return parseToLegacy(new Message(format, params));
|
||||||
}
|
}
|
||||||
|
In neuem Issue referenzieren
Einen Benutzer sperren