Merge branch 'master' into 2020-08-19-firelocks

# Conflicts:
#	Content.Server/GameObjects/Components/Atmos/AirtightComponent.cs
#	Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs
#	SpaceStation14.sln.DotSettings
This commit is contained in:
Víctor Aguilera Puerto
2020-08-28 14:35:45 +02:00
494 changed files with 11527 additions and 3829 deletions

View File

@@ -1,4 +1,5 @@
using System;
#nullable enable
using System;
using System.Threading;
using System.Threading.Tasks;
using Content.Server.GameObjects.Components.Interactable;
@@ -34,10 +35,7 @@ namespace Content.Server.GameObjects.Components.Doors
/// </summary>
private static readonly TimeSpan PowerWiresTimeout = TimeSpan.FromSeconds(5.0);
private PowerReceiverComponent _powerReceiver;
private WiresComponent _wires;
private CancellationTokenSource _powerWiresPulsedTimerCancel;
private CancellationTokenSource _powerWiresPulsedTimerCancel = new CancellationTokenSource();
private bool _powerWiresPulsed;
@@ -89,13 +87,15 @@ namespace Content.Server.GameObjects.Components.Doors
private void UpdateWiresStatus()
{
WiresComponent? wires;
var powerLight = new StatusLightData(Color.Yellow, StatusLightState.On, "POWR");
if (PowerWiresPulsed)
{
powerLight = new StatusLightData(Color.Yellow, StatusLightState.BlinkingFast, "POWR");
}
else if (_wires.IsWireCut(Wires.MainPower) &&
_wires.IsWireCut(Wires.BackupPower))
else if (Owner.TryGetComponent(out wires) &&
wires.IsWireCut(Wires.MainPower) &&
wires.IsWireCut(Wires.BackupPower))
{
powerLight = new StatusLightData(Color.Red, StatusLightState.On, "POWR");
}
@@ -114,12 +114,17 @@ namespace Content.Server.GameObjects.Components.Doors
var safetyStatus =
new StatusLightData(Color.Red, Safety ? StatusLightState.On : StatusLightState.Off, "SAFE");
_wires.SetStatus(AirlockWireStatus.PowerIndicator, powerLight);
_wires.SetStatus(AirlockWireStatus.BoltIndicator, boltStatus);
_wires.SetStatus(AirlockWireStatus.BoltLightIndicator, boltLightsStatus);
_wires.SetStatus(AirlockWireStatus.AIControlIndicator, new StatusLightData(Color.Purple, StatusLightState.BlinkingSlow, "AICT"));
_wires.SetStatus(AirlockWireStatus.TimingIndicator, timingStatus);
_wires.SetStatus(AirlockWireStatus.SafetyIndicator, safetyStatus);
if (!Owner.TryGetComponent(out wires))
{
return;
}
wires.SetStatus(AirlockWireStatus.PowerIndicator, powerLight);
wires.SetStatus(AirlockWireStatus.BoltIndicator, boltStatus);
wires.SetStatus(AirlockWireStatus.BoltLightIndicator, boltLightsStatus);
wires.SetStatus(AirlockWireStatus.AIControlIndicator, new StatusLightData(Color.Purple, StatusLightState.BlinkingSlow, "AICT"));
wires.SetStatus(AirlockWireStatus.TimingIndicator, timingStatus);
wires.SetStatus(AirlockWireStatus.SafetyIndicator, safetyStatus);
/*
_wires.SetStatus(6, powerLight);
_wires.SetStatus(7, powerLight);
@@ -131,26 +136,45 @@ namespace Content.Server.GameObjects.Components.Doors
private void UpdatePowerCutStatus()
{
_powerReceiver.PowerDisabled = PowerWiresPulsed ||
_wires.IsWireCut(Wires.MainPower) ||
_wires.IsWireCut(Wires.BackupPower);
if (!Owner.TryGetComponent(out PowerReceiverComponent? receiver))
{
return;
}
if (PowerWiresPulsed)
{
receiver.PowerDisabled = true;
return;
}
if (!Owner.TryGetComponent(out WiresComponent? wires))
{
return;
}
receiver.PowerDisabled =
wires.IsWireCut(Wires.MainPower) ||
wires.IsWireCut(Wires.BackupPower);
}
private void UpdateBoltLightStatus()
{
if (Owner.TryGetComponent(out AppearanceComponent appearance))
if (Owner.TryGetComponent(out AppearanceComponent? appearance))
{
appearance.SetData(DoorVisuals.BoltLights, BoltLightsVisible);
}
}
protected override DoorState State
public override DoorState State
{
set
protected set
{
base.State = value;
// Only show the maintenance panel if the airlock is closed
_wires.IsPanelVisible = value != DoorState.Open;
if (Owner.TryGetComponent(out WiresComponent? wires))
{
wires.IsPanelVisible = value != DoorState.Open;
}
// If the door is closed, we should look if the bolt was locked while closing
UpdateBoltLightStatus();
}
@@ -159,25 +183,32 @@ namespace Content.Server.GameObjects.Components.Doors
public override void Initialize()
{
base.Initialize();
_powerReceiver = Owner.GetComponent<PowerReceiverComponent>();
_wires = Owner.GetComponent<WiresComponent>();
_powerReceiver.OnPowerStateChanged += PowerDeviceOnOnPowerStateChanged;
if (Owner.TryGetComponent(out AppearanceComponent appearance))
if (Owner.TryGetComponent(out PowerReceiverComponent? receiver))
{
appearance.SetData(DoorVisuals.Powered, _powerReceiver.Powered);
receiver.OnPowerStateChanged += PowerDeviceOnOnPowerStateChanged;
if (Owner.TryGetComponent(out AppearanceComponent? appearance))
{
appearance.SetData(DoorVisuals.Powered, receiver.Powered);
}
}
}
public override void OnRemove()
{
_powerReceiver.OnPowerStateChanged -= PowerDeviceOnOnPowerStateChanged;
if (Owner.TryGetComponent(out PowerReceiverComponent? receiver))
{
receiver.OnPowerStateChanged -= PowerDeviceOnOnPowerStateChanged;
}
base.OnRemove();
}
private void PowerDeviceOnOnPowerStateChanged(object sender, PowerStateEventArgs e)
private void PowerDeviceOnOnPowerStateChanged(object? sender, PowerStateEventArgs e)
{
if (Owner.TryGetComponent(out AppearanceComponent appearance))
if (Owner.TryGetComponent(out AppearanceComponent? appearance))
{
appearance.SetData(DoorVisuals.Powered, e.Powered);
}
@@ -188,11 +219,12 @@ namespace Content.Server.GameObjects.Components.Doors
protected override void ActivateImpl(ActivateEventArgs args)
{
if (_wires.IsPanelOpen)
if (Owner.TryGetComponent(out WiresComponent? wires) &&
wires.IsPanelOpen)
{
if (args.User.TryGetComponent(out IActorComponent actor))
if (args.User.TryGetComponent(out IActorComponent? actor))
{
_wires.OpenInterface(actor.playerSession);
wires.OpenInterface(actor.playerSession);
}
}
else
@@ -272,8 +304,7 @@ namespace Content.Server.GameObjects.Components.Doors
case Wires.MainPower:
case Wires.BackupPower:
PowerWiresPulsed = true;
_powerWiresPulsedTimerCancel?.Cancel();
_powerWiresPulsedTimerCancel = new CancellationTokenSource();
_powerWiresPulsedTimerCancel.Cancel();
Timer.Spawn(PowerWiresTimeout,
() => PowerWiresPulsed = false,
_powerWiresPulsedTimerCancel.Token);
@@ -377,7 +408,8 @@ namespace Content.Server.GameObjects.Components.Doors
private bool IsPowered()
{
return _powerReceiver.Powered;
return !Owner.TryGetComponent(out PowerReceiverComponent? receiver)
|| receiver.Powered;
}
public async Task<bool> InteractUsing(InteractUsingEventArgs eventArgs)
@@ -388,11 +420,12 @@ namespace Content.Server.GameObjects.Components.Doors
if (tool.HasQuality(ToolQuality.Cutting)
|| tool.HasQuality(ToolQuality.Multitool))
{
if (_wires.IsPanelOpen)
if (Owner.TryGetComponent(out WiresComponent? wires)
&& wires.IsPanelOpen)
{
if (eventArgs.User.TryGetComponent(out IActorComponent actor))
if (eventArgs.User.TryGetComponent(out IActorComponent? actor))
{
_wires.OpenInterface(actor.playerSession);
wires.OpenInterface(actor.playerSession);
return true;
}
}

View File

@@ -1,4 +1,5 @@
using System;
#nullable enable
using System;
using System.Linq;
using System.Threading;
using Content.Server.Atmos;
@@ -35,10 +36,10 @@ namespace Content.Server.GameObjects.Components.Doors
private DoorState _state = DoorState.Closed;
protected virtual DoorState State
public virtual DoorState State
{
get => _state;
set => _state = value;
protected set => _state = value;
}
protected float OpenTimeCounter;
@@ -46,10 +47,7 @@ namespace Content.Server.GameObjects.Components.Doors
protected const float AutoCloseDelay = 5;
protected float CloseSpeed = AutoCloseDelay;
private AirtightComponent airtightComponent;
private ICollidableComponent _collidableComponent;
private AppearanceComponent _appearance;
private CancellationTokenSource _cancellationTokenSource;
private CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();
protected virtual TimeSpan CloseTimeOne => TimeSpan.FromSeconds(0.3f);
protected virtual TimeSpan CloseTimeTwo => TimeSpan.FromSeconds(0.9f);
@@ -72,21 +70,9 @@ namespace Content.Server.GameObjects.Components.Doors
serializer.DataField(ref _occludes, "occludes", true);
}
public override void Initialize()
{
base.Initialize();
airtightComponent = Owner.GetComponent<AirtightComponent>();
_collidableComponent = Owner.GetComponent<ICollidableComponent>();
_appearance = Owner.GetComponent<AppearanceComponent>();
_cancellationTokenSource = new CancellationTokenSource();
}
public override void OnRemove()
{
_cancellationTokenSource.Cancel();
_collidableComponent = null;
_appearance = null;
_cancellationTokenSource?.Cancel();
base.OnRemove();
}
@@ -108,7 +94,6 @@ namespace Content.Server.GameObjects.Components.Doors
ActivateImpl(eventArgs);
}
void ICollideBehavior.CollideWith(IEntity entity)
{
if (State != DoorState.Closed)
@@ -139,8 +124,10 @@ namespace Content.Server.GameObjects.Components.Doors
protected void SetAppearance(DoorVisualState state)
{
if (_appearance != null || Owner.TryGetComponent(out _appearance))
_appearance.SetData(DoorVisuals.VisualState, state);
if (Owner.TryGetComponent(out AppearanceComponent? appearance))
{
appearance.SetData(DoorVisuals.VisualState, state);
}
}
public virtual bool CanOpen()
@@ -151,28 +138,53 @@ namespace Content.Server.GameObjects.Components.Doors
public virtual bool CanOpen(IEntity user)
{
if (!CanOpen()) return false;
if (!Owner.TryGetComponent(out AccessReader accessReader))
if (!Owner.TryGetComponent<AccessReader>(out var accessReader))
{
return true;
}
return accessReader.IsAllowed(user);
var doorSystem = EntitySystem.Get<DoorSystem>();
var isAirlockExternal = HasAccessType("External");
return doorSystem.AccessType switch
{
DoorSystem.AccessTypes.AllowAll => true,
DoorSystem.AccessTypes.AllowAllIdExternal => isAirlockExternal ? accessReader.IsAllowed(user) : true,
DoorSystem.AccessTypes.AllowAllNoExternal => !isAirlockExternal,
_ => accessReader.IsAllowed(user)
};
}
/// <summary>
/// Returns whether a door has a certain access type. For example, maintenance doors will have access type
/// "Maintenance" in their AccessReader.
/// </summary>
private bool HasAccessType(string accesType)
{
if(Owner.TryGetComponent<AccessReader>(out var accessReader))
{
return accessReader.AccessLists.Any(list => list.Contains(accesType));
}
return true;
}
public void TryOpen(IEntity user)
{
if (!CanOpen(user))
if (CanOpen(user))
{
Open();
if (user.TryGetComponent(out HandsComponent? hands) && hands.Count == 0)
{
EntitySystem.Get<AudioSystem>().PlayFromEntity("/Audio/Effects/bang.ogg", Owner,
AudioParams.Default.WithVolume(-2));
}
}
else
{
Deny();
return;
}
Open();
if (user.TryGetComponent(out HandsComponent hands) && hands.Count == 0)
{
EntitySystem.Get<AudioSystem>().PlayFromEntity("/Audio/Effects/bang.ogg", Owner,
AudioParams.Default.WithVolume(-2));
}
}
@@ -185,15 +197,22 @@ namespace Content.Server.GameObjects.Components.Doors
State = DoorState.Opening;
SetAppearance(DoorVisualState.Opening);
if (_occludes && Owner.TryGetComponent(out OccluderComponent occluder))
if (_occludes && Owner.TryGetComponent(out OccluderComponent? occluder))
{
occluder.Enabled = false;
}
Timer.Spawn(OpenTimeOne, async () =>
{
airtightComponent.AirBlocked = false;
_collidableComponent.Hard = false;
if (Owner.TryGetComponent(out AirtightComponent? airtight))
{
airtight.AirBlocked = false;
}
if (Owner.TryGetComponent(out ICollidableComponent? collidable))
{
collidable.Hard = false;
}
await Timer.Delay(OpenTimeTwo, _cancellationTokenSource.Token);
@@ -212,7 +231,7 @@ namespace Content.Server.GameObjects.Components.Doors
public virtual bool CanClose(IEntity user)
{
if (!CanClose()) return false;
if (!Owner.TryGetComponent(out AccessReader accessReader))
if (!Owner.TryGetComponent(out AccessReader? accessReader))
{
return true;
}
@@ -233,18 +252,22 @@ namespace Content.Server.GameObjects.Components.Doors
private void CheckCrush()
{
if (!Owner.TryGetComponent(out ICollidableComponent? body))
{
return;
}
// Check if collides with something
var collidesWith = _collidableComponent.GetCollidingEntities(Vector2.Zero, false);
var collidesWith = body.GetCollidingEntities(Vector2.Zero, false);
if (collidesWith.Count() != 0)
{
// Crush
bool hitSomeone = false;
foreach (var e in collidesWith)
{
if (!e.TryGetComponent(out StunnableComponent stun)
|| !e.TryGetComponent(out IDamageableComponent damage)
|| !e.TryGetComponent(out ICollidableComponent otherBody)
|| !Owner.TryGetComponent(out ICollidableComponent body))
if (!e.TryGetComponent(out StunnableComponent? stun)
|| !e.TryGetComponent(out IDamageableComponent? damage)
|| !e.TryGetComponent(out ICollidableComponent? otherBody))
continue;
var percentage = otherBody.WorldAABB.IntersectPercentage(body.WorldAABB);
@@ -319,7 +342,8 @@ namespace Content.Server.GameObjects.Components.Doors
public bool Close()
{
bool shouldCheckCrush = false;
if (_collidableComponent.IsColliding(Vector2.Zero, false))
if (Owner.TryGetComponent(out ICollidableComponent? collidable) && collidable.IsColliding(Vector2.Zero, false))
{
if (Safety)
return false;
@@ -331,7 +355,7 @@ namespace Content.Server.GameObjects.Components.Doors
State = DoorState.Closing;
OpenTimeCounter = 0;
SetAppearance(DoorVisualState.Closing);
if (_occludes && Owner.TryGetComponent(out OccluderComponent occluder))
if (_occludes && Owner.TryGetComponent(out OccluderComponent? occluder))
{
occluder.Enabled = true;
}
@@ -343,8 +367,15 @@ namespace Content.Server.GameObjects.Components.Doors
CheckCrush();
}
airtightComponent.AirBlocked = true;
_collidableComponent.Hard = true;
if (Owner.TryGetComponent(out AirtightComponent? airtight))
{
airtight.AirBlocked = true;
}
if (Owner.TryGetComponent(out ICollidableComponent? body))
{
body.Hard = true;
}
await Timer.Delay(CloseTimeTwo, _cancellationTokenSource.Token);
@@ -391,7 +422,7 @@ namespace Content.Server.GameObjects.Components.Doors
}
}
protected enum DoorState
public enum DoorState
{
Closed,
Open,