diff --git a/src/de/steamwar/bungeecore/SubserverSystem.java b/src/de/steamwar/bungeecore/SubserverSystem.java index 46d5b139..2ba494a6 100644 --- a/src/de/steamwar/bungeecore/SubserverSystem.java +++ b/src/de/steamwar/bungeecore/SubserverSystem.java @@ -9,11 +9,16 @@ import net.md_5.bungee.api.connection.ProxiedPlayer; import java.io.File; import java.io.IOException; -import java.util.UUID; +import java.util.*; public class SubserverSystem { private SubserverSystem(){} - private static final String MC_SCRIPT = "/home/minecraft/mc"; + private static final String BACKBONE = "/home/minecraft/backbone/"; + private static final List JVM_ARGS = Arrays.asList("-Dlog4j.configurationFile=log4j2.xml", "-server", "-Xms128M", "-XX:ThreadPriorityPolicy=42", "-XX:+TieredCompilation", "-XX:TargetSurvivorRatio=90", "-XX:SurvivorRatio=8", "-XX:MaxTenuringThreshold=15", "-XX:+UnlockExperimentalVMOptions", "-XX:+UseBiasedLocking", "-XX:UseSSE=3", "-XX:+UseCodeCacheFlushing", "-XX:+UseThreadPriorities", "-XX:+UseFastAccessorMethods", "-XX:+AggressiveOpts", "-XX:+ReduceSignalUsage", "-XX:+UseInterpreter", "-XX:+UseFastEmptyMethods", "-XX:+UseSharedSpaces", "-XX:AllocatePrefetchStyle=1", "-XX:+AlwaysCompileLoopMethods", "-XX:SharedReadOnlySize=30m", "-XX:+UseConcMarkSweepGC", "-XX:+RewriteFrequentPairs", "-XX:+OptimizeStringConcat", "-XX:+CMSCleanOnEnter", "-XX:+UseInlineCaches"); + 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 String BINARY_PATH = "/binarys/"; public static void sendDeniedMessage(ProxiedPlayer p, UUID owner){ ProxiedPlayer o = ProxyServer.getInstance().getPlayer(owner); @@ -26,103 +31,218 @@ public class SubserverSystem { new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/bau addmember " + p.getName())); } - public static Subserver startArena(ArenaMode modus, String map){ + /** + * This function starts every arena (even test- and eventarenas). + * + * @param modus + * This has to be a valid arena mode + * + * @param map + * This String must be the internal map name of the selected map + * + * @param eventFightID + * For a normal arena: 0 + * For a test arena: -1 + * For an event arena: EventFightID of the fight + * + * @param serverName + * The name of the server (for event and test arenas) + * or null (autogenerated arena name modus.getDisplayName() + number) + * + * @param mapName + * The name of the map copy the server runs on (for event and test arenas) + * or null (autogenerated map name equals server name) + * + * @param player1 + * For event and normal arenas: The UUID of the designated leader for the blue team + * or null (no designated leader). + * For test arenas: The owner's UUID of the test arena (disables normal function). + * + * @param player2 + * For event, test and normal arenas: The UUID of the designated leader for the red team + * or null (no designated leader). + * + * @return + * The new started subserver. + */ + public static Subserver startArena(ArenaMode modus, String map, int eventFightID, String serverName, String mapName, UUID player1, UUID player2){ + //Generate missing parameters int port = freePort(2500); - String serverName = modus.getDisplayName() + (port - 2500); - return new Subserver(Servertype.ARENA, serverName, port, () -> { - try { - new ProcessBuilder("rm", "-r", "/home/minecraft/backbone/arenaserver/" + serverName).start(); - } catch (IOException e) { - throw new SecurityException("Could not clean up folder", e); - } - }, MC_SCRIPT, "-a", modus.getInternalName(), serverName, Integer.toString(port), map, "0", modus.serverJar()); + if(serverName == null) + serverName = modus.getDisplayName() + (port - 2500); + if(mapName == null) + mapName = serverName; + + String worldDir; + if(eventFightID > 0) + worldDir = ARENA_PATH; + else + worldDir = EVENT_PATH; + + //Copy world + try { + new ProcessBuilder("cp", "-r", SERVER_PATH + modus.getInternalName() + "/" + map, worldDir + mapName).start().waitFor(); + } catch (IOException | InterruptedException e) { + throw new SecurityException("Could not copy folder", e); + } + + //Generate launch command + List cmd = new LinkedList<>(); + cmd.add("java"); + cmd.add("-DlogPath=" + serverName); + cmd.add("-DfightID=" + eventFightID); + if(player1 != null && eventFightID != -1) + cmd.add("-DblueLeader=" + player1.toString()); + if(player2 != null) + cmd.add("-DredLeader=" + player2.toString()); + cmd.add("-Xmx2G"); + cmd.addAll(JVM_ARGS); + cmd.add("-jar"); + cmd.add(BINARY_PATH + modus.serverJar()); + cmd.add("--log-strip-color"); + cmd.add("--world-dir"); + cmd.add(worldDir); + cmd.add("--level-name"); + cmd.add(mapName); + cmd.add("--port"); + cmd.add(String.valueOf(port)); + + //Start server + ProcessBuilder process = new ProcessBuilder(cmd); + process.directory(new File(SERVER_PATH, modus.getInternalName())); + + String finalMapName = mapName; + if(eventFightID == -1) + return new Bauserver(serverName, player1, port, process, () -> { + try { + new ProcessBuilder("rm", "-r", ARENA_PATH + finalMapName).start(); + } catch (IOException e) { + throw new SecurityException("Could not clean up folder", e); + } + }); + else + return new Subserver(Servertype.ARENA, serverName, port, process, () -> { + if(eventFightID > 0) + return; + + try { + new ProcessBuilder("rm", "-r", ARENA_PATH + finalMapName).start(); + } catch (IOException e) { + throw new SecurityException("Could not clean up folder", e); + } + }); + } + + public static Subserver startArena(ArenaMode modus, String map){ + return startArena(modus, map, 0, null, null, null, null); } public static Subserver startEventArena(EventFight eventFight, String serverName){ - int port = freePort(2500); - - return new Subserver(Servertype.ARENA, serverName, port, - MC_SCRIPT, "-a", eventFight.getSpielmodus().getInternalName(), serverName.replace(' ', '_') + eventFight.getStartTime().toLocalDateTime().format(EventCommand.TIME_FORMAT), Integer.toString(port), eventFight.getMap(), Integer.toString(eventFight.getFightID()), eventFight.getSpielmodus().serverJar()); + return startArena( + eventFight.getSpielmodus(), + eventFight.getMap(), + eventFight.getFightID(), + serverName, + serverName.replace(' ', '_') + eventFight.getStartTime().toLocalDateTime().format(EventCommand.TIME_FORMAT), + null, + null); } public static void sendToTestServer(ProxiedPlayer p, ArenaMode m, String map){ - int port = freePort(4000); - - new Bauserver(p.getName() + "s Bau", p.getUniqueId(), port, () -> { - try { - new ProcessBuilder("rm", "-r", "/home/minecraft/backbone/arenaserver/" + p.getName()).start(); - } catch (IOException e) { - throw new SecurityException("Could not clean up folder", e); - } - }, MC_SCRIPT, "-a", m.getInternalName(), p.getName(), Integer.toString(port), map, "-1", m.serverJar()).sendPlayer(p); + startArena(m, map, -1, p.getName() + "s Bau", p.getName(), p.getUniqueId(), null); } public static void sendToBauServer(ProxiedPlayer p, UUID owner){ - for(Subserver subserver : Subserver.getServerList()){ - if(subserver.getType() == Servertype.BAUSERVER && ((Bauserver)subserver).getOwner().equals(owner)){ - subserver.sendPlayer(p); - return; - } - } - - File w = new File(BungeeCore.WORLD_FOLDER + owner); - if (!w.exists() || !w.isDirectory()){ - try { - Process pr; - ProcessBuilder pb = new ProcessBuilder( - "cp", "-r", BungeeCore.BAUWELT_PROTOTYP, BungeeCore.WORLD_FOLDER + owner); - pr = pb.start(); - pr.waitFor(); - } catch (IOException e) { - BungeeCore.log("Could not create Bauwelt", e); - BungeeCore.send(p, BungeeCore.CHAT_PREFIX + "§cDas Erstellen der Welt ist fehlgeschlagen."); - return; - } catch (InterruptedException e){ - BungeeCore.log("Could not create Bauwelt", e); - BungeeCore.send(p, BungeeCore.CHAT_PREFIX + "§cDas Erstellen der Welt ist fehlgeschlagen."); - Thread.currentThread().interrupt(); - } - } + if(bauRunning(p, owner)) + return; SteamwarUser user = SteamwarUser.get(owner); + copyBauwelt(p, BungeeCore.BAUWELT_PROTOTYP, BungeeCore.WORLD_FOLDER + owner.toString()); int port = freePort(4000); - new Bauserver(user.getUserName() + "s Bau", owner, port, - MC_SCRIPT, "-b", owner.toString(), Integer.toString(port)).sendPlayer(p); + //Generate launch command + List cmd = new LinkedList<>(); + cmd.add("java"); + cmd.add("-DlogPath=" + owner.toString()); + cmd.add("-Xmx256M"); + cmd.addAll(JVM_ARGS); + cmd.add("-jar"); + cmd.add(BINARY_PATH + "spigot-1.12.2.jar"); + cmd.add("--log-strip-color"); + cmd.add("--world-dir"); + cmd.add("/home/minecraft/userworlds"); + cmd.add("--level-name"); + cmd.add(owner.toString()); + cmd.add("--port"); + cmd.add(String.valueOf(port)); + + //Start server + ProcessBuilder process = new ProcessBuilder(cmd); + process.directory(new File(SERVER_PATH, "UserBau")); + + new Bauserver(user.getUserName() + "s Bau", owner, port, process, () -> {}).sendPlayer(p); } public static void sendToBau15(ProxiedPlayer p, UUID owner){ + if(bauRunning(p, owner)) + return; + + SteamwarUser user = SteamwarUser.get(owner); + copyBauwelt(p, BungeeCore.BAUWELT15, BungeeCore.USERWORLDS15 + user.getId()); + int port = freePort(4000); + + //Generate launch command + List cmd = new LinkedList<>(); + cmd.add("java"); + cmd.add("-DlogPath=" + user.getId()); + cmd.add("-Xmx384M"); + cmd.addAll(JVM_ARGS); + cmd.add("-jar"); + cmd.add(BINARY_PATH + "spigot-1.15.1.jar"); + cmd.add("--log-strip-color"); + cmd.add("--world-dir"); + cmd.add("/home/minecraft/userworlds15"); + cmd.add("--level-name"); + cmd.add(String.valueOf(user.getId())); + cmd.add("--port"); + cmd.add(String.valueOf(port)); + + //Start server + ProcessBuilder process = new ProcessBuilder(cmd); + process.directory(new File(SERVER_PATH, "Bau15")); + + new Bauserver(user.getUserName() + "s Bau", owner, port, process, () -> {}).sendPlayer(p); + } + + private static boolean bauRunning(ProxiedPlayer p, UUID owner){ for(Subserver subserver : Subserver.getServerList()){ if(subserver.getType() == Servertype.BAUSERVER && ((Bauserver)subserver).getOwner().equals(owner)){ subserver.sendPlayer(p); - return; + return true; } } + return false; + } - SteamwarUser user = SteamwarUser.get(owner); - File w = new File(BungeeCore.USERWORLDS15 + user.getId()); + private static void copyBauwelt(ProxiedPlayer p, String sourcePath, String targetPath){ + File w = new File(targetPath); if (!w.exists() || !w.isDirectory()){ try { Process pr; ProcessBuilder pb = new ProcessBuilder( - "cp", "-r", BungeeCore.BAUWELT15, BungeeCore.USERWORLDS15 + user.getId()); + "cp", "-r", sourcePath, targetPath); pr = pb.start(); pr.waitFor(); } catch (IOException e) { - BungeeCore.log("Could not create Bauwelt", e); BungeeCore.send(p, BungeeCore.CHAT_PREFIX + "§cDas Erstellen der Welt ist fehlgeschlagen."); - return; + throw new SecurityException("Could not create Bauwelt", e); } catch (InterruptedException e){ BungeeCore.log("Could not create Bauwelt", e); BungeeCore.send(p, BungeeCore.CHAT_PREFIX + "§cDas Erstellen der Welt ist fehlgeschlagen."); Thread.currentThread().interrupt(); } } - int port = freePort(4000); - - new Bauserver(user.getUserName() + "s Bau", owner, port, - MC_SCRIPT, "-n", Integer.toString(user.getId()), Integer.toString(port)).sendPlayer(p); } private static int freePort(int start){ diff --git a/src/de/steamwar/bungeecore/commands/ChallengeCommand.java b/src/de/steamwar/bungeecore/commands/ChallengeCommand.java index f58e8e82..a271435d 100644 --- a/src/de/steamwar/bungeecore/commands/ChallengeCommand.java +++ b/src/de/steamwar/bungeecore/commands/ChallengeCommand.java @@ -58,7 +58,7 @@ public class ChallengeCommand extends BasicCommand { challenges.remove(target); challenges.remove(player); - Subserver arena = SubserverSystem.startArena(mode, map); + Subserver arena = SubserverSystem.startArena(mode, map, 0, null, null, player.getUniqueId(), target.getUniqueId()); arena.sendPlayer(player); arena.sendPlayer(target); diff --git a/src/de/steamwar/bungeecore/commands/FightCommand.java b/src/de/steamwar/bungeecore/commands/FightCommand.java index 72541bf7..131ec44c 100644 --- a/src/de/steamwar/bungeecore/commands/FightCommand.java +++ b/src/de/steamwar/bungeecore/commands/FightCommand.java @@ -61,7 +61,7 @@ public class FightCommand extends BasicCommand { if(map == null) return; - Subserver arena = SubserverSystem.startArena(mode, map); + Subserver arena = SubserverSystem.startArena(mode, map, 0, null, null, player.getUniqueId(), null); arena.sendPlayer(player); TextComponent tc = new TextComponent(BungeeCore.CHAT_PREFIX + "§7Klicke §ehier§7, um §e" + mode.getDisplayName() + " §7gegen §e" + player.getName() + " §7zu §7kämpfen!"); tc.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder("§aGegen §7" + player.getName() + " §ekämpfen").create()));