Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mirror 26441: Fix atmos NaN error #449

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 29 additions & 3 deletions Content.Server/Atmos/Components/AirtightComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,53 @@ public sealed partial class AirtightComponent : Component
{
public (EntityUid Grid, Vector2i Tile) LastPosition { get; set; }

/// <summary>
/// The directions in which this entity should block airflow, relative to its own reference frame.
/// </summary>
[DataField("airBlockedDirection", customTypeSerializer: typeof(FlagSerializer<AtmosDirectionFlags>))]
public int InitialAirBlockedDirection { get; set; } = (int) AtmosDirection.All;

/// <summary>
/// The directions in which the entity is currently blocking airflow, relative to the grid that the entity is on.
/// I.e., this is a variant of <see cref="InitialAirBlockedDirection"/> that takes into account the entity's
/// current rotation.
/// </summary>
[ViewVariables]
public int CurrentAirBlockedDirection;

[DataField("airBlocked")]
/// <summary>
/// Whether the airtight entity is currently blocking airflow.
/// </summary>
[DataField]
public bool AirBlocked { get; set; } = true;

[DataField("fixVacuum")]
/// <summary>
/// If true, entities on this tile will attempt to draw air from surrounding tiles when they become unblocked
/// and currently have no air. This is generally only required when <see cref="NoAirWhenFullyAirBlocked"/> is
/// true, or if the entity is likely to occupy the same tile as another no-air airtight entity.
/// </summary>
[DataField]
public bool FixVacuum { get; set; } = true;
// I think fixvacuum exists to ensure that repeatedly closing/opening air-blocking doors doesn't end up
// depressurizing a room. However it can also effectively be used as a means of generating gasses for free
// TODO ATMOS Mass conservation. Make it actually push/pull air from adjacent tiles instead of destroying & creating,


// TODO ATMOS Do we need these two fields?
[DataField("rotateAirBlocked")]
public bool RotateAirBlocked { get; set; } = true;

// TODO ATMOS remove this? What is this even for??
[DataField("fixAirBlockedDirectionInitialize")]
public bool FixAirBlockedDirectionInitialize { get; set; } = true;

[DataField("noAirWhenFullyAirBlocked")]
/// <summary>
/// If true, then the tile that this entity is on will have no air at all if all directions are blocked.
/// </summary>
[DataField]
public bool NoAirWhenFullyAirBlocked { get; set; } = true;

/// <inheritdoc cref="CurrentAirBlockedDirection"/>
[Access(Other = AccessPermissions.ReadWriteExecute)]
public AtmosDirection AirBlockedDirection => (AtmosDirection)CurrentAirBlockedDirection;
}
Expand Down
2 changes: 0 additions & 2 deletions Content.Server/Atmos/EntitySystems/AirtightSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,6 @@ private void OnAirtightMoved(Entity<AirtightComponent> airtight, ref MoveEvent e
private bool AirtightMove(Entity<AirtightComponent> ent, ref MoveEvent ev)
{
var (owner, airtight) = ent;
if (!airtight.RotateAirBlocked || airtight.InitialAirBlockedDirection == (int)AtmosDirection.Invalid)
return false;

airtight.CurrentAirBlockedDirection = (int) Rotate((AtmosDirection)airtight.InitialAirBlockedDirection, ev.NewRotation);
var pos = airtight.LastPosition;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -399,10 +399,7 @@ private void GridIsHotspotActive(EntityUid uid, GridAtmosphereComponent componen
args.Handled = true;
}

private void GridFixTileVacuum(
Entity<GridAtmosphereComponent, GasTileOverlayComponent, MapGridComponent, TransformComponent> ent,
TileAtmosphere tile,
float volume)
private void GridFixTileVacuum(TileAtmosphere tile)
{
DebugTools.AssertNotNull(tile.Air);
DebugTools.Assert(tile.Air?.Immutable == false );
Expand All @@ -416,6 +413,9 @@ private void GridFixTileVacuum(
count++;
}

if (count == 0)
return;

var ratio = 1f / count;
var totalTemperature = 0f;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ private void UpdateTileAir(
tile.Air = new GasMixture(volume){Temperature = Atmospherics.T20C};

if (data.FixVacuum)
GridFixTileVacuum(ent, tile, volume);
GridFixTileVacuum(tile);
}

private void QueueRunTiles(
Expand Down
3 changes: 2 additions & 1 deletion Content.Server/Atmos/EntitySystems/AtmosphereSystem.Utils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,13 @@ private AirtightData GetAirtightData(EntityUid uid, MapGridComponent grid, Vecto
if (!_airtightQuery.TryGetComponent(ent, out var airtight))
continue;

fixVacuum |= airtight.FixVacuum;

if(!airtight.AirBlocked)
continue;

blockedDirs |= airtight.AirBlockedDirection;
noAirWhenBlocked |= airtight.NoAirWhenFullyAirBlocked;
fixVacuum |= airtight.FixVacuum;

if (blockedDirs == AtmosDirection.All && noAirWhenBlocked && fixVacuum)
break;
Expand Down
7 changes: 4 additions & 3 deletions Content.Server/Atmos/GasMixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ public float Temperature
get => _temperature;
set
{
DebugTools.Assert(!float.IsNaN(_temperature));
if (Immutable) return;
_temperature = MathF.Min(MathF.Max(value, Atmospherics.TCMB), Atmospherics.Tmax);
DebugTools.Assert(!float.IsNaN(value));
if (!Immutable)
_temperature = MathF.Min(MathF.Max(value, Atmospherics.TCMB), Atmospherics.Tmax);
}
}

Expand All @@ -91,6 +91,7 @@ public GasMixture(float[] moles, float temp, float volume = Atmospherics.CellVol
if (volume < 0)
volume = 0;

DebugTools.Assert(!float.IsNaN(temp));
_temperature = temp;
Moles = moles;
Volume = volume;
Expand Down
3 changes: 3 additions & 0 deletions Content.Server/Atmos/TileAtmosphere.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ public sealed class TileAtmosphere : IGasMixtureHolder
[ViewVariables]
public TileAtmosphere? PressureSpecificTarget { get; set; }

/// <summary>
/// This is either the pressure difference, or the quantity of moles transferred if monstermos is enabled.
/// </summary>
[ViewVariables]
public float PressureDifference { get; set; }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,6 @@
- key: enum.WiresUiKey.Key
type: WiresBoundUserInterface
- type: Airtight
fixVacuum: true
noAirWhenFullyAirBlocked: false
- type: RadiationBlocker
resistance: 3
Expand Down
209 changes: 104 additions & 105 deletions Resources/Prototypes/Entities/Structures/Doors/Airlocks/highsec.yml
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this doing here?? 🤨

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm genuinely not sure why it has to diff the entire entity, but the only thing being removed is the Airtight fixVacuum argument.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Turning on 'hide whitespace' removes the odd changes, so just some funky whitespace stuff. Consider redoing the important changes so we don't have the ugly diff, merge otherwise.

Original file line number Diff line number Diff line change
@@ -1,105 +1,104 @@
- type: entity
id: HighSecDoor
parent: BaseStructure
name: high security door
description: Keeps the bad out and keeps the good in.
placement:
mode: SnapgridCenter
components:
- type: InteractionOutline
- type: Sprite
sprite: Structures/Doors/Airlocks/highsec/highsec.rsi
layers:
- state: closed
map: ["enum.DoorVisualLayers.Base"]
- state: closed_unlit
shader: unshaded
map: ["enum.DoorVisualLayers.BaseUnlit"]
- state: welded
map: ["enum.WeldableLayers.BaseWelded"]
- state: bolted_unlit
shader: unshaded
map: ["enum.DoorVisualLayers.BaseBolted"]
- state: emergency_unlit
map: ["enum.DoorVisualLayers.BaseEmergencyAccess"]
shader: unshaded
- state: panel_open
map: ["enum.WiresVisualLayers.MaintenancePanel"]
- type: AnimationPlayer
- type: Physics
- type: Fixtures
fixtures:
fix1:
shape:
!type:PhysShapeAabb
bounds: "-0.49,-0.49,0.49,0.49" # don't want this colliding with walls or they won't close
density: 100
mask:
- FullTileMask
layer:
- WallLayer
- type: ContainerFill
containers:
board: [ DoorElectronics ]
- type: ContainerContainer
containers:
board: !type:Container
- type: Door
crushDamage:
types:
Blunt: 50
openSound:
path: /Audio/Machines/airlock_open.ogg
closeSound:
path: /Audio/Machines/airlock_close.ogg
denySound:
path: /Audio/Machines/airlock_deny.ogg
- type: Weldable
time: 10
- type: Airlock
- type: NavMapDoor
- type: DoorBolt
- type: AccessReader
- type: Appearance
- type: WiresVisuals
- type: ApcPowerReceiver
powerLoad: 20
- type: ExtensionCableReceiver
- type: Electrified
enabled: false
usesApcPower: true
- type: WiresPanel
- type: WiresPanelSecurity
securityLevel: maxSecurity
- type: Wires
boardName: wires-board-name-highsec
layoutId: HighSec
alwaysRandomize: true
- type: UserInterface
interfaces:
- key: enum.WiresUiKey.Key
type: WiresBoundUserInterface
- type: Airtight
fixVacuum: true
- type: Occluder
- type: Damageable
damageContainer: StructuralInorganic
damageModifierSet: StrongMetallic
- type: Destructible
thresholds:
- trigger:
!type:DamageTrigger
damage: 1500
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- type: IconSmooth
key: walls
mode: NoSprite
- type: Construction
graph: Airlock
node: highSecDoor
- type: Tag
tags:
- HighSecDoor
# This tag is used to nagivate the Airlock construction graph. It's needed because this construction graph is shared between Airlock, AirlockGlass, and HighSecDoor
- type: entity
id: HighSecDoor
parent: BaseStructure
name: high security door
description: Keeps the bad out and keeps the good in.
placement:
mode: SnapgridCenter
components:
- type: InteractionOutline
- type: Sprite
sprite: Structures/Doors/Airlocks/highsec/highsec.rsi
layers:
- state: closed
map: ["enum.DoorVisualLayers.Base"]
- state: closed_unlit
shader: unshaded
map: ["enum.DoorVisualLayers.BaseUnlit"]
- state: welded
map: ["enum.WeldableLayers.BaseWelded"]
- state: bolted_unlit
shader: unshaded
map: ["enum.DoorVisualLayers.BaseBolted"]
- state: emergency_unlit
map: ["enum.DoorVisualLayers.BaseEmergencyAccess"]
shader: unshaded
- state: panel_open
map: ["enum.WiresVisualLayers.MaintenancePanel"]
- type: AnimationPlayer
- type: Physics
- type: Fixtures
fixtures:
fix1:
shape:
!type:PhysShapeAabb
bounds: "-0.49,-0.49,0.49,0.49" # don't want this colliding with walls or they won't close
density: 100
mask:
- FullTileMask
layer:
- WallLayer
- type: ContainerFill
containers:
board: [ DoorElectronics ]
- type: ContainerContainer
containers:
board: !type:Container
- type: Door
crushDamage:
types:
Blunt: 50
openSound:
path: /Audio/Machines/airlock_open.ogg
closeSound:
path: /Audio/Machines/airlock_close.ogg
denySound:
path: /Audio/Machines/airlock_deny.ogg
- type: Weldable
time: 10
- type: Airlock
- type: NavMapDoor
- type: DoorBolt
- type: AccessReader
- type: Appearance
- type: WiresVisuals
- type: ApcPowerReceiver
powerLoad: 20
- type: ExtensionCableReceiver
- type: Electrified
enabled: false
usesApcPower: true
- type: WiresPanel
- type: WiresPanelSecurity
securityLevel: maxSecurity
- type: Wires
boardName: wires-board-name-highsec
layoutId: HighSec
alwaysRandomize: true
- type: UserInterface
interfaces:
- key: enum.WiresUiKey.Key
type: WiresBoundUserInterface
- type: Airtight
- type: Occluder
- type: Damageable
damageContainer: StructuralInorganic
damageModifierSet: StrongMetallic
- type: Destructible
thresholds:
- trigger:
!type:DamageTrigger
damage: 1500
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- type: IconSmooth
key: walls
mode: NoSprite
- type: Construction
graph: Airlock
node: highSecDoor
- type: Tag
tags:
- HighSecDoor
# This tag is used to nagivate the Airlock construction graph. It's needed because this construction graph is shared between Airlock, AirlockGlass, and HighSecDoor
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@
denySound:
path: /Audio/Machines/airlock_deny.ogg
- type: Airtight
fixVacuum: true
noAirWhenFullyAirBlocked: false
- type: Tag
tags:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@
- type: Physics
canCollide: false
- type: Airtight
fixVacuum: true
airBlocked: false
noAirWhenFullyAirBlocked: true
- type: RadiationBlocker
Expand Down Expand Up @@ -158,7 +157,6 @@
sprite: Structures/Doors/edge_door_hazard.rsi
snapCardinals: false
- type: Airtight
fixVacuum: true
airBlocked: false
noAirWhenFullyAirBlocked: false
airBlockedDirection:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
path: /Audio/Effects/stonedoor_openclose.ogg
- type: Appearance
- type: Airtight
fixVacuum: true
- type: Damageable
damageContainer: Inorganic
damageModifierSet: Metallic
Expand Down
Loading
Loading