geforkt von SteamWar/BungeeCore
Merge branch 'master' into fabric_mod_sender
Dieser Commit ist enthalten in:
Commit
626a876f0f
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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){
|
||||
|
@ -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{
|
||||
|
@ -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))
|
||||
|
@ -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){
|
||||
|
@ -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());
|
||||
});
|
||||
|
@ -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());
|
||||
});
|
||||
|
@ -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);
|
||||
|
70
src/de/steamwar/bungeecore/commands/RankCommand.java
Normale Datei
70
src/de/steamwar/bungeecore/commands/RankCommand.java
Normale Datei
@ -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()));
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -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);
|
||||
|
176
src/de/steamwar/bungeecore/commands/TutorialCommand.java
Normale Datei
176
src/de/steamwar/bungeecore/commands/TutorialCommand.java
Normale Datei
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
25
src/de/steamwar/bungeecore/comms/packets/StartingServerPacket.java
Normale Datei
25
src/de/steamwar/bungeecore/comms/packets/StartingServerPacket.java
Normale Datei
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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()){
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
49
src/de/steamwar/bungeecore/sql/SchemElo.java
Normale Datei
49
src/de/steamwar/bungeecore/sql/SchemElo.java
Normale Datei
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
137
src/de/steamwar/bungeecore/sql/Tutorial.java
Normale Datei
137
src/de/steamwar/bungeecore/sql/Tutorial.java
Normale Datei
@ -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);
|
||||
}
|
||||
}
|
175
src/de/steamwar/bungeecore/sql/UserElo.java
Normale Datei
175
src/de/steamwar/bungeecore/sql/UserElo.java
Normale Datei
@ -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();
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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)
|
||||
|
In neuem Issue referenzieren
Einen Benutzer sperren