diff --git a/src/de/steamwar/bungeecore/BungeeCore.java b/src/de/steamwar/bungeecore/BungeeCore.java index f2bd01f1..5d78dc15 100644 --- a/src/de/steamwar/bungeecore/BungeeCore.java +++ b/src/de/steamwar/bungeecore/BungeeCore.java @@ -128,6 +128,7 @@ public class BungeeCore extends Plugin { new ListCommand(); new StatCommand(); new VerifyCommand(); + new ReplayCommand(); if(!EVENT_MODE){ new WebregisterCommand(); diff --git a/src/de/steamwar/bungeecore/SubserverSystem.java b/src/de/steamwar/bungeecore/SubserverSystem.java index d5e85b03..714fbc5e 100644 --- a/src/de/steamwar/bungeecore/SubserverSystem.java +++ b/src/de/steamwar/bungeecore/SubserverSystem.java @@ -66,6 +66,7 @@ public class SubserverSystem { * 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) @@ -89,7 +90,7 @@ public class SubserverSystem { * @return * The new started subserver. */ - public static synchronized Subserver startArena(ArenaMode modus, String map, int eventFightID, int checkSchemID, int prepareSchemID, String serverName, String mapName, UUID player1, UUID player2, boolean ranked){ + 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, boolean ranked){ //Generate missing parameters int port = freePort(FIRST_ARENA_PORT); @@ -132,6 +133,7 @@ public class SubserverSystem { "ranked=" + ranked, "checkSchemID=" + checkSchemID, "prepareSchemID=" + prepareSchemID, + "replay=" + replayID, player1 != null && eventFightID != -1 ? "blueLeader=" + player1 : null, player2 != null ? "redLeader=" + player2 : null); @@ -168,7 +170,7 @@ public class SubserverSystem { eventFight.getFightID(), 0, 0, - serverName, + 0, serverName, serverName.replace(' ', '_') + eventFight.getStartTime().toLocalDateTime().format(DateTimeFormatter.ISO_TIME), null, null, @@ -176,7 +178,7 @@ public class SubserverSystem { } public static void startTestServer(ProxiedPlayer p, ArenaMode m, String map, int checkSchemId, int prepareSchemId){ - startArena(m, map, -1, checkSchemId, prepareSchemId, p.getName() + "s Bau", p.getName(), p.getUniqueId(), null, false).sendPlayer(p); + startArena(m, map, -1, checkSchemId, prepareSchemId, 0, p.getName() + "s Bau", p.getName(), p.getUniqueId(), null, false).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){ diff --git a/src/de/steamwar/bungeecore/commands/ChallengeCommand.java b/src/de/steamwar/bungeecore/commands/ChallengeCommand.java index 3d4150d3..a059c8d5 100644 --- a/src/de/steamwar/bungeecore/commands/ChallengeCommand.java +++ b/src/de/steamwar/bungeecore/commands/ChallengeCommand.java @@ -75,7 +75,7 @@ public class ChallengeCommand extends BasicCommand { challenges.remove(target); challenges.remove(player); - Subserver arena = SubserverSystem.startArena(mode, map, 0, 0, 0, null, null, player.getUniqueId(), target.getUniqueId(), false); + Subserver arena = SubserverSystem.startArena(mode, map, 0, 0, 0, 0, null, null, player.getUniqueId(), target.getUniqueId(), false); arena.sendPlayer(player); arena.sendPlayer(target); diff --git a/src/de/steamwar/bungeecore/commands/FightCommand.java b/src/de/steamwar/bungeecore/commands/FightCommand.java index 984bc06b..65eea1c6 100644 --- a/src/de/steamwar/bungeecore/commands/FightCommand.java +++ b/src/de/steamwar/bungeecore/commands/FightCommand.java @@ -164,7 +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, null, null, player.getUniqueId(), null, false); + Subserver arena = SubserverSystem.startArena(mode, map, 0, 0, 0, 0, null, null, player.getUniqueId(), null, false); arena.sendPlayer(player); Message.broadcast("FIGHT_BROADCAST", "FIGHT_BROADCAST_HOVER" , new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/join " + player.getName()), mode.getDisplayName(), player.getName()); diff --git a/src/de/steamwar/bungeecore/commands/HistoricCommand.java b/src/de/steamwar/bungeecore/commands/HistoricCommand.java index ebf93123..b7d8e4e1 100644 --- a/src/de/steamwar/bungeecore/commands/HistoricCommand.java +++ b/src/de/steamwar/bungeecore/commands/HistoricCommand.java @@ -33,7 +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, null, null, player.getUniqueId(), null, false); + Subserver arena = SubserverSystem.startArena(mode, map, 0, 0, 0, 0, null, null, player.getUniqueId(), null, false); arena.sendPlayer(player); Message.broadcast("HISTORIC_BROADCAST", "HISTORIC_BROADCAST_HOVER" , new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/join " + player.getName()), mode.getDisplayName(), player.getName()); diff --git a/src/de/steamwar/bungeecore/commands/RankedCommand.java b/src/de/steamwar/bungeecore/commands/RankedCommand.java index 1a978b55..a1666cbe 100644 --- a/src/de/steamwar/bungeecore/commands/RankedCommand.java +++ b/src/de/steamwar/bungeecore/commands/RankedCommand.java @@ -165,7 +165,7 @@ public class RankedCommand extends BasicCommand { removeFromAll(wp1.player); removeFromAll(wp2.player); - Subserver arena = SubserverSystem.startArena(mode, mode.getRandomMap(), 0, 0, 0, null, null, wp1.player.getUniqueId(), wp2.player.getUniqueId(), true); + Subserver arena = SubserverSystem.startArena(mode, mode.getRandomMap(), 0, 0, 0, 0, null, null, wp1.player.getUniqueId(), wp2.player.getUniqueId(), true); arena.sendPlayer(wp1.player); arena.sendPlayer(wp2.player); diff --git a/src/de/steamwar/bungeecore/commands/ReplayCommand.java b/src/de/steamwar/bungeecore/commands/ReplayCommand.java new file mode 100644 index 00000000..71d92806 --- /dev/null +++ b/src/de/steamwar/bungeecore/commands/ReplayCommand.java @@ -0,0 +1,51 @@ +package de.steamwar.bungeecore.commands; + +import de.steamwar.bungeecore.ArenaMode; +import de.steamwar.bungeecore.SubserverSystem; +import de.steamwar.bungeecore.inventory.SWItem; +import de.steamwar.bungeecore.inventory.SWListInv; +import de.steamwar.bungeecore.inventory.SWStreamInv; +import de.steamwar.bungeecore.sql.Fight; +import net.md_5.bungee.api.CommandSender; +import net.md_5.bungee.api.connection.ProxiedPlayer; + +import java.util.Arrays; +import java.util.stream.Collectors; + +public class ReplayCommand extends BasicCommand { + + public ReplayCommand() { + super("replay", null); + } + + @Override + public void execute(CommandSender sender, String[] args) { + if(!(sender instanceof ProxiedPlayer)) + return; + + //TODO Translate + ProxiedPlayer player = (ProxiedPlayer) sender; + new SWStreamInv<>(player, "Letzte Kämpfe", (click, fight) -> { + ArenaMode mode = fight.getGameMode(); + if(mode == null){ + player.sendMessage("Replay kann aufgrund deaktivertem Spielmodus nicht gestartet werden"); + return; + } + + SubserverSystem.startArena(mode, mode.getRandomMap(), 0, 0, 0, fight.getFightID(), null, null, null, null, false).sendPlayer(player); + }, page -> Fight.getPage(page, 45).stream().map(fight -> new SWListInv.SWListEntry<>(getFightItem(player, fight), fight)).collect(Collectors.toList())).open(); + } + + private SWItem getFightItem(ProxiedPlayer player, Fight fight) { + String title = "§3" + (fight.getWin() == 1 ? "§l" : "") + fight.getBlueLeader().getUserName() + " §r§8vs §c" + (fight.getWin() == 2 ? "§l" : "") + fight.getRedLeader().getUserName(); + SWItem item = new SWItem("JUKEBOX", title); + item.setLore(Arrays.asList( + "§7" + fight.getStartTime().toString(), + "§7" + fight.getServer(), + "§7" + fight.getWinCondition() + " §8nach §e" + fight.getDuration() + "§8s", + fight.getBluePlayers().size() > 1 ? "§3+" + (fight.getBluePlayers().size() - 1) + " §8Spieler" : "", + fight.getRedPlayers().size() > 1 ? "§c+" + (fight.getRedPlayers().size() - 1) + " §8Spieler" : "" + )); + return item; + } +} diff --git a/src/de/steamwar/bungeecore/inventory/SWStreamInv.java b/src/de/steamwar/bungeecore/inventory/SWStreamInv.java new file mode 100644 index 00000000..ef41dcb3 --- /dev/null +++ b/src/de/steamwar/bungeecore/inventory/SWStreamInv.java @@ -0,0 +1,51 @@ +package de.steamwar.bungeecore.inventory; + +import net.md_5.bungee.api.connection.ProxiedPlayer; + +import java.util.List; +import java.util.function.Function; + +public class SWStreamInv extends SWInventory { + private final SWListInv.ListCallback callback; + private final Function>> constructor; + private int page; + + public SWStreamInv(ProxiedPlayer proxiedPlayer, String title, SWListInv.ListCallback callback, Function>> constructor) { + super(proxiedPlayer, 54, title); + this.callback = callback; + this.constructor = constructor; + page = 0; + } + + @Override + public void open(){ + List> entries = constructor.apply(page); + + if(page != 0) + addItem(45, new SWItem("§eSeite zurück", 10), (InvCallback.ClickType click) -> { + page--; + open(); + }); + else + addItem(45, new SWItem("§7Seite zurück", 8), (InvCallback.ClickType click) -> {}); + + if(entries.size() < 45) + addItem(53, new SWItem("§eSeite vor", 10), (InvCallback.ClickType click) -> { + page++; + open(); + }); + else + addItem(53, new SWItem("§eSeite vor", 8), (InvCallback.ClickType click) -> {}); + + for(int i = 0; i < entries.size(); i++) { + SWListInv.SWListEntry item = entries.get(i); + addItem(i, item.getItem()); + setCallback(i, (InvCallback.ClickType click) -> { + close(); + callback.clicked(click, item.getObject()); + }); + } + + super.open(); + } +} diff --git a/src/de/steamwar/bungeecore/sql/Fight.java b/src/de/steamwar/bungeecore/sql/Fight.java new file mode 100644 index 00000000..08c24e60 --- /dev/null +++ b/src/de/steamwar/bungeecore/sql/Fight.java @@ -0,0 +1,126 @@ +package de.steamwar.bungeecore.sql; + +import de.steamwar.bungeecore.ArenaMode; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +public class Fight { + + 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 List bluePlayers = new ArrayList<>(); + private final List redPlayers = new ArrayList<>(); + + private Fight(ResultSet rs) throws SQLException { + fightID = rs.getInt("FightID"); + 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"); + win = rs.getInt("Win"); + winCondition = rs.getString("WinCondition"); + } + + private void initPlayers(List fightPlayers) { + for(FightPlayer fp : fightPlayers) { + if(fp.getFightID() != fightID) + continue; + + if(fp.getTeam() == 1) + bluePlayers.add(fp); + else + redPlayers.add(fp); + } + } + + public static List getPage(int page, int elementsPerPage) { + ResultSet rs = SQL.select("SELECT FightID, GameMode, Server, StartTime, Duration, BlueLeader, RedLeader, BlueSchem, RedSchem, Win, WinCondition FROM Fight WHERE Replay is not NULL ORDER BY FightID DESC LIMIT ?, ?", page * elementsPerPage, elementsPerPage); + List fights = new ArrayList<>(); + try { + while(rs.next()){ + fights.add(new Fight(rs)); + } + }catch (SQLException e) { + throw new SecurityException("Could not load Fights", e); + } + + List fightPlayers = FightPlayer.batchGet(fights.stream().map(f -> f.fightID).collect(Collectors.toSet())); + for(Fight fight : fights) { + fight.initPlayers(fightPlayers); + } + + SteamwarUser.batchCache(fightPlayers.stream().map(FightPlayer::getUserID).collect(Collectors.toSet())); + return fights; + } + + public ArenaMode getGameMode() { + SchematicType schemType = SchematicType.fromDB(gameMode); + if(schemType == null) + return null; + return ArenaMode.getBySchemType(schemType); + } + + public String getRawGameMode() { + return gameMode; + } + + public int getFightID() { + return fightID; + } + + public Timestamp getStartTime() { + return startTime; + } + + public int getDuration() { + return duration; + } + + public SteamwarUser getBlueLeader() { + return SteamwarUser.get(blueLeader); + } + + public SteamwarUser getRedLeader() { + return SteamwarUser.get(redLeader); + } + + public int getWin() { + return win; + } + + public String getServer() { + return server; + } + + public String getWinCondition() { + return winCondition; + } + + public List getBluePlayers() { + return bluePlayers; + } + + public List getRedPlayers() { + return redPlayers; + } +} diff --git a/src/de/steamwar/bungeecore/sql/FightPlayer.java b/src/de/steamwar/bungeecore/sql/FightPlayer.java new file mode 100644 index 00000000..760bf815 --- /dev/null +++ b/src/de/steamwar/bungeecore/sql/FightPlayer.java @@ -0,0 +1,55 @@ +package de.steamwar.bungeecore.sql; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +public class FightPlayer { + + private final int fightID; + private final int userID; + private final int team; + private final String kit; + private final int kills; + private final boolean isOut; + + private FightPlayer(ResultSet rs) throws SQLException { + fightID = rs.getInt("FightID"); + userID = rs.getInt("UserID"); + team = rs.getInt("Team"); + kit = rs.getString("Kit"); + kills = rs.getInt("Kills"); + isOut = rs.getBoolean("IsOut"); + } + + public static List batchGet(Set fightIds) { + List fightPlayers = new ArrayList<>(); + if(fightIds.isEmpty()) + return fightPlayers; + + ResultSet rs = SQL.select("SELECT * FROM FightPlayer WHERE FightID IN (" + fightIds.stream().map(Object::toString).collect(Collectors.joining(", ")) + ")"); + try { + while(rs.next()){ + fightPlayers.add(new FightPlayer(rs)); + } + }catch (SQLException e) { + throw new SecurityException("Could not load FightPlayers", e); + } + return fightPlayers; + } + + public int getFightID() { + return fightID; + } + + public int getTeam() { + return team; + } + + public int getUserID() { + return userID; + } +} diff --git a/src/de/steamwar/bungeecore/sql/SteamwarUser.java b/src/de/steamwar/bungeecore/sql/SteamwarUser.java index 00fd2218..063adcd0 100644 --- a/src/de/steamwar/bungeecore/sql/SteamwarUser.java +++ b/src/de/steamwar/bungeecore/sql/SteamwarUser.java @@ -24,24 +24,22 @@ import de.steamwar.bungeecore.BungeeCore; import de.steamwar.bungeecore.Message; import de.steamwar.bungeecore.commands.WebregisterCommand; import de.steamwar.bungeecore.listeners.ConnectionListener; -import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.Scanner; import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.chat.TextComponent; import net.md_5.bungee.api.connection.PendingConnection; import net.md_5.bungee.api.connection.ProxiedPlayer; +import java.io.IOException; import java.net.InetAddress; +import java.net.MalformedURLException; +import java.net.URL; import java.net.UnknownHostException; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Timestamp; import java.time.format.DateTimeFormatter; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; +import java.util.*; +import java.util.stream.Collectors; public class SteamwarUser { @@ -151,6 +149,17 @@ public class SteamwarUser { return dbInit(SQL.select("SELECT * FROM UserData WHERE id = ?", id)); } + public static void batchCache(Set ids) { + ids.removeIf(usersById::containsKey); + + if(!ids.isEmpty()) { + ResultSet rs = SQL.select("SELECT * FROM UserData WHERE id IN (" + ids.stream().map(Object::toString).collect(Collectors.joining(", ")) + ")"); + while(dbInit(rs) != null) { + // nothing to do + } + } + } + public static SteamwarUser get(Long discordId) { if(usersByDiscord.containsKey(discordId.toString())) return usersByDiscord.get(discordId.toString());