From 6fb72abcfb45cd96cc8e61795c54e8e3595fecbb Mon Sep 17 00:00:00 2001 From: Vasilis The Pikachu Date: Tue, 26 Dec 2023 16:12:09 +0100 Subject: [PATCH 01/16] Save round information into the replay --- .../GameTicking/GameTicker.Replays.cs | 20 +++++++++++++++++++ .../GameTicking/GameTicker.RoundFlow.cs | 5 +++++ .../GameTicking/SharedGameTicker.cs | 1 + 3 files changed, 26 insertions(+) diff --git a/Content.Server/GameTicking/GameTicker.Replays.cs b/Content.Server/GameTicking/GameTicker.Replays.cs index 7e1a553a856802..fb7176b69a7814 100644 --- a/Content.Server/GameTicking/GameTicker.Replays.cs +++ b/Content.Server/GameTicking/GameTicker.Replays.cs @@ -2,7 +2,10 @@ using Robust.Shared; using Robust.Shared.ContentPack; using Robust.Shared.Replays; +using Robust.Shared.Serialization.Markdown.Mapping; +using Robust.Shared.Serialization.Markdown.Value; using Robust.Shared.Utility; +using YamlDotNet.Serialization; namespace Content.Server.GameTicking; @@ -16,6 +19,7 @@ public sealed partial class GameTicker private void InitializeReplays() { _replays.RecordingFinished += ReplaysOnRecordingFinished; + _replays.RecordingStopped += ReplaysOnRecordingStopped; } /// @@ -108,6 +112,22 @@ private void ReplaysOnRecordingFinished(ReplayRecordingFinished data) data.Directory.Rename(data.Path, state.MoveToPath.Value); } + private void ReplaysOnRecordingStopped(MappingDataNode metadata) + { + // Write round info like map and round end summery into the replay_final.yml file. Useful for external parsers. + + metadata["map"] = new ValueDataNode(_gameMapManager.GetSelectedMap()?.MapName); + metadata["gamemode"] = new ValueDataNode(CurrentPreset != null ? Loc.GetString(CurrentPreset.ModeTitle) : string.Empty); + string final = SerializeToYaml(_replayRoundPlayerInfo); + metadata["roundEndMetadata"] = new ValueDataNode(final); + } + + private static string SerializeToYaml(T data) + { + var serializer = new SerializerBuilder().Build(); + return serializer.Serialize(data!); + } + private ResPath GetAutoReplayPath() { var cfgValue = _cfg.GetCVar(CCVars.ReplayAutoRecordName); diff --git a/Content.Server/GameTicking/GameTicker.RoundFlow.cs b/Content.Server/GameTicking/GameTicker.RoundFlow.cs index 42810779dd0528..f0c4c0d84d4d42 100644 --- a/Content.Server/GameTicking/GameTicker.RoundFlow.cs +++ b/Content.Server/GameTicking/GameTicker.RoundFlow.cs @@ -49,6 +49,8 @@ public sealed partial class GameTicker [ViewVariables] private GameRunLevel _runLevel; + private Array? _replayRoundPlayerInfo; + [ViewVariables] public GameRunLevel RunLevel { @@ -375,6 +377,7 @@ public void ShowRoundEndScoreboard(string text = "") PlayerOOCName = contentPlayerData?.Name ?? "(IMPOSSIBLE: REGISTERED MIND WITH NO OWNER)", // Character name takes precedence over current entity name PlayerICName = playerIcName, + PlayerGuid = userId.ToString() ?? "(IMPOSSIBLE: REGISTERED MIND WITH NO OWNER)", PlayerNetEntity = GetNetEntity(entity), Role = antag ? roles.First(role => role.Antagonist).Name @@ -392,6 +395,8 @@ public void ShowRoundEndScoreboard(string text = "") RaiseNetworkEvent(new RoundEndMessageEvent(gamemodeTitle, roundEndText, roundDuration, RoundId, listOfPlayerInfoFinal.Length, listOfPlayerInfoFinal, LobbySong, new SoundCollectionSpecifier("RoundEnd").GetSound())); + + _replayRoundPlayerInfo = listOfPlayerInfoFinal; } private async void SendRoundEndDiscordMessage() diff --git a/Content.Shared/GameTicking/SharedGameTicker.cs b/Content.Shared/GameTicking/SharedGameTicker.cs index b4e82184297159..98707d782cba21 100644 --- a/Content.Shared/GameTicking/SharedGameTicker.cs +++ b/Content.Shared/GameTicking/SharedGameTicker.cs @@ -142,6 +142,7 @@ public struct RoundEndPlayerInfo { public string PlayerOOCName; public string? PlayerICName; + public string PlayerGuid; public string Role; public NetEntity? PlayerNetEntity; public bool Antag; From ea90dba4dd60f5a83572ec32065b751cb60da80e Mon Sep 17 00:00:00 2001 From: Vasilis The Pikachu Date: Tue, 26 Dec 2023 16:52:24 +0100 Subject: [PATCH 02/16] Add round end text too --- Content.Server/GameTicking/GameTicker.Replays.cs | 5 +++-- Content.Server/GameTicking/GameTicker.RoundFlow.cs | 4 ++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Content.Server/GameTicking/GameTicker.Replays.cs b/Content.Server/GameTicking/GameTicker.Replays.cs index fb7176b69a7814..90728e7c35dd77 100644 --- a/Content.Server/GameTicking/GameTicker.Replays.cs +++ b/Content.Server/GameTicking/GameTicker.Replays.cs @@ -118,8 +118,9 @@ private void ReplaysOnRecordingStopped(MappingDataNode metadata) metadata["map"] = new ValueDataNode(_gameMapManager.GetSelectedMap()?.MapName); metadata["gamemode"] = new ValueDataNode(CurrentPreset != null ? Loc.GetString(CurrentPreset.ModeTitle) : string.Empty); - string final = SerializeToYaml(_replayRoundPlayerInfo); - metadata["roundEndMetadata"] = new ValueDataNode(final); + string finalPlayers = SerializeToYaml(_replayRoundPlayerInfo); + metadata["roundEndPlayers"] = new ValueDataNode(finalPlayers); + metadata["roundEndText"] = new ValueDataNode(_replayRoundText); } private static string SerializeToYaml(T data) diff --git a/Content.Server/GameTicking/GameTicker.RoundFlow.cs b/Content.Server/GameTicking/GameTicker.RoundFlow.cs index f0c4c0d84d4d42..98f2fdc828d336 100644 --- a/Content.Server/GameTicking/GameTicker.RoundFlow.cs +++ b/Content.Server/GameTicking/GameTicker.RoundFlow.cs @@ -50,6 +50,7 @@ public sealed partial class GameTicker private GameRunLevel _runLevel; private Array? _replayRoundPlayerInfo; + private string? _replayRoundText; [ViewVariables] public GameRunLevel RunLevel @@ -188,6 +189,8 @@ public void StartRound(bool force = false) if (RoundId == 0) IncrementRoundNumber(); + _replayRoundPlayerInfo = null; + _replayRoundText = null; ReplayStartRound(); DebugTools.Assert(RunLevel == GameRunLevel.PreRoundLobby); @@ -397,6 +400,7 @@ public void ShowRoundEndScoreboard(string text = "") new SoundCollectionSpecifier("RoundEnd").GetSound())); _replayRoundPlayerInfo = listOfPlayerInfoFinal; + _replayRoundText = roundEndText; } private async void SendRoundEndDiscordMessage() From df5fc30b2c2192df918e3599477f3dfd31f1bf3e Mon Sep 17 00:00:00 2001 From: Vasilis The Pikachu Date: Tue, 26 Dec 2023 17:35:54 +0100 Subject: [PATCH 03/16] This is way better --- .../GameTicking/GameTicker.Replays.cs | 19 ++++++++++++++++--- .../GameTicking/GameTicker.RoundFlow.cs | 2 -- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/Content.Server/GameTicking/GameTicker.Replays.cs b/Content.Server/GameTicking/GameTicker.Replays.cs index 90728e7c35dd77..1ec0a6be57d9ba 100644 --- a/Content.Server/GameTicking/GameTicker.Replays.cs +++ b/Content.Server/GameTicking/GameTicker.Replays.cs @@ -118,9 +118,22 @@ private void ReplaysOnRecordingStopped(MappingDataNode metadata) metadata["map"] = new ValueDataNode(_gameMapManager.GetSelectedMap()?.MapName); metadata["gamemode"] = new ValueDataNode(CurrentPreset != null ? Loc.GetString(CurrentPreset.ModeTitle) : string.Empty); - string finalPlayers = SerializeToYaml(_replayRoundPlayerInfo); - metadata["roundEndPlayers"] = new ValueDataNode(finalPlayers); - metadata["roundEndText"] = new ValueDataNode(_replayRoundText); + + // These should be set to null to prepare them for the next round. + if (_replayRoundPlayerInfo != null) + { + string finalPlayers = SerializeToYaml(_replayRoundPlayerInfo); + metadata["roundEndPlayers"] = new ValueDataNode(finalPlayers); + metadata["roundEndText"] = new ValueDataNode(_replayRoundText!.Replace("\n", " ")); + _replayRoundPlayerInfo = null; + _replayRoundText = null; + } + else + { + // If theres no players then there probably nothing interesting in round end text worth saving. + metadata["roundEndPlayers"] = new ValueDataNode(string.Empty); + metadata["roundEndText"] = new ValueDataNode(string.Empty); + } } private static string SerializeToYaml(T data) diff --git a/Content.Server/GameTicking/GameTicker.RoundFlow.cs b/Content.Server/GameTicking/GameTicker.RoundFlow.cs index 98f2fdc828d336..9a447d17faf48f 100644 --- a/Content.Server/GameTicking/GameTicker.RoundFlow.cs +++ b/Content.Server/GameTicking/GameTicker.RoundFlow.cs @@ -189,8 +189,6 @@ public void StartRound(bool force = false) if (RoundId == 0) IncrementRoundNumber(); - _replayRoundPlayerInfo = null; - _replayRoundText = null; ReplayStartRound(); DebugTools.Assert(RunLevel == GameRunLevel.PreRoundLobby); From 12a0a50ec8fc7c2aa416e939eac4f48fd2aa8971 Mon Sep 17 00:00:00 2001 From: Vasilis The Pikachu Date: Tue, 26 Dec 2023 17:54:56 +0100 Subject: [PATCH 04/16] Get actual job --- Content.Server/GameTicking/GameTicker.RoundFlow.cs | 1 + Content.Shared/GameTicking/SharedGameTicker.cs | 1 + 2 files changed, 2 insertions(+) diff --git a/Content.Server/GameTicking/GameTicker.RoundFlow.cs b/Content.Server/GameTicking/GameTicker.RoundFlow.cs index 9a447d17faf48f..8c9b0f82c4f0e1 100644 --- a/Content.Server/GameTicking/GameTicker.RoundFlow.cs +++ b/Content.Server/GameTicking/GameTicker.RoundFlow.cs @@ -383,6 +383,7 @@ public void ShowRoundEndScoreboard(string text = "") Role = antag ? roles.First(role => role.Antagonist).Name : roles.FirstOrDefault().Name ?? Loc.GetString("game-ticker-unknown-role"), + JobRole = roles.FirstOrDefault(role => !role.Antagonist).Name ?? Loc.GetString("game-ticker-unknown-role"), Antag = antag, Observer = observer, Connected = connected diff --git a/Content.Shared/GameTicking/SharedGameTicker.cs b/Content.Shared/GameTicking/SharedGameTicker.cs index 98707d782cba21..b12856996b8df5 100644 --- a/Content.Shared/GameTicking/SharedGameTicker.cs +++ b/Content.Shared/GameTicking/SharedGameTicker.cs @@ -144,6 +144,7 @@ public struct RoundEndPlayerInfo public string? PlayerICName; public string PlayerGuid; public string Role; + public string JobRole; public NetEntity? PlayerNetEntity; public bool Antag; public bool Observer; From de7df89005fab6908a2fab5f497c0982e8a141b8 Mon Sep 17 00:00:00 2001 From: Vasilis The Pikachu Date: Sun, 7 Jan 2024 02:11:34 +0100 Subject: [PATCH 05/16] oop --- Content.Server/GameTicking/GameTicker.RoundFlow.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Content.Server/GameTicking/GameTicker.RoundFlow.cs b/Content.Server/GameTicking/GameTicker.RoundFlow.cs index dd547b0338e6d3..f2e8263b866fe1 100644 --- a/Content.Server/GameTicking/GameTicker.RoundFlow.cs +++ b/Content.Server/GameTicking/GameTicker.RoundFlow.cs @@ -393,8 +393,7 @@ public void ShowRoundEndScoreboard(string text = "") RaiseNetworkEvent(new RoundEndMessageEvent(gamemodeTitle, roundEndText, roundDuration, RoundId, listOfPlayerInfoFinal.Length, listOfPlayerInfoFinal, LobbySong)); - listOfPlayerInfoFinal.Length, listOfPlayerInfoFinal, LobbySong, - new SoundCollectionSpecifier("RoundEnd").GetSound())); + new SoundCollectionSpecifier("RoundEnd").GetSound(); _replayRoundPlayerInfo = listOfPlayerInfoFinal; _replayRoundText = roundEndText; From 6db1531a8589de3be8c7198bba84454c27394982 Mon Sep 17 00:00:00 2001 From: Vasilis The Pikachu Date: Sun, 7 Jan 2024 02:17:03 +0100 Subject: [PATCH 06/16] OK THERE --- Content.Server/GameTicking/GameTicker.RoundFlow.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Content.Server/GameTicking/GameTicker.RoundFlow.cs b/Content.Server/GameTicking/GameTicker.RoundFlow.cs index f2e8263b866fe1..ccf20eaafba67b 100644 --- a/Content.Server/GameTicking/GameTicker.RoundFlow.cs +++ b/Content.Server/GameTicking/GameTicker.RoundFlow.cs @@ -393,7 +393,6 @@ public void ShowRoundEndScoreboard(string text = "") RaiseNetworkEvent(new RoundEndMessageEvent(gamemodeTitle, roundEndText, roundDuration, RoundId, listOfPlayerInfoFinal.Length, listOfPlayerInfoFinal, LobbySong)); - new SoundCollectionSpecifier("RoundEnd").GetSound(); _replayRoundPlayerInfo = listOfPlayerInfoFinal; _replayRoundText = roundEndText; From 31ef5cc7b898de215712c1716aec2e3b63c85f8e Mon Sep 17 00:00:00 2001 From: Vasilis The Pikachu Date: Tue, 30 Jan 2024 01:13:59 +0100 Subject: [PATCH 07/16] Fake line endings to make life easier --- Content.Server/GameTicking/GameTicker.Replays.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Content.Server/GameTicking/GameTicker.Replays.cs b/Content.Server/GameTicking/GameTicker.Replays.cs index 1ec0a6be57d9ba..d7940eb0584a7e 100644 --- a/Content.Server/GameTicking/GameTicker.Replays.cs +++ b/Content.Server/GameTicking/GameTicker.Replays.cs @@ -124,7 +124,8 @@ private void ReplaysOnRecordingStopped(MappingDataNode metadata) { string finalPlayers = SerializeToYaml(_replayRoundPlayerInfo); metadata["roundEndPlayers"] = new ValueDataNode(finalPlayers); - metadata["roundEndText"] = new ValueDataNode(_replayRoundText!.Replace("\n", " ")); + // Fake line seperator so that the format in the yaml file does not break, but you can still use tools to manually make new lines. + metadata["roundEndText"] = new ValueDataNode(_replayRoundText!.Replace("\n", "/n")); _replayRoundPlayerInfo = null; _replayRoundText = null; } From 05e451cb20ab3c02f8311767c61d4cb671979e7d Mon Sep 17 00:00:00 2001 From: Vasilis The Pikachu Date: Tue, 30 Jan 2024 01:27:35 +0100 Subject: [PATCH 08/16] I was told this yaml is legal --- Content.Server/GameTicking/GameTicker.Replays.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Content.Server/GameTicking/GameTicker.Replays.cs b/Content.Server/GameTicking/GameTicker.Replays.cs index d7940eb0584a7e..e90479daf3ccde 100644 --- a/Content.Server/GameTicking/GameTicker.Replays.cs +++ b/Content.Server/GameTicking/GameTicker.Replays.cs @@ -124,8 +124,7 @@ private void ReplaysOnRecordingStopped(MappingDataNode metadata) { string finalPlayers = SerializeToYaml(_replayRoundPlayerInfo); metadata["roundEndPlayers"] = new ValueDataNode(finalPlayers); - // Fake line seperator so that the format in the yaml file does not break, but you can still use tools to manually make new lines. - metadata["roundEndText"] = new ValueDataNode(_replayRoundText!.Replace("\n", "/n")); + metadata["roundEndText"] = new ValueDataNode(_replayRoundText); _replayRoundPlayerInfo = null; _replayRoundText = null; } From 6eb2f2de3477dcd308a563acef383cea008bca55 Mon Sep 17 00:00:00 2001 From: Vasilis The Pikachu Date: Sat, 3 Feb 2024 15:29:28 +0100 Subject: [PATCH 09/16] I just realised this will make my life easier --- Content.Server/GameTicking/GameTicker.Replays.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Content.Server/GameTicking/GameTicker.Replays.cs b/Content.Server/GameTicking/GameTicker.Replays.cs index e90479daf3ccde..31b1a542bde868 100644 --- a/Content.Server/GameTicking/GameTicker.Replays.cs +++ b/Content.Server/GameTicking/GameTicker.Replays.cs @@ -125,6 +125,7 @@ private void ReplaysOnRecordingStopped(MappingDataNode metadata) string finalPlayers = SerializeToYaml(_replayRoundPlayerInfo); metadata["roundEndPlayers"] = new ValueDataNode(finalPlayers); metadata["roundEndText"] = new ValueDataNode(_replayRoundText); + metadata["server_id"] = new ValueDataNode(_configurationManager.GetCVar(CCVars.ServerId)); _replayRoundPlayerInfo = null; _replayRoundText = null; } From 32987380d8349abc83a5237a301f6a62f7343759 Mon Sep 17 00:00:00 2001 From: Vasilis The Pikachu Date: Mon, 12 Feb 2024 23:19:49 +0100 Subject: [PATCH 10/16] REVIEWS BABY IM A PROGRAMMER MOMMY --- .../GameTicking/GameTicker.Replays.cs | 32 +++++++------------ .../GameTicking/GameTicker.RoundFlow.cs | 5 +-- .../GameTicking/SharedGameTicker.cs | 24 +++++++++++--- 3 files changed, 35 insertions(+), 26 deletions(-) diff --git a/Content.Server/GameTicking/GameTicker.Replays.cs b/Content.Server/GameTicking/GameTicker.Replays.cs index 31b1a542bde868..f8feb00d56f64a 100644 --- a/Content.Server/GameTicking/GameTicker.Replays.cs +++ b/Content.Server/GameTicking/GameTicker.Replays.cs @@ -2,10 +2,11 @@ using Robust.Shared; using Robust.Shared.ContentPack; using Robust.Shared.Replays; +using Robust.Shared.Serialization.Manager; +using Robust.Shared.Serialization.Markdown; using Robust.Shared.Serialization.Markdown.Mapping; using Robust.Shared.Serialization.Markdown.Value; using Robust.Shared.Utility; -using YamlDotNet.Serialization; namespace Content.Server.GameTicking; @@ -13,6 +14,8 @@ public sealed partial class GameTicker { [Dependency] private readonly IReplayRecordingManager _replays = default!; [Dependency] private readonly IResourceManager _resourceManager = default!; + [Dependency] private readonly ISerializationManager _serialman = default!; + private ISawmill _sawmillReplays = default!; @@ -118,29 +121,18 @@ private void ReplaysOnRecordingStopped(MappingDataNode metadata) metadata["map"] = new ValueDataNode(_gameMapManager.GetSelectedMap()?.MapName); metadata["gamemode"] = new ValueDataNode(CurrentPreset != null ? Loc.GetString(CurrentPreset.ModeTitle) : string.Empty); - + metadata["roundEndPlayers"] = SerializeToYaml(_replayRoundPlayerInfo); + metadata["roundEndText"] = new ValueDataNode(_replayRoundText); + metadata["server_id"] = new ValueDataNode(_configurationManager.GetCVar(CCVars.ServerId)); // These should be set to null to prepare them for the next round. - if (_replayRoundPlayerInfo != null) - { - string finalPlayers = SerializeToYaml(_replayRoundPlayerInfo); - metadata["roundEndPlayers"] = new ValueDataNode(finalPlayers); - metadata["roundEndText"] = new ValueDataNode(_replayRoundText); - metadata["server_id"] = new ValueDataNode(_configurationManager.GetCVar(CCVars.ServerId)); - _replayRoundPlayerInfo = null; - _replayRoundText = null; - } - else - { - // If theres no players then there probably nothing interesting in round end text worth saving. - metadata["roundEndPlayers"] = new ValueDataNode(string.Empty); - metadata["roundEndText"] = new ValueDataNode(string.Empty); - } + _replayRoundPlayerInfo = null!; + _replayRoundText = null; } - private static string SerializeToYaml(T data) + private DataNode SerializeToYaml(T data) { - var serializer = new SerializerBuilder().Build(); - return serializer.Serialize(data!); + var result = _serialman.WriteValue(data); + return result; } private ResPath GetAutoReplayPath() diff --git a/Content.Server/GameTicking/GameTicker.RoundFlow.cs b/Content.Server/GameTicking/GameTicker.RoundFlow.cs index 65ea48bf7a9b14..0109313621deed 100644 --- a/Content.Server/GameTicking/GameTicker.RoundFlow.cs +++ b/Content.Server/GameTicking/GameTicker.RoundFlow.cs @@ -46,7 +46,8 @@ public sealed partial class GameTicker [ViewVariables] private GameRunLevel _runLevel; - private Array? _replayRoundPlayerInfo; + private RoundEndMessageEvent.RoundEndPlayerInfo[] _replayRoundPlayerInfo = null!; + private string? _replayRoundText; [ViewVariables] @@ -375,7 +376,7 @@ public void ShowRoundEndScoreboard(string text = "") PlayerOOCName = contentPlayerData?.Name ?? "(IMPOSSIBLE: REGISTERED MIND WITH NO OWNER)", // Character name takes precedence over current entity name PlayerICName = playerIcName, - PlayerGuid = userId.ToString() ?? "(IMPOSSIBLE: REGISTERED MIND WITH NO OWNER)", + PlayerGuid = userId?.ToString() ?? "(IMPOSSIBLE: REGISTERED MIND WITH NO OWNER)", PlayerNetEntity = GetNetEntity(entity), Role = antag ? roles.First(role => role.Antagonist).Name diff --git a/Content.Shared/GameTicking/SharedGameTicker.cs b/Content.Shared/GameTicking/SharedGameTicker.cs index bbbd013bcd2a2b..4750b8e9fe8d4e 100644 --- a/Content.Shared/GameTicking/SharedGameTicker.cs +++ b/Content.Shared/GameTicking/SharedGameTicker.cs @@ -144,20 +144,36 @@ public TickerJobsAvailableEvent(Dictionary stationNames, Dict } } - [Serializable, NetSerializable] - public sealed class RoundEndMessageEvent : EntityEventArgs + [Serializable, NetSerializable, DataDefinition] + public sealed partial class RoundEndMessageEvent : EntityEventArgs { - [Serializable, NetSerializable] - public struct RoundEndPlayerInfo + [Serializable, NetSerializable, DataDefinition] + public partial struct RoundEndPlayerInfo { + [DataField] public string PlayerOOCName; + + [DataField] public string? PlayerICName; + + [DataField] public string PlayerGuid; + + [DataField] public string Role; + + [DataField] public string JobRole; + public NetEntity? PlayerNetEntity; + + [DataField] public bool Antag; + + [DataField] public bool Observer; + + [DataField] public bool Connected; } From b04bc0cfead05e8eba6e45359c844e77db7820a6 Mon Sep 17 00:00:00 2001 From: Vasilis The Pikachu Date: Mon, 12 Feb 2024 23:23:55 +0100 Subject: [PATCH 11/16] Live pjb reaction --- Content.Server/GameTicking/GameTicker.Replays.cs | 10 ++-------- Content.Server/GameTicking/GameTicker.RoundFlow.cs | 2 +- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/Content.Server/GameTicking/GameTicker.Replays.cs b/Content.Server/GameTicking/GameTicker.Replays.cs index f8feb00d56f64a..f23482585cc37f 100644 --- a/Content.Server/GameTicking/GameTicker.Replays.cs +++ b/Content.Server/GameTicking/GameTicker.Replays.cs @@ -121,20 +121,14 @@ private void ReplaysOnRecordingStopped(MappingDataNode metadata) metadata["map"] = new ValueDataNode(_gameMapManager.GetSelectedMap()?.MapName); metadata["gamemode"] = new ValueDataNode(CurrentPreset != null ? Loc.GetString(CurrentPreset.ModeTitle) : string.Empty); - metadata["roundEndPlayers"] = SerializeToYaml(_replayRoundPlayerInfo); + metadata["roundEndPlayers"] = _serialman.WriteValue(_replayRoundPlayerInfo); metadata["roundEndText"] = new ValueDataNode(_replayRoundText); metadata["server_id"] = new ValueDataNode(_configurationManager.GetCVar(CCVars.ServerId)); // These should be set to null to prepare them for the next round. - _replayRoundPlayerInfo = null!; + _replayRoundPlayerInfo = null; _replayRoundText = null; } - private DataNode SerializeToYaml(T data) - { - var result = _serialman.WriteValue(data); - return result; - } - private ResPath GetAutoReplayPath() { var cfgValue = _cfg.GetCVar(CCVars.ReplayAutoRecordName); diff --git a/Content.Server/GameTicking/GameTicker.RoundFlow.cs b/Content.Server/GameTicking/GameTicker.RoundFlow.cs index 0109313621deed..be11f1afa37bf5 100644 --- a/Content.Server/GameTicking/GameTicker.RoundFlow.cs +++ b/Content.Server/GameTicking/GameTicker.RoundFlow.cs @@ -46,7 +46,7 @@ public sealed partial class GameTicker [ViewVariables] private GameRunLevel _runLevel; - private RoundEndMessageEvent.RoundEndPlayerInfo[] _replayRoundPlayerInfo = null!; + private RoundEndMessageEvent.RoundEndPlayerInfo[]? _replayRoundPlayerInfo; private string? _replayRoundText; From 1c336224189564acf94b8786b56f47bb06f862b1 Mon Sep 17 00:00:00 2001 From: Vasilis The Pikachu Date: Wed, 14 Feb 2024 17:29:40 +0100 Subject: [PATCH 12/16] Live pjb reaction 2 --- Content.Server/GameTicking/GameTicker.RoundFlow.cs | 4 ++-- Content.Shared/GameTicking/SharedGameTicker.cs | 5 +++-- Content.Shared/Roles/MindGetAllRolesEvent.cs | 3 ++- Content.Shared/Roles/SharedRoleSystem.cs | 8 ++++++-- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/Content.Server/GameTicking/GameTicker.RoundFlow.cs b/Content.Server/GameTicking/GameTicker.RoundFlow.cs index a7d3af94e32521..9e5e8763b8149d 100644 --- a/Content.Server/GameTicking/GameTicker.RoundFlow.cs +++ b/Content.Server/GameTicking/GameTicker.RoundFlow.cs @@ -376,12 +376,12 @@ public void ShowRoundEndScoreboard(string text = "") PlayerOOCName = contentPlayerData?.Name ?? "(IMPOSSIBLE: REGISTERED MIND WITH NO OWNER)", // Character name takes precedence over current entity name PlayerICName = playerIcName, - PlayerGuid = userId?.ToString() ?? "(IMPOSSIBLE: REGISTERED MIND WITH NO OWNER)", + PlayerGuid = userId ?? null, PlayerNetEntity = GetNetEntity(entity), Role = antag ? roles.First(role => role.Antagonist).Name : roles.FirstOrDefault().Name ?? Loc.GetString("game-ticker-unknown-role"), - JobRole = roles.FirstOrDefault(role => !role.Antagonist).Name ?? Loc.GetString("game-ticker-unknown-role"), + RolePrototypes = string.Join(", ", roles.Select(role => role.Prototype)), Antag = antag, Observer = observer, Connected = connected diff --git a/Content.Shared/GameTicking/SharedGameTicker.cs b/Content.Shared/GameTicking/SharedGameTicker.cs index 4750b8e9fe8d4e..de103dd8ec1ad0 100644 --- a/Content.Shared/GameTicking/SharedGameTicker.cs +++ b/Content.Shared/GameTicking/SharedGameTicker.cs @@ -1,4 +1,5 @@ using Content.Shared.Roles; +using Robust.Shared.Network; using Robust.Shared.Replays; using Robust.Shared.Serialization; using Robust.Shared.Serialization.Markdown.Mapping; @@ -157,13 +158,13 @@ public partial struct RoundEndPlayerInfo public string? PlayerICName; [DataField] - public string PlayerGuid; + public NetUserId? PlayerGuid; [DataField] public string Role; [DataField] - public string JobRole; + public string RolePrototypes; public NetEntity? PlayerNetEntity; diff --git a/Content.Shared/Roles/MindGetAllRolesEvent.cs b/Content.Shared/Roles/MindGetAllRolesEvent.cs index 9313d94edfd671..69878739084bc7 100644 --- a/Content.Shared/Roles/MindGetAllRolesEvent.cs +++ b/Content.Shared/Roles/MindGetAllRolesEvent.cs @@ -16,4 +16,5 @@ namespace Content.Shared.Roles; /// Name of the role. /// Whether or not this role makes this player an antagonist. /// The id associated with the role. -public readonly record struct RoleInfo(Component Component, string Name, bool Antagonist, string? PlayTimeTrackerId); +/// The prototype ID of the role +public readonly record struct RoleInfo(Component Component, string Name, bool Antagonist, string? PlayTimeTrackerId, string Prototype); diff --git a/Content.Shared/Roles/SharedRoleSystem.cs b/Content.Shared/Roles/SharedRoleSystem.cs index 05d6ab9f37f3d2..24db1d56774774 100644 --- a/Content.Shared/Roles/SharedRoleSystem.cs +++ b/Content.Shared/Roles/SharedRoleSystem.cs @@ -27,16 +27,18 @@ public override void Initialize() private void OnJobGetAllRoles(EntityUid uid, JobComponent component, ref MindGetAllRolesEvent args) { var name = "game-ticker-unknown-role"; + var prototype = ""; string? playTimeTracker = null; if (component.Prototype != null && _prototypes.TryIndex(component.Prototype, out JobPrototype? job)) { name = job.Name; + prototype = job.ID; playTimeTracker = job.PlayTimeTracker; } name = Loc.GetString(name); - args.Roles.Add(new RoleInfo(component, name, false, playTimeTracker)); + args.Roles.Add(new RoleInfo(component, name, false, playTimeTracker, prototype)); } protected void SubscribeAntagEvents() where T : AntagonistRoleComponent @@ -44,13 +46,15 @@ protected void SubscribeAntagEvents() where T : AntagonistRoleComponent SubscribeLocalEvent((EntityUid _, T component, ref MindGetAllRolesEvent args) => { var name = "game-ticker-unknown-role"; + var prototype = ""; if (component.PrototypeId != null && _prototypes.TryIndex(component.PrototypeId, out AntagPrototype? antag)) { name = antag.Name; + prototype = antag.ID; } name = Loc.GetString(name); - args.Roles.Add(new RoleInfo(component, name, true, null)); + args.Roles.Add(new RoleInfo(component, name, true, null, prototype)); }); SubscribeLocalEvent((EntityUid _, T _, ref MindIsAntagonistEvent args) => args.IsAntagonist = true); From 1bcc2f1abd22699fe54360e287f80b9190684ea9 Mon Sep 17 00:00:00 2001 From: Vasilis The Pikachu Date: Thu, 15 Feb 2024 14:38:21 +0100 Subject: [PATCH 13/16] Reviews 2 --- Content.Server/GameTicking/GameTicker.RoundFlow.cs | 6 +++--- Content.Shared/GameTicking/SharedGameTicker.cs | 10 ++++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/Content.Server/GameTicking/GameTicker.RoundFlow.cs b/Content.Server/GameTicking/GameTicker.RoundFlow.cs index 9e5e8763b8149d..14576d6e9e8394 100644 --- a/Content.Server/GameTicking/GameTicker.RoundFlow.cs +++ b/Content.Server/GameTicking/GameTicker.RoundFlow.cs @@ -376,13 +376,13 @@ public void ShowRoundEndScoreboard(string text = "") PlayerOOCName = contentPlayerData?.Name ?? "(IMPOSSIBLE: REGISTERED MIND WITH NO OWNER)", // Character name takes precedence over current entity name PlayerICName = playerIcName, - PlayerGuid = userId ?? null, + PlayerGuid = userId, PlayerNetEntity = GetNetEntity(entity), Role = antag ? roles.First(role => role.Antagonist).Name : roles.FirstOrDefault().Name ?? Loc.GetString("game-ticker-unknown-role"), - RolePrototypes = string.Join(", ", roles.Select(role => role.Prototype)), - Antag = antag, + JobPrototypes = roles.Where(role => !role.Antagonist).Select(role => role.Prototype).ToArray(), + AntagPrototypes = roles.Where(role => role.Antagonist).Select(role => role.Prototype).ToArray(), Observer = observer, Connected = connected }; diff --git a/Content.Shared/GameTicking/SharedGameTicker.cs b/Content.Shared/GameTicking/SharedGameTicker.cs index de103dd8ec1ad0..269421dacfc6bd 100644 --- a/Content.Shared/GameTicking/SharedGameTicker.cs +++ b/Content.Shared/GameTicking/SharedGameTicker.cs @@ -157,14 +157,16 @@ public partial struct RoundEndPlayerInfo [DataField] public string? PlayerICName; - [DataField] + [DataField, NonSerialized] public NetUserId? PlayerGuid; - [DataField] public string Role; - [DataField] - public string RolePrototypes; + [DataField, NonSerialized] + public Array JobPrototypes; + + [DataField, NonSerialized] + public Array AntagPrototypes; public NetEntity? PlayerNetEntity; From 49e48a2f0a082f0b374ece011695a8f44ba1bb6e Mon Sep 17 00:00:00 2001 From: Vasilis The Pikachu Date: Thu, 15 Feb 2024 14:40:08 +0100 Subject: [PATCH 14/16] Dont need this --- Content.Shared/GameTicking/SharedGameTicker.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Content.Shared/GameTicking/SharedGameTicker.cs b/Content.Shared/GameTicking/SharedGameTicker.cs index 269421dacfc6bd..368e8c84bdc555 100644 --- a/Content.Shared/GameTicking/SharedGameTicker.cs +++ b/Content.Shared/GameTicking/SharedGameTicker.cs @@ -176,7 +176,6 @@ public partial struct RoundEndPlayerInfo [DataField] public bool Observer; - [DataField] public bool Connected; } From 9b471c831ef040ac09feb776633eb8044082fcb8 Mon Sep 17 00:00:00 2001 From: Vasilis The Pikachu Date: Thu, 15 Feb 2024 19:03:06 +0100 Subject: [PATCH 15/16] Please no more have mercy on my soul --- Content.Shared/GameTicking/SharedGameTicker.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Content.Shared/GameTicking/SharedGameTicker.cs b/Content.Shared/GameTicking/SharedGameTicker.cs index 368e8c84bdc555..2677d499c2ff99 100644 --- a/Content.Shared/GameTicking/SharedGameTicker.cs +++ b/Content.Shared/GameTicking/SharedGameTicker.cs @@ -163,10 +163,10 @@ public partial struct RoundEndPlayerInfo public string Role; [DataField, NonSerialized] - public Array JobPrototypes; + public string[] JobPrototypes; [DataField, NonSerialized] - public Array AntagPrototypes; + public string[] AntagPrototypes; public NetEntity? PlayerNetEntity; From 85584bde58f91b55f1130ddec9d4c8b7d6feff7a Mon Sep 17 00:00:00 2001 From: Vasilis The Pikachu Date: Sat, 17 Feb 2024 18:30:07 +0100 Subject: [PATCH 16/16] Oh frick --- Content.Server/GameTicking/GameTicker.RoundFlow.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Content.Server/GameTicking/GameTicker.RoundFlow.cs b/Content.Server/GameTicking/GameTicker.RoundFlow.cs index 14576d6e9e8394..ffe26aeb346ad3 100644 --- a/Content.Server/GameTicking/GameTicker.RoundFlow.cs +++ b/Content.Server/GameTicking/GameTicker.RoundFlow.cs @@ -381,6 +381,7 @@ public void ShowRoundEndScoreboard(string text = "") Role = antag ? roles.First(role => role.Antagonist).Name : roles.FirstOrDefault().Name ?? Loc.GetString("game-ticker-unknown-role"), + Antag = antag, JobPrototypes = roles.Where(role => !role.Antagonist).Select(role => role.Prototype).ToArray(), AntagPrototypes = roles.Where(role => role.Antagonist).Select(role => role.Prototype).ToArray(), Observer = observer,