Skip to content

Commit

Permalink
Partial atmos refactor (#22521)
Browse files Browse the repository at this point in the history
* Reduce atmos component queries

* Remove method events

* Cache airtight data

* Make MolesArchived nullable

* Fix airtight cache

* only get tile def once

* Immutable mixtures

* firelock queries

* misc

* misc cleanup

* Trim disconnected tiles

* Fix merge issues and bugs

* Why does the PR keep increasing in scope

* debug overlay

* Fix bugs

* Fix test, remove unused events

* Add setmapatmos command

* Fix overlays

* Add map check

* A

* Resolve conflicts with #26102

* Remove some obsolete methods
  • Loading branch information
ElectroJr authored and stellar-novas committed Mar 27, 2024
1 parent b702cbd commit a43f8e9
Show file tree
Hide file tree
Showing 43 changed files with 892 additions and 636 deletions.
70 changes: 46 additions & 24 deletions Content.Client/Atmos/Overlays/GasTileOverlay.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
using Robust.Client.Graphics;
using Robust.Client.ResourceManagement;
using Robust.Shared.Enums;
using Robust.Shared.Graphics;
using Robust.Shared.Graphics.RSI;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;
Expand All @@ -23,7 +22,7 @@ public sealed class GasTileOverlay : Overlay
private readonly IEntityManager _entManager;
private readonly IMapManager _mapManager;

public override OverlaySpace Space => OverlaySpace.WorldSpaceEntities;
public override OverlaySpace Space => OverlaySpace.WorldSpaceEntities | OverlaySpace.WorldSpaceBelowWorld;
private readonly ShaderInstance _shader;

// Gas overlays
Expand Down Expand Up @@ -79,7 +78,8 @@ public GasTileOverlay(GasTileOverlaySystem system, IEntityManager entManager, IR
var rsi = resourceCache.GetResource<RSIResource>(animated.RsiPath).RSI;
var stateId = animated.RsiState;

if (!rsi.TryGetState(stateId, out var state)) continue;
if (!rsi.TryGetState(stateId, out var state))
continue;

_frames[i] = state.GetFrames(RsiDirection.South);
_frameDelays[i] = state.GetDelays();
Expand Down Expand Up @@ -111,7 +111,8 @@ protected override void FrameUpdate(FrameEventArgs args)
for (var i = 0; i < _gasCount; i++)
{
var delays = _frameDelays[i];
if (delays.Length == 0) continue;
if (delays.Length == 0)
continue;

var frameCount = _frameCounter[i];
_timer[i] += args.DeltaSeconds;
Expand All @@ -127,7 +128,8 @@ protected override void FrameUpdate(FrameEventArgs args)
for (var i = 0; i < FireStates; i++)
{
var delays = _fireFrameDelays[i];
if (delays.Length == 0) continue;
if (delays.Length == 0)
continue;

var frameCount = _fireFrameCounter[i];
_fireTimer[i] += args.DeltaSeconds;
Expand Down Expand Up @@ -161,26 +163,10 @@ protected override void Draw(in OverlayDrawArgs args)
var mapUid = _mapManager.GetMapEntityId(args.MapId);

if (_entManager.TryGetComponent<MapAtmosphereComponent>(mapUid, out var atmos))
{
var bottomLeft = args.WorldAABB.BottomLeft.Floored();
var topRight = args.WorldAABB.TopRight.Ceiled();

for (var x = bottomLeft.X; x <= topRight.X; x++)
{
for (var y = bottomLeft.Y; y <= topRight.Y; y++)
{
var tilePosition = new Vector2(x, y);

for (var i = 0; i < atmos.OverlayData.Opacity.Length; i++)
{
var opacity = atmos.OverlayData.Opacity[i];
DrawMapOverlay(drawHandle, args, mapUid, atmos);

if (opacity > 0)
args.WorldHandle.DrawTexture(_frames[i][_frameCounter[i]], tilePosition, Color.White.WithAlpha(opacity));
}
}
}
}
if (args.Space != OverlaySpace.WorldSpaceEntities)
return;

// TODO: WorldBounds callback.
_mapManager.FindGridsIntersecting(args.MapId, args.WorldAABB, ref gridState,
Expand Down Expand Up @@ -265,5 +251,41 @@ protected override void Draw(in OverlayDrawArgs args)
drawHandle.UseShader(null);
drawHandle.SetTransform(Matrix3.Identity);
}

private void DrawMapOverlay(
DrawingHandleWorld handle,
OverlayDrawArgs args,
EntityUid map,
MapAtmosphereComponent atmos)
{
var mapGrid = _entManager.HasComponent<MapGridComponent>(map);

// map-grid atmospheres get drawn above grids
if (mapGrid && args.Space != OverlaySpace.WorldSpaceEntities)
return;

// Normal map atmospheres get drawn below grids
if (!mapGrid && args.Space != OverlaySpace.WorldSpaceBelowWorld)
return;

var bottomLeft = args.WorldAABB.BottomLeft.Floored();
var topRight = args.WorldAABB.TopRight.Ceiled();

for (var x = bottomLeft.X; x <= topRight.X; x++)
{
for (var y = bottomLeft.Y; y <= topRight.Y; y++)
{
var tilePosition = new Vector2(x, y);

for (var i = 0; i < atmos.OverlayData.Opacity.Length; i++)
{
var opacity = atmos.OverlayData.Opacity[i];

if (opacity > 0)
handle.DrawTexture(_frames[i][_frameCounter[i]], tilePosition, Color.White.WithAlpha(opacity));
}
}
}
}
}
}
2 changes: 1 addition & 1 deletion Content.Client/Mapping/MappingSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ private void OnFillActionSlot(FillActionSlotEvent ev)
if (tileDef is not ContentTileDefinition contentTileDef)
return;

var tileIcon = contentTileDef.IsSpace
var tileIcon = contentTileDef.MapAtmosphere
? _spaceIcon
: new Texture(contentTileDef.Sprite!.Value);

Expand Down
2 changes: 1 addition & 1 deletion Content.IntegrationTests/Tests/Body/LungTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ await server.WaitAssertion(() =>
metaSys.Update(1.0f);
metaSys.Update(1.0f);
respSys.Update(2.0f);
Assert.That(GetMapMoles(), Is.EqualTo(startingMoles).Within(0.0001));
Assert.That(GetMapMoles(), Is.EqualTo(startingMoles).Within(0.0002));
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1006,15 +1006,10 @@ protected async Task AddAtmosphere(EntityUid? uid = null)
await Server.WaitPost(() =>
{
var atmosSystem = SEntMan.System<AtmosphereSystem>();
var atmos = SEntMan.EnsureComponent<MapAtmosphereComponent>(target);
var moles = new float[Atmospherics.AdjustedNumberOfGases];
moles[(int) Gas.Oxygen] = 21.824779f;
moles[(int) Gas.Nitrogen] = 82.10312f;
atmosSystem.SetMapAtmosphere(target, false, new GasMixture(2500)
{
Temperature = 293.15f,
Moles = moles,
}, atmos);
atmosSystem.SetMapAtmosphere(target, false, new GasMixture(moles, Atmospherics.T20C));
});
}

Expand Down
94 changes: 94 additions & 0 deletions Content.Server/Atmos/Commands/SetMapAtmosCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
using Content.Server.Administration;
using Content.Server.Atmos.Components;
using Content.Server.Atmos.EntitySystems;
using Content.Shared.Administration;
using Content.Shared.Atmos;
using Robust.Shared.Console;
using Robust.Shared.Map;

namespace Content.Server.Atmos.Commands;

[AdminCommand(AdminFlags.Admin)]
public sealed class AddMapAtmosCommand : LocalizedCommands
{
[Dependency] private readonly IEntityManager _entities = default!;
[Dependency] private readonly IMapManager _map = default!;

private const string _cmd = "cmd-set-map-atmos";
public override string Command => "setmapatmos";
public override string Description => Loc.GetString($"{_cmd}-desc");
public override string Help => Loc.GetString($"{_cmd}-help");

public override void Execute(IConsoleShell shell, string argStr, string[] args)
{
if (args.Length < 2)
{
shell.WriteLine(Help);
return;
}

int.TryParse(args[0], out var id);
var map = _map.GetMapEntityId(new MapId(id));
if (!map.IsValid())
{
shell.WriteError(Loc.GetString("cmd-parse-failure-mapid", ("arg", args[0])));
return;
}

if (!bool.TryParse(args[1], out var space))
{
shell.WriteError(Loc.GetString("cmd-parse-failure-bool", ("arg", args[1])));
return;
}

if (space || args.Length < 4)
{
_entities.RemoveComponent<MapAtmosphereComponent>(map);
shell.WriteLine(Loc.GetString($"{_cmd}-removed", ("map", id)));
return;
}

if (!float.TryParse(args[2], out var temp))
{
shell.WriteError(Loc.GetString("cmd-parse-failure-float", ("arg", args[2])));
return;
}

var mix = new GasMixture(Atmospherics.CellVolume) {Temperature = Math.Min(temp, Atmospherics.TCMB)};
for (var i = 0; i < Atmospherics.TotalNumberOfGases; i++)
{
if (args.Length == 3 + i)
break;

if (!float.TryParse(args[3+i], out var moles))
{
shell.WriteError(Loc.GetString("cmd-parse-failure-float", ("arg", args[3+i])));
return;
}

mix.AdjustMoles(i, moles);
}

var atmos = _entities.EntitySysManager.GetEntitySystem<AtmosphereSystem>();
atmos.SetMapAtmosphere(map, space, mix);
shell.WriteLine(Loc.GetString($"{_cmd}-updated", ("map", id)));
}

public override CompletionResult GetCompletion(IConsoleShell shell, string[] args)
{
if (args.Length == 1)
return CompletionResult.FromHintOptions(CompletionHelper.MapIds(_entities), Loc.GetString($"{_cmd}-hint-map"));

if (args.Length == 2)
return CompletionResult.FromHintOptions(new[]{ "false", "true"}, Loc.GetString($"{_cmd}-hint-space"));

if (!bool.TryParse(args[1], out var space) || space)
return CompletionResult.Empty;

if (args.Length == 3)
return CompletionResult.FromHint(Loc.GetString($"{_cmd}-hint-temp"));

var gas = (Gas) args.Length - 4;
return CompletionResult.FromHint(Loc.GetString($"{_cmd}-hint-gas" , ("gas", gas.ToString())));
}
}
4 changes: 3 additions & 1 deletion Content.Server/Atmos/Components/AirtightComponent.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
using Content.Server.Atmos.EntitySystems;
using Content.Shared.Atmos;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;

namespace Content.Server.Atmos.Components
{
[RegisterComponent]
[RegisterComponent, Access(typeof(AirtightSystem))]
public sealed partial class AirtightComponent : Component
{
public (EntityUid Grid, Vector2i Tile) LastPosition { get; set; }
Expand All @@ -29,6 +30,7 @@ public sealed partial class AirtightComponent : Component
[DataField("noAirWhenFullyAirBlocked")]
public bool NoAirWhenFullyAirBlocked { get; set; } = true;

[Access(Other = AccessPermissions.ReadWriteExecute)]
public AtmosDirection AirBlockedDirection => (AtmosDirection)CurrentAirBlockedDirection;
}
}
8 changes: 7 additions & 1 deletion Content.Server/Atmos/Components/GridAtmosphereComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ public sealed partial class GridAtmosphereComponent : Component
[IncludeDataField(customTypeSerializer:typeof(TileAtmosCollectionSerializer))]
public Dictionary<Vector2i, TileAtmosphere> Tiles = new(1000);

[ViewVariables]
public HashSet<TileAtmosphere> MapTiles = new(1000);

[ViewVariables]
public readonly HashSet<TileAtmosphere> ActiveTiles = new(1000);

Expand Down Expand Up @@ -80,7 +83,10 @@ public sealed partial class GridAtmosphereComponent : Component
public readonly HashSet<Vector2i> InvalidatedCoords = new(1000);

[ViewVariables]
public readonly Queue<Vector2i> CurrentRunInvalidatedCoordinates = new();
public readonly Queue<TileAtmosphere> CurrentRunInvalidatedTiles = new();

[ViewVariables]
public readonly List<TileAtmosphere> PossiblyDisconnectedTiles = new(100);

[ViewVariables]
public int InvalidatedCoordsCount => InvalidatedCoords.Count;
Expand Down
8 changes: 5 additions & 3 deletions Content.Server/Atmos/Components/MapAtmosphereComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ public sealed partial class MapAtmosphereComponent : SharedMapAtmosphereComponen
/// <summary>
/// The default GasMixture a map will have. Space mixture by default.
/// </summary>
[DataField("mixture"), ViewVariables(VVAccess.ReadWrite)]
public GasMixture? Mixture = GasMixture.SpaceGas;
[DataField, ViewVariables(VVAccess.ReadWrite)]
public GasMixture Mixture = GasMixture.SpaceGas;

/// <summary>
/// Whether empty tiles will be considered space or not.
/// </summary>
[DataField("space"), ViewVariables(VVAccess.ReadWrite)]
[DataField, ViewVariables(VVAccess.ReadWrite)]
public bool Space = true;

public SharedGasTileOverlaySystem.GasOverlayData Overlay;
}
18 changes: 7 additions & 11 deletions Content.Server/Atmos/EntitySystems/AirtightSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,14 @@
using Content.Server.Explosion.EntitySystems;
using Content.Shared.Atmos;
using JetBrains.Annotations;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;

namespace Content.Server.Atmos.EntitySystems
{
[UsedImplicitly]
public sealed class AirtightSystem : EntitySystem
{
[Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly SharedTransformSystem _transform = default!;
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
[Dependency] private readonly ExplosionSystem _explosionSystem = default!;

Expand Down Expand Up @@ -121,19 +120,16 @@ public void UpdatePosition(Entity<AirtightComponent> ent, TransformComponent? xf
if (!xform.Anchored || !TryComp(xform.GridUid, out MapGridComponent? grid))
return;

airtight.LastPosition = (xform.GridUid.Value, grid.TileIndicesFor(xform.Coordinates));
InvalidatePosition(airtight.LastPosition.Item1, airtight.LastPosition.Item2, airtight.FixVacuum && !airtight.AirBlocked);
var indices = _transform.GetGridTilePositionOrDefault((ent, xform), grid);
airtight.LastPosition = (xform.GridUid.Value, indices);
InvalidatePosition((xform.GridUid.Value, grid), indices);
}

public void InvalidatePosition(EntityUid gridId, Vector2i pos, bool fixVacuum = false)
public void InvalidatePosition(Entity<MapGridComponent?> grid, Vector2i pos)
{
if (!TryComp(gridId, out MapGridComponent? grid))
return;

var query = EntityManager.GetEntityQuery<AirtightComponent>();
_explosionSystem.UpdateAirtightMap(gridId, pos, grid, query);
// TODO make atmos system use query
_atmosphereSystem.InvalidateTile(gridId, pos);
_explosionSystem.UpdateAirtightMap(grid, pos, grid, query);
_atmosphereSystem.InvalidateTile(grid.Owner, pos);
}

private AtmosDirection Rotate(AtmosDirection myDirection, Angle myAngle)
Expand Down
11 changes: 4 additions & 7 deletions Content.Server/Atmos/EntitySystems/AtmosDebugOverlaySystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,22 +97,19 @@ private void OnPlayerStatusChanged(object? sender, SessionStatusEventArgs e)
}
}

private AtmosDebugOverlayData ConvertTileToData(TileAtmosphere? tile)
private AtmosDebugOverlayData? ConvertTileToData(TileAtmosphere tile)
{
if (tile == null)
return default;

return new AtmosDebugOverlayData(
tile.GridIndices,
tile.Air?.Temperature ?? default,
tile.Air?.Moles,
tile.PressureDirection,
tile.LastPressureDirection,
tile.BlockedAirflow,
tile.AirtightData.BlockedDirections,
tile.ExcitedGroup?.GetHashCode(),
tile.Space,
false,
false);
tile.MapAtmosphere,
tile.NoGridTile);
}

public override void Update(float frameTime)
Expand Down
Loading

0 comments on commit a43f8e9

Please sign in to comment.