From afd054103966276217285cdc28d7d5109cefe7e8 Mon Sep 17 00:00:00 2001 From: Lixfel Date: Fri, 17 Jan 2025 13:46:02 +0100 Subject: [PATCH] Move Replays to File system --- CommonCore/SQL/src/de/steamwar/sql/Fight.java | 11 ++- .../SQL/src/de/steamwar/sql/Replay.java | 74 ------------------- .../fightsystem/record/FileSource.java | 11 ++- .../fightsystem/utils/FightStatistics.java | 9 ++- 4 files changed, 22 insertions(+), 83 deletions(-) delete mode 100644 CommonCore/SQL/src/de/steamwar/sql/Replay.java diff --git a/CommonCore/SQL/src/de/steamwar/sql/Fight.java b/CommonCore/SQL/src/de/steamwar/sql/Fight.java index efa230d2..66efbef9 100644 --- a/CommonCore/SQL/src/de/steamwar/sql/Fight.java +++ b/CommonCore/SQL/src/de/steamwar/sql/Fight.java @@ -35,8 +35,9 @@ import java.util.stream.Collectors; public class Fight { private static final Table table = new Table<>(Fight.class); - private static final SelectStatement getPage = new SelectStatement<>(table, "SELECT f.*, (b.NodeId IS NULL OR b.AllowReplay) AND (r.NodeId IS NULL OR r.AllowReplay) AS ReplayAllowed, (SELECT COUNT(1) FROM Replay WHERE Replay.FightID = f.FightID) as ReplayAvailable 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 static final SelectStatement getPage = new SelectStatement<>(table, "SELECT f.*, (b.NodeId IS NULL OR b.AllowReplay) AND (r.NodeId IS NULL OR r.AllowReplay) AS ReplayAllowed 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 static final Statement insert = table.insertFields(true, "GameMode", "Server", "StartTime", "Duration", "BlueLeader", "RedLeader", "BlueSchem", "RedSchem", "Win", "WinCondition"); + private static final Statement updateReplayAvailable = table.update(Table.PRIMARY, "ReplayAvailable"); public static List getPage(int page, int elementsPerPage) { List fights = getPage.listSelect(page * elementsPerPage, elementsPerPage); @@ -54,6 +55,10 @@ public class Fight { return insert.insertGetKey(gamemode, server, starttime, duration, blueleader, redleader, blueschem, redschem, win, wincondition); } + public static void markReplayAvailable(int fightID) { + updateReplayAvailable.update(true, fightID); + } + @Getter @Field(keys = {Table.PRIMARY}, autoincrement = true) private final int fightID; @@ -80,10 +85,10 @@ public class Fight { private final int win; @Field private final String wincondition; + @Field + private final boolean replayAvailable; @Field // Virtual field for easy select private final boolean replayAllowed; - @Field // Virtual field for easy select - private final boolean replayAvailable; @Getter private final List bluePlayers = new ArrayList<>(); diff --git a/CommonCore/SQL/src/de/steamwar/sql/Replay.java b/CommonCore/SQL/src/de/steamwar/sql/Replay.java deleted file mode 100644 index a90e2392..00000000 --- a/CommonCore/SQL/src/de/steamwar/sql/Replay.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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 . - */ - -package de.steamwar.sql; - -import de.steamwar.sql.internal.*; -import lombok.AllArgsConstructor; -import lombok.Getter; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.StandardCopyOption; -import java.sql.SQLException; - -@AllArgsConstructor -public class Replay { - - static { - new SqlTypeMapper<>(File.class, "BLOB", (rs, identifier) -> { - try { - File file = File.createTempFile("replay", ".replay"); - file.deleteOnExit(); - Files.copy(rs.getBinaryStream(identifier), file.toPath(), StandardCopyOption.REPLACE_EXISTING); - return file; - } catch (IOException e) { - throw new SQLException(e); - } - }, (st, index, value) -> { - try { - st.setBinaryStream(index, new FileInputStream(value)); - } catch (FileNotFoundException e) { - throw new SQLException(e); - } - }); - } - - private static final Table table = new Table<>(Replay.class); - private static final SelectStatement get = table.select(Table.PRIMARY); - - public static final Statement insert = table.insertAll(); - - public static Replay get(int fightID) { - return get.select(fightID); - } - - public static void save(int fightID, File file) { - insert.update(fightID, file); - } - - @Field(keys = {Table.PRIMARY}) - private final int fightID; - @Getter - @Field - private final File replay; -} diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/record/FileSource.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/record/FileSource.java index 2fcaa59e..9e1a05ea 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/record/FileSource.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/record/FileSource.java @@ -20,15 +20,18 @@ package de.steamwar.fightsystem.record; import de.steamwar.fightsystem.Config; -import de.steamwar.sql.Replay; import java.io.File; -import java.io.FileInputStream; import java.io.IOException; +import java.nio.file.Files; import java.util.zip.GZIPInputStream; public class FileSource extends PacketSource { + public static File replayFile(int fightId) { + return new File("/mnt/storage/replays", fightId + ".replay"); + } + public static void startReplay() { if(Config.replayserver()) { try { @@ -41,7 +44,7 @@ public class FileSource extends PacketSource { if(Config.ReplayID > 0) { try { - new FileSource(Replay.get(Config.ReplayID).getReplay()); + new FileSource(replayFile(Config.ReplayID)); } catch (IOException e) { throw new SecurityException("Could not start replay", e); } @@ -49,7 +52,7 @@ public class FileSource extends PacketSource { } public FileSource(File fightFile) throws IOException { - super(new GZIPInputStream(new FileInputStream(fightFile))); + super(new GZIPInputStream(Files.newInputStream(fightFile.toPath()))); new PacketProcessor(this); } diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/FightStatistics.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/FightStatistics.java index 1f46a3a8..35e0fc80 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/FightStatistics.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/FightStatistics.java @@ -27,23 +27,25 @@ import de.steamwar.fightsystem.fight.Fight; import de.steamwar.fightsystem.fight.FightPlayer; import de.steamwar.fightsystem.fight.FightTeam; import de.steamwar.fightsystem.record.FileRecorder; +import de.steamwar.fightsystem.record.FileSource; import de.steamwar.fightsystem.states.FightState; import de.steamwar.fightsystem.states.OneShotStateDependent; import de.steamwar.fightsystem.winconditions.Wincondition; import de.steamwar.network.NetworkSender; import de.steamwar.network.packets.common.FightEndsPacket; -import de.steamwar.sql.Replay; import de.steamwar.sql.SchematicNode; import de.steamwar.sql.SteamwarUser; import lombok.Getter; import org.bukkit.Bukkit; +import java.io.IOException; import java.sql.Timestamp; import java.time.Instant; import java.util.logging.Level; import java.util.stream.Collectors; import static de.steamwar.sql.Fight.create; +import static de.steamwar.sql.Fight.markReplayAvailable; public class FightStatistics { @@ -125,7 +127,10 @@ public class FightStatistics { } try { - Replay.save(fightId, FileRecorder.getFile()); + if(!FileRecorder.getFile().renameTo(FileSource.replayFile(fightId))) + throw new IOException("Failed to move replay"); + + markReplayAvailable(fightId); } catch (Exception e) { Bukkit.getLogger().log(Level.INFO, "Failed to save replay", e); }