Merge branch 'master' into replace-sounds-with-sound-specifier

# Conflicts:
#	Content.Server/Actions/Actions/DisarmAction.cs
#	Content.Server/Actions/Actions/ScreamAction.cs
#	Content.Server/Arcade/Components/SpaceVillainArcadeComponent.cs
#	Content.Server/Damage/Components/DamageOnHighSpeedImpactComponent.cs
#	Content.Server/Explosion/Components/FlashExplosiveComponent.cs
#	Content.Server/Physics/Controllers/MoverController.cs
#	Content.Server/Portal/Components/PortalComponent.cs
#	Content.Server/Portal/Components/TeleporterComponent.cs
#	Content.Server/Projectiles/Components/ProjectileComponent.cs
#	Content.Server/Singularity/Components/EmitterComponent.cs
#	Content.Server/Sound/EmitSoundSystem.cs
#	Content.Server/Stunnable/Components/StunbatonComponent.cs
#	Content.Server/Tools/Components/MultitoolComponent.cs
#	Content.Server/Weapon/Ranged/Barrels/Components/ServerBatteryBarrelComponent.cs
#	Content.Shared/Gravity/GravityComponent.cs
#	Content.Shared/Light/Component/SharedExpendableLightComponent.cs
#	Content.Shared/Maps/ContentTileDefinition.cs
#	Content.Shared/Slippery/SlipperyComponent.cs
#	Content.Shared/Standing/StandingStateComponent.cs
#	Resources/Prototypes/Entities/Objects/Fun/bike_horn.yml
This commit is contained in:
Galactic Chimp
2021-07-25 14:12:00 +02:00
4171 changed files with 15603 additions and 14404 deletions

View File

@@ -1,4 +1,3 @@
#nullable enable
using Content.Server.Atmos.EntitySystems;
using Content.Shared.Atmos;
using Robust.Shared.GameObjects;
@@ -12,163 +11,37 @@ using Robust.Shared.ViewVariables;
namespace Content.Server.Atmos.Components
{
[RegisterComponent]
public class AirtightComponent : Component, IMapInit
public class AirtightComponent : Component
{
[Dependency] private readonly IMapManager _mapManager = default!;
private (GridId, Vector2i) _lastPosition;
private AtmosphereSystem _atmosphereSystem = default!;
public override string Name => "Airtight";
public (GridId Grid, Vector2i Tile) LastPosition { get; set; }
[DataField("airBlockedDirection", customTypeSerializer: typeof(FlagSerializer<AtmosDirectionFlags>))]
[ViewVariables]
private int _initialAirBlockedDirection = (int) AtmosDirection.All;
public int InitialAirBlockedDirection { get; set; } = (int) AtmosDirection.All;
[ViewVariables]
private int _currentAirBlockedDirection;
public int CurrentAirBlockedDirection;
[DataField("airBlocked")]
private bool _airBlocked = true;
public bool AirBlocked { get; set; } = true;
[DataField("fixVacuum")]
private bool _fixVacuum = true;
public bool FixVacuum { get; set; } = true;
[ViewVariables]
[DataField("rotateAirBlocked")]
private bool _rotateAirBlocked = true;
public bool RotateAirBlocked { get; set; } = true;
[ViewVariables]
[DataField("fixAirBlockedDirectionInitialize")]
private bool _fixAirBlockedDirectionInitialize = true;
public bool FixAirBlockedDirectionInitialize { get; set; } = true;
[ViewVariables]
[DataField("noAirWhenFullyAirBlocked")]
public bool NoAirWhenFullyAirBlocked { get; } = true;
public bool NoAirWhenFullyAirBlocked { get; set; } = true;
[ViewVariables(VVAccess.ReadWrite)]
public bool AirBlocked
{
get => _airBlocked;
set
{
_airBlocked = value;
UpdatePosition();
}
}
public AtmosDirection AirBlockedDirection
{
get => (AtmosDirection)_currentAirBlockedDirection;
set
{
_currentAirBlockedDirection = (int) value;
_initialAirBlockedDirection = (int)Rotate(AirBlockedDirection, -Owner.Transform.LocalRotation);
UpdatePosition();
}
}
[ViewVariables]
public bool FixVacuum => _fixVacuum;
protected override void Initialize()
{
base.Initialize();
_atmosphereSystem = EntitySystem.Get<AtmosphereSystem>();
if (_fixAirBlockedDirectionInitialize)
RotateEvent(new RotateEvent(Owner, Angle.Zero, Owner.Transform.WorldRotation));
// Adding this component will immediately anchor the entity, because the atmos system
// requires airtight entities to be anchored for performance.
Owner.Transform.Anchored = true;
UpdatePosition();
}
public void RotateEvent(RotateEvent ev)
{
if (!_rotateAirBlocked || ev.Sender != Owner || _initialAirBlockedDirection == (int)AtmosDirection.Invalid)
return;
_currentAirBlockedDirection = (int) Rotate((AtmosDirection)_initialAirBlockedDirection, ev.NewRotation);
UpdatePosition();
}
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;
}
public void MapInit()
{
UpdatePosition();
}
protected override void Shutdown()
{
base.Shutdown();
_airBlocked = false;
InvalidatePosition(_lastPosition.Item1, _lastPosition.Item2);
if (_fixVacuum)
{
_atmosphereSystem.GetGridAtmosphere(_lastPosition.Item1)?.FixVacuum(_lastPosition.Item2);
}
}
public void AnchorStateChanged()
{
var gridId = Owner.Transform.GridID;
var coords = Owner.Transform.Coordinates;
var grid = _mapManager.GetGrid(gridId);
var tilePos = grid.TileIndicesFor(coords);
// Update and invalidate new position.
_lastPosition = (gridId, tilePos);
InvalidatePosition(gridId, tilePos);
}
private void UpdatePosition()
{
if (!Owner.Transform.Anchored || !Owner.Transform.GridID.IsValid())
return;
var grid = _mapManager.GetGrid(Owner.Transform.GridID);
_lastPosition = (Owner.Transform.GridID, grid.TileIndicesFor(Owner.Transform.Coordinates));
InvalidatePosition(_lastPosition.Item1, _lastPosition.Item2);
}
private void InvalidatePosition(GridId gridId, Vector2i pos)
{
if (!gridId.IsValid())
return;
var gridAtmos = _atmosphereSystem.GetGridAtmosphere(gridId);
gridAtmos?.UpdateAdjacentBits(pos);
gridAtmos?.Invalidate(pos);
}
public AtmosDirection AirBlockedDirection => (AtmosDirection)CurrentAirBlockedDirection;
}
}

View File

@@ -1,5 +1,4 @@
#nullable enable
using Content.Server.Atmos.EntitySystems;
using Content.Server.Atmos.EntitySystems;
using Content.Server.Temperature.Components;
using Robust.Shared.GameObjects;
using Robust.Shared.ViewVariables;

View File

@@ -1,5 +1,4 @@
#nullable enable
using Content.Server.Body.Respiratory;
using Content.Server.Body.Respiratory;
using Content.Shared.Inventory;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization.Manager.Attributes;

View File

@@ -1,4 +1,3 @@
#nullable enable
using Content.Server.Atmos.EntitySystems;
using Content.Server.Doors;
using Content.Server.Doors.Components;
@@ -29,7 +28,7 @@ namespace Content.Server.Atmos.Components
_doorComponent.Close();
if (Owner.TryGetComponent(out AirtightComponent? airtight))
{
airtight.AirBlocked = true;
EntitySystem.Get<AirtightSystem>().SetAirblocked(airtight, true);
}
return true;
}
@@ -75,15 +74,12 @@ namespace Content.Server.Atmos.Components
{
var atmosphereSystem = EntitySystem.Get<AtmosphereSystem>();
var gridAtmosphere = atmosphereSystem.GetGridAtmosphere(Owner.Transform.Coordinates);
var minMoles = float.MaxValue;
var maxMoles = 0f;
foreach (var (_, adjacent) in gridAtmosphere.GetAdjacentTiles(Owner.Transform.Coordinates))
foreach (var adjacent in atmosphereSystem.GetAdjacentTileMixtures(Owner.Transform.Coordinates))
{
// includeAirBlocked remains false, and therefore Air must be present
var moles = adjacent.Air!.TotalMoles;
var moles = adjacent.TotalMoles;
if (moles < minMoles)
minMoles = moles;
if (moles > maxMoles)
@@ -97,17 +93,18 @@ namespace Content.Server.Atmos.Components
{
var atmosphereSystem = EntitySystem.Get<AtmosphereSystem>();
if (!Owner.Transform.Coordinates.TryGetTileAtmosphere(out var tileAtmos))
if (!atmosphereSystem.TryGetGridAndTile(Owner.Transform.Coordinates, out var tuple))
return false;
if (tileAtmos.Hotspot.Valid)
if (atmosphereSystem.GetTileMixture(tuple.Value.Grid, tuple.Value.Tile) == null)
return false;
if (atmosphereSystem.IsHotspotActive(tuple.Value.Grid, tuple.Value.Tile))
return true;
var gridAtmosphere = atmosphereSystem.GetGridAtmosphere(Owner.Transform.Coordinates);
foreach (var (_, adjacent) in gridAtmosphere.GetAdjacentTiles(tileAtmos.GridIndices))
foreach (var adjacent in atmosphereSystem.GetAdjacentTiles(Owner.Transform.Coordinates))
{
if (adjacent.Hotspot.Valid)
if (atmosphereSystem.IsHotspotActive(tuple.Value.Grid, adjacent))
return true;
}

View File

@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Content.Server.Alert;
using Content.Server.Atmos.EntitySystems;
using Content.Server.Stunnable.Components;
using Content.Server.Temperature.Components;
using Content.Shared.ActionBlocker;
@@ -17,24 +18,22 @@ using Robust.Server.GameObjects;
using Robust.Shared.GameObjects;
using Robust.Shared.Localization;
using Robust.Shared.Physics;
using Robust.Shared.Physics.Collision;
using Robust.Shared.Physics.Dynamics;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables;
namespace Content.Server.Atmos.Components
{
[RegisterComponent]
public class FlammableComponent : SharedFlammableComponent, IStartCollide, IFireAct, IInteractUsing
public class FlammableComponent : SharedFlammableComponent, IFireAct, IInteractUsing
{
private bool _resisting = false;
private readonly List<EntityUid> _collided = new();
[ViewVariables(VVAccess.ReadWrite)]
public bool OnFire { get; private set; }
public bool OnFire { get; set; }
[ViewVariables(VVAccess.ReadWrite)]
public float FireStacks { get; private set; }
public float FireStacks { get; set; }
[ViewVariables(VVAccess.ReadWrite)]
[DataField("fireSpread")]
@@ -44,17 +43,6 @@ namespace Content.Server.Atmos.Components
[DataField("canResistFire")]
public bool CanResistFire { get; private set; } = false;
public void Ignite()
{
if (FireStacks > 0 && !OnFire)
{
OnFire = true;
}
UpdateAppearance();
}
public void Extinguish()
{
if (!OnFire) return;
@@ -122,7 +110,7 @@ namespace Content.Server.Atmos.Components
return;
}
tile.HotspotExpose(700, 50, true);
EntitySystem.Get<AtmosphereSystem>().HotspotExpose(tile.GridIndex, tile.GridIndices, 700f, 50f, true);
var physics = Owner.GetComponent<IPhysBody>();
@@ -144,37 +132,7 @@ namespace Content.Server.Atmos.Components
}
}
void IStartCollide.CollideWith(Fixture ourFixture, Fixture otherFixture, in Manifold manifold)
{
if (!otherFixture.Body.Owner.TryGetComponent(out FlammableComponent? otherFlammable))
return;
if (!FireSpread || !otherFlammable.FireSpread)
return;
if (OnFire)
{
if (otherFlammable.OnFire)
{
var fireSplit = (FireStacks + otherFlammable.FireStacks) / 2;
FireStacks = fireSplit;
otherFlammable.FireStacks = fireSplit;
}
else
{
FireStacks /= 2;
otherFlammable.FireStacks += FireStacks;
otherFlammable.Ignite();
}
} else if (otherFlammable.OnFire)
{
otherFlammable.FireStacks /= 2;
FireStacks += otherFlammable.FireStacks;
Ignite();
}
}
private void UpdateAppearance()
public void UpdateAppearance()
{
if (Owner.Deleted || !Owner.TryGetComponent(out AppearanceComponent? appearanceComponent)) return;
appearanceComponent.SetData(FireVisuals.OnFire, OnFire);
@@ -184,7 +142,7 @@ namespace Content.Server.Atmos.Components
public void FireAct(float temperature, float volume)
{
AdjustFireStacks(3);
Ignite();
EntitySystem.Get<FlammableSystem>().Ignite(this);
}
// This needs some improvements...
@@ -211,7 +169,7 @@ namespace Content.Server.Atmos.Components
{
if (hotItem.IsCurrentlyHot())
{
Ignite();
EntitySystem.Get<FlammableSystem>().Ignite(this);
return true;
}
}

View File

@@ -1,4 +1,3 @@
#nullable enable
using System.Collections.Generic;
using System.Threading.Tasks;
using Content.Server.Atmos.EntitySystems;
@@ -124,8 +123,7 @@ namespace Content.Server.Atmos.Components
{
// Already get the pressure before Dirty(), because we can't get the EntitySystem in that thread or smth
var pressure = 0f;
var gam = EntitySystem.Get<AtmosphereSystem>().GetGridAtmosphere(Owner.Transform.Coordinates);
var tile = gam?.GetTile(Owner.Transform.Coordinates)?.Air;
var tile = EntitySystem.Get<AtmosphereSystem>().GetTileMixture(Owner.Transform.Coordinates);
if (tile != null)
{
pressure = tile.Pressure;
@@ -183,9 +181,8 @@ namespace Content.Server.Atmos.Components
pos = _position.Value;
}
var atmosSystem = EntitySystem.Get<AtmosphereSystem>();
var gam = atmosSystem.GetGridAtmosphere(pos);
var tile = gam.GetTile(pos)?.Air;
var atmosphereSystem = EntitySystem.Get<AtmosphereSystem>();
var tile = atmosphereSystem.GetTileMixture(pos);
if (tile == null)
{
error = "No Atmosphere!";
@@ -202,7 +199,7 @@ namespace Content.Server.Atmos.Components
for (var i = 0; i < Atmospherics.TotalNumberOfGases; i++)
{
var gas = atmosSystem.GetGas(i);
var gas = atmosphereSystem.GetGas(i);
if (tile.Moles[i] <= Atmospherics.GasMinMoles) continue;

View File

@@ -1,5 +1,4 @@
using Content.Server.Interfaces;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables;

View File

@@ -1,10 +1,8 @@
#nullable enable
#nullable disable warnings
using System;
using Content.Server.Atmos.EntitySystems;
using Content.Server.Body.Respiratory;
using Content.Server.Explosion;
using Content.Server.Interfaces;
using Content.Server.NodeContainer;
using Content.Server.NodeContainer.Nodes;
using Content.Server.UserInterface;
@@ -282,8 +280,9 @@ namespace Content.Server.Atmos.Components
{
if (_integrity <= 0)
{
var tileAtmos = Owner.Transform.Coordinates.GetTileAtmosphere();
tileAtmos?.AssumeAir(Air);
var environment = atmosphereSystem.GetTileMixture(Owner.Transform.Coordinates, true);
if(environment != null)
atmosphereSystem.Merge(environment, Air);
if(_ruptureSound.TryGetSound(out var sound))
SoundSystem.Play(Filter.Pvs(Owner), sound, Owner.Transform.Coordinates, AudioHelpers.WithVariation(0.125f));
@@ -300,12 +299,12 @@ namespace Content.Server.Atmos.Components
{
if (_integrity <= 0)
{
var tileAtmos = Owner.Transform.Coordinates.GetTileAtmosphere();
if (tileAtmos == null)
var environment = atmosphereSystem.GetTileMixture(Owner.Transform.Coordinates, true);
if (environment == null)
return;
var leakedGas = Air.RemoveRatio(0.25f);
tileAtmos.AssumeAir(leakedGas);
atmosphereSystem.Merge(environment, leakedGas);
}
else
{

View File

@@ -1,25 +1,13 @@
#nullable enable
// ReSharper disable once RedundantUsingDirective
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using Content.Server.Atmos.EntitySystems;
using Content.Server.Atmos.Piping.Components;
using Content.Server.CPUJob.JobQueues.Queues;
using Content.Server.NodeContainer.NodeGroups;
using Content.Shared.Atmos;
using Content.Shared.Maps;
using Robust.Server.GameObjects;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.Timing;
using Robust.Shared.ViewVariables;
using Dependency = Robust.Shared.IoC.DependencyAttribute;
@@ -32,34 +20,21 @@ namespace Content.Server.Atmos.Components
[RegisterComponent, Serializable]
public class GridAtmosphereComponent : Component, IGridAtmosphereComponent, ISerializationHooks
{
[Dependency] private IMapManager _mapManager = default!;
[Dependency] private ITileDefinitionManager _tileDefinitionManager = default!;
[Dependency] private IServerEntityManager _serverEntityManager = default!;
[Dependency] private IGameTiming _gameTiming = default!;
public GridTileLookupSystem GridTileLookupSystem { get; private set; } = default!;
internal GasTileOverlaySystem GasTileOverlaySystem { get; private set; } = default!;
public AtmosphereSystem AtmosphereSystem { get; private set; } = default!;
public override string Name => "GridAtmosphere";
public bool ProcessingPaused { get; set; } = false;
public float Timer { get; set; }
private GridId _gridId;
[ComponentDependency] private IMapGridComponent? _mapGridComponent;
public virtual bool Simulated => true;
[ViewVariables]
public bool RevalidatePaused { get; set; } = false;
[ViewVariables]
public bool ProcessingPaused { get; set; } = false;
[ViewVariables]
public float Timer { get; set; } = 0f;
[ViewVariables]
public int UpdateCounter { get; set; } = 0;
[ViewVariables]
public readonly HashSet<ExcitedGroup> ExcitedGroups = new(1000);
[ViewVariables]
public int ExcitedGroupCount => ExcitedGroups.Count;
[DataField("uniqueMixes")]
public List<GasMixture>? UniqueMixes;
@@ -75,6 +50,12 @@ namespace Content.Server.Atmos.Components
[ViewVariables]
public int ActiveTilesCount => ActiveTiles.Count;
[ViewVariables]
public readonly HashSet<ExcitedGroup> ExcitedGroups = new(1000);
[ViewVariables]
public int ExcitedGroupCount => ExcitedGroups.Count;
[ViewVariables]
public readonly HashSet<TileAtmosphere> HotspotTiles = new(1000);
@@ -87,9 +68,6 @@ namespace Content.Server.Atmos.Components
[ViewVariables]
public int SuperconductivityTilesCount => SuperconductivityTiles.Count;
[ViewVariables]
public readonly HashSet<Vector2i> InvalidatedCoords = new(1000);
[ViewVariables]
public HashSet<TileAtmosphere> HighPressureDelta = new(1000);
@@ -114,22 +92,21 @@ namespace Content.Server.Atmos.Components
[ViewVariables]
public Queue<AtmosDeviceComponent> CurrentRunAtmosDevices = new();
[ViewVariables]
public readonly HashSet<Vector2i> InvalidatedCoords = new(1000);
[ViewVariables]
public Queue<Vector2i> CurrentRunInvalidatedCoordinates = new();
[ViewVariables]
public int InvalidatedCoordsCount => InvalidatedCoords.Count;
[ViewVariables]
public long EqualizationQueueCycleControl { get; set; }
[ViewVariables]
public AtmosphereProcessingState State { get; set; } = AtmosphereProcessingState.TileEqualize;
public GridAtmosphereComponent()
{
ProcessingPaused = false;
}
/// <inheritdoc />
public virtual void PryTile(Vector2i indices)
{
if (IsSpace(indices) || IsAirBlocked(indices)) return;
indices.PryTile(_gridId, _mapManager, _tileDefinitionManager, _serverEntityManager);
}
void ISerializationHooks.BeforeSerialization()
{
var uniqueMixes = new List<GasMixture>();
@@ -158,404 +135,5 @@ namespace Content.Server.Atmos.Components
UniqueMixes = uniqueMixes;
TilesUniqueMixes = tiles;
}
protected override void Initialize()
{
base.Initialize();
Tiles.Clear();
if (TilesUniqueMixes != null && Owner.TryGetComponent(out IMapGridComponent? mapGrid))
{
foreach (var (indices, mix) in TilesUniqueMixes)
{
try
{
Tiles.Add(indices, new TileAtmosphere(this, mapGrid.GridIndex, indices, (GasMixture) UniqueMixes![mix].Clone()));
}
catch (ArgumentOutOfRangeException)
{
Logger.Error($"Error during atmos serialization! Tile at {indices} points to an unique mix ({mix}) out of range!");
throw;
}
Invalidate(indices);
}
}
GridTileLookupSystem = EntitySystem.Get<GridTileLookupSystem>();
GasTileOverlaySystem = EntitySystem.Get<GasTileOverlaySystem>();
AtmosphereSystem = EntitySystem.Get<AtmosphereSystem>();
RepopulateTiles();
}
protected override void OnAdd()
{
base.OnAdd();
if (Owner.TryGetComponent(out IMapGridComponent? mapGrid))
_gridId = mapGrid.GridIndex;
}
public virtual void RepopulateTiles()
{
if (!Owner.TryGetComponent(out IMapGridComponent? mapGrid)) return;
foreach (var tile in mapGrid.Grid.GetAllTiles())
{
if(!Tiles.ContainsKey(tile.GridIndices))
Tiles.Add(tile.GridIndices, new TileAtmosphere(this, tile.GridIndex, tile.GridIndices, new GasMixture(GetVolumeForCells(1)){Temperature = Atmospherics.T20C}));
Invalidate(tile.GridIndices);
}
foreach (var (_, tile) in Tiles.ToArray())
{
tile.UpdateAdjacent();
tile.UpdateVisuals();
}
}
/// <inheritdoc />
public virtual void Invalidate(Vector2i indices)
{
InvalidatedCoords.Add(indices);
}
public virtual void Revalidate()
{
foreach (var indices in InvalidatedCoords)
{
var tile = GetTile(indices);
if (tile == null)
{
tile = new TileAtmosphere(this, _gridId, indices, new GasMixture(GetVolumeForCells(1)){Temperature = Atmospherics.T20C});
Tiles[indices] = tile;
}
var isAirBlocked = IsAirBlocked(indices);
if (IsSpace(indices) && !isAirBlocked)
{
tile.Air = new GasMixture(GetVolumeForCells(1));
tile.Air.MarkImmutable();
Tiles[indices] = tile;
} else if (isAirBlocked)
{
var nullAir = false;
foreach (var airtight in GetObstructingComponents(indices))
{
if (airtight.NoAirWhenFullyAirBlocked)
{
nullAir = true;
break;
}
}
if(nullAir)
tile.Air = null;
}
else
{
if (tile.Air == null && NeedsVacuumFixing(indices))
{
FixVacuum(tile.GridIndices);
}
// Tile used to be space, but isn't anymore.
if (tile.Air?.Immutable ?? false)
{
tile.Air = null;
}
tile.Air ??= new GasMixture(GetVolumeForCells(1)){Temperature = Atmospherics.T20C};
}
// By removing the active tile, we effectively remove its excited group, if any.
RemoveActiveTile(tile);
// Then we activate the tile again.
AddActiveTile(tile);
tile.BlockedAirflow = GetBlockedDirections(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;
tile.UpdateAdjacent();
GasTileOverlaySystem.Invalidate(_gridId, indices);
for (var i = 0; i < Atmospherics.Directions; i++)
{
var direction = (AtmosDirection) (1 << i);
var otherIndices = indices.Offset(direction.ToDirection());
var otherTile = GetTile(otherIndices);
if (otherTile != null) AddActiveTile(otherTile);
}
}
InvalidatedCoords.Clear();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void UpdateAdjacentBits(Vector2i indices)
{
GetTile(indices)?.UpdateAdjacent();
}
/// <inheritdoc />
public virtual void FixVacuum(Vector2i indices)
{
var tile = GetTile(indices);
if (tile?.GridIndex != _gridId) return;
// includeAirBlocked is false, therefore all tiles in this have Air != null.
var adjacent = GetAdjacentTiles(indices);
tile.Air = new GasMixture(GetVolumeForCells(1)){Temperature = Atmospherics.T20C};
Tiles[indices] = tile;
var ratio = 1f / adjacent.Count;
foreach (var (_, adj) in adjacent)
{
var mix = adj.Air!.RemoveRatio(ratio);
AtmosphereSystem.Merge(tile.Air, mix);
AtmosphereSystem.Merge(adj.Air, mix);
}
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public virtual void AddActiveTile(TileAtmosphere tile)
{
if (tile?.GridIndex != _gridId || tile.Air == null) return;
tile.Excited = true;
ActiveTiles.Add(tile);
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public virtual void RemoveActiveTile(TileAtmosphere tile, bool disposeGroup = true)
{
ActiveTiles.Remove(tile);
tile.Excited = false;
if(disposeGroup)
tile.ExcitedGroup?.Dispose();
else
tile.ExcitedGroup?.RemoveTile(tile);
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public virtual void AddHotspotTile(TileAtmosphere tile)
{
if (tile?.GridIndex != _gridId || tile?.Air == null) return;
HotspotTiles.Add(tile);
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public virtual void RemoveHotspotTile(TileAtmosphere tile)
{
HotspotTiles.Remove(tile);
}
public virtual void AddSuperconductivityTile(TileAtmosphere tile)
{
if (tile?.GridIndex != _gridId || !AtmosphereSystem.Superconduction) return;
SuperconductivityTiles.Add(tile);
}
public virtual void RemoveSuperconductivityTile(TileAtmosphere tile)
{
SuperconductivityTiles.Remove(tile);
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public virtual void AddHighPressureDelta(TileAtmosphere tile)
{
if (tile.GridIndex != _gridId) return;
HighPressureDelta.Add(tile);
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public virtual bool HasHighPressureDelta(TileAtmosphere tile)
{
return HighPressureDelta.Contains(tile);
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public virtual void AddExcitedGroup(ExcitedGroup excitedGroup)
{
ExcitedGroups.Add(excitedGroup);
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public virtual void RemoveExcitedGroup(ExcitedGroup excitedGroup)
{
ExcitedGroups.Remove(excitedGroup);
}
public virtual void AddPipeNet(IPipeNet pipeNet)
{
PipeNets.Add(pipeNet);
}
public virtual void RemovePipeNet(IPipeNet pipeNet)
{
PipeNets.Remove(pipeNet);
}
public virtual void AddAtmosDevice(AtmosDeviceComponent atmosDevice)
{
AtmosDevices.Add(atmosDevice);
}
public virtual void RemoveAtmosDevice(AtmosDeviceComponent atmosDevice)
{
AtmosDevices.Remove(atmosDevice);
}
/// <inheritdoc />
public virtual TileAtmosphere? GetTile(EntityCoordinates coordinates, bool createSpace = true)
{
return GetTile(coordinates.ToVector2i(_serverEntityManager, _mapManager), createSpace);
}
/// <inheritdoc />
public virtual TileAtmosphere? GetTile(Vector2i indices, bool createSpace = true)
{
if (Tiles.TryGetValue(indices, out var tile)) return tile;
// We don't have that tile!
if (IsSpace(indices) && createSpace)
{
return new TileAtmosphere(this, _gridId, indices, new GasMixture(GetVolumeForCells(1)){Temperature = Atmospherics.TCMB}, true);
}
return null;
}
/// <inheritdoc />
public bool IsAirBlocked(Vector2i indices, AtmosDirection direction = AtmosDirection.All)
{
var directions = AtmosDirection.Invalid;
foreach (var obstructingComponent in GetObstructingComponents(indices))
{
if (!obstructingComponent.AirBlocked)
continue;
// We set the directions that are air-blocked so far,
// as you could have a full obstruction with only 4 directional air blockers.
directions |= obstructingComponent.AirBlockedDirection;
if (directions.IsFlagSet(direction))
return true;
}
return false;
}
/// <inheritdoc />
public virtual bool IsSpace(Vector2i indices)
{
if (_mapGridComponent == null) return default;
return _mapGridComponent.Grid.GetTileRef(indices).IsSpace();
}
public Dictionary<AtmosDirection, TileAtmosphere> GetAdjacentTiles(EntityCoordinates coordinates, bool includeAirBlocked = false)
{
return GetAdjacentTiles(coordinates.ToVector2i(_serverEntityManager, _mapManager), includeAirBlocked);
}
public Dictionary<AtmosDirection, TileAtmosphere> GetAdjacentTiles(Vector2i indices, bool includeAirBlocked = false)
{
var sides = new Dictionary<AtmosDirection, TileAtmosphere>();
for (var i = 0; i < Atmospherics.Directions; i++)
{
var direction = (AtmosDirection) (1 << i);
var side = indices.Offset(direction.ToDirection());
var tile = GetTile(side);
if (tile != null && (tile.Air != null || includeAirBlocked))
sides[direction] = tile;
}
return sides;
}
public long EqualizationQueueCycleControl { get; set; }
/// <inheritdoc />
public float GetVolumeForCells(int cellCount)
{
if (_mapGridComponent == null) return default;
return _mapGridComponent.Grid.TileSize * cellCount * Atmospherics.CellVolume;
}
protected virtual IEnumerable<AirtightComponent> GetObstructingComponents(Vector2i indices)
{
var gridLookup = EntitySystem.Get<GridTileLookupSystem>();
foreach (var v in gridLookup.GetEntitiesIntersecting(_gridId, indices))
{
if (v.TryGetComponent<AirtightComponent>(out var ac))
yield return ac;
}
}
private bool NeedsVacuumFixing(Vector2i indices)
{
var value = false;
foreach (var airtightComponent in GetObstructingComponents(indices))
{
value |= airtightComponent.FixVacuum;
}
return value;
}
private AtmosDirection GetBlockedDirections(Vector2i indices)
{
var value = AtmosDirection.Invalid;
foreach (var airtightComponent in GetObstructingComponents(indices))
{
if(airtightComponent.AirBlocked)
value |= airtightComponent.AirBlockedDirection;
}
return value;
}
public void Dispose()
{
}
public IEnumerator<TileAtmosphere> GetEnumerator()
{
return Tiles.Values.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
/// <inheritdoc />
public virtual void BurnTile(Vector2i gridIndices)
{
// TODO ATMOS
}
}
}

View File

@@ -1,182 +1,12 @@
#nullable enable
using System.Collections.Generic;
using Content.Server.Atmos.Piping.Components;
using Content.Server.NodeContainer.NodeGroups;
using Content.Shared.Atmos;
using Robust.Shared.GameObjects;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.GameObjects;
namespace Content.Server.Atmos.Components
{
public interface IGridAtmosphereComponent : IComponent, IEnumerable<TileAtmosphere>
public interface IGridAtmosphereComponent : IComponent
{
/// <summary>
/// Whether this atmosphere is simulated or not.
/// </summary>
bool Simulated { get; }
/// <summary>
/// Number of times <see cref="Update"/> has been called.
/// </summary>
int UpdateCounter { get; }
/// <summary>
/// Control variable for equalization.
/// </summary>
long EqualizationQueueCycleControl { get; set; }
/// <summary>
/// Attemps to pry a tile.
/// </summary>
/// <param name="indices"></param>
void PryTile(Vector2i indices);
/// <summary>
/// Burns a tile.
/// </summary>
/// <param name="gridIndices"></param>
void BurnTile(Vector2i gridIndices);
/// <summary>
/// Invalidates a coordinate to be revalidated again.
/// Use this after changing a tile's gas contents, or when the tile becomes space, etc.
/// </summary>
/// <param name="indices"></param>
void Invalidate(Vector2i indices);
/// <summary>
/// Attempts to fix a sudden vacuum by creating gas.
/// </summary>
void FixVacuum(Vector2i indices);
/// <summary>
/// Revalidates indices immediately.
/// </summary>
/// <param name="indices"></param>
void UpdateAdjacentBits(Vector2i indices);
/// <summary>
/// Adds an active tile so it becomes processed every update until it becomes inactive.
/// Also makes the tile excited.
/// </summary>
/// <param name="tile"></param>
void AddActiveTile(TileAtmosphere tile);
/// <summary>
/// Removes an active tile and disposes of its <seealso cref="ExcitedGroup"/>.
/// Use with caution.
/// </summary>
/// <param name="tile"></param>
void RemoveActiveTile(TileAtmosphere tile, bool disposeGroup = true);
/// <summary>
/// Marks a tile as having a hotspot so it can be processed.
/// </summary>
/// <param name="tile"></param>
void AddHotspotTile(TileAtmosphere tile);
/// <summary>
/// Removes a tile from the hotspot processing list.
/// </summary>
/// <param name="tile"></param>
void RemoveHotspotTile(TileAtmosphere tile);
/// <summary>
/// Marks a tile as superconductive so it can be processed.
/// </summary>
/// <param name="tile"></param>
void AddSuperconductivityTile(TileAtmosphere tile);
/// <summary>
/// Removes a tile from the superconductivity processing list.
/// </summary>
/// <param name="tile"></param>
void RemoveSuperconductivityTile(TileAtmosphere tile);
/// <summary>
/// Marks a tile has having high pressure differences that need to be equalized.
/// </summary>
/// <param name="tile"></param>
void AddHighPressureDelta(TileAtmosphere tile);
/// <summary>
/// Returns whether the tile in question is marked as having high pressure differences or not.
/// </summary>
/// <param name="tile"></param>
/// <returns></returns>
bool HasHighPressureDelta(TileAtmosphere tile);
/// <summary>
/// Adds a excited group to be processed.
/// </summary>
/// <param name="excitedGroup"></param>
void AddExcitedGroup(ExcitedGroup excitedGroup);
/// <summary>
/// Removes an excited group.
/// </summary>
/// <param name="excitedGroup"></param>
void RemoveExcitedGroup(ExcitedGroup excitedGroup);
/// <summary>
/// Returns a tile.
/// </summary>
/// <param name="indices"></param>
/// <param name="createSpace"></param>
/// <returns></returns>
TileAtmosphere? GetTile(Vector2i indices, bool createSpace = true);
/// <summary>
/// Returns a tile.
/// </summary>
/// <param name="coordinates"></param>
/// <param name="createSpace"></param>
/// <returns></returns>
TileAtmosphere? GetTile(EntityCoordinates coordinates, bool createSpace = true);
/// <summary>
/// Returns if the tile in question is air-blocked.
/// This could be due to a wall, an airlock, etc.
/// <seealso cref="AirtightComponent"/>
/// </summary>
/// <param name="indices"></param>
/// <param name="direction"></param>
/// <returns></returns>
bool IsAirBlocked(Vector2i indices, AtmosDirection direction);
/// <summary>
/// Returns if the tile in question is space.
/// </summary>
/// <param name="indices"></param>
/// <returns></returns>
bool IsSpace(Vector2i indices);
/// <summary>
/// Returns the volume in liters for a number of cells/tiles.
/// </summary>
/// <param name="cellCount"></param>
/// <returns></returns>
float GetVolumeForCells(int cellCount);
void RepopulateTiles();
/// <summary>
/// Returns a dictionary of adjacent TileAtmospheres.
/// </summary>
Dictionary<AtmosDirection, TileAtmosphere> GetAdjacentTiles(EntityCoordinates coordinates, bool includeAirBlocked = false);
/// <summary>
/// Returns a dictionary of adjacent TileAtmospheres.
/// </summary>
Dictionary<AtmosDirection, TileAtmosphere> GetAdjacentTiles(Vector2i indices, bool includeAirBlocked = false);
void AddPipeNet(IPipeNet pipeNet);
void RemovePipeNet(IPipeNet pipeNet);
void AddAtmosDevice(AtmosDeviceComponent atmosDevice);
void RemoveAtmosDevice(AtmosDeviceComponent atmosDevice);
}
}

View File

@@ -1,5 +1,4 @@
#nullable enable
using System;
using System;
using System.Diagnostics.CodeAnalysis;
using Content.Shared.Atmos;
using Content.Shared.MobState;

View File

@@ -1,5 +1,4 @@
#nullable enable
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using Content.Shared.Atmos;
using Robust.Shared.GameObjects;
@@ -13,22 +12,5 @@ namespace Content.Server.Atmos.Components
public class SpaceGridAtmosphereComponent : UnsimulatedGridAtmosphereComponent
{
public override string Name => "SpaceGridAtmosphere";
public override void RepopulateTiles() { }
public override bool IsSpace(Vector2i indices)
{
return true;
}
public override TileAtmosphere GetTile(Vector2i indices, bool createSpace = true)
{
return new(this, GridId.Invalid, indices, new GasMixture(Atmospherics.CellVolume), true);
}
protected override IEnumerable<AirtightComponent> GetObstructingComponents(Vector2i indices)
{
return Enumerable.Empty<AirtightComponent>();
}
}
}

View File

@@ -1,5 +1,4 @@
#nullable enable
using System;
using System;
using Content.Server.Atmos.Piping.Components;
using Content.Server.NodeContainer.NodeGroups;
using Content.Shared.Atmos;
@@ -17,55 +16,5 @@ namespace Content.Server.Atmos.Components
public override string Name => "UnsimulatedGridAtmosphere";
public override bool Simulated => false;
public override void PryTile(Vector2i indices) { }
public override void RepopulateTiles()
{
if (!Owner.TryGetComponent(out IMapGridComponent? mapGrid)) return;
foreach (var tile in mapGrid.Grid.GetAllTiles())
{
if(!Tiles.ContainsKey(tile.GridIndices))
Tiles.Add(tile.GridIndices, new TileAtmosphere(this, tile.GridIndex, tile.GridIndices, new GasMixture(GetVolumeForCells(1)){Temperature = Atmospherics.T20C}));
}
}
public override void Invalidate(Vector2i indices) { }
public override void Revalidate() { }
public override void FixVacuum(Vector2i indices) { }
public override void AddActiveTile(TileAtmosphere? tile) { }
public override void RemoveActiveTile(TileAtmosphere? tile, bool disposeGroup = true) { }
public override void AddHotspotTile(TileAtmosphere? tile) { }
public override void RemoveHotspotTile(TileAtmosphere? tile) { }
public override void AddSuperconductivityTile(TileAtmosphere? tile) { }
public override void RemoveSuperconductivityTile(TileAtmosphere? tile) { }
public override void AddHighPressureDelta(TileAtmosphere? tile) { }
public override bool HasHighPressureDelta(TileAtmosphere tile)
{
return false;
}
public override void AddExcitedGroup(ExcitedGroup excitedGroup) { }
public override void RemoveExcitedGroup(ExcitedGroup excitedGroup) { }
public override void AddPipeNet(IPipeNet pipeNet) { }
public override void RemovePipeNet(IPipeNet pipeNet) { }
public override void AddAtmosDevice(AtmosDeviceComponent atmosDevice) { }
public override void RemoveAtmosDevice(AtmosDeviceComponent atmosDevice) { }
}
}