Add atmos tick time to atmos device update event (#18781)
This commit is contained in:
@@ -21,6 +21,12 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
public bool ExcitedGroupsSpaceIsAllConsuming { get; private set; }
|
public bool ExcitedGroupsSpaceIsAllConsuming { get; private set; }
|
||||||
public float AtmosMaxProcessTime { get; private set; }
|
public float AtmosMaxProcessTime { get; private set; }
|
||||||
public float AtmosTickRate { get; private set; }
|
public float AtmosTickRate { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Time between each atmos sub-update. If you are writing an atmos device, use AtmosDeviceUpdateEvent.dt
|
||||||
|
/// instead of this value, because atmos devices do not update each are sub-update and sometimes are skipped to
|
||||||
|
/// meet the tick deadline.
|
||||||
|
/// </summary>
|
||||||
public float AtmosTime => 1f / AtmosTickRate;
|
public float AtmosTime => 1f / AtmosTickRate;
|
||||||
|
|
||||||
private void InitializeCVars()
|
private void InitializeCVars()
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
{
|
{
|
||||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||||
|
|
||||||
private readonly AtmosDeviceUpdateEvent _updateEvent = new();
|
|
||||||
private readonly Stopwatch _simulationStopwatch = new();
|
private readonly Stopwatch _simulationStopwatch = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -337,7 +336,7 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
var number = 0;
|
var number = 0;
|
||||||
while (atmosphere.CurrentRunAtmosDevices.TryDequeue(out var device))
|
while (atmosphere.CurrentRunAtmosDevices.TryDequeue(out var device))
|
||||||
{
|
{
|
||||||
RaiseLocalEvent(device.Owner, _updateEvent, false);
|
RaiseLocalEvent(device.Owner, new AtmosDeviceUpdateEvent(AtmosTime * (int)AtmosphereProcessingState.NumStates), false);
|
||||||
device.LastProcess = time;
|
device.LastProcess = time;
|
||||||
|
|
||||||
if (number++ < LagCheckIterations) continue;
|
if (number++ < LagCheckIterations) continue;
|
||||||
@@ -509,5 +508,6 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
Superconductivity,
|
Superconductivity,
|
||||||
PipeNet,
|
PipeNet,
|
||||||
AtmosDevices,
|
AtmosDevices,
|
||||||
|
NumStates
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,32 +7,50 @@ namespace Content.Server.Atmos.Piping.Components
|
|||||||
public sealed class AtmosDeviceComponent : Component
|
public sealed class AtmosDeviceComponent : Component
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether this device requires being anchored to join an atmosphere.
|
/// If true, this device must be anchored before it will receive any AtmosDeviceUpdateEvents.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
[DataField("requireAnchored")]
|
[DataField("requireAnchored")]
|
||||||
public bool RequireAnchored { get; private set; } = true;
|
public bool RequireAnchored { get; private set; } = true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether this device will join an entity system to process when not in a grid.
|
/// If true, update even when there is no grid atmosphere. Normally, atmos devices only
|
||||||
|
/// update when inside a grid atmosphere, because they work with gases in the environment
|
||||||
|
/// and won't do anything useful if there is no environment. This is useful for devices
|
||||||
|
/// like gas canisters whose contents can still react if the canister itself is not inside
|
||||||
|
/// a grid atmosphere.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("joinSystem")]
|
[DataField("joinSystem")]
|
||||||
public bool JoinSystem { get; } = false;
|
public bool JoinSystem { get; } = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether we have joined an entity system to process.
|
/// If non-null, the grid that this device is part of.
|
||||||
|
/// </summary>
|
||||||
|
public EntityUid? JoinedGrid { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that a device is not on a grid atmosphere but still being updated.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public bool JoinedSystem { get; set; } = false;
|
public bool JoinedSystem { get; set; } = false;
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public TimeSpan LastProcess { get; set; } = TimeSpan.Zero;
|
public TimeSpan LastProcess { get; set; } = TimeSpan.Zero;
|
||||||
|
|
||||||
public EntityUid? JoinedGrid { get; set; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class AtmosDeviceUpdateEvent : EntityEventArgs
|
public sealed class AtmosDeviceUpdateEvent : EntityEventArgs
|
||||||
{}
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Time elapsed since last update, in seconds. Multiply values used in the update handler
|
||||||
|
/// by this number to make them tickrate-invariant. Use this number instead of AtmosphereSystem.AtmosTime.
|
||||||
|
/// </summary>
|
||||||
|
public float dt;
|
||||||
|
|
||||||
|
public AtmosDeviceUpdateEvent(float dt)
|
||||||
|
{
|
||||||
|
this.dt = dt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public sealed class AtmosDeviceEnabledEvent : EntityEventArgs
|
public sealed class AtmosDeviceEnabledEvent : EntityEventArgs
|
||||||
{}
|
{}
|
||||||
|
|||||||
@@ -11,9 +11,9 @@ namespace Content.Server.Atmos.Piping.EntitySystems
|
|||||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||||
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
|
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
|
||||||
|
|
||||||
private readonly AtmosDeviceUpdateEvent _updateEvent = new();
|
|
||||||
|
|
||||||
private float _timer = 0f;
|
private float _timer = 0f;
|
||||||
|
|
||||||
|
// Set of atmos devices that are off-grid but have JoinSystem set.
|
||||||
private readonly HashSet<AtmosDeviceComponent> _joinedDevices = new();
|
private readonly HashSet<AtmosDeviceComponent> _joinedDevices = new();
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
@@ -27,40 +27,23 @@ namespace Content.Server.Atmos.Piping.EntitySystems
|
|||||||
SubscribeLocalEvent<AtmosDeviceComponent, AnchorStateChangedEvent>(OnDeviceAnchorChanged);
|
SubscribeLocalEvent<AtmosDeviceComponent, AnchorStateChangedEvent>(OnDeviceAnchorChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool CanJoinAtmosphere(AtmosDeviceComponent component, TransformComponent transform)
|
|
||||||
{
|
|
||||||
return (!component.RequireAnchored || transform.Anchored) && transform.GridUid != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void JoinAtmosphere(AtmosDeviceComponent component)
|
public void JoinAtmosphere(AtmosDeviceComponent component)
|
||||||
{
|
{
|
||||||
var transform = Transform(component.Owner);
|
var transform = Transform(component.Owner);
|
||||||
|
|
||||||
if (!CanJoinAtmosphere(component, transform))
|
if (component.RequireAnchored && !transform.Anchored)
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: low-hanging fruit for perf improvements around here
|
// Attempt to add device to a grid atmosphere.
|
||||||
|
bool onGrid = (transform.GridUid != null) && _atmosphereSystem.AddAtmosDevice(transform.GridUid!.Value, component);
|
||||||
|
|
||||||
// GridUid is not null because we can join atmosphere.
|
if (!onGrid && component.JoinSystem)
|
||||||
// We try to add the device to a valid atmosphere, and if we can't, try to add it to the entity system.
|
|
||||||
if (!_atmosphereSystem.AddAtmosDevice(transform.GridUid!.Value, component))
|
|
||||||
{
|
|
||||||
if (component.JoinSystem)
|
|
||||||
{
|
{
|
||||||
_joinedDevices.Add(component);
|
_joinedDevices.Add(component);
|
||||||
component.JoinedSystem = true;
|
component.JoinedSystem = true;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
component.LastProcess = _gameTiming.CurTime;
|
component.LastProcess = _gameTiming.CurTime;
|
||||||
|
|
||||||
RaiseLocalEvent(component.Owner, new AtmosDeviceEnabledEvent(), false);
|
RaiseLocalEvent(component.Owner, new AtmosDeviceEnabledEvent(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,6 +100,10 @@ namespace Content.Server.Atmos.Piping.EntitySystems
|
|||||||
RejoinAtmosphere(component);
|
RejoinAtmosphere(component);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Update atmos devices that are off-grid but have JoinSystem set. For devices updates when
|
||||||
|
/// a device is on a grid, see AtmosphereSystem:UpdateProcessing().
|
||||||
|
/// </summary>
|
||||||
public override void Update(float frameTime)
|
public override void Update(float frameTime)
|
||||||
{
|
{
|
||||||
_timer += frameTime;
|
_timer += frameTime;
|
||||||
@@ -129,7 +116,7 @@ namespace Content.Server.Atmos.Piping.EntitySystems
|
|||||||
var time = _gameTiming.CurTime;
|
var time = _gameTiming.CurTime;
|
||||||
foreach (var device in _joinedDevices)
|
foreach (var device in _joinedDevices)
|
||||||
{
|
{
|
||||||
RaiseLocalEvent(device.Owner, _updateEvent, false);
|
RaiseLocalEvent(device.Owner, new AtmosDeviceUpdateEvent(_atmosphereSystem.AtmosTime), false);
|
||||||
device.LastProcess = time;
|
device.LastProcess = time;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user