SteamWar/BungeeCore
Archiviert
13
2

Fabric Mod Sender Integration. Mod itself is not final #307

Zusammengeführt
Lixfel hat 12 Commits von fabric_mod_sender nach master 2022-03-26 10:01:51 +01:00 zusammengeführt
33 geänderte Dateien mit 1126 neuen und 373 gelöschten Zeilen
Nur Änderungen aus Commit 626a876f0f werden angezeigt - Alle Commits anzeigen

Datei anzeigen

@ -25,10 +25,7 @@ import de.steamwar.bungeecore.commands.*;
import de.steamwar.bungeecore.comms.SpigotReceiver;
import de.steamwar.bungeecore.listeners.*;
import de.steamwar.bungeecore.listeners.mods.*;
import de.steamwar.bungeecore.sql.Punishment;
import de.steamwar.bungeecore.sql.Statement;
import de.steamwar.bungeecore.sql.SteamwarUser;
import de.steamwar.bungeecore.sql.Team;
import de.steamwar.bungeecore.sql.*;
import net.md_5.bungee.api.ChatMessageType;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.ProxyServer;
@ -125,10 +122,10 @@ public class BungeeCore extends Plugin {
new ListCommand();
new StatCommand();
new VerifyCommand();
new ReplayCommand();
new GDPRQuery();
new PlaytimeCommand();
new ArenaCommand();
new RankCommand();
// Punishment Commands:
new PunishmentCommand("ban", Punishment.PunishmentType.Ban);
@ -145,6 +142,8 @@ public class BungeeCore extends Plugin {
new ChallengeCommand();
new HistoricCommand();
new CheckCommand();
new ReplayCommand();
new TutorialCommand();
new Broadcaster();
}else{
@ -158,6 +157,7 @@ public class BungeeCore extends Plugin {
getProxy().getScheduler().schedule(this, () -> {
SteamwarUser.clearCache();
UserElo.clearCache();
Team.clearCache();
}, 1, 1, TimeUnit.HOURS);

Datei anzeigen

@ -64,12 +64,13 @@ public class EventStarter implements Runnable {
Team blue = Team.get(next.getTeamBlue());
Team red = Team.get(next.getTeamRed());
String serverName = blue.getTeamKuerzel() + " vs " + red.getTeamKuerzel();
Subserver subserver = SubserverSystem.startEventArena(next, serverName);
ServerStarter starter = new ServerStarter().event(next);
ProxiedPlayer leiter = ProxyServer.getInstance().getPlayer(SteamwarUser.get(next.getKampfleiter()).getUuid());
if(leiter != null)
subserver.sendPlayer(leiter);
starter.send(leiter);
Subserver subserver = starter.start();
eventServer.put(blue.getTeamId(), subserver);
eventServer.put(red.getTeamId(), subserver);

Datei anzeigen

@ -28,20 +28,15 @@ import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.io.IOException;
import java.io.InputStream;
import java.text.DateFormat;
import java.text.MessageFormat;
import java.util.Date;
import java.util.Locale;
import java.util.ResourceBundle;
import java.util.*;
public class Message {
private static final ResourceBundle.Control CONTROL = new ResourceBundle.Control() {
@Override
public long getTimeToLive(String arg0, Locale arg1) {
return 60000; //Cache only 1 minute
}
};
private static final Map<String, ResourceBundle> bundles = new HashMap<>();
public static TextComponent parseToComponent(String message, boolean prefixed, CommandSender sender, Object... params){
return new TextComponent(TextComponent.fromLegacyText(parse(message, prefixed, locale(sender), params)));
@ -63,10 +58,29 @@ public class Message {
return sender instanceof ProxiedPlayer ? ((ProxiedPlayer)sender).getLocale() : Locale.getDefault();
}
private static final String BASE_PATH = "/" + "de.steamwar.messages.BungeeCore".replace('.', '/');
private static ResourceBundle getResourceBundle(String locale, ResourceBundle parent) {
return bundles.computeIfAbsent(locale, locale1 -> {
InputStream inputStream = Message.class.getResourceAsStream(BASE_PATH + ("".equals(locale) ? "" : "_" + locale) + ".properties");
if(inputStream == null)
return parent;
try {
return new SteamwarResourceBundle(inputStream, parent);
} catch (IOException e) {
return parent;
}
});
}
private static ResourceBundle getResourceBundle(Locale locale) {
return getResourceBundle(locale.toString(), getResourceBundle(locale.getLanguage(), getResourceBundle( "", (ResourceBundle) null)));
}
private static String parse(String message, boolean prefixed, Locale locale, Object... params){
if(locale == null)
locale = Locale.getDefault();
ResourceBundle resourceBundle = ResourceBundle.getBundle("de.steamwar.messages.BungeeCore", locale, CONTROL);
ResourceBundle resourceBundle = getResourceBundle(locale);
String pattern = "";
if(prefixed)
pattern = resourceBundle.getObject("PREFIX") + " ";
@ -174,4 +188,11 @@ public class Message {
public Object[] getParams() {
return params;
}
private static class SteamwarResourceBundle extends PropertyResourceBundle {
public SteamwarResourceBundle(InputStream stream, ResourceBundle parent) throws IOException {
super(stream);
setParent(parent);
}
}
}

Datei anzeigen

@ -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;
}
}
}

Datei anzeigen

@ -19,156 +19,23 @@
package de.steamwar.bungeecore;
import de.steamwar.bungeecore.sql.EventFight;
import de.steamwar.bungeecore.comms.handlers.FightInfoHandler;
import de.steamwar.bungeecore.comms.packets.StartingServerPacket;
import de.steamwar.bungeecore.sql.IgnoreSystem;
import de.steamwar.bungeecore.sql.SteamwarUser;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.io.File;
import java.net.InetSocketAddress;
import java.time.format.DateTimeFormatter;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
public class SubserverSystem {
private SubserverSystem(){}
private static final String BACKBONE = "/home/minecraft/";
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);
}
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){
startArena(m, map, -1, checkSchemId, prepareSchemId, 0, p.getName() + "s Bau", p.getName(), p.getUniqueId(), null).sendPlayer(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();
new Bauserver(user.getUserName() + "s Bau", owner, port, node.startServer(
serverJar, directory, worldDir, worldName, port, xmx, "logPath=" + worldName
), () -> {}).sendPlayer(p);
}
public static void sendToBauServer(ProxiedPlayer p, UUID owner){
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){
ProxiedPlayer o = ProxyServer.getInstance().getPlayer(owner);
if(o == null)
@ -183,56 +50,9 @@ public class SubserverSystem {
new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/bau addmember " + p.getName()));
}
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 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;
}
public static void sendPlayer(Subserver subserver, ProxiedPlayer player) {
subserver.sendPlayer(player);
if(!subserver.hasStarted() && FightInfoHandler.onLobby(player))
new StartingServerPacket(SteamwarUser.get(player.getUniqueId())).send(player);
}
}

Datei anzeigen

@ -22,6 +22,7 @@ package de.steamwar.bungeecore.commands;
import de.steamwar.bungeecore.Message;
import de.steamwar.bungeecore.Servertype;
import de.steamwar.bungeecore.Subserver;
import de.steamwar.bungeecore.SubserverSystem;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.config.ServerInfo;
@ -51,6 +52,6 @@ public class ArenaCommand extends BasicCommand {
return;
}
subserver.sendPlayer(player);
SubserverSystem.sendPlayer(subserver, player);
}
}

Datei anzeigen

@ -45,20 +45,17 @@ public class BauCommand extends BasicCommand {
ProxiedPlayer p = (ProxiedPlayer) sender;
if(args.length == 0){
if(bau15(p, args, 0))
SubserverSystem.sendToBau15(p, p.getUniqueId());
else
SubserverSystem.sendToBauServer(p, p.getUniqueId());
(bau15(p, args, 0) ? new ServerStarter().build15(p.getUniqueId()) : new ServerStarter().build12(p.getUniqueId())).send(p).start();
return;
}
switch(args[0].toLowerCase()){
case "ws":
case "warship":
case "12":
case "1.12":
SubserverSystem.sendToBauServer(p, p.getUniqueId());
new ServerStarter().build12(p.getUniqueId()).send(p).start();
break;
case "ws":
case "warship":
case "as":
case "airship":
case "mwg":
@ -67,7 +64,7 @@ public class BauCommand extends BasicCommand {
case "wargear":
case "15":
case "1.15":
SubserverSystem.sendToBau15(p, p.getUniqueId());
new ServerStarter().build15(p.getUniqueId()).send(p).start();
break;
case "addmember":
addmember(p, args);
@ -143,10 +140,7 @@ public class BauCommand extends BasicCommand {
return;
}
if(bau15(p, args, 2))
SubserverSystem.sendToBau15(p, worldOwner.getUuid());
else
SubserverSystem.sendToBauServer(p, worldOwner.getUuid());
(bau15(p, args, 2) ? new ServerStarter().build15(worldOwner.getUuid()) : new ServerStarter().build12(worldOwner.getUuid())).send(p).start();
}
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){
FightCommand.createArena(p, "/bau testarena ", args, 1, false, (player, mode, map) -> ProxyServer.getInstance().getScheduler().runAsync(BungeeCore.get(), () -> {
if(stopBauserver(p))
SubserverSystem.startTestServer(p, mode, map, 0, 0);
}));
FightCommand.createArena(p, "/bau testarena ", args, 1, false, (player, mode, map) -> ProxyServer.getInstance().getScheduler().runAsync(BungeeCore.get(), () -> new ServerStarter().test(mode, map, p).start()));
}
private static BauweltMember member(ProxiedPlayer p, SteamwarUser member){

Datei anzeigen

@ -76,11 +76,7 @@ public class ChallengeCommand extends BasicCommand {
challenges.remove(target);
challenges.remove(player);
Subserver arena = SubserverSystem.startArena(mode, map, 0, 0, 0, 0, null, null, player.getUniqueId(), target.getUniqueId());
arena.sendPlayer(player);
arena.sendPlayer(target);
Subserver arena = new ServerStarter().arena(mode, map).blueLeader(player).redLeader(target).start();
Message.broadcast("CHALLENGE_BROADCAST", "CHALLENGE_BROADCAST_HOVER",
new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/arena " + arena.getServer().getName()), mode.getDisplayName(), player.getName(), target.getName());
}else{

Datei anzeigen

@ -228,13 +228,12 @@ public class CheckCommand extends BasicCommand {
this.checkList = checkQuestions.get(schematic.getSchemtype()).listIterator();
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();
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);
currentSchems.put(schematic.getId(), this);
for(CheckedSchematic previous : CheckedSchematic.previousChecks(schematic))

Datei anzeigen

@ -19,10 +19,7 @@
package de.steamwar.bungeecore.commands;
import de.steamwar.bungeecore.BungeeCore;
import de.steamwar.bungeecore.EventStarter;
import de.steamwar.bungeecore.Message;
import de.steamwar.bungeecore.Subserver;
import de.steamwar.bungeecore.*;
import de.steamwar.bungeecore.sql.Event;
import de.steamwar.bungeecore.sql.EventFight;
import de.steamwar.bungeecore.sql.Team;
@ -72,7 +69,7 @@ public class EventCommand extends BasicCommand {
return;
}
eventArena.sendPlayer(player);
SubserverSystem.sendPlayer(eventArena, player);
}
private void noCurrentEvent(ProxiedPlayer player){

Datei anzeigen

@ -164,8 +164,7 @@ public class FightCommand extends BasicCommand {
@Override
public void execute(CommandSender sender, String[] args) {
createArena(sender, "/fight ", args, 0, false, (player, mode, map) -> {
Subserver arena = SubserverSystem.startArena(mode, map, 0, 0, 0, 0, null, null, player.getUniqueId(), null);
arena.sendPlayer(player);
Subserver arena = new ServerStarter().arena(mode, map).blueLeader(player).start();
Message.broadcast("FIGHT_BROADCAST", "FIGHT_BROADCAST_HOVER"
, new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/arena " + arena.getServer().getName()), mode.getDisplayName(), player.getName());
});

Datei anzeigen

@ -19,10 +19,7 @@
package de.steamwar.bungeecore.commands;
import de.steamwar.bungeecore.ArenaMode;
import de.steamwar.bungeecore.Message;
import de.steamwar.bungeecore.Subserver;
import de.steamwar.bungeecore.SubserverSystem;
import de.steamwar.bungeecore.*;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.chat.ClickEvent;
@ -36,8 +33,7 @@ public class HistoricCommand extends BasicCommand {
@Override
public void execute(CommandSender sender, String[] args) {
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);
arena.sendPlayer(player);
Subserver arena = new ServerStarter().arena(mode, map).blueLeader(player).start();
Message.broadcast("HISTORIC_BROADCAST", "HISTORIC_BROADCAST_HOVER"
, new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/arena " + arena.getServer().getName()), mode.getDisplayName(), player.getName());
});

Datei anzeigen

@ -59,12 +59,12 @@ public class JoinmeCommand extends BasicCommand {
if(subserver != null) {
Servertype type = subserver.getType();
if (type == Servertype.ARENA) {
subserver.sendPlayer(player);
SubserverSystem.sendPlayer(subserver, player);
} else if (type == Servertype.BAUSERVER) {
Bauserver bauserver = (Bauserver) subserver;
if (bauserver.getOwner().equals(player.getUniqueId()) ||
BauweltMember.getBauMember(bauserver.getOwner(), player.getUniqueId()) != null) {
subserver.sendPlayer(player);
SubserverSystem.sendPlayer(subserver, player);
} else {
SubserverSystem.sendDeniedMessage(player, bauserver.getOwner());
Message.send("JOIN_PLAYER_BLOCK", player);

Datei anzeigen

@ -0,0 +1,70 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2020 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.commands;
import de.steamwar.bungeecore.ArenaMode;
import de.steamwar.bungeecore.Message;
import de.steamwar.bungeecore.sql.SteamwarUser;
import de.steamwar.bungeecore.sql.UserElo;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.util.Optional;
public class RankCommand extends BasicCommand {
public RankCommand() {
super("rank", null);
}
@Override
public void execute(CommandSender sender, String[] args) {
if(!(sender instanceof ProxiedPlayer))
return;
ProxiedPlayer player = (ProxiedPlayer) sender;
SteamwarUser user = SteamwarUser.get(player.getUniqueId());
if (args.length > 0) {
SteamwarUser nUser = SteamwarUser.get(args[0]);
if (nUser == null) {
Message.send("RANK_PLAYER_NOT_FOUND", player);
return;
}
Message.send("RANK_PLAYER_FOUND", player, nUser.getUserName());
user = nUser;
}
for(ArenaMode mode : ArenaMode.getAllModes()) {
if (!mode.isRanked())
continue;
Message.send("RANK_HEADER", player, mode.getChatName());
Optional<Integer> elo = UserElo.getElo(user.getId(), mode.getSchemType());
if (elo.isPresent()) {
int placement = UserElo.getPlacement(elo.get(), mode.getSchemType());
Message.send("RANK_PLACED", player, placement, elo.get());
} else {
Message.send("RANK_UNPLACED", player);
}
Message.send("RANK_EMBLEM", player, UserElo.getEmblemProgression(player, mode.getChatName(), user.getId()));
}
}
}

Datei anzeigen

@ -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;
import de.steamwar.bungeecore.ArenaMode;
import de.steamwar.bungeecore.Message;
import de.steamwar.bungeecore.SubserverSystem;
import de.steamwar.bungeecore.*;
import de.steamwar.bungeecore.inventory.SWItem;
import de.steamwar.bungeecore.inventory.SWListInv;
import de.steamwar.bungeecore.inventory.SWStreamInv;
@ -29,13 +46,17 @@ public class ReplayCommand extends BasicCommand {
ProxiedPlayer player = (ProxiedPlayer) sender;
new SWStreamInv<>(player, Message.parse("REPLAY_TITLE", player), (click, fight) -> {
if(!fight.isReplayAvailable()) {
Message.send("REPLAY_UNAVAILABLE", player);
return;
}
SteamwarUser user = SteamwarUser.get(player.getUniqueId());
ArenaMode mode = fight.getGameMode();
ServerStarter starter = new ServerStarter().replay(fight.getFightID()).blueLeader(player);
SubserverSystem.startArena(mode, mode.getRandomMap(), 0, 0, 0, fight.getFightID(), null, null, null, null).sendPlayer(player);
if (user.getUserGroup().isAdminGroup() && click.isShiftClick() && fight.replayExists()) {
starter.test(mode, mode.getRandomMap(), player).start();
} else if(!fight.replayAllowed()) {
Message.send("REPLAY_UNAVAILABLE", player);
} else {
starter.arena(mode, mode.getRandomMap()).start();
}
}, page -> Fight.getPage(page, 45).stream().map(fight -> new SWListInv.SWListEntry<>(getFightItem(player, fight), fight)).collect(Collectors.toList())).open();
}
@ -48,11 +69,11 @@ public class ReplayCommand extends BasicCommand {
lore.add(Message.parse("REPLAY_TIME", player, fight.getStartTime()));
lore.add("");
lore.add(Message.parse("REPLAY_SERVER", player, fight.getServer()));
if(!fight.isReplayAvailable())
if(!fight.replayAllowed())
lore.add(Message.parse("REPLAY_UNAVAILABLE", player));
item.setLore(lore);
if(fight.isReplayAvailable())
if(fight.replayAllowed())
item.setEnchanted(true);
return item;

Datei anzeigen

@ -118,12 +118,12 @@ public class TpCommand extends BasicCommand {
if(subserver != null) {
Servertype type = subserver.getType();
if (type == Servertype.ARENA) {
subserver.sendPlayer(player);
SubserverSystem.sendPlayer(subserver, player);
} else if (type == Servertype.BAUSERVER) {
Bauserver bauserver = (Bauserver) subserver;
if (bauserver.getOwner().equals(player.getUniqueId()) ||
BauweltMember.getBauMember(bauserver.getOwner(), player.getUniqueId()) != null) {
subserver.sendPlayer(player);
SubserverSystem.sendPlayer(subserver, player);
} else {
SubserverSystem.sendDeniedMessage(player, bauserver.getOwner());
Message.send("JOIN_PLAYER_BLOCK", player);

Datei anzeigen

@ -0,0 +1,176 @@
/*
* 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.ProxyServer;
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.concurrent.TimeUnit;
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) {
openInventory(player, true, false);
return;
}
switch(args[0].toLowerCase()) {
case "rate":
if(args.length < 2) {
player.chat("/tutorial rate");
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;
}
create(player, Arrays.stream(args).skip(2).collect(Collectors.joining(" ")), args[1].toUpperCase());
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);
}
}
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();
openInventory(player, released, own);
return;
} else if(own && click.isShiftClick() && click.isRightClick()) {
tutorial.delete();
openInventory(player, released, own);
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 personalHighlights) {
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, String.format("%.1f", tutorial.stars())));
if (personalHighlights)
lore.add(Message.parse("TUTORIAL_DELETE", player));
item.setLore(lore);
if (personalHighlights && 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");
ProxyServer.getInstance().getScheduler().schedule(BungeeCore.get(), () -> {
Tutorial tutorial = Tutorial.create(user, name, item);
File tutorialWorld = tutorial.world();
if (tutorialWorld.exists())
SubserverSystem.deleteFolder(Node.local, tutorialWorld.getPath());
ServerStarter.copyWorld(Node.local, tempWorld.getPath(), tutorialWorld.getPath());
Message.send("TUTORIAL_CREATED", player);
}, 1, TimeUnit.SECONDS);
}
}

Datei anzeigen

@ -37,4 +37,5 @@ public class PacketIdManager {
public static final byte I_AM_A_LOBBY = 0x20;
public static final byte FIGHT_INFO = 0x21;
public static final byte FIGHT_ENDS = 0x22;
public static final byte STARTING_SERVER = 0x23;
}

Datei anzeigen

@ -20,15 +20,71 @@
package de.steamwar.bungeecore.comms.handlers;
import com.google.common.io.ByteArrayDataInput;
import de.steamwar.bungeecore.ArenaMode;
import de.steamwar.bungeecore.comms.SpigotHandler;
import de.steamwar.bungeecore.comms.packets.FightEndsPacket;
import de.steamwar.bungeecore.sql.SchemElo;
import de.steamwar.bungeecore.sql.SchematicNode;
import de.steamwar.bungeecore.sql.SchematicType;
import de.steamwar.bungeecore.sql.UserElo;
import net.md_5.bungee.api.config.ServerInfo;
import java.util.List;
public class FightEndsHandler implements SpigotHandler {
private int K = 20;
@Override
public void handle(ByteArrayDataInput in, ServerInfo info) {
FightEndsPacket fightEndsPacket = new FightEndsPacket(in);
if (!ArenaMode.getBySchemType(SchematicType.fromDB(fightEndsPacket.getGameMode())).isRanked()) {
return;
}
int bluePlayerSize = fightEndsPacket.getBluePlayers().size();
int redPlayerSize = fightEndsPacket.getRedPlayers().size();
double playerRatio = bluePlayerSize > redPlayerSize ? (double) redPlayerSize / bluePlayerSize : (double) bluePlayerSize / redPlayerSize;
if (playerRatio < 0.6) {
return;
}
boolean bluePublic = SchematicNode.getSchematicNode(fightEndsPacket.getBlueSchem()).getOwner() == 0;
boolean redPublic = SchematicNode.getSchematicNode(fightEndsPacket.getRedSchem()).getOwner() == 0;
if (bluePublic ^ redPublic) {
return;
}
double blueResult;
if (fightEndsPacket.getWin() == 0) {
blueResult = 0.5;
} else if (fightEndsPacket.getWin() == 1) {
blueResult = 1;
} else {
blueResult = 0;
}
int blueSchemElo = SchemElo.getElo(fightEndsPacket.getBlueSchem());
int redSchemElo = SchemElo.getElo(fightEndsPacket.getRedSchem());
int blueTeamElo = fightEndsPacket.getBluePlayers().stream().mapToInt(player -> UserElo.getEloOrDefault(player, fightEndsPacket.getGameMode())).sum();
int redTeamElo = fightEndsPacket.getRedPlayers().stream().mapToInt(player -> UserElo.getEloOrDefault(player, fightEndsPacket.getGameMode())).sum();
calculateEloOfTeam(fightEndsPacket.getBlueSchem(), blueSchemElo, redSchemElo, blueTeamElo, redTeamElo, blueResult, fightEndsPacket.getBluePlayers(), fightEndsPacket.getGameMode(), bluePublic || redPublic);
calculateEloOfTeam(fightEndsPacket.getRedSchem(), redSchemElo, blueSchemElo, redTeamElo, blueTeamElo, 1 - blueResult, fightEndsPacket.getRedPlayers(), fightEndsPacket.getGameMode(), bluePublic || redPublic);
}
private void calculateEloOfTeam(int schemId, int eloSchemOwn, int eloSchemEnemy, int eloTeamOwn, int eloTeamEnemy, double result, List<Integer> players, String gameMode, boolean noPlayerRank) {
double winSchemExpectation = 1 / (1 + Math.pow(10, (eloSchemEnemy - eloSchemOwn) / 600f));
SchemElo.setElo(schemId, (int) Math.round(eloSchemOwn + K * (result - winSchemExpectation)));
if (noPlayerRank) return;
double winTeamExpectation = 1 / (1 + Math.pow(10, (eloTeamEnemy - eloTeamOwn) / 600f));
for (int player : players) {
int playerElo = UserElo.getEloOrDefault(player, gameMode);
UserElo.setElo(player, gameMode, (int) Math.round(playerElo + K * (result - winTeamExpectation)));
}
}
}

Datei anzeigen

@ -38,6 +38,10 @@ public class FightInfoHandler implements SpigotHandler {
lobbys.add(lobby);
}
public static boolean onLobby(ProxiedPlayer player) {
return lobbys.contains(player.getServer().getInfo());
}
@Override
public void handle(ByteArrayDataInput in, ServerInfo info) {
FightInfoPacket packet = new FightInfoPacket(in);

Datei anzeigen

@ -21,8 +21,7 @@ package de.steamwar.bungeecore.comms.handlers;
import com.google.common.io.ByteArrayDataInput;
import de.steamwar.bungeecore.ArenaMode;
import de.steamwar.bungeecore.SubserverSystem;
import de.steamwar.bungeecore.commands.BauCommand;
import de.steamwar.bungeecore.ServerStarter;
import de.steamwar.bungeecore.comms.SpigotHandler;
import de.steamwar.bungeecore.sql.SchematicType;
import de.steamwar.bungeecore.sql.SteamwarUser;
@ -37,7 +36,6 @@ public class PrepareSchemHandler implements SpigotHandler {
int schematicID = in.readInt();
ArenaMode mode = ArenaMode.getBySchemType(SchematicType.fromDB(in.readUTF()));
BauCommand.stopBauserver(player);
SubserverSystem.startTestServer(player, mode, mode.getRandomMap(), 0, schematicID);
new ServerStarter().test(mode, mode.getRandomMap(), player).prepare(schematicID).start();
}
}

Datei anzeigen

@ -0,0 +1,25 @@
package de.steamwar.bungeecore.comms.packets;
import com.google.common.io.ByteArrayDataOutput;
import de.steamwar.bungeecore.comms.BungeePacket;
import de.steamwar.bungeecore.comms.PacketIdManager;
import de.steamwar.bungeecore.sql.SteamwarUser;
public class StartingServerPacket extends BungeePacket {
private final int user;
public StartingServerPacket(SteamwarUser user) {
this.user = user.getId();
}
@Override
public int getId() {
return PacketIdManager.STARTING_SERVER;
}
@Override
public void writeVars(ByteArrayDataOutput out) {
out.writeInt(user);
}
}

Datei anzeigen

@ -116,6 +116,10 @@ public class SWInventory {
}
public void close() {
close(player);
}
public static void close(ProxiedPlayer player) {
new CloseInventoryPacket(SteamwarUser.get(player).getId()).send(player);
}

Datei anzeigen

@ -23,10 +23,7 @@ import de.steamwar.bungeecore.*;
import de.steamwar.bungeecore.bot.SteamwarDiscordBot;
import de.steamwar.bungeecore.commands.TpCommand;
import de.steamwar.bungeecore.comms.packets.PingPacket;
import de.steamwar.bungeecore.sql.Punishment;
import de.steamwar.bungeecore.sql.SteamwarUser;
import de.steamwar.bungeecore.sql.Team;
import de.steamwar.bungeecore.sql.UserGroup;
import de.steamwar.bungeecore.sql.*;
import net.md_5.bungee.api.*;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.connection.ProxiedPlayer;
@ -200,7 +197,7 @@ public class ChatListener extends BasicListener {
}
private void publicChat(SteamwarUser user, ProxiedPlayer sender, String message){
String name = sender.getDisplayName();
String name = UserElo.getEmblem(user) + sender.getDisplayName();
String chatcolor = user.getUserGroup().getChatColorCode();
if(user.getUserGroup() != UserGroup.Member || user.getTeam() == 12 || user.getTeam() == 285 || user.getTeam() == 54)

Datei anzeigen

@ -76,10 +76,10 @@ public class ConnectionListener extends BasicListener {
if(user.getUserGroup() != UserGroup.Member) {
player.setPermission(YOUTUBER_MODS, true);
player.setDisplayName(user.getUserGroup().getColorCode() + user.getUserGroup().name() + " " + player.getName() + "§r");
player.setDisplayName(user.getUserGroup().getColorCode() + user.getUserGroup().getChatPrefix() + " " + player.getName() + "§r");
player.setPermission("bungeecore.group." + user.getUserGroup().name().toLowerCase(), true);
}else {
player.setDisplayName(player.getName());
player.setDisplayName("§f" + player.getName());
}
for(Subserver subserver : Subserver.getServerList()){

Datei anzeigen

@ -1,52 +0,0 @@
/*
This file is a part of the SteamWar software.
Copyright (C) 2020 SteamWar.de-Serverteam
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.sql;
public class Elo {
private static final Statement elo = new Statement("SELECT Elo FROM Elo WHERE UserID = ? AND GameMode = ? AND Season = ?");
private static final Statement place = new Statement("SELECT COUNT(*) AS Place FROM Elo WHERE GameMode = ? AND Elo > ? AND Season = ?");
private Elo(){}
public static int getElo(int userID, String gameMode){
return getElo(Season.getSeason(), userID, gameMode);
}
public static int getElo(int season, int userID, String gameMode){
return elo.select(rs -> {
if(rs.next())
return rs.getInt("Elo");
return 1000;
}, userID, gameMode, season);
}
public static int getPlacement(int elo, String gameMode){
return getPlacement(Season.getSeason(), elo, gameMode);
}
public static int getPlacement(int season, int elo, String gameMode){
return place.select(rs -> {
if(rs.next())
return rs.getInt("Place");
return -1;
}, gameMode, elo, season);
}
}

Datei anzeigen

@ -5,30 +5,25 @@ import de.steamwar.bungeecore.ArenaMode;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class Fight {
private static final Statement getPage = new Statement("SELECT FightID, GameMode, Server, StartTime, Duration, BlueLeader, RedLeader, BlueSchem, RedSchem, Win, WinCondition, ReplayLock, Replay is not NULL AS ReplayAvailable FROM Fight ORDER BY FightID DESC LIMIT ?, ?");
private static final Statement getPage = new Statement("SELECT f.FightID, f.GameMode, f.Server, f.StartTime, f.BlueLeader, f.RedLeader, (b.NodeId IS NULL OR b.AllowReplay) AND (r.NodeId IS NULL OR r.AllowReplay) AS ReplayAllowed, f.Win, f.Replay IS NOT NULL AS ReplayExists FROM Fight f LEFT OUTER JOIN SchematicNode b ON f.BlueSchem = b.NodeId LEFT OUTER JOIN SchematicNode r ON f.RedSchem = r.NodeId ORDER BY FightID DESC LIMIT ?, ?");
private final int fightID;
private final String gameMode;
private final String server;
private final Timestamp startTime;
private final int duration;
private final int blueLeader;
private final int redLeader;
private final int blueSchem;
private final int redSchem;
private final int win;
private final String winCondition;
private final Timestamp replayLock;
private final boolean replayAvailable;
private final boolean replayExists;
private final boolean replayAllowed;
private final List<FightPlayer> bluePlayers = new ArrayList<>();
private final List<FightPlayer> redPlayers = new ArrayList<>();
@ -38,15 +33,11 @@ public class Fight {
gameMode = rs.getString("GameMode");
server = rs.getString("Server");
startTime = rs.getTimestamp("StartTime");
duration = rs.getInt("Duration");
blueLeader = rs.getInt("BlueLeader");
redLeader = rs.getInt("RedLeader");
blueSchem = rs.getInt("BlueSchem");
redSchem = rs.getInt("RedSchem");
replayAllowed = rs.getBoolean("ReplayAllowed");
win = rs.getInt("Win");
winCondition = rs.getString("WinCondition");
replayLock = rs.getTimestamp("ReplayLock");
replayAvailable = rs.getBoolean("ReplayAvailable");
replayExists = rs.getBoolean("ReplayExists");
}
private void initPlayers(List<FightPlayer> fightPlayers) {
@ -122,7 +113,11 @@ public class Fight {
return redPlayers;
}
public boolean isReplayAvailable() {
return replayAvailable && replayLock.before(Timestamp.from(Instant.now())) && getGameMode() != null;
public boolean replayAllowed() {
return replayExists() && replayAllowed;
}
public boolean replayExists() {
return replayExists && getGameMode() != null;
}
}

Datei anzeigen

@ -0,0 +1,49 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2020 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.sql;
import static de.steamwar.bungeecore.sql.UserElo.ELO_DEFAULT;
public class SchemElo {
private SchemElo() {}
private static final Statement elo = new Statement("SELECT Elo FROM SchemElo WHERE SchemID = ? AND Season = ?");
private static final Statement setElo = new Statement("INSERT INTO SchemElo (Season, SchemID, Elo) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE Elo = VALUES(Elo)");
public static int getElo(int schemID) {
return getElo(Season.getSeason(), schemID);
}
public static int getElo(int season, int schemID) {
return elo.select(rs -> {
if (rs.next())
return rs.getInt("Elo");
return ELO_DEFAULT;
}, schemID, season);
}
public static void setElo(int schemID, int elo) {
setElo(Season.getSeason(), schemID, elo);
}
public static void setElo(int season, int schemID, int elo) {
setElo.update(season, schemID, elo);
}
}

Datei anzeigen

@ -30,6 +30,11 @@ public class Season {
return (calendar.get(Calendar.YEAR) * 3 + yearIndex);
}
public static String getSeasonStart() {
Calendar calendar = Calendar.getInstance();
return calendar.get(Calendar.YEAR) + "-" + (calendar.get(Calendar.MONTH) / 3 * 3 + 1) + "-1";
}
public static String convertSeasonToString(int season){
if (season == -1) return "";
int yearSeason = season % 3;

Datei anzeigen

@ -0,0 +1,137 @@
/*
* 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 de.steamwar.bungeecore.Node;
import de.steamwar.bungeecore.ServerStarter;
import de.steamwar.bungeecore.SubserverSystem;
import java.io.File;
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 = ?");
private static final Statement delete = new Statement("DELETE FROM Tutorial 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 delete() {
delete.update(id);
SubserverSystem.deleteFolder(Node.local, world().getPath());
}
public File world() {
return new File(ServerStarter.TUTORIAL_PATH, String.valueOf(id));
}
public void rate(SteamwarUser user, int rating) {
rate.update(id, user.getId(), rating);
}
}

Datei anzeigen

@ -0,0 +1,175 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2020 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.sql;
import de.steamwar.bungeecore.ArenaMode;
import de.steamwar.bungeecore.Message;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
public class UserElo {
private UserElo() {}
public static final int ELO_DEFAULT = 1000;
private static final Map<String, Map<Integer, Optional<Integer>>> gameModeUserEloCache = new HashMap<>();
private static final Map<String, Integer> maxEloCache = new HashMap<>();
private static final Map<Integer, String> emblemCache = new HashMap<>();
private static final Statement elo = new Statement("SELECT Elo FROM UserElo WHERE UserID = ? AND GameMode = ? AND Season = ?");
private static final Statement setElo = new Statement("INSERT INTO UserElo (Season, GameMode, UserID, Elo) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE Elo = VALUES(Elo)");
private static final Statement maxElo = new Statement("SELECT MAX(Elo) AS MaxElo FROM UserElo WHERE Season = ? AND GameMode = ?");
private static final Statement place = new Statement("SELECT COUNT(*) AS Place FROM UserElo WHERE GameMode = ? AND Elo > ? AND Season = ?");
private static final Statement fightsOfSeason = new Statement("SELECT COUNT(*) AS Fights FROM FightPlayer INNER JOIN Fight F on FightPlayer.FightID = F.FightID WHERE UserID = ? AND GameMode = ? AND UNIX_TIMESTAMP(StartTime) + Duration >= UNIX_TIMESTAMP(?)");
public static int getEloOrDefault(int userID, String gameMode) {
return getElo(userID, gameMode).orElse(ELO_DEFAULT);
}
public static Optional<Integer> getElo(int userID, String gameMode) {
return gameModeUserEloCache.computeIfAbsent(gameMode, gm -> new HashMap<>()).computeIfAbsent(userID, uid -> elo.select(rs -> {
if (rs.next())
return Optional.of(rs.getInt("Elo"));
return Optional.empty();
}, userID, gameMode, Season.getSeason()));
}
private static int getFightsOfSeason(int userID, String gameMode) {
return fightsOfSeason.select(rs -> {
if (rs.next())
return rs.getInt("Fights");
return 0;
}, userID, gameMode, Season.getSeasonStart());
}
private static int getMaxElo(String gameMode) {
return maxEloCache.computeIfAbsent(gameMode, gm -> maxElo.select(rs -> {
if (rs.next())
return rs.getInt("MaxElo");
return 0;
}, Season.getSeason(), gameMode));
}
public static void setElo(int userId, String gameMode, int elo) {
emblemCache.remove(userId);
Optional<Integer> oldElo = Optional.ofNullable(gameModeUserEloCache.computeIfAbsent(gameMode, gm -> new HashMap<>()).put(userId, Optional.of(elo))).orElse(Optional.empty());
int maxElo = getMaxElo(gameMode);
if (elo > maxElo || (oldElo.isPresent() && oldElo.get() == maxElo)) {
maxEloCache.remove(gameMode);
emblemCache.clear();
}
setElo.update(Season.getSeason(), gameMode, userId, elo);
}
public static int getPlacement(int elo, String gameMode) {
return place.select(rs -> {
if (rs.next())
return rs.getInt("Place") + 1;
return -1;
}, gameMode, elo, Season.getSeason());
}
public static String getEmblem(SteamwarUser user) {
return emblemCache.computeIfAbsent(user.getId(), userId -> {
switch(
ArenaMode.getAllModes().stream().filter(
ArenaMode::isRanked
).filter(
mode -> UserElo.getFightsOfSeason(user.getId(), mode.getSchemType()) >= 10
).map(
mode -> getProgression(user.getId(), mode.getSchemType())
).max(Integer::compareTo).orElse(0)
) {
case 0:
return "";
case 1:
return "§7✧ ";
case 2:
return "§f✦ ";
case 3:
return "§e✶ ";
case 4:
return "§a✷ ";
case 5:
return "§b✸ ";
case 6:
return "§c✹ ";
case 7:
return "§5❂ ";
default:
throw new SecurityException("Progression out of range");
}
});
}
public static String getEmblemProgression(ProxiedPlayer player, String gameMode, int userId) {
int fightsOfSeason = getFightsOfSeason(userId, gameMode);
if (fightsOfSeason < 10)
return Message.parse("RANK_NEEDED_FIGHTS_LEFT", player, "§8✧ ✦ ✶ ✷ ✸ ✹ ❂", 10 - fightsOfSeason);
switch (getProgression(userId, gameMode)) {
case 0:
return "§8✧ ✦ ✶ ✷ ✸ ✹ ❂";
case 1:
return "§7✧ §8✦ ✶ ✷ ✸ ✹ ❂";
case 2:
return "§8✧ §f✦ §8✶ ✷ ✸ ✹ ❂";
case 3:
return "§8✧ ✦ §e✶ §8✷ ✸ ✹ ❂";
case 4:
return "§8✧ ✦ ✶ §a✷ §8✸ ✹ ❂";
case 5:
return "§8✧ ✦ ✶ ✷ §b✸ §8✹ ❂";
case 6:
return "§8✧ ✦ ✶ ✷ ✸ §c✹ §8❂";
case 7:
return "§8✧ ✦ ✶ ✷ ✸ ✹ §5❂";
default:
throw new SecurityException("Progression is not in range");
}
}
private static int getProgression(int userId, String gameMode) {
int elo = UserElo.getElo(userId, gameMode).orElse(0);
if(elo == 0)
return 0;
int maxElo = UserElo.getMaxElo(gameMode);
if (elo > maxElo * 0.99) return 7;
if (elo > maxElo * 0.97) return 6;
if (elo > maxElo * 0.94) return 5;
if (elo > maxElo * 0.88) return 4;
if (elo > maxElo * 0.76) return 3;
if (elo > maxElo * 0.51) return 2;
return 1;
}
public static void clearCache() {
gameModeUserEloCache.clear();
maxEloCache.clear();
emblemCache.clear();
}
}

Datei anzeigen

@ -24,24 +24,26 @@ import java.util.stream.Collectors;
public enum UserGroup {
Admin("§4", "§e", true, true, true, true),
Developer("§3", "§f", true, true, true, true),
Moderator("§c", "§f", true, true, true, true),
Supporter("§9", "§f", false, true, true, true),
Builder("§2", "§f", false, true, false, true),
YouTuber("§5", "§f", false, false, false, true),
Member("§7", "§7", false, false, false, false);
Admin("§4", "§e", "Admin", true, true, true, true),
Developer("§3", "§f", "Dev", true, true, true, true),
Moderator("§c", "§f", "Mod", true, true, true, true),
Supporter("§9", "§f", "Sup", false, true, true, true),
Builder("§2", "§f", "Arch", false, true, false, true),
YouTuber("§5", "§f", "YT", false, false, false, true),
Member("§7", "§7", "", false, false, false, false);
private final String colorCode;
private final String chatColorCode;
private final String chatPrefix;
private final boolean adminGroup;
private final boolean teamGroup;
private final boolean checkSchematics;
private final boolean privilegedMods;
UserGroup(String colorCode, String chatColorCode, boolean adminGroup, boolean teamGroup, boolean checkSchematics, boolean privilegedMods) {
UserGroup(String colorCode, String chatColorCode, String chatPrefix, boolean adminGroup, boolean teamGroup, boolean checkSchematics, boolean privilegedMods) {
this.colorCode = colorCode;
this.chatColorCode = chatColorCode;
this.chatPrefix = chatPrefix;
this.adminGroup = adminGroup;
this.teamGroup = teamGroup;
this.checkSchematics = checkSchematics;
@ -75,4 +77,8 @@ public enum UserGroup {
public static UserGroup getUsergroup(String name) {
return Arrays.stream(UserGroup.values()).filter(userGroup -> userGroup.name().equalsIgnoreCase(name)).collect(Collectors.toList()).get(0);
}
public String getChatPrefix() {
return chatPrefix;
}
}

Datei anzeigen

@ -333,6 +333,19 @@ REPLAY_LOSER=§e{0} §7+§e{1}
REPLAY_TIME=§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_DELETE=§cMit Shift+Rechtsklick löschen
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
STC_USAGE=§8/§7stc §8[§eNachricht an das Team§8]
STC_FORMAT=§8STC §e{0}» §r{1}
@ -561,3 +574,12 @@ HOURS_PLAYED=§7Deine Spielzeit beträgt§8: §e{0}h
#Arena command
ARENA_NOT_FOUND=§cDie angegebene Arena konnte nicht gefunden werden
#Rank
RANK_PLAYER_NOT_FOUND=§cSpieler nicht gefunden
RANK_PLAYER_FOUND=§eRang §7von §e{0}
RANK_HEADER=§7§lModus {0}
RANK_UNPLACED=§eunplatziert
RANK_PLACED=§e{0}§8. §7mit §e{1} §7Elo§8.
RANK_EMBLEM=§eEmblem§8: {0}
RANK_NEEDED_FIGHTS_LEFT={0} §8(§7noch §e{1}§7 Kämpfe nötig§8)