Improve canister admin logs (#34495)

This commit is contained in:
Partmedia
2025-01-17 17:37:40 -08:00
committed by GitHub
3 changed files with 92 additions and 15 deletions

View File

@@ -109,7 +109,15 @@ public sealed class GasCanisterSystem : EntitySystem
var item = canister.GasTankSlot.Item;
_slots.TryEjectToHands(uid, canister.GasTankSlot, args.Actor);
_adminLogger.Add(LogType.CanisterTankEjected, LogImpact.Medium, $"Player {ToPrettyString(args.Actor):player} ejected tank {ToPrettyString(item):tank} from {ToPrettyString(uid):canister}");
if (canister.ReleaseValve)
{
_adminLogger.Add(LogType.CanisterTankEjected, LogImpact.High, $"Player {ToPrettyString(args.Actor):player} ejected tank {ToPrettyString(item):tank} from {ToPrettyString(uid):canister} while the valve was open, releasing [{GetContainedGasesString((uid, canister))}] to atmosphere");
}
else
{
_adminLogger.Add(LogType.CanisterTankEjected, LogImpact.Medium, $"Player {ToPrettyString(args.Actor):player} ejected tank {ToPrettyString(item):tank} from {ToPrettyString(uid):canister}");
}
}
private void OnCanisterChangeReleasePressure(EntityUid uid, GasCanisterComponent canister, GasCanisterChangeReleasePressureMessage args)
@@ -124,24 +132,24 @@ public sealed class GasCanisterSystem : EntitySystem
private void OnCanisterChangeReleaseValve(EntityUid uid, GasCanisterComponent canister, GasCanisterChangeReleaseValveMessage args)
{
var impact = LogImpact.High;
// filling a jetpack with plasma is less important than filling a room with it
impact = canister.GasTankSlot.HasItem ? LogImpact.Medium : LogImpact.High;
var hasItem = canister.GasTankSlot.HasItem;
var impact = hasItem ? LogImpact.Medium : LogImpact.High;
var containedGasDict = new Dictionary<Gas, float>();
var containedGasArray = Enum.GetValues(typeof(Gas));
for (int i = 0; i < containedGasArray.Length; i++)
{
containedGasDict.Add((Gas)i, canister.Air[i]);
}
_adminLogger.Add(LogType.CanisterValve, impact, $"{ToPrettyString(args.Actor):player} set the valve on {ToPrettyString(uid):canister} to {args.Valve:valveState} while it contained [{string.Join(", ", containedGasDict)}]");
_adminLogger.Add(
LogType.CanisterValve,
impact,
$"{ToPrettyString(args.Actor):player} {(args.Valve ? "opened" : "closed")} the valve on {ToPrettyString(uid):canister} to {(hasItem ? "inserted tank" : "environment")} while it contained [{GetContainedGasesString((uid, canister))}]");
canister.ReleaseValve = args.Valve;
DirtyUI(uid, canister);
}
private static string GetContainedGasesString(Entity<GasCanisterComponent> canister)
{
return string.Join(", ", canister.Comp.Air);
}
private void OnCanisterUpdated(EntityUid uid, GasCanisterComponent canister, ref AtmosDeviceUpdateEvent args)
{
_atmos.React(canister.Air, canister);

View File

@@ -1,4 +1,5 @@
using System.Diagnostics.CodeAnalysis;
using System.Collections;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Runtime.CompilerServices;
using Content.Shared.Atmos.EntitySystems;
@@ -13,12 +14,12 @@ namespace Content.Shared.Atmos
/// </summary>
[Serializable]
[DataDefinition]
public sealed partial class GasMixture : IEquatable<GasMixture>, ISerializationHooks
public sealed partial class GasMixture : IEquatable<GasMixture>, ISerializationHooks, IEnumerable<(Gas gas, float moles)>
{
public static GasMixture SpaceGas => new() {Volume = Atmospherics.CellVolume, Temperature = Atmospherics.TCMB, Immutable = true};
// No access, to ensure immutable mixtures are never accidentally mutated.
[Access(typeof(SharedAtmosphereSystem), typeof(SharedAtmosDebugOverlaySystem), Other = AccessPermissions.None)]
[Access(typeof(SharedAtmosphereSystem), typeof(SharedAtmosDebugOverlaySystem), typeof(GasEnumerator), Other = AccessPermissions.None)]
[DataField]
public float[] Moles = new float[Atmospherics.AdjustedNumberOfGases];
@@ -249,6 +250,16 @@ namespace Content.Shared.Atmos
return new GasMixtureStringRepresentation(TotalMoles, Temperature, Pressure, molesPerGas);
}
GasEnumerator GetEnumerator()
{
return new GasEnumerator(this);
}
IEnumerator<(Gas gas, float moles)> IEnumerable<(Gas gas, float moles)>.GetEnumerator()
{
return GetEnumerator();
}
public override bool Equals(object? obj)
{
if (obj is GasMixture mix)
@@ -289,6 +300,11 @@ namespace Content.Shared.Atmos
return hashCode.ToHashCode();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public GasMixture Clone()
{
if (Immutable)
@@ -302,5 +318,28 @@ namespace Content.Shared.Atmos
};
return newMixture;
}
public struct GasEnumerator(GasMixture mixture) : IEnumerator<(Gas gas, float moles)>
{
private int _idx = -1;
public void Dispose()
{
// Nada.
}
public bool MoveNext()
{
return ++_idx < Atmospherics.TotalNumberOfGases;
}
public void Reset()
{
_idx = -1;
}
public (Gas gas, float moles) Current => ((Gas)_idx, mixture.Moles[_idx]);
object? IEnumerator.Current => Current;
}
}
}

View File

@@ -0,0 +1,30 @@
using Content.Shared.Atmos;
using NUnit.Framework;
namespace Content.Tests.Shared.Atmos;
[TestFixture, TestOf(typeof(GasMixture))]
[Parallelizable(ParallelScope.All)]
public sealed class GasMixtureTest
{
[Test]
public void TestEnumerate()
{
var mixture = new GasMixture();
mixture.SetMoles(Gas.Oxygen, 20);
mixture.SetMoles(Gas.Nitrogen, 10);
mixture.SetMoles(Gas.Plasma, 80);
var expectedList = new (Gas, float)[Atmospherics.TotalNumberOfGases];
for (var i = 0; i < Atmospherics.TotalNumberOfGases; i++)
{
expectedList[i].Item1 = (Gas)i;
}
expectedList[(int)Gas.Oxygen].Item2 = 20f;
expectedList[(int)Gas.Nitrogen].Item2 = 10f;
expectedList[(int)Gas.Plasma].Item2 = 80f;
Assert.That(mixture, Is.EquivalentTo(expectedList));
}
}