Fix duplicate suit signals (#35918)

* Include the suit owner’s UID in suit sensor status updates.

* Show a single monitoring entry per crew member

* Rewrite sensor collection using a dictionary
This commit is contained in:
Ciarán Walsh
2025-04-16 22:14:05 +01:00
committed by GitHub
parent a28a12140e
commit a16097fa33
3 changed files with 28 additions and 5 deletions

View File

@@ -79,10 +79,28 @@ public sealed partial class CrewMonitoringWindow : FancyWindow
NoServerLabel.Visible = false; NoServerLabel.Visible = false;
// Collect one status per user, using the sensor with the most data available.
Dictionary<NetEntity, SuitSensorStatus> uniqueSensorsMap = new();
foreach (var sensor in sensors)
{
if (uniqueSensorsMap.TryGetValue(sensor.OwnerUid, out var existingSensor))
{
// Skip if we already have a sensor with more data for this mob.
if (existingSensor.Coordinates != null && sensor.Coordinates == null)
continue;
if (existingSensor.DamagePercentage != null && sensor.DamagePercentage == null)
continue;
}
uniqueSensorsMap[sensor.OwnerUid] = sensor;
}
var uniqueSensors = uniqueSensorsMap.Values.ToList();
// Order sensor data // Order sensor data
var orderedSensors = sensors.OrderBy(n => n.Name).OrderBy(j => j.Job); var orderedSensors = uniqueSensors.OrderBy(n => n.Name).OrderBy(j => j.Job);
var assignedSensors = new HashSet<SuitSensorStatus>(); var assignedSensors = new HashSet<SuitSensorStatus>();
var departments = sensors.SelectMany(d => d.JobDepartments).Distinct().OrderBy(n => n); var departments = uniqueSensors.SelectMany(d => d.JobDepartments).Distinct().OrderBy(n => n);
// Create department labels and populate lists // Create department labels and populate lists
foreach (var department in departments) foreach (var department in departments)

View File

@@ -406,7 +406,7 @@ public sealed class SuitSensorSystem : EntitySystem
totalDamageThreshold = critThreshold.Value.Int(); totalDamageThreshold = critThreshold.Value.Int();
// finally, form suit sensor status // finally, form suit sensor status
var status = new SuitSensorStatus(GetNetEntity(uid), userName, userJob, userJobIcon, userJobDepartments); var status = new SuitSensorStatus(GetNetEntity(sensor.User.Value), GetNetEntity(uid), userName, userJob, userJobIcon, userJobDepartments);
switch (sensor.Mode) switch (sensor.Mode)
{ {
case SuitSensorMode.SensorBinary: case SuitSensorMode.SensorBinary:
@@ -461,6 +461,7 @@ public sealed class SuitSensorSystem : EntitySystem
[SuitSensorConstants.NET_JOB_DEPARTMENTS] = status.JobDepartments, [SuitSensorConstants.NET_JOB_DEPARTMENTS] = status.JobDepartments,
[SuitSensorConstants.NET_IS_ALIVE] = status.IsAlive, [SuitSensorConstants.NET_IS_ALIVE] = status.IsAlive,
[SuitSensorConstants.NET_SUIT_SENSOR_UID] = status.SuitSensorUid, [SuitSensorConstants.NET_SUIT_SENSOR_UID] = status.SuitSensorUid,
[SuitSensorConstants.NET_OWNER_UID] = status.OwnerUid,
}; };
if (status.TotalDamage != null) if (status.TotalDamage != null)
@@ -491,13 +492,14 @@ public sealed class SuitSensorSystem : EntitySystem
if (!payload.TryGetValue(SuitSensorConstants.NET_JOB_DEPARTMENTS, out List<string>? jobDepartments)) return null; if (!payload.TryGetValue(SuitSensorConstants.NET_JOB_DEPARTMENTS, out List<string>? jobDepartments)) return null;
if (!payload.TryGetValue(SuitSensorConstants.NET_IS_ALIVE, out bool? isAlive)) return null; if (!payload.TryGetValue(SuitSensorConstants.NET_IS_ALIVE, out bool? isAlive)) return null;
if (!payload.TryGetValue(SuitSensorConstants.NET_SUIT_SENSOR_UID, out NetEntity suitSensorUid)) return null; if (!payload.TryGetValue(SuitSensorConstants.NET_SUIT_SENSOR_UID, out NetEntity suitSensorUid)) return null;
if (!payload.TryGetValue(SuitSensorConstants.NET_OWNER_UID, out NetEntity ownerUid)) return null;
// try get total damage and cords (optionals) // try get total damage and cords (optionals)
payload.TryGetValue(SuitSensorConstants.NET_TOTAL_DAMAGE, out int? totalDamage); payload.TryGetValue(SuitSensorConstants.NET_TOTAL_DAMAGE, out int? totalDamage);
payload.TryGetValue(SuitSensorConstants.NET_TOTAL_DAMAGE_THRESHOLD, out int? totalDamageThreshold); payload.TryGetValue(SuitSensorConstants.NET_TOTAL_DAMAGE_THRESHOLD, out int? totalDamageThreshold);
payload.TryGetValue(SuitSensorConstants.NET_COORDINATES, out NetCoordinates? coords); payload.TryGetValue(SuitSensorConstants.NET_COORDINATES, out NetCoordinates? coords);
var status = new SuitSensorStatus(suitSensorUid, name, job, jobIcon, jobDepartments) var status = new SuitSensorStatus(ownerUid, suitSensorUid, name, job, jobIcon, jobDepartments)
{ {
IsAlive = isAlive.Value, IsAlive = isAlive.Value,
TotalDamage = totalDamage, TotalDamage = totalDamage,

View File

@@ -7,8 +7,9 @@ namespace Content.Shared.Medical.SuitSensor;
[Serializable, NetSerializable] [Serializable, NetSerializable]
public sealed class SuitSensorStatus public sealed class SuitSensorStatus
{ {
public SuitSensorStatus(NetEntity suitSensorUid, string name, string job, string jobIcon, List<string> jobDepartments) public SuitSensorStatus(NetEntity ownerUid, NetEntity suitSensorUid, string name, string job, string jobIcon, List<string> jobDepartments)
{ {
OwnerUid = ownerUid;
SuitSensorUid = suitSensorUid; SuitSensorUid = suitSensorUid;
Name = name; Name = name;
Job = job; Job = job;
@@ -18,6 +19,7 @@ public sealed class SuitSensorStatus
public TimeSpan Timestamp; public TimeSpan Timestamp;
public NetEntity SuitSensorUid; public NetEntity SuitSensorUid;
public NetEntity OwnerUid;
public string Name; public string Name;
public string Job; public string Job;
public string JobIcon; public string JobIcon;
@@ -55,6 +57,7 @@ public enum SuitSensorMode : byte
public static class SuitSensorConstants public static class SuitSensorConstants
{ {
public const string NET_OWNER_UID = "ownerUid";
public const string NET_NAME = "name"; public const string NET_NAME = "name";
public const string NET_JOB = "job"; public const string NET_JOB = "job";
public const string NET_JOB_ICON = "jobIcon"; public const string NET_JOB_ICON = "jobIcon";