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;
}