From 19326be2d49d4ed782b706eee49cf381d503ed7f Mon Sep 17 00:00:00 2001 From: Vordenburg <114301317+Vordenburg@users.noreply.github.com> Date: Sun, 13 Aug 2023 12:55:04 -0400 Subject: [PATCH] Expand PVS entities to all players at round end (#18963) --- .../GameTicking/GameTicker.RoundFlow.cs | 55 +++++++++++++++++++ Content.Server/GameTicking/GameTicker.cs | 1 + 2 files changed, 56 insertions(+) diff --git a/Content.Server/GameTicking/GameTicker.RoundFlow.cs b/Content.Server/GameTicking/GameTicker.RoundFlow.cs index 3364931125..a3efaff9b9 100644 --- a/Content.Server/GameTicking/GameTicker.RoundFlow.cs +++ b/Content.Server/GameTicking/GameTicker.RoundFlow.cs @@ -7,6 +7,7 @@ using Content.Shared.GameTicking; using Content.Shared.Preferences; using JetBrains.Annotations; using Prometheus; +using Robust.Server.GameStates; using Robust.Server.Maps; using Robust.Server.Player; using Robust.Shared.Audio; @@ -45,6 +46,22 @@ namespace Content.Server.GameTicking [ViewVariables] private bool _startingRound; + /// + /// This is a list of players that are going to appear in the round-end + /// crew manifest so their children entities can be collected each update + /// and sent to far-away players. + /// + [ViewVariables] + private HashSet _expandPvsPlayers = new(); + + /// + /// This is the list of the children entities that should be sent to + /// all players at the end of the round, to keep distant characters from + /// looking naked in the crew manifest. + /// + [ViewVariables] + private List _expandPvsEntities = new(); + [ViewVariables] private GameRunLevel _runLevel; @@ -64,6 +81,11 @@ namespace Content.Server.GameTicking } } + private void InitializeRoundFlow() + { + SubscribeLocalEvent(OnExpandPvs); + } + /// /// Returns true if the round's map is eligible to be updated. /// @@ -299,6 +321,14 @@ namespace Content.Server.GameTicking ShowRoundEndScoreboard(text); } + private void OnExpandPvs(ref ExpandPvsEvent args) + { + if (RunLevel != GameRunLevel.PostRound) + return; + + args.Entities.AddRange(_expandPvsEntities); + } + public void ShowRoundEndScoreboard(string text = "") { // Log end of round @@ -316,6 +346,10 @@ namespace Content.Server.GameTicking //Get the timespan of the round. var roundDuration = RoundDuration(); + // Should already be empty, but just in case. + _expandPvsEntities.Clear(); + _expandPvsPlayers.Clear(); + //Generate a list of basic player info to display in the end round summary. var listOfPlayerInfo = new List(); // Grab the great big book of all the Minds, we'll need them for this. @@ -349,6 +383,9 @@ namespace Content.Server.GameTicking else if (mind.CurrentEntity != null && TryName(mind.CurrentEntity.Value, out var icName)) playerIcName = icName; + if (Exists(mind.OriginalOwnedEntity)) + _expandPvsPlayers.Add(mind.OriginalOwnedEntity.Value); + var playerEndRoundInfo = new RoundEndMessageEvent.RoundEndPlayerInfo() { // Note that contentPlayerData?.Name sticks around after the player is disconnected. @@ -366,6 +403,21 @@ namespace Content.Server.GameTicking }; listOfPlayerInfo.Add(playerEndRoundInfo); } + + // Recursively collect entities for the crew manifest. + void RecursePvsEntities(IEnumerable entities) + { + _expandPvsEntities.AddRange(entities); + + foreach (var entity in entities) + { + if (TryComp(entity, out var xform)) + RecursePvsEntities(xform.ChildEntities); + } + } + + RecursePvsEntities(_expandPvsPlayers); + // This ordering mechanism isn't great (no ordering of minds) but functions var listOfPlayerInfoFinal = listOfPlayerInfo.OrderBy(pi => pi.PlayerOOCName).ToArray(); @@ -464,6 +516,9 @@ namespace Content.Server.GameTicking _allPreviousGameRules.Clear(); + _expandPvsPlayers.Clear(); + _expandPvsEntities.Clear(); + // Round restart cleanup event, so entity systems can reset. var ev = new RoundRestartCleanupEvent(); RaiseLocalEvent(ev); diff --git a/Content.Server/GameTicking/GameTicker.cs b/Content.Server/GameTicking/GameTicker.cs index dc9b24085f..fbe40ee6d6 100644 --- a/Content.Server/GameTicking/GameTicker.cs +++ b/Content.Server/GameTicking/GameTicker.cs @@ -70,6 +70,7 @@ namespace Content.Server.GameTicking "Overflow role does not have the correct name!"); InitializeGameRules(); InitializeReplays(); + InitializeRoundFlow(); _initialized = true; }