diff --git a/SoulstormReplayReader.Core/Domain/GameSettings.cs b/SoulstormReplayReader.Core/Domain/GameSettings.cs index dc53452..69e6919 100644 --- a/SoulstormReplayReader.Core/Domain/GameSettings.cs +++ b/SoulstormReplayReader.Core/Domain/GameSettings.cs @@ -1,15 +1,24 @@ namespace SoulstormReplayReader.Core.Domain; -public sealed class GameSettings +public sealed class GameSettings(int gameSettingsCount = 8) { - public byte AiDifficulty { get; set; } - public byte StartResources { get; set; } - public byte LockTeams { get; set; } - public byte CheatsOn { get; set; } - public byte StartingLocation { get; set; } - public byte GameSpeed { get; set; } - public byte ResourceSharing { get; set; } - public byte ResourceRate { get; set; } + private readonly Dictionary _settings = new(gameSettingsCount); + public IReadOnlyDictionary Settings => _settings; + + public void AddSetting(string name, int value) + { + _settings.Add(name, value); + } + + public int AiDifficulty => _settings["FDIA"]; // FDIA = AIDF = AI Difficulty + public int StartResources => _settings["TSSR"]; // TSSR = RSST = Starting Resources + public int LockTeams => _settings["MTKL"]; // MTKL = LKTM = Lock Teams + public int CheatsOn => _settings["AEHC"]; // AEHC = CHEA = Cheats Enabled + public int StartingLocation => _settings["COLS"]; // COLS = SLOC = Starting Location + public int GameSpeed => _settings["DPSG"]; // DPSG = GSPD = Game Speed + public int ResourceSharing => _settings["HSSR"]; // HSSR = RSSH = Resource Sharing + public int ResourceRate => _settings["TRSR"]; // TRSR = RSRT = Resource Rate + public int DisableFlyers => _settings["YLFN"]; // YLFN = NFLY = No flyers public bool IsQuickStart => StartResources == 1; public bool AreCheatsOn => CheatsOn == 1; diff --git a/SoulstormReplayReader.Core/Domain/Replay/ReplayModel.cs b/SoulstormReplayReader.Core/Domain/Replay/ReplayModel.cs index 3366b81..18b1f02 100644 --- a/SoulstormReplayReader.Core/Domain/Replay/ReplayModel.cs +++ b/SoulstormReplayReader.Core/Domain/Replay/ReplayModel.cs @@ -23,7 +23,7 @@ public sealed class ReplayModel public List Actions { get; set; } public List ChatMessages { get; set; } - public GameSettings GameSettings { get; } = new(); + public GameSettings GameSettings { get; set; } public WinConditions WinConditions { get; } = new(); public Exception Exception { get; set; } diff --git a/SoulstormReplayReader.Core/SsReplayReader.cs b/SoulstormReplayReader.Core/SsReplayReader.cs index 6cf8870..f7cb573 100644 --- a/SoulstormReplayReader.Core/SsReplayReader.cs +++ b/SoulstormReplayReader.Core/SsReplayReader.cs @@ -152,7 +152,6 @@ public sealed class SsReplayReader(Stream stream) : IDisposable _binaryReader.SkipInt32(3); Replay.WorldSeed = _binaryReader.ReadUInt32(); - _binaryReader.SkipInt32(); // Размер слотов в игре. Всегда 8 Descriptor.DataBaseStart = _binaryReader.Position; Descriptor.DataBaseSize = Descriptor.DataBaseChunkSize - 20; @@ -188,42 +187,30 @@ public sealed class SsReplayReader(Stream stream) : IDisposable // Game setting: // * 0000 - value // * AAAA - compact name - // res: 0000COLS = (0000)random (COLS=SLOC)Starting locations + // res: 0000COLS = (0000)(COLS=SLOC=Starting locations) private void ReadGameSettings() { - Replay.GameSettings.AiDifficulty = _binaryReader.ReadByte(); // FDIA = AIDF = AI Difficulty - _binaryReader.Skip(7); + var gameSettingsCount = _binaryReader.ReadInt32(); + Replay.GameSettings = new GameSettings(gameSettingsCount); - Replay.GameSettings.StartResources = _binaryReader.ReadByte(); // TSSR = RSST = Starting Resources - _binaryReader.Skip(7); + for (var i = 0; i < gameSettingsCount; i++) + { + var value = _binaryReader.ReadInt32(); + var name = _binaryReader.ReadAsciiString(4); + Replay.GameSettings.AddSetting(name, value); + } - Replay.GameSettings.LockTeams = _binaryReader.ReadByte(); // MTKL = LKTM = Lock Teams - _binaryReader.Skip(7); - - Replay.GameSettings.CheatsOn = _binaryReader.ReadByte(); // AEHC = CHEA = Cheats Enabled - _binaryReader.Skip(7); - - Replay.GameSettings.StartingLocation = _binaryReader.ReadByte(); // COLS = SLOC = Starting Location - _binaryReader.Skip(7); - - Replay.GameSettings.GameSpeed = _binaryReader.ReadByte(); // DPSG = GSPD = Game Speed - _binaryReader.Skip(7); - - Replay.GameSettings.ResourceSharing = _binaryReader.ReadByte(); // HSSR = RSSH = Resource Sharing - _binaryReader.Skip(7); - - Replay.GameSettings.ResourceRate = _binaryReader.ReadByte(); // TRSR = RSRT = Resource Rate - _binaryReader.Skip(7); - -#if DEBUGLOGGING - Console.WriteLine($"{Replay.GameSettings.AiDifficulty} " + - $"{Replay.GameSettings.StartResources} " + - $"{Replay.GameSettings.LockTeams} " + - $"{Replay.GameSettings.CheatsOn} " + - $"{Replay.GameSettings.StartingLocation} " + - $"{Replay.GameSettings.GameSpeed} " + - $"{Replay.GameSettings.ResourceSharing} " + - $"{Replay.GameSettings.ResourceRate}" +#if DEBUG + Console.WriteLine($"Game settings ({gameSettingsCount}):\n" + + $"AI Difficulty: {Replay.GameSettings.AiDifficulty}\n" + + $"Starting Resources: {Replay.GameSettings.StartResources}\n" + + $"Lock Teams: {Replay.GameSettings.LockTeams}\n" + + $"Cheats Enabled: {Replay.GameSettings.CheatsOn}\n" + + $"Starting Location: {Replay.GameSettings.StartingLocation}\n" + + $"Game Speed: {Replay.GameSettings.GameSpeed}\n" + + $"Resource Sharing: {Replay.GameSettings.ResourceSharing}\n" + + $"Resource Rate: {Replay.GameSettings.ResourceRate}\n" + + $"No flyers: {Replay.GameSettings.DisableFlyers}\n" ); #endif diff --git a/SoulstormReplayReader.Playground/Program.cs b/SoulstormReplayReader.Playground/Program.cs index 8c56172..fdd9276 100644 --- a/SoulstormReplayReader.Playground/Program.cs +++ b/SoulstormReplayReader.Playground/Program.cs @@ -2,6 +2,7 @@ string[] filePaths = { + @"TestReplaysDE\Broken\2p_blood_river_[Rem].2025-10-26.18-13-28.rec", // @"TestReplays\replay_6p_2v2v2_001.rec", // @"TestReplays\gens_builds\ork_many_researches.rec", // @"TestReplays\lag\lag3.rec", @@ -18,6 +19,8 @@ string[] filePaths = // "TestReplays\\unification_anon_2_races.rec" // "TestReplays\\Unfair\\Bugs\\SoB_2commanders_1squad.rec", // @"TestReplays\Unfair\Cheats\eresArchitect_delet.rec", + // @"TestReplays\Unfair\Cheats\deleted_necron_mainbuilding.rec", + // @"TestReplays\destroy_actions\destroy_necron_mainbuilding.rec", // @"TestReplays\Broken\#860994_empty_name.rec", // "TestReplays\\Unfair\\Cheats\\mono_in_1_min.rec", // @"TestReplays\old\BM.rec" @@ -25,6 +28,7 @@ string[] filePaths = }; string[] dirPaths = { + // "TestReplaysDE", // "TestReplays\\Many", // "TestReplays\\Many", // "TestReplays\\Many", @@ -72,6 +76,9 @@ foreach (var replayPath in replayPaths) }; var replay = replayReader.ReadFull(); + Console.WriteLine(string.Join('\n', replay.Players.Select(x => $"{x.Name} {x.Badge.Name} {x.ColorScheme.Eyes}"))); + + Console.WriteLine(replay.Version); Console.WriteLine(string.Join(' ', replay.WinConditions)); // #if DEBUGLOGGING diff --git a/SoulstormReplayReader.Playground/SoulstormReplayReader.Playground.csproj b/SoulstormReplayReader.Playground/SoulstormReplayReader.Playground.csproj index 09ee198..a94fe84 100644 --- a/SoulstormReplayReader.Playground/SoulstormReplayReader.Playground.csproj +++ b/SoulstormReplayReader.Playground/SoulstormReplayReader.Playground.csproj @@ -13,6 +13,7 @@ + diff --git a/SoulstormReplayReader.Playground/TestReplaysDE/2p_ancient_jungle_BM.2025-09-05.22-58-12.rec b/SoulstormReplayReader.Playground/TestReplaysDE/2p_ancient_jungle_BM.2025-09-05.22-58-12.rec new file mode 100644 index 0000000..0a8a4f2 Binary files /dev/null and b/SoulstormReplayReader.Playground/TestReplaysDE/2p_ancient_jungle_BM.2025-09-05.22-58-12.rec differ diff --git a/SoulstormReplayReader.Playground/TestReplaysDE/2p_ouches_raitches.2025-09-05.22-49-51.rec b/SoulstormReplayReader.Playground/TestReplaysDE/2p_ouches_raitches.2025-09-05.22-49-51.rec new file mode 100644 index 0000000..6625bc9 Binary files /dev/null and b/SoulstormReplayReader.Playground/TestReplaysDE/2p_ouches_raitches.2025-09-05.22-49-51.rec differ diff --git a/SoulstormReplayReader.Playground/TestReplaysDE/4P_GURMUNS_PASS.2025-09-04.20-41-47.rec b/SoulstormReplayReader.Playground/TestReplaysDE/4P_GURMUNS_PASS.2025-09-04.20-41-47.rec new file mode 100644 index 0000000..9d82693 Binary files /dev/null and b/SoulstormReplayReader.Playground/TestReplaysDE/4P_GURMUNS_PASS.2025-09-04.20-41-47.rec differ diff --git a/SoulstormReplayReader.Playground/TestReplaysDE/8p_dowDE.rec b/SoulstormReplayReader.Playground/TestReplaysDE/8p_dowDE.rec new file mode 100644 index 0000000..692e476 Binary files /dev/null and b/SoulstormReplayReader.Playground/TestReplaysDE/8p_dowDE.rec differ diff --git a/SoulstormReplayReader.Playground/TestReplaysDE/Broken/2p_blood_river_[Rem].2025-10-26.18-13-28.rec b/SoulstormReplayReader.Playground/TestReplaysDE/Broken/2p_blood_river_[Rem].2025-10-26.18-13-28.rec new file mode 100644 index 0000000..59eae5e Binary files /dev/null and b/SoulstormReplayReader.Playground/TestReplaysDE/Broken/2p_blood_river_[Rem].2025-10-26.18-13-28.rec differ diff --git a/SoulstormReplayReader.Playground/TestReplaysDE/Broken/2p_tranquilitys_end_[Rem].2025-10-26.18-41-15.rec b/SoulstormReplayReader.Playground/TestReplaysDE/Broken/2p_tranquilitys_end_[Rem].2025-10-26.18-41-15.rec new file mode 100644 index 0000000..03140e2 Binary files /dev/null and b/SoulstormReplayReader.Playground/TestReplaysDE/Broken/2p_tranquilitys_end_[Rem].2025-10-26.18-41-15.rec differ