Gas Canisters and Ports (#2151)

* CanisterComponent start

* GasCanisterPort

* canister

* GasCanister yaml

* More Gas Canisters

* Canister & port fixes

* Placeholder canister and port sprites

* GasMixture serialization

* Component ignores

* Fix duplicate component ignore

Co-authored-by: py01 <pyronetics01@gmail.com>
Co-authored-by: DrSmugleaf <DrSmugleaf@users.noreply.github.com>
This commit is contained in:
py01
2020-10-10 05:37:52 -06:00
committed by GitHub
parent ccfc035a2a
commit 5aa866548b
6 changed files with 223 additions and 5 deletions

View File

@@ -180,6 +180,8 @@
"Headset",
"ComputerBoard",
"BreakableConstruction",
"GasCanister",
"GasCanisterPort",
};
}
}

View File

@@ -1,10 +1,91 @@
using Robust.Shared.GameObjects;
using Content.Server.Atmos;
using Content.Server.GameObjects.Components.Atmos.Piping;
using Content.Server.Interfaces;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Components;
using Robust.Shared.GameObjects.Components.Transform;
using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables;
using System;
using System.Linq;
namespace Content.Server.GameObjects.Components.Atmos
{
[RegisterComponent]
public class GasCanisterComponent : Component
public class GasCanisterComponent : Component, IGasMixtureHolder
{
public override string Name => "GasCanister";
[ViewVariables]
public GasMixture Air { get; set; }
[ViewVariables]
public bool Anchored => !Owner.TryGetComponent<ICollidableComponent>(out var collidable) || collidable.Anchored;
[ViewVariables]
public GasCanisterPortComponent ConnectedPort { get; private set; }
[ViewVariables]
public bool ConnectedToPort => ConnectedPort != null;
private const float DefaultVolume = 10;
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
serializer.DataField(this, x => Air, "gasMixture", new GasMixture(DefaultVolume));
}
public override void Initialize()
{
base.Initialize();
if (Owner.TryGetComponent<ICollidableComponent>(out var collidable))
{
AnchorUpdate();
collidable.AnchoredChanged += AnchorUpdate;
}
}
public override void OnRemove()
{
base.OnRemove();
if (Owner.TryGetComponent<ICollidableComponent>(out var collidable))
{
collidable.AnchoredChanged -= AnchorUpdate;
}
DisconnectFromPort();
}
public void TryConnectToPort()
{
if (!Owner.TryGetComponent<SnapGridComponent>(out var snapGrid)) return;
var port = snapGrid.GetLocal()
.Select(entity => entity.TryGetComponent<GasCanisterPortComponent>(out var port) ? port : null)
.Where(port => port != null)
.Where(port => !port.ConnectedToCanister)
.FirstOrDefault();
if (port == null) return;
ConnectedPort = port;
ConnectedPort.ConnectGasCanister(this);
}
public void DisconnectFromPort()
{
ConnectedPort?.DisconnectGasCanister();
ConnectedPort = null;
}
private void AnchorUpdate()
{
if (Anchored)
{
TryConnectToPort();
}
else
{
DisconnectFromPort();
}
}
}
}

View File

@@ -0,0 +1,77 @@
using Content.Server.GameObjects.Components.NodeContainer;
using Content.Server.GameObjects.Components.NodeContainer.Nodes;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Components.Transform;
using Robust.Shared.Log;
using Robust.Shared.ViewVariables;
using System.Linq;
namespace Content.Server.GameObjects.Components.Atmos.Piping
{
[RegisterComponent]
public class GasCanisterPortComponent : PipeNetDeviceComponent
{
public override string Name => "GasCanisterPort";
[ViewVariables]
public GasCanisterComponent ConnectedCanister { get; private set; }
[ViewVariables]
public bool ConnectedToCanister => ConnectedCanister != null;
[ViewVariables]
private PipeNode _gasPort;
public override void Initialize()
{
base.Initialize();
if (!Owner.TryGetComponent<NodeContainerComponent>(out var container))
{
JoinedGridAtmos?.RemovePipeNetDevice(this);
Logger.Error($"{typeof(GasCanisterPortComponent)} on entity {Owner.Uid} did not have a {nameof(NodeContainerComponent)}.");
return;
}
_gasPort = container.Nodes.OfType<PipeNode>().FirstOrDefault();
if (_gasPort == null)
{
JoinedGridAtmos?.RemovePipeNetDevice(this);
Logger.Error($"{typeof(GasCanisterPortComponent)} on entity {Owner.Uid} could not find compatible {nameof(PipeNode)}s on its {nameof(NodeContainerComponent)}.");
return;
}
if (Owner.TryGetComponent<SnapGridComponent>(out var snapGrid))
{
var anchoredCanister = snapGrid.GetLocal()
.Select(entity => entity.TryGetComponent<GasCanisterComponent>(out var canister) ? canister : null)
.Where(canister => canister != null)
.Where(canister => canister.Anchored)
.Where(canister => !canister.ConnectedToPort)
.FirstOrDefault();
if (anchoredCanister != null)
{
anchoredCanister.TryConnectToPort();
}
}
}
public override void OnRemove()
{
base.OnRemove();
ConnectedCanister?.DisconnectFromPort();
}
public override void Update()
{
ConnectedCanister?.Air.Share(_gasPort.Air, 1);
}
public void ConnectGasCanister(GasCanisterComponent gasCanister)
{
ConnectedCanister = gasCanister;
}
public void DisconnectGasCanister()
{
ConnectedCanister = null;
}
}
}

View File

@@ -60,22 +60,23 @@ namespace Content.Server.GameObjects.Components.NodeContainer.Nodes
public GasMixture LocalAir { get; set; }
[ViewVariables]
public float Volume { get; private set; }
public float Volume => LocalAir.Volume;
private AppearanceComponent _appearance;
private const float DefaultVolume = 1;
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
serializer.DataField(ref _pipeDirection, "pipeDirection", PipeDirection.None);
serializer.DataField(this, x => Volume, "volume", 10);
serializer.DataField(this, x => LocalAir, "gasMixture", new GasMixture(DefaultVolume));
serializer.DataField(ref _conduitLayer, "conduitLayer", ConduitLayer.Two);
}
public override void Initialize(IEntity owner)
{
base.Initialize(owner);
LocalAir = new GasMixture(Volume);
Owner.TryGetComponent(out _appearance);
UpdateAppearance();
}

View File

@@ -0,0 +1,30 @@
- type: entity
abstract: true
id: GasCanisterPortBase
placement:
mode: SnapgridCenter
components:
- type: Clickable
- type: InteractionOutline
- type: Collidable
- type: SnapGrid
offset: Center
- type: Sprite
- type: Destructible
thresholdvalue: 100
- type: GasCanisterPort
- type: entity
parent: GasCanisterPortBase
id: FourwayGasCanisterPort
name: Fourway Gas Canister Port
components:
- type: NodeContainer
nodes:
- !type:PipeNode
nodeGroupID: Pipe
pipeDirection: Fourway
- type: Sprite
sprite: Constructible/Power/smes.rsi
state: smes

View File

@@ -0,0 +1,27 @@
- type: entity
abstract: true
id: GasCanisterBase
placement:
mode: SnapgridCenter
components:
- type: Clickable
- type: InteractionOutline
- type: Collidable
- type: SnapGrid
offset: Center
- type: Sprite
- type: Destructible
thresholdvalue: 100
- type: GasCanister
- type: Anchorable
- type: Pullable
- type: entity
parent: GasCanisterBase
id: GasCanister
name: Gas Canister
components:
- type: Sprite
sprite: "Constructible/Power/apc.rsi"
state: apc0