Makes Airtight ECS. (#4351)

* Makes Airtight ECS.

* Remove atmos holdovers while at it!
This commit is contained in:
Vera Aguilera Puerto
2021-07-25 09:04:58 +02:00
committed by GitHub
parent 0aaa2727c8
commit 93acc565f0
44 changed files with 151 additions and 193 deletions

View File

@@ -1,26 +1,121 @@
using Content.Server.Atmos.Components;
using Content.Shared.Atmos;
using JetBrains.Annotations;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Map;
using Robust.Shared.Maths;
namespace Content.Server.Atmos.EntitySystems
{
[UsedImplicitly]
public class AirtightSystem : EntitySystem
{
[Dependency] private readonly IMapManager _mapManager = default!;
public override void Initialize()
{
SubscribeLocalEvent<AirtightComponent, ComponentInit>(OnAirtightInit);
SubscribeLocalEvent<AirtightComponent, ComponentShutdown>(OnAirtightShutdown);
SubscribeLocalEvent<AirtightComponent, MapInitEvent>(OnMapInit);
SubscribeLocalEvent<AirtightComponent, AnchorStateChangedEvent>(OnAirtightPositionChanged);
SubscribeLocalEvent<AirtightComponent, RotateEvent>(OnAirtightRotated);
}
private void OnAirtightPositionChanged(EntityUid uid, AirtightComponent component, AnchorStateChangedEvent args)
private void OnAirtightInit(EntityUid uid, AirtightComponent airtight, ComponentInit args)
{
component.AnchorStateChanged();
if (airtight.FixAirBlockedDirectionInitialize)
OnAirtightRotated(uid, airtight, new RotateEvent(airtight.Owner, Angle.Zero, airtight.Owner.Transform.WorldRotation));
// Adding this component will immediately anchor the entity, because the atmos system
// requires airtight entities to be anchored for performance.
airtight.Owner.Transform.Anchored = true;
UpdatePosition(airtight);
}
private void OnAirtightShutdown(EntityUid uid, AirtightComponent airtight, ComponentShutdown args)
{
SetAirblocked(airtight, false);
InvalidatePosition(airtight.LastPosition.Item1, airtight.LastPosition.Item2);
if (airtight.FixVacuum)
{
Get<AtmosphereSystem>().FixVacuum(airtight.LastPosition.Item1, airtight.LastPosition.Item2);
}
}
private void OnMapInit(EntityUid uid, AirtightComponent airtight, MapInitEvent args)
{
}
private void OnAirtightPositionChanged(EntityUid uid, AirtightComponent airtight, AnchorStateChangedEvent args)
{
var gridId = airtight.Owner.Transform.GridID;
var coords = airtight.Owner.Transform.Coordinates;
var grid = _mapManager.GetGrid(gridId);
var tilePos = grid.TileIndicesFor(coords);
// Update and invalidate new position.
airtight.LastPosition = (gridId, tilePos);
InvalidatePosition(gridId, tilePos);
}
private void OnAirtightRotated(EntityUid uid, AirtightComponent airtight, RotateEvent ev)
{
airtight.RotateEvent(ev);
if (!airtight.RotateAirBlocked || airtight.InitialAirBlockedDirection == (int)AtmosDirection.Invalid)
return;
airtight.CurrentAirBlockedDirection = (int) Rotate((AtmosDirection)airtight.InitialAirBlockedDirection, ev.NewRotation);
UpdatePosition(airtight);
}
public void SetAirblocked(AirtightComponent airtight, bool airblocked)
{
airtight.AirBlocked = airblocked;
UpdatePosition(airtight);
}
public void UpdatePosition(AirtightComponent airtight)
{
if (!airtight.Owner.Transform.Anchored || !airtight.Owner.Transform.GridID.IsValid())
return;
var grid = _mapManager.GetGrid(airtight.Owner.Transform.GridID);
airtight.LastPosition = (airtight.Owner.Transform.GridID, grid.TileIndicesFor(airtight.Owner.Transform.Coordinates));
InvalidatePosition(airtight.LastPosition.Item1, airtight.LastPosition.Item2);
}
public void InvalidatePosition(GridId gridId, Vector2i pos)
{
if (!gridId.IsValid())
return;
var atmosphereSystem = Get<AtmosphereSystem>();
atmosphereSystem.UpdateAdjacent(gridId, pos);
atmosphereSystem.InvalidateTile(gridId, pos);
}
private AtmosDirection Rotate(AtmosDirection myDirection, Angle myAngle)
{
var newAirBlockedDirs = AtmosDirection.Invalid;
if (myAngle == Angle.Zero)
return myDirection;
// TODO ATMOS MULTIZ: When we make multiZ atmos, special case this.
for (var i = 0; i < Atmospherics.Directions; i++)
{
var direction = (AtmosDirection) (1 << i);
if (!myDirection.IsFlagSet(direction)) continue;
var angle = direction.ToAngle();
angle += myAngle;
newAirBlockedDirs |= angle.ToAtmosDirectionCardinal();
}
return newAirBlockedDirs;
}
}
}

View File

@@ -2,7 +2,6 @@ using System;
using System.Collections.Generic;
using System.Linq;
using Content.Server.Atmos.Reactions;
using Content.Server.Interfaces;
using Content.Shared.Atmos;
using Robust.Shared.IoC;
using Robust.Shared.Maths;

View File

@@ -246,6 +246,9 @@ namespace Content.Server.Atmos.EntitySystems
var isAirBlocked = IsTileAirBlocked(mapGrid, indices);
tile.BlockedAirflow = GetBlockedDirections(mapGrid, indices);
UpdateAdjacent(mapGrid, gridAtmosphere, tile);
if (IsTileSpace(mapGrid, indices) && !isAirBlocked)
{
tile.Air = new GasMixture(volume);
@@ -293,11 +296,8 @@ namespace Content.Server.Atmos.EntitySystems
// Then we activate the tile again.
AddActiveTile(gridAtmosphere, tile);
tile.BlockedAirflow = GetBlockedDirections(mapGrid, indices);
// TODO ATMOS: Query all the contents of this tile (like walls) and calculate the correct thermal conductivity
tile.ThermalConductivity = tile.Tile?.Tile.GetContentTileDefinition().ThermalConductivity ?? 0.5f;
UpdateAdjacent(mapGrid, gridAtmosphere, tile);
InvalidateVisuals(mapGrid.Index, indices);
for (var i = 0; i < Atmospherics.Directions; i++)
@@ -993,11 +993,25 @@ namespace Content.Server.Atmos.EntitySystems
public IEnumerable<GasMixture> GetAdjacentTileMixtures(GridAtmosphereComponent gridAtmosphere, Vector2i tile, bool includeBlocked = false, bool invalidate = false)
{
if (!gridAtmosphere.Tiles.TryGetValue(tile, out var tileAtmosphere))
yield break;
return Enumerable.Empty<GasMixture>();
for (var i = 0; i < tileAtmosphere.AdjacentTiles.Length; i++)
return GetAdjacentTileMixtures(gridAtmosphere, tileAtmosphere, includeBlocked, invalidate);
}
/// <summary>
/// Gets all tile gas mixtures adjacent to a specific tile, and optionally invalidates them.
/// Does not return the tile in question, only the adjacent ones.
/// </summary>
/// <param name="gridAtmosphere">Grid Atmosphere where the tile is.</param>
/// <param name="tile">Tile Atmosphere in question.</param>
/// <param name="includeBlocked">Whether to include tiles in directions the tile is air-blocked in.</param>
/// <param name="invalidate">Whether to invalidate all adjacent tiles.</param>
/// <returns>All adjacent tile gas mixtures to the tile in question</returns>
private IEnumerable<GasMixture> GetAdjacentTileMixtures(GridAtmosphereComponent gridAtmosphere, TileAtmosphere tile, bool includeBlocked = false, bool invalidate = false)
{
for (var i = 0; i < tile.AdjacentTiles.Length; i++)
{
var adjacentTile = tileAtmosphere.AdjacentTiles[i];
var adjacentTile = tile.AdjacentTiles[i];
// TileAtmosphere has nullable disabled, so just in case...
// ReSharper disable once ConditionIsAlwaysTrueOrFalse
@@ -1007,7 +1021,7 @@ namespace Content.Server.Atmos.EntitySystems
if (!includeBlocked)
{
var direction = (AtmosDirection) (1 << i);
if (tileAtmosphere.BlockedAirflow.IsFlagSet(direction))
if (tile.BlockedAirflow.IsFlagSet(direction))
continue;
}
@@ -1465,7 +1479,7 @@ namespace Content.Server.Atmos.EntitySystems
if (!gridAtmosphere.Tiles.TryGetValue(tile, out var tileAtmosphere))
return;
var adjacent = GetAdjacentTileMixtures(gridAtmosphere, tile, invalidate:true).ToArray();
var adjacent = GetAdjacentTileMixtures(gridAtmosphere, tileAtmosphere, false, true).ToArray();
tileAtmosphere.Air = new GasMixture(GetVolumeForTiles(tileAtmosphere.GridIndex, 1))
{Temperature = Atmospherics.T20C};