Merge pull request 'Server start refactoring, Tutorial system' (#317) from tutorial into master
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
Reviewed-on: #317 Reviewed-by: YoyoNow <jwsteam@nidido.de>
Dieser Commit ist enthalten in:
Commit
95ed6925da
@ -120,10 +120,10 @@ public class BungeeCore extends Plugin {
|
|||||||
new ListCommand();
|
new ListCommand();
|
||||||
new StatCommand();
|
new StatCommand();
|
||||||
new VerifyCommand();
|
new VerifyCommand();
|
||||||
new ReplayCommand();
|
|
||||||
new GDPRQuery();
|
new GDPRQuery();
|
||||||
new PlaytimeCommand();
|
new PlaytimeCommand();
|
||||||
new ArenaCommand();
|
new ArenaCommand();
|
||||||
|
new RankCommand();
|
||||||
|
|
||||||
// Punishment Commands:
|
// Punishment Commands:
|
||||||
new PunishmentCommand("ban", Punishment.PunishmentType.Ban);
|
new PunishmentCommand("ban", Punishment.PunishmentType.Ban);
|
||||||
@ -140,7 +140,8 @@ public class BungeeCore extends Plugin {
|
|||||||
new ChallengeCommand();
|
new ChallengeCommand();
|
||||||
new HistoricCommand();
|
new HistoricCommand();
|
||||||
new CheckCommand();
|
new CheckCommand();
|
||||||
new RankCommand();
|
new ReplayCommand();
|
||||||
|
new TutorialCommand();
|
||||||
|
|
||||||
new Broadcaster();
|
new Broadcaster();
|
||||||
}else{
|
}else{
|
||||||
|
@ -64,12 +64,13 @@ public class EventStarter implements Runnable {
|
|||||||
|
|
||||||
Team blue = Team.get(next.getTeamBlue());
|
Team blue = Team.get(next.getTeamBlue());
|
||||||
Team red = Team.get(next.getTeamRed());
|
Team red = Team.get(next.getTeamRed());
|
||||||
String serverName = blue.getTeamKuerzel() + " vs " + red.getTeamKuerzel();
|
ServerStarter starter = new ServerStarter().event(next);
|
||||||
Subserver subserver = SubserverSystem.startEventArena(next, serverName);
|
|
||||||
|
|
||||||
ProxiedPlayer leiter = ProxyServer.getInstance().getPlayer(SteamwarUser.get(next.getKampfleiter()).getUuid());
|
ProxiedPlayer leiter = ProxyServer.getInstance().getPlayer(SteamwarUser.get(next.getKampfleiter()).getUuid());
|
||||||
if(leiter != null)
|
if(leiter != null)
|
||||||
SubserverSystem.sendPlayer(subserver, leiter);
|
starter.send(leiter);
|
||||||
|
|
||||||
|
Subserver subserver = starter.start();
|
||||||
|
|
||||||
eventServer.put(blue.getTeamId(), subserver);
|
eventServer.put(blue.getTeamId(), subserver);
|
||||||
eventServer.put(red.getTeamId(), subserver);
|
eventServer.put(red.getTeamId(), subserver);
|
||||||
|
272
src/de/steamwar/bungeecore/ServerStarter.java
Normale Datei
272
src/de/steamwar/bungeecore/ServerStarter.java
Normale Datei
@ -0,0 +1,272 @@
|
|||||||
|
package de.steamwar.bungeecore;
|
||||||
|
|
||||||
|
import de.steamwar.bungeecore.sql.EventFight;
|
||||||
|
import de.steamwar.bungeecore.sql.SteamwarUser;
|
||||||
|
import de.steamwar.bungeecore.sql.Team;
|
||||||
|
import de.steamwar.bungeecore.sql.Tutorial;
|
||||||
|
import net.md_5.bungee.api.ProxyServer;
|
||||||
|
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.function.BooleanSupplier;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class ServerStarter {
|
||||||
|
|
||||||
|
private static final boolean MAIN_SERVER = ProxyServer.getInstance().getConfig().getListeners().stream().anyMatch(info -> ((InetSocketAddress) info.getSocketAddress()).getPort() == 25565);
|
||||||
|
private static final Portrange BAU_PORTS = MAIN_SERVER ? new Portrange(10100, 20000) : new Portrange(2100, 2200);
|
||||||
|
private static final Portrange ARENA_PORTS = MAIN_SERVER ? new Portrange(3000, 3100) : (BungeeCore.EVENT_MODE ? new Portrange(4000, 5000) : BAU_PORTS);
|
||||||
|
|
||||||
|
private static final String BACKBONE = "/home/minecraft/";
|
||||||
|
private static final String SERVER_PATH = BACKBONE + "server/";
|
||||||
|
private static final String EVENT_PATH = BACKBONE + "event/";
|
||||||
|
public static final String TEMP_WORLD_PATH = BACKBONE + "arenaserver/";
|
||||||
|
public static final String TUTORIAL_PATH = BACKBONE + "tutorials/";
|
||||||
|
|
||||||
|
private File directory = null;
|
||||||
|
private String worldDir = null;
|
||||||
|
|
||||||
|
private Node node = null;
|
||||||
|
private String serverJar = "spigot-1.15.2.jar";
|
||||||
|
private String xmx = "768M";
|
||||||
|
private Portrange portrange = BAU_PORTS;
|
||||||
|
private Function<Integer, String> serverNameProvider = port -> node.getName() + port;
|
||||||
|
private BooleanSupplier startCondition = () -> true;
|
||||||
|
private ServerConstructor constructor = (serverName, port, builder, shutdownCallback) -> new Subserver(Servertype.ARENA, serverName, port, builder, shutdownCallback);
|
||||||
|
private Runnable worldSetup = () -> {};
|
||||||
|
private String worldName = null;
|
||||||
|
private Runnable worldCleanup = () -> {};
|
||||||
|
|
||||||
|
private final Set<ProxiedPlayer> playersToSend = new HashSet<>();
|
||||||
|
private final Map<String, String> arguments = new HashMap<>();
|
||||||
|
|
||||||
|
public ServerStarter arena(ArenaMode mode, String map) {
|
||||||
|
portrange = ARENA_PORTS;
|
||||||
|
serverNameProvider = port -> mode.getChatName() + (port - portrange.start);
|
||||||
|
serverJar = mode.serverJar();
|
||||||
|
directory = new File(SERVER_PATH, mode.getFolder());
|
||||||
|
arguments.put("config", mode.getConfig());
|
||||||
|
tempWorld(SERVER_PATH + mode.getFolder() + "/arenas/" + map);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ServerStarter event(EventFight eventFight) {
|
||||||
|
arena(eventFight.getSpielmodus(), eventFight.getMap());
|
||||||
|
node = Node.local;
|
||||||
|
worldDir = EVENT_PATH;
|
||||||
|
worldCleanup = () -> {};
|
||||||
|
arguments.put("fightID", String.valueOf(eventFight.getFightID()));
|
||||||
|
|
||||||
|
String serverName = Team.get(eventFight.getTeamBlue()).getTeamKuerzel() + " vs " + Team.get(eventFight.getTeamRed()).getTeamKuerzel();
|
||||||
|
serverNameProvider = port -> serverName;
|
||||||
|
worldName = serverToWorldName(serverName + eventFight.getStartTime().toLocalDateTime().format(DateTimeFormatter.ISO_TIME));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ServerStarter test(ArenaMode mode, String map, ProxiedPlayer owner) {
|
||||||
|
arena(mode, map);
|
||||||
|
buildWithTemp(owner);
|
||||||
|
portrange = BAU_PORTS;
|
||||||
|
arguments.put("fightID", String.valueOf(-1));
|
||||||
|
return send(owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ServerStarter blueLeader(ProxiedPlayer player) {
|
||||||
|
arguments.put("blueLeader", player.getUniqueId().toString());
|
||||||
|
return send(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ServerStarter redLeader(ProxiedPlayer player) {
|
||||||
|
arguments.put("redLeader", player.getUniqueId().toString());
|
||||||
|
return send(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ServerStarter check(int schemID) {
|
||||||
|
arguments.put("checkSchemID", String.valueOf(schemID));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ServerStarter prepare(int schemID) {
|
||||||
|
arguments.put("prepareSchemID", String.valueOf(schemID));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ServerStarter replay(int replayID) {
|
||||||
|
arguments.put("replay", String.valueOf(replayID));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ServerStarter build15(UUID owner) {
|
||||||
|
directory = new File(SERVER_PATH, "Bau15");
|
||||||
|
worldDir = BungeeCore.USERWORLDS15;
|
||||||
|
worldName = String.valueOf(SteamwarUser.get(owner).getId());
|
||||||
|
buildWithWorld(owner, BungeeCore.BAUWELT15);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ServerStarter build12(UUID owner) {
|
||||||
|
directory = new File(SERVER_PATH, "UserBau");
|
||||||
|
serverJar = "spigot-1.12.2.jar";
|
||||||
|
xmx = "256M";
|
||||||
|
worldDir = BungeeCore.WORLD_FOLDER;
|
||||||
|
worldName = owner.toString();
|
||||||
|
buildWithWorld(owner, BungeeCore.BAUWELT_PROTOTYP);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ServerStarter tutorial(ProxiedPlayer owner, Tutorial tutorial) {
|
||||||
|
directory = new File(SERVER_PATH, "Tutorial");
|
||||||
|
buildWithTemp(owner);
|
||||||
|
tempWorld(TUTORIAL_PATH + tutorial.id());
|
||||||
|
arguments.put("tutorial", String.valueOf(tutorial.id()));
|
||||||
|
return send(owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void tempWorld(String template) {
|
||||||
|
worldDir = TEMP_WORLD_PATH;
|
||||||
|
worldSetup = () -> copyWorld(node, template, worldDir + worldName);
|
||||||
|
worldCleanup = () -> SubserverSystem.deleteFolder(node, worldDir + worldName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void buildWithWorld(UUID owner, String prototype) {
|
||||||
|
build(owner);
|
||||||
|
|
||||||
|
worldSetup = () -> {
|
||||||
|
File world = new File(worldDir, worldName);
|
||||||
|
if (!world.exists())
|
||||||
|
copyWorld(node, prototype, world.getPath());
|
||||||
|
};
|
||||||
|
|
||||||
|
// Send players to existing server
|
||||||
|
startCondition = () -> {
|
||||||
|
for(Subserver subserver : Subserver.getServerList()) {
|
||||||
|
if(subserver.getType() == Servertype.BAUSERVER && ((Bauserver)subserver).getOwner().equals(owner)) {
|
||||||
|
for(ProxiedPlayer p : playersToSend)
|
||||||
|
SubserverSystem.sendPlayer(subserver, p);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private void buildWithTemp(ProxiedPlayer owner) {
|
||||||
|
build(owner.getUniqueId());
|
||||||
|
|
||||||
|
// Stop existing build server
|
||||||
|
startCondition = () -> {
|
||||||
|
if(startingBau(owner))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (Subserver subserver : Subserver.getServerList()) {
|
||||||
|
if (subserver.getType() == Servertype.BAUSERVER && ((Bauserver) subserver).getOwner().equals(owner.getUniqueId()) && subserver.hasStarted()) {
|
||||||
|
subserver.stop();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return !startingBau(owner);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private void build(UUID owner) {
|
||||||
|
constructor = (serverName, port, builder, shutdownCallback) -> new Bauserver(serverName, owner, port, builder, shutdownCallback);
|
||||||
|
serverNameProvider = port -> bauServerName(SteamwarUser.get(owner));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ServerStarter send(ProxiedPlayer player) {
|
||||||
|
playersToSend.add(player);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Subserver start() {
|
||||||
|
if(!startCondition.getAsBoolean())
|
||||||
|
return null;
|
||||||
|
|
||||||
|
int port = portrange.freePort();
|
||||||
|
String serverName = serverNameProvider.apply(port);
|
||||||
|
|
||||||
|
if(node == null)
|
||||||
|
node = Node.getNode();
|
||||||
|
if(worldName == null)
|
||||||
|
worldName = serverToWorldName(serverName);
|
||||||
|
|
||||||
|
worldSetup.run();
|
||||||
|
arguments.put("logPath", worldName);
|
||||||
|
|
||||||
|
Subserver subserver = constructor.construct(serverName, port, node.startServer(
|
||||||
|
serverJar, directory, worldDir, worldName, port, xmx, arguments.entrySet().stream().map(entry -> entry.getKey() + "=" + entry.getValue()).toArray(String[]::new)
|
||||||
|
), worldCleanup);
|
||||||
|
|
||||||
|
for(ProxiedPlayer p : playersToSend)
|
||||||
|
SubserverSystem.sendPlayer(subserver, p);
|
||||||
|
|
||||||
|
return subserver;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean startingBau(ProxiedPlayer p) {
|
||||||
|
for (Subserver subserver : Subserver.getServerList()) {
|
||||||
|
if (subserver.getType() == Servertype.BAUSERVER && ((Bauserver) subserver).getOwner().equals(p.getUniqueId()) && !subserver.hasStarted()) {
|
||||||
|
Message.send("BAU_START_ALREADY", p);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String bauServerName(SteamwarUser user) {
|
||||||
|
return user.getUserName() + "s Bau";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String serverToWorldName(String serverName) {
|
||||||
|
return serverName.replace(' ', '_').replace("[", "").replace("]", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void copyWorld(Node node, String template, String target) {
|
||||||
|
node.execute("cp", "-r", template, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
private interface ServerConstructor {
|
||||||
|
Subserver construct(String serverName, int port, ProcessBuilder builder, Runnable shutdownCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
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<Integer> usedPorts;
|
||||||
|
|
||||||
|
synchronized (Subserver.getServerList()) {
|
||||||
|
usedPorts = Subserver.getServerList().stream().map(server -> ((InetSocketAddress) server.getServer().getSocketAddress()).getPort()).collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
while(usedPorts.contains(current)) {
|
||||||
|
increment();
|
||||||
|
}
|
||||||
|
|
||||||
|
int result = current;
|
||||||
|
increment();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -21,157 +21,21 @@ package de.steamwar.bungeecore;
|
|||||||
|
|
||||||
import de.steamwar.bungeecore.comms.handlers.FightInfoHandler;
|
import de.steamwar.bungeecore.comms.handlers.FightInfoHandler;
|
||||||
import de.steamwar.bungeecore.comms.packets.StartingServerPacket;
|
import de.steamwar.bungeecore.comms.packets.StartingServerPacket;
|
||||||
import de.steamwar.bungeecore.sql.EventFight;
|
|
||||||
import de.steamwar.bungeecore.sql.IgnoreSystem;
|
import de.steamwar.bungeecore.sql.IgnoreSystem;
|
||||||
import de.steamwar.bungeecore.sql.SteamwarUser;
|
import de.steamwar.bungeecore.sql.SteamwarUser;
|
||||||
import net.md_5.bungee.api.ProxyServer;
|
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.io.File;
|
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.time.format.DateTimeFormatter;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class SubserverSystem {
|
public class SubserverSystem {
|
||||||
private SubserverSystem(){}
|
private SubserverSystem(){}
|
||||||
|
|
||||||
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 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).
|
|
||||||
*
|
|
||||||
* @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 replayID
|
|
||||||
* @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 synchronized Subserver startArena(ArenaMode modus, String map, int eventFightID, int checkSchemID, int prepareSchemID, int replayID, String serverName, String mapName, UUID player1, UUID player2){
|
|
||||||
//Generate missing parameters
|
|
||||||
Node node = eventFightID > 0 ? Node.local : Node.getNode();
|
|
||||||
int port = arenaPorts.freePort();
|
|
||||||
|
|
||||||
if(serverName == null){
|
|
||||||
serverName = modus.getDisplayName() + (port - arenaPorts.start);
|
|
||||||
}
|
|
||||||
if(mapName == null)
|
|
||||||
mapName = serverName;
|
|
||||||
|
|
||||||
mapName = mapName.replace(' ', '_').replace("[", "").replace("]", "");
|
|
||||||
|
|
||||||
String worldDir;
|
|
||||||
if(eventFightID > 0)
|
|
||||||
worldDir = EVENT_PATH;
|
|
||||||
else
|
|
||||||
worldDir = ARENA_PATH;
|
|
||||||
|
|
||||||
//Copy world
|
|
||||||
node.execute("cp", "-r", SERVER_PATH + modus.getFolder() + "/arenas/" + map, worldDir + mapName);
|
|
||||||
|
|
||||||
File directory = new File(SERVER_PATH, modus.getFolder());
|
|
||||||
ProcessBuilder builder = node.startServer(
|
|
||||||
modus.serverJar(), directory, worldDir, mapName, port, "768M",
|
|
||||||
"logPath=" + mapName, "config=" + modus.getConfig(),
|
|
||||||
"fightID=" + eventFightID,
|
|
||||||
"checkSchemID=" + checkSchemID, "prepareSchemID=" + prepareSchemID,
|
|
||||||
"replay=" + replayID,
|
|
||||||
player1 != null && eventFightID != -1 ? "blueLeader=" + player1 : null,
|
|
||||||
player2 != null ? "redLeader=" + player2 : null
|
|
||||||
);
|
|
||||||
|
|
||||||
String finalMapName = mapName;
|
|
||||||
if(eventFightID == -1)
|
|
||||||
return new Bauserver(serverName, player1, port, builder, () -> deleteFolder(node, ARENA_PATH + finalMapName));
|
|
||||||
else
|
|
||||||
return new Subserver(Servertype.ARENA, serverName, port, builder, () -> {
|
|
||||||
if(eventFightID > 0)
|
|
||||||
return;
|
|
||||||
deleteFolder(node, ARENA_PATH + finalMapName);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void deleteFolder(Node node, String worldName) {
|
public static void deleteFolder(Node node, String worldName) {
|
||||||
node.execute("rm", "-r", worldName);
|
node.execute("rm", "-r", worldName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Subserver startEventArena(EventFight eventFight, String serverName){
|
|
||||||
return startArena(
|
|
||||||
eventFight.getSpielmodus(),
|
|
||||||
eventFight.getMap(),
|
|
||||||
eventFight.getFightID(),
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0, serverName,
|
|
||||||
serverName + eventFight.getStartTime().toLocalDateTime().format(DateTimeFormatter.ISO_TIME),
|
|
||||||
null,
|
|
||||||
null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void startTestServer(ProxiedPlayer p, ArenaMode m, String map, int checkSchemId, int prepareSchemId){
|
|
||||||
sendPlayer(startArena(m, map, -1, checkSchemId, prepareSchemId, 0, p.getName() + "s Bau", p.getName(), p.getUniqueId(), null), p);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static synchronized void sendToBau(ProxiedPlayer p, UUID owner, String prototype, String worldFolder, String serverJar, String worldDir, String worldName, String xmx, String serverName){
|
|
||||||
if(bauRunning(p, owner))
|
|
||||||
return;
|
|
||||||
|
|
||||||
copyBauweltIfRequired(prototype, worldFolder + worldName);
|
|
||||||
SteamwarUser user = SteamwarUser.get(owner);
|
|
||||||
File directory = new File(SERVER_PATH, serverName);
|
|
||||||
Node node = Node.getNode();
|
|
||||||
int port = bauPorts.freePort();
|
|
||||||
|
|
||||||
|
|
||||||
sendPlayer(new Bauserver(user.getUserName() + "s Bau", owner, port, node.startServer(
|
|
||||||
serverJar, directory, worldDir, worldName, port, xmx, "logPath=" + worldName
|
|
||||||
), () -> {}), p);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void sendToBauServer(ProxiedPlayer p, UUID owner){
|
|
||||||
sendToBau(p, owner, BungeeCore.BAUWELT_PROTOTYP, BungeeCore.WORLD_FOLDER, "spigot-1.12.2.jar", "/home/minecraft/userworlds", owner.toString(), "256M", "UserBau");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void sendToBau15(ProxiedPlayer p, UUID owner){
|
|
||||||
SteamwarUser user = SteamwarUser.get(owner);
|
|
||||||
sendToBau(p, owner, BungeeCore.BAUWELT15, BungeeCore.USERWORLDS15, "spigot-1.15.2.jar", "/home/minecraft/userworlds15", String.valueOf(user.getId()), "768M", "Bau15");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void sendDeniedMessage(ProxiedPlayer p, UUID owner){
|
public static void sendDeniedMessage(ProxiedPlayer p, UUID owner){
|
||||||
ProxiedPlayer o = ProxyServer.getInstance().getPlayer(owner);
|
ProxiedPlayer o = ProxyServer.getInstance().getPlayer(owner);
|
||||||
if(o == null)
|
if(o == null)
|
||||||
@ -191,57 +55,4 @@ public class SubserverSystem {
|
|||||||
if(!subserver.hasStarted() && FightInfoHandler.onLobby(player))
|
if(!subserver.hasStarted() && FightInfoHandler.onLobby(player))
|
||||||
new StartingServerPacket(SteamwarUser.get(player.getUniqueId())).send(player);
|
new StartingServerPacket(SteamwarUser.get(player.getUniqueId())).send(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean bauRunning(ProxiedPlayer p, UUID owner){
|
|
||||||
for(Subserver subserver : Subserver.getServerList()){
|
|
||||||
if(subserver.getType() == Servertype.BAUSERVER && ((Bauserver)subserver).getOwner().equals(owner)){
|
|
||||||
sendPlayer(subserver, p);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void copyBauweltIfRequired(String sourcePath, String targetPath){
|
|
||||||
File w = new File(targetPath);
|
|
||||||
if (!w.exists() || !w.isDirectory())
|
|
||||||
Node.local.execute("cp", "-r", sourcePath, targetPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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<Integer> usedPorts;
|
|
||||||
|
|
||||||
synchronized (Subserver.getServerList()) {
|
|
||||||
usedPorts = Subserver.getServerList().stream().map(server -> ((InetSocketAddress) server.getServer().getSocketAddress()).getPort()).collect(Collectors.toSet());
|
|
||||||
}
|
|
||||||
|
|
||||||
while(usedPorts.contains(current)) {
|
|
||||||
increment();
|
|
||||||
}
|
|
||||||
|
|
||||||
int result = current;
|
|
||||||
increment();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -45,20 +45,17 @@ public class BauCommand extends BasicCommand {
|
|||||||
ProxiedPlayer p = (ProxiedPlayer) sender;
|
ProxiedPlayer p = (ProxiedPlayer) sender;
|
||||||
|
|
||||||
if(args.length == 0){
|
if(args.length == 0){
|
||||||
if(bau15(p, args, 0))
|
(bau15(p, args, 0) ? new ServerStarter().build15(p.getUniqueId()) : new ServerStarter().build12(p.getUniqueId())).send(p).start();
|
||||||
SubserverSystem.sendToBau15(p, p.getUniqueId());
|
|
||||||
else
|
|
||||||
SubserverSystem.sendToBauServer(p, p.getUniqueId());
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(args[0].toLowerCase()){
|
switch(args[0].toLowerCase()){
|
||||||
case "ws":
|
|
||||||
case "warship":
|
|
||||||
case "12":
|
case "12":
|
||||||
case "1.12":
|
case "1.12":
|
||||||
SubserverSystem.sendToBauServer(p, p.getUniqueId());
|
new ServerStarter().build12(p.getUniqueId()).send(p).start();
|
||||||
break;
|
break;
|
||||||
|
case "ws":
|
||||||
|
case "warship":
|
||||||
case "as":
|
case "as":
|
||||||
case "airship":
|
case "airship":
|
||||||
case "mwg":
|
case "mwg":
|
||||||
@ -67,7 +64,7 @@ public class BauCommand extends BasicCommand {
|
|||||||
case "wargear":
|
case "wargear":
|
||||||
case "15":
|
case "15":
|
||||||
case "1.15":
|
case "1.15":
|
||||||
SubserverSystem.sendToBau15(p, p.getUniqueId());
|
new ServerStarter().build15(p.getUniqueId()).send(p).start();
|
||||||
break;
|
break;
|
||||||
case "addmember":
|
case "addmember":
|
||||||
addmember(p, args);
|
addmember(p, args);
|
||||||
@ -143,10 +140,7 @@ public class BauCommand extends BasicCommand {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(bau15(p, args, 2))
|
(bau15(p, args, 2) ? new ServerStarter().build15(worldOwner.getUuid()) : new ServerStarter().build12(worldOwner.getUuid())).send(p).start();
|
||||||
SubserverSystem.sendToBau15(p, worldOwner.getUuid());
|
|
||||||
else
|
|
||||||
SubserverSystem.sendToBauServer(p, worldOwner.getUuid());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean bau15(ProxiedPlayer p, String[] args, int pos){
|
private static boolean bau15(ProxiedPlayer p, String[] args, int pos){
|
||||||
@ -259,40 +253,8 @@ public class BauCommand extends BasicCommand {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean startingBau(ProxiedPlayer p) {
|
|
||||||
for (Subserver subserver : Subserver.getServerList()) {
|
|
||||||
if (subserver.getType() == Servertype.BAUSERVER && ((Bauserver) subserver).getOwner().equals(p.getUniqueId()) && !subserver.hasStarted()) {
|
|
||||||
Message.send("BAU_START_ALREADY", p);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean stopBauserver(ProxiedPlayer p){
|
|
||||||
if(startingBau(p))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
for (Subserver subserver : Subserver.getServerList()) {
|
|
||||||
if (subserver.getType() == Servertype.BAUSERVER && ((Bauserver) subserver).getOwner().equals(p.getUniqueId()) && subserver.hasStarted()) {
|
|
||||||
subserver.stop();
|
|
||||||
try {
|
|
||||||
Thread.sleep(200); // Wait until possible testarena-World has been deleted
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
throw new SecurityException("Subserver stop interrupted", e);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return !startingBau(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void testarena(ProxiedPlayer p, String[] args){
|
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(), () -> {
|
FightCommand.createArena(p, "/bau testarena ", args, 1, false, (player, mode, map) -> ProxyServer.getInstance().getScheduler().runAsync(BungeeCore.get(), () -> new ServerStarter().test(mode, map, p).start()));
|
||||||
if(stopBauserver(p))
|
|
||||||
SubserverSystem.startTestServer(p, mode, map, 0, 0);
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static BauweltMember member(ProxiedPlayer p, SteamwarUser member){
|
private static BauweltMember member(ProxiedPlayer p, SteamwarUser member){
|
||||||
|
@ -76,11 +76,7 @@ public class ChallengeCommand extends BasicCommand {
|
|||||||
challenges.remove(target);
|
challenges.remove(target);
|
||||||
challenges.remove(player);
|
challenges.remove(player);
|
||||||
|
|
||||||
Subserver arena = SubserverSystem.startArena(mode, map, 0, 0, 0, 0, null, null, player.getUniqueId(), target.getUniqueId());
|
Subserver arena = new ServerStarter().arena(mode, map).blueLeader(player).redLeader(target).start();
|
||||||
|
|
||||||
SubserverSystem.sendPlayer(arena, player);
|
|
||||||
SubserverSystem.sendPlayer(arena, target);
|
|
||||||
|
|
||||||
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(), player.getName(), target.getName());
|
new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/arena " + arena.getServer().getName()), mode.getDisplayName(), player.getName(), target.getName());
|
||||||
}else{
|
}else{
|
||||||
|
@ -228,13 +228,12 @@ public class CheckCommand extends BasicCommand {
|
|||||||
this.checkList = checkQuestions.get(schematic.getSchemtype()).listIterator();
|
this.checkList = checkQuestions.get(schematic.getSchemtype()).listIterator();
|
||||||
|
|
||||||
ProxyServer.getInstance().getScheduler().runAsync(BungeeCore.get(), () -> {
|
ProxyServer.getInstance().getScheduler().runAsync(BungeeCore.get(), () -> {
|
||||||
if(!BauCommand.stopBauserver(checker)){
|
ArenaMode mode = ArenaMode.getBySchemType(schematic.getSchemtype().fightType());
|
||||||
|
if(new ServerStarter().test(mode, mode.getRandomMap(), checker).check(schematic.getId()).start() == null) {
|
||||||
remove();
|
remove();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArenaMode mode = ArenaMode.getBySchemType(schematic.getSchemtype().fightType());
|
|
||||||
SubserverSystem.startTestServer(checker, mode, FightCommand.getMap(checker, mode, "Random"), schematic.getId(), 0);
|
|
||||||
currentCheckers.put(checker.getUniqueId(), this);
|
currentCheckers.put(checker.getUniqueId(), this);
|
||||||
currentSchems.put(schematic.getId(), this);
|
currentSchems.put(schematic.getId(), this);
|
||||||
for(CheckedSchematic previous : CheckedSchematic.previousChecks(schematic))
|
for(CheckedSchematic previous : CheckedSchematic.previousChecks(schematic))
|
||||||
|
@ -164,8 +164,7 @@ public class FightCommand extends BasicCommand {
|
|||||||
@Override
|
@Override
|
||||||
public void execute(CommandSender sender, String[] args) {
|
public void execute(CommandSender sender, String[] args) {
|
||||||
createArena(sender, "/fight ", args, 0, false, (player, mode, map) -> {
|
createArena(sender, "/fight ", args, 0, false, (player, mode, map) -> {
|
||||||
Subserver arena = SubserverSystem.startArena(mode, map, 0, 0, 0, 0, null, null, player.getUniqueId(), null);
|
Subserver arena = new ServerStarter().arena(mode, map).blueLeader(player).start();
|
||||||
SubserverSystem.sendPlayer(arena, player);
|
|
||||||
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(), player.getName());
|
, new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/arena " + arena.getServer().getName()), mode.getDisplayName(), player.getName());
|
||||||
});
|
});
|
||||||
|
@ -19,10 +19,7 @@
|
|||||||
|
|
||||||
package de.steamwar.bungeecore.commands;
|
package de.steamwar.bungeecore.commands;
|
||||||
|
|
||||||
import de.steamwar.bungeecore.ArenaMode;
|
import de.steamwar.bungeecore.*;
|
||||||
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.CommandSender;
|
||||||
import net.md_5.bungee.api.chat.ClickEvent;
|
import net.md_5.bungee.api.chat.ClickEvent;
|
||||||
|
|
||||||
@ -36,8 +33,7 @@ public class HistoricCommand extends BasicCommand {
|
|||||||
@Override
|
@Override
|
||||||
public void execute(CommandSender sender, String[] args) {
|
public void execute(CommandSender sender, String[] args) {
|
||||||
FightCommand.createArena(sender, "/historic ", args, 0, true, (player, mode, map) -> {
|
FightCommand.createArena(sender, "/historic ", args, 0, true, (player, mode, map) -> {
|
||||||
Subserver arena = SubserverSystem.startArena(mode, map, 0, 0, 0, 0, null, null, player.getUniqueId(), null);
|
Subserver arena = new ServerStarter().arena(mode, map).blueLeader(player).start();
|
||||||
SubserverSystem.sendPlayer(arena, player);
|
|
||||||
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(), player.getName());
|
, new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/arena " + arena.getServer().getName()), mode.getDisplayName(), player.getName());
|
||||||
});
|
});
|
||||||
|
@ -1,8 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of the SteamWar software.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 SteamWar.de-Serverteam
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
package de.steamwar.bungeecore.commands;
|
package de.steamwar.bungeecore.commands;
|
||||||
|
|
||||||
import de.steamwar.bungeecore.ArenaMode;
|
import de.steamwar.bungeecore.*;
|
||||||
import de.steamwar.bungeecore.Message;
|
|
||||||
import de.steamwar.bungeecore.SubserverSystem;
|
|
||||||
import de.steamwar.bungeecore.inventory.SWItem;
|
import de.steamwar.bungeecore.inventory.SWItem;
|
||||||
import de.steamwar.bungeecore.inventory.SWListInv;
|
import de.steamwar.bungeecore.inventory.SWListInv;
|
||||||
import de.steamwar.bungeecore.inventory.SWStreamInv;
|
import de.steamwar.bungeecore.inventory.SWStreamInv;
|
||||||
@ -30,16 +47,16 @@ public class ReplayCommand extends BasicCommand {
|
|||||||
|
|
||||||
new SWStreamInv<>(player, Message.parse("REPLAY_TITLE", player), (click, fight) -> {
|
new SWStreamInv<>(player, Message.parse("REPLAY_TITLE", player), (click, fight) -> {
|
||||||
SteamwarUser user = SteamwarUser.get(player.getUniqueId());
|
SteamwarUser user = SteamwarUser.get(player.getUniqueId());
|
||||||
boolean adminReplay = false;
|
ArenaMode mode = fight.getGameMode();
|
||||||
|
ServerStarter starter = new ServerStarter().replay(fight.getFightID()).blueLeader(player);
|
||||||
|
|
||||||
if (user.getUserGroup().isAdminGroup() && click.isShiftClick() && fight.replayExists()) {
|
if (user.getUserGroup().isAdminGroup() && click.isShiftClick() && fight.replayExists()) {
|
||||||
adminReplay = true;
|
starter.test(mode, mode.getRandomMap(), player).start();
|
||||||
} else if(!fight.replayAllowed()) {
|
} else if(!fight.replayAllowed()) {
|
||||||
Message.send("REPLAY_UNAVAILABLE", player);
|
Message.send("REPLAY_UNAVAILABLE", player);
|
||||||
return;
|
} else {
|
||||||
|
starter.arena(mode, mode.getRandomMap()).start();
|
||||||
}
|
}
|
||||||
ArenaMode mode = fight.getGameMode();
|
|
||||||
|
|
||||||
SubserverSystem.sendPlayer(SubserverSystem.startArena(mode, mode.getRandomMap(), adminReplay ? -1 : 0, 0, 0, fight.getFightID(), null, null, null, null), player);
|
|
||||||
}, page -> Fight.getPage(page, 45).stream().map(fight -> new SWListInv.SWListEntry<>(getFightItem(player, fight), fight)).collect(Collectors.toList())).open();
|
}, page -> Fight.getPage(page, 45).stream().map(fight -> new SWListInv.SWListEntry<>(getFightItem(player, fight), fight)).collect(Collectors.toList())).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
173
src/de/steamwar/bungeecore/commands/TutorialCommand.java
Normale Datei
173
src/de/steamwar/bungeecore/commands/TutorialCommand.java
Normale Datei
@ -0,0 +1,173 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of the SteamWar software.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 SteamWar.de-Serverteam
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.bungeecore.commands;
|
||||||
|
|
||||||
|
import de.steamwar.bungeecore.*;
|
||||||
|
import de.steamwar.bungeecore.inventory.SWInventory;
|
||||||
|
import de.steamwar.bungeecore.inventory.SWItem;
|
||||||
|
import de.steamwar.bungeecore.inventory.SWListInv;
|
||||||
|
import de.steamwar.bungeecore.inventory.SWStreamInv;
|
||||||
|
import de.steamwar.bungeecore.sql.SteamwarUser;
|
||||||
|
import de.steamwar.bungeecore.sql.Tutorial;
|
||||||
|
import net.md_5.bungee.api.CommandSender;
|
||||||
|
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class TutorialCommand extends BasicCommand {
|
||||||
|
|
||||||
|
public TutorialCommand() {
|
||||||
|
super("tutorial", null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(CommandSender sender, String[] args) {
|
||||||
|
if(!(sender instanceof ProxiedPlayer))
|
||||||
|
return;
|
||||||
|
ProxiedPlayer player = (ProxiedPlayer) sender;
|
||||||
|
|
||||||
|
if(args.length != 0) {
|
||||||
|
switch(args[0].toLowerCase()) {
|
||||||
|
case "rate":
|
||||||
|
if(args.length < 2) {
|
||||||
|
BungeeCore.get().getLogger().log(Level.SEVERE, "rate executed with missing argument");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int id;
|
||||||
|
try {
|
||||||
|
id = Integer.parseInt(args[1]);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
BungeeCore.get().getLogger().log(Level.SEVERE, "rate executed with non number: " + args[1]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Tutorial tutorial = Tutorial.get(id);
|
||||||
|
if(tutorial == null) {
|
||||||
|
BungeeCore.get().getLogger().log(Level.SEVERE, "rate executed with nonexistent id: " + id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rate(player, tutorial);
|
||||||
|
break;
|
||||||
|
case "create":
|
||||||
|
if(args.length < 3) {
|
||||||
|
Message.send("TUTORIAL_CREATE_HELP", player);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String material = args[1].toUpperCase();
|
||||||
|
String name = Arrays.stream(args).skip(2).collect(Collectors.joining(" "));
|
||||||
|
create(player, name, material);
|
||||||
|
break;
|
||||||
|
case "own":
|
||||||
|
openInventory(player, false, true);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "unreleased":
|
||||||
|
if (SteamwarUser.get(player.getUniqueId()).getUserGroup().isTeamGroup()) {
|
||||||
|
openInventory(player, false, false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
Message.send("TUTORIAL_CREATE_HELP", player);
|
||||||
|
Message.send("TUTORIAL_OWN_HELP", player);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
openInventory(player, true, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void openInventory(ProxiedPlayer player, boolean released, boolean own) {
|
||||||
|
SteamwarUser user = SteamwarUser.get(player.getUniqueId());
|
||||||
|
|
||||||
|
new SWStreamInv<>(
|
||||||
|
player,
|
||||||
|
Message.parse("TUTORIAL_TITLE", player),
|
||||||
|
(click, tutorial) -> {
|
||||||
|
if(!released && click.isShiftClick() && user.getUserGroup().isTeamGroup() && user != tutorial.creator()) {
|
||||||
|
tutorial.release();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
new ServerStarter().tutorial(player, tutorial).start();
|
||||||
|
},
|
||||||
|
page -> (own ? Tutorial.getOwn(user, page, 45) : Tutorial.getPage(page, 45, released)).stream().map(tutorial -> new SWListInv.SWListEntry<>(getTutorialItem(player, tutorial, own), tutorial)).collect(Collectors.toList())
|
||||||
|
).open();
|
||||||
|
}
|
||||||
|
|
||||||
|
private SWItem getTutorialItem(ProxiedPlayer player, Tutorial tutorial, boolean highlightReleased) {
|
||||||
|
SWItem item = new SWItem(tutorial.item(), Message.parse("TUTORIAL_NAME", player, tutorial.name()));
|
||||||
|
item.setHideAttributes(true);
|
||||||
|
|
||||||
|
List<String> lore = new ArrayList<>();
|
||||||
|
lore.add(Message.parse("TUTORIAL_BY", player, tutorial.creator().getUserName()));
|
||||||
|
lore.add(Message.parse("TUTORIAL_STARS", player, tutorial.stars()));
|
||||||
|
item.setLore(lore);
|
||||||
|
|
||||||
|
if (highlightReleased && tutorial.released())
|
||||||
|
item.setEnchanted(true);
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void rate(ProxiedPlayer player, Tutorial tutorial) {
|
||||||
|
SteamwarUser user = SteamwarUser.get(player.getUniqueId());
|
||||||
|
int[] rates = new int[]{1, 2, 3, 4, 5};
|
||||||
|
|
||||||
|
new SWListInv<>(player, Message.parse("TUTORIAL_RATE_TITLE", player), Arrays.stream(rates).mapToObj(rate -> new SWListInv.SWListEntry<>(new SWItem("NETHER_STAR", Message.parse("TUTORIAL_RATE", player, rate)), rate)).collect(Collectors.toList()), (click, rate) -> {
|
||||||
|
tutorial.rate(user, rate);
|
||||||
|
SWInventory.close(player);
|
||||||
|
}).open();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void create(ProxiedPlayer player, String name, String item) {
|
||||||
|
Subserver subserver = Subserver.getSubserver(player);
|
||||||
|
SteamwarUser user = SteamwarUser.get(player.getUniqueId());
|
||||||
|
File tempWorld = new File(ServerStarter.TEMP_WORLD_PATH, ServerStarter.serverToWorldName(ServerStarter.bauServerName(user)));
|
||||||
|
|
||||||
|
if(subserver == null || !subserver.hasStarted() || subserver.getType() != Servertype.BAUSERVER || !tempWorld.exists()) {
|
||||||
|
Message.send("TUTORIAL_CREATE_MISSING", player);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
subserver.execute("save-all");
|
||||||
|
try {
|
||||||
|
Thread.sleep(1000);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
BungeeCore.get().getLogger().log(Level.WARNING, "Tutorial creation interrupted", e);
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
}
|
||||||
|
|
||||||
|
Tutorial tutorial = Tutorial.create(user, name, item);
|
||||||
|
File tutorialWorld = new File(ServerStarter.TUTORIAL_PATH, String.valueOf(tutorial.id()));
|
||||||
|
|
||||||
|
if (tutorialWorld.exists())
|
||||||
|
SubserverSystem.deleteFolder(Node.local, tutorialWorld.getPath());
|
||||||
|
ServerStarter.copyWorld(Node.local, tempWorld.getPath(), tutorialWorld.getPath());
|
||||||
|
Message.send("TUTORIAL_CREATED", player);
|
||||||
|
}
|
||||||
|
}
|
@ -21,8 +21,7 @@ package de.steamwar.bungeecore.comms.handlers;
|
|||||||
|
|
||||||
import com.google.common.io.ByteArrayDataInput;
|
import com.google.common.io.ByteArrayDataInput;
|
||||||
import de.steamwar.bungeecore.ArenaMode;
|
import de.steamwar.bungeecore.ArenaMode;
|
||||||
import de.steamwar.bungeecore.SubserverSystem;
|
import de.steamwar.bungeecore.ServerStarter;
|
||||||
import de.steamwar.bungeecore.commands.BauCommand;
|
|
||||||
import de.steamwar.bungeecore.comms.SpigotHandler;
|
import de.steamwar.bungeecore.comms.SpigotHandler;
|
||||||
import de.steamwar.bungeecore.sql.SchematicType;
|
import de.steamwar.bungeecore.sql.SchematicType;
|
||||||
import de.steamwar.bungeecore.sql.SteamwarUser;
|
import de.steamwar.bungeecore.sql.SteamwarUser;
|
||||||
@ -37,7 +36,6 @@ public class PrepareSchemHandler implements SpigotHandler {
|
|||||||
int schematicID = in.readInt();
|
int schematicID = in.readInt();
|
||||||
ArenaMode mode = ArenaMode.getBySchemType(SchematicType.fromDB(in.readUTF()));
|
ArenaMode mode = ArenaMode.getBySchemType(SchematicType.fromDB(in.readUTF()));
|
||||||
|
|
||||||
BauCommand.stopBauserver(player);
|
new ServerStarter().test(mode, mode.getRandomMap(), player).prepare(schematicID).start();
|
||||||
SubserverSystem.startTestServer(player, mode, mode.getRandomMap(), 0, schematicID);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,6 +116,10 @@ public class SWInventory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void close() {
|
public void close() {
|
||||||
|
close(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void close(ProxiedPlayer player) {
|
||||||
new CloseInventoryPacket(SteamwarUser.get(player).getId()).send(player);
|
new CloseInventoryPacket(SteamwarUser.get(player).getId()).send(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
122
src/de/steamwar/bungeecore/sql/Tutorial.java
Normale Datei
122
src/de/steamwar/bungeecore/sql/Tutorial.java
Normale Datei
@ -0,0 +1,122 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of the SteamWar software.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 SteamWar.de-Serverteam
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.bungeecore.sql;
|
||||||
|
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class Tutorial {
|
||||||
|
|
||||||
|
private static final Statement by_popularity = new Statement("SELECT t.*, AVG(r.Stars) AS Stars FROM Tutorial t LEFT OUTER JOIN TutorialRating r ON t.TutorialID = r.TutorialID WHERE t.Released = ? GROUP BY t.TutorialID ORDER BY SUM(r.Stars) DESC LIMIT ?, ?");
|
||||||
|
private static final Statement own = new Statement("SELECT t.*, AVG(r.Stars) AS Stars FROM Tutorial t LEFT OUTER JOIN TutorialRating r ON t.TutorialID = r.TutorialID WHERE t.Creator = ? GROUP BY t.TutorialID ORDER BY t.TutorialID ASC LIMIT ?, ?");
|
||||||
|
private static final Statement by_creator_name = new Statement("SELECT t.*, AVG(r.Stars) AS Stars FROM Tutorial t LEFT OUTER JOIN TutorialRating r ON t.TutorialID = r.TutorialID WHERE t.Creator = ? AND t.Name = ? GROUP BY t.TutorialID");
|
||||||
|
private static final Statement by_id = new Statement("SELECT t.*, AVG(r.Stars) AS Stars FROM Tutorial t LEFT OUTER JOIN TutorialRating r ON t.TutorialID = r.TutorialID WHERE t.TutorialID = ? GROUP BY t.TutorialID");
|
||||||
|
private static final Statement rate = new Statement("INSERT INTO TutorialRating (TutorialID, UserID, Stars) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE Stars = VALUES(Stars)");
|
||||||
|
private static final Statement create = new Statement("INSERT INTO Tutorial (Creator, Name, Item) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE Item = VALUES(Item), Released = 0");
|
||||||
|
private static final Statement release = new Statement("UPDATE Tutorial SET Released = 1 WHERE TutorialID = ?");
|
||||||
|
|
||||||
|
public static List<Tutorial> getPage(int page, int elementsPerPage, boolean released) {
|
||||||
|
List<Tutorial> tutorials = by_popularity.select(rs -> {
|
||||||
|
List<Tutorial> t = new ArrayList<>();
|
||||||
|
while(rs.next())
|
||||||
|
t.add(new Tutorial(rs));
|
||||||
|
return t;
|
||||||
|
}, released, page * elementsPerPage, elementsPerPage);
|
||||||
|
|
||||||
|
SteamwarUser.batchCache(tutorials.stream().map(tutorial -> tutorial.creator).collect(Collectors.toSet()));
|
||||||
|
return tutorials;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<Tutorial> getOwn(SteamwarUser user, int page, int elementsPerPage) {
|
||||||
|
return own.select(rs -> {
|
||||||
|
List<Tutorial> t = new ArrayList<>();
|
||||||
|
while(rs.next())
|
||||||
|
t.add(new Tutorial(rs));
|
||||||
|
return t;
|
||||||
|
}, user.getId(), page * elementsPerPage, elementsPerPage);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Tutorial create(SteamwarUser creator, String name, String item) {
|
||||||
|
create.update(creator.getId(), name, item);
|
||||||
|
return by_creator_name.select(rs -> {
|
||||||
|
rs.next();
|
||||||
|
return new Tutorial(rs);
|
||||||
|
}, creator.getId(), name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Tutorial get(int id) {
|
||||||
|
return by_id.select(rs -> {
|
||||||
|
if(rs.next())
|
||||||
|
return new Tutorial(rs);
|
||||||
|
return null;
|
||||||
|
}, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final int id;
|
||||||
|
private final int creator;
|
||||||
|
private final String name;
|
||||||
|
private final String item;
|
||||||
|
private final double stars;
|
||||||
|
private final boolean released;
|
||||||
|
|
||||||
|
public Tutorial(ResultSet rs) throws SQLException {
|
||||||
|
this.id = rs.getInt("TutorialID");
|
||||||
|
this.creator = rs.getInt("Creator");
|
||||||
|
this.name = rs.getString("Name");
|
||||||
|
this.item = rs.getString("Item");
|
||||||
|
this.released = rs.getBoolean("Released");
|
||||||
|
this.stars = rs.getDouble("Stars");
|
||||||
|
}
|
||||||
|
|
||||||
|
public SteamwarUser creator() {
|
||||||
|
return SteamwarUser.get(creator);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double stars() {
|
||||||
|
return stars;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int id() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String name() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String item() {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean released() {
|
||||||
|
return released;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void release() {
|
||||||
|
release.update(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void rate(SteamwarUser user, int rating) {
|
||||||
|
rate.update(id, user.getId(), rating);
|
||||||
|
}
|
||||||
|
}
|
@ -333,6 +333,18 @@ REPLAY_LOSER=§e{0} §7+§e{1}
|
|||||||
REPLAY_TIME=§7{0}
|
REPLAY_TIME=§7{0}
|
||||||
REPLAY_SERVER=§7{0}
|
REPLAY_SERVER=§7{0}
|
||||||
|
|
||||||
|
#TutorialCommand
|
||||||
|
TUTORIAL_TITLE=Tutorials
|
||||||
|
TUTORIAL_NAME=§e{0}
|
||||||
|
TUTORIAL_BY=§8von §7{0}
|
||||||
|
TUTORIAL_STARS=§e{0} §7Sterne
|
||||||
|
TUTORIAL_RATE_TITLE=Tutorial bewerten
|
||||||
|
TUTORIAL_RATE=§e{0} §7Stern(e)
|
||||||
|
TUTORIAL_CREATE_HELP=§8/§7tutorial create §8[§eMaterial§8] §8[§eName§8]
|
||||||
|
TUTORIAL_CREATE_MISSING=§cEin Tutorial kann nur von einem Tutorialserver aus erstellt werden!
|
||||||
|
TUTORIAL_CREATED=§7Das Tutorial wurde erstellt§8.
|
||||||
|
TUTORIAL_OWN_HELP=§8/§7tutorial own §8- §7Liste der eigenen Tutorials
|
||||||
|
|
||||||
#ServerTeamchatCommand
|
#ServerTeamchatCommand
|
||||||
STC_USAGE=§8/§7stc §8[§eNachricht an das Team§8]
|
STC_USAGE=§8/§7stc §8[§eNachricht an das Team§8]
|
||||||
STC_FORMAT=§8STC §e{0}» §r{1}
|
STC_FORMAT=§8STC §e{0}» §r{1}
|
||||||
|
In neuem Issue referenzieren
Einen Benutzer sperren