Fix Atmospherics dP not trolling partially airtight entities (#40435)

* Fix dP not trolling partially airtight entities

* Assumptions in atmospherics are the root of all evil
This commit is contained in:
ArtisticRoomba
2025-10-14 15:35:25 -07:00
committed by GitHub
parent 1a5be55c70
commit df6ce7f473
5 changed files with 27 additions and 26 deletions

View File

@@ -93,6 +93,12 @@ public sealed class DeltaPressureTest
private readonly ResPath _testMap = new("Maps/Test/Atmospherics/DeltaPressure/deltapressuretest.yml");
// TODO ATMOS TESTS
// - Check for directional windows (partial airtight ents) properly computing pressure differences
// - Check for multi-tick damage (window with n damage threshold should take n ticks to destroy)
// - Check that all maps do not explode into a million pieces on load due to dP
// - Ensure that all tests work for a map that has an origin at a non zero coordinate
/// <summary>
/// Asserts that an entity with a DeltaPressureComponent with autoJoinProcessingList
/// set to true is automatically added to the DeltaPressure processing list

View File

@@ -34,18 +34,13 @@ public sealed partial class DeltaPressureComponent : Component
[Access(typeof(DeltaPressureSystem), typeof(AtmosphereSystem))]
public bool IsTakingDamage;
/// <summary>
/// The current cached position of this entity on the grid.
/// Updated via MoveEvent.
/// </summary>
[DataField(readOnly: true)]
public Vector2i CurrentPosition = Vector2i.Zero;
/// <summary>
/// The grid this entity is currently joined to for processing.
/// Required for proper deletion, as we cannot reference the grid
/// for removal while the entity is being deleted.
/// </summary>
/// <remarks>Note that while <see cref="AirtightComponent"/> already stores the grid,
/// we cannot trust it to be available on init or when the entity is being deleted. Tragic.</remarks>
[DataField]
public EntityUid? GridUid;

View File

@@ -355,10 +355,6 @@ public partial class AtmosphereSystem
grid.Comp.DeltaPressureEntityLookup[ent.Owner] = grid.Comp.DeltaPressureEntities.Count;
grid.Comp.DeltaPressureEntities.Add(ent);
ent.Comp.CurrentPosition = _map.CoordinatesToTile(grid,
Comp<MapGridComponent>(grid),
xform.Coordinates);
ent.Comp.GridUid = grid.Owner;
ent.Comp.InProcessingList = true;

View File

@@ -39,11 +39,13 @@ public sealed partial class AtmosphereSystem
so simple vector operations like min/max/abs can be performed on them.
*/
var airtightComp = _airtightQuery.Comp(ent);
var currentPos = airtightComp.LastPosition.Tile;
var tiles = new TileAtmosphere?[Atmospherics.Directions];
for (var i = 0; i < Atmospherics.Directions; i++)
{
var direction = (AtmosDirection)(1 << i);
var offset = ent.Comp.CurrentPosition.Offset(direction);
var offset = currentPos.Offset(direction);
tiles[i] = gridAtmosComp.Tiles.GetValueOrDefault(offset);
}
@@ -51,6 +53,21 @@ public sealed partial class AtmosphereSystem
GetBulkTileAtmospherePressures(tiles, pressures);
// This entity could be airtight but still be able to contain air on the tile it's on (ex. directional windows).
// As such, substitute the pressure of the pressure on top of the entity for the directions that it can accept air from.
// (Or rather, don't do so for directions that it blocks air from.)
if (!airtightComp.NoAirWhenFullyAirBlocked)
{
for (var i = 0; i < Atmospherics.Directions; i++)
{
var direction = (AtmosDirection)(1 << i);
if (!airtightComp.AirBlockedDirection.HasFlag(direction))
{
pressures[i] = gridAtmosComp.Tiles.GetValueOrDefault(currentPos)?.Air?.Pressure ?? 0f;
}
}
}
Span<float> opposingGroupA = stackalloc float[DeltaPressurePairCount];
Span<float> opposingGroupB = stackalloc float[DeltaPressurePairCount];
Span<float> opposingGroupMax = stackalloc float[DeltaPressurePairCount];

View File

@@ -17,7 +17,6 @@ namespace Content.Server.Atmos.EntitySystems;
public sealed class DeltaPressureSystem : EntitySystem
{
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
[Dependency] private readonly SharedMapSystem _map = default!;
public override void Initialize()
{
@@ -26,29 +25,17 @@ public sealed class DeltaPressureSystem : EntitySystem
SubscribeLocalEvent<DeltaPressureComponent, ComponentInit>(OnComponentInit);
SubscribeLocalEvent<DeltaPressureComponent, ComponentShutdown>(OnComponentShutdown);
SubscribeLocalEvent<DeltaPressureComponent, ExaminedEvent>(OnExamined);
SubscribeLocalEvent<DeltaPressureComponent, MoveEvent>(OnMoveEvent);
SubscribeLocalEvent<DeltaPressureComponent, GridUidChangedEvent>(OnGridChanged);
}
private void OnMoveEvent(Entity<DeltaPressureComponent> ent, ref MoveEvent args)
{
var xform = Transform(ent);
// May move off-grid, so, might as well protect against that.
if (!TryComp<MapGridComponent>(xform.GridUid, out var mapGridComponent))
{
return;
}
ent.Comp.CurrentPosition = _map.CoordinatesToTile(xform.GridUid.Value, mapGridComponent, args.NewPosition);
}
private void OnComponentInit(Entity<DeltaPressureComponent> ent, ref ComponentInit args)
{
var xform = Transform(ent);
if (xform.GridUid == null)
return;
EnsureComp<AirtightComponent>(ent);
_atmosphereSystem.TryAddDeltaPressureEntity(xform.GridUid.Value, ent);
}