Files
tbd-station-14/Content.Server/GameObjects/Components/NodeContainer/NodeGroups/ApcNetNodeGroup.cs
collinlunn fabc580df9 ApcNet updating fix (#3078)
* GridPowerComponent

* ApcNet Powered update bugfix

* PowerTest fix

* Add GridPower to Saltern

* test fix

* Update canceling cleanup

* code cleanup

* nullable & code cleanup for test

* undo power test nullable

* Replaces GridPowerSystem with ApcNetSystem

* build fix

* Update Content.Server/GameObjects/EntitySystems/ApcNetSystem.cs

Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
2021-02-18 00:51:30 +11:00

223 lines
6.6 KiB
C#

#nullable enable
using System.Collections.Generic;
using System.Linq;
using Content.Server.GameObjects.Components.NodeContainer.Nodes;
using Content.Server.GameObjects.Components.Power;
using Content.Server.GameObjects.Components.Power.ApcNetComponents;
using Content.Server.GameObjects.EntitySystems;
using Robust.Shared.GameObjects;
using Robust.Shared.Map;
using Robust.Shared.Utility;
using Robust.Shared.ViewVariables;
namespace Content.Server.GameObjects.Components.NodeContainer.NodeGroups
{
public interface IApcNet
{
bool Powered { get; }
void AddApc(ApcComponent apc);
void RemoveApc(ApcComponent apc);
void AddPowerProvider(PowerProviderComponent provider);
void RemovePowerProvider(PowerProviderComponent provider);
void UpdatePowerProviderReceivers(PowerProviderComponent provider, int oldLoad, int newLoad);
void Update(float frameTime);
GridId? GridId { get; }
}
[NodeGroup(NodeGroupID.Apc)]
public class ApcNetNodeGroup : BaseNetConnectorNodeGroup<BaseApcNetComponent, IApcNet>, IApcNet
{
[ViewVariables]
private readonly Dictionary<ApcComponent, BatteryComponent> _apcBatteries = new();
[ViewVariables]
private readonly List<PowerProviderComponent> _providers = new();
[ViewVariables]
public bool Powered { get => _powered; private set => SetPowered(value); }
private bool _powered = false;
//Debug property
[ViewVariables]
private int TotalReceivers => _providers.SelectMany(provider => provider.LinkedReceivers).Count();
[ViewVariables]
private int TotalPowerReceiverLoad { get => _totalPowerReceiverLoad; set => SetTotalPowerReceiverLoad(value); }
GridId? IApcNet.GridId => GridId;
private int _totalPowerReceiverLoad = 0;
public static readonly IApcNet NullNet = new NullApcNet();
public override void Initialize(Node sourceNode)
{
base.Initialize(sourceNode);
EntitySystem.Get<ApcNetSystem>().AddApcNet(this);
}
protected override void AfterRemake(IEnumerable<INodeGroup> newGroups)
{
base.AfterRemake(newGroups);
foreach (var group in newGroups)
{
if (group is not ApcNetNodeGroup apcNet)
continue;
apcNet.Powered = Powered;
}
StopUpdates();
}
protected override void OnGivingNodesForCombine(INodeGroup newGroup)
{
base.OnGivingNodesForCombine(newGroup);
if (newGroup is ApcNetNodeGroup apcNet)
{
apcNet.Powered = Powered;
}
StopUpdates();
}
private void StopUpdates()
{
EntitySystem.Get<ApcNetSystem>().RemoveApcNet(this);
}
#region IApcNet Methods
protected override void SetNetConnectorNet(BaseApcNetComponent netConnectorComponent)
{
netConnectorComponent.Net = this;
}
public void AddApc(ApcComponent apc)
{
if (!apc.Owner.TryGetComponent(out BatteryComponent? battery))
{
return;
}
_apcBatteries.Add(apc, battery);
}
public void RemoveApc(ApcComponent apc)
{
_apcBatteries.Remove(apc);
}
public void AddPowerProvider(PowerProviderComponent provider)
{
_providers.Add(provider);
foreach (var receiver in provider.LinkedReceivers)
{
TotalPowerReceiverLoad += receiver.Load;
}
}
public void RemovePowerProvider(PowerProviderComponent provider)
{
_providers.Remove(provider);
foreach (var receiver in provider.LinkedReceivers)
{
TotalPowerReceiverLoad -= receiver.Load;
}
}
public void UpdatePowerProviderReceivers(PowerProviderComponent provider, int oldLoad, int newLoad)
{
DebugTools.Assert(_providers.Contains(provider));
TotalPowerReceiverLoad -= oldLoad;
TotalPowerReceiverLoad += newLoad;
}
public void Update(float frameTime)
{
var remainingPowerNeeded = TotalPowerReceiverLoad * frameTime;
foreach (var apcBatteryPair in _apcBatteries)
{
var apc = apcBatteryPair.Key;
if (!apc.MainBreakerEnabled)
continue;
var battery = apcBatteryPair.Value;
if (battery.CurrentCharge < remainingPowerNeeded)
{
remainingPowerNeeded -= battery.CurrentCharge;
battery.CurrentCharge = 0;
}
else
{
battery.UseCharge(remainingPowerNeeded);
remainingPowerNeeded = 0;
}
if (remainingPowerNeeded == 0)
break;
}
Powered = remainingPowerNeeded == 0;
}
private void SetPowered(bool powered)
{
if (powered != Powered)
{
_powered = powered;
PoweredChanged();
}
}
private void PoweredChanged()
{
foreach (var provider in _providers)
{
foreach (var receiver in provider.LinkedReceivers)
{
receiver.ApcPowerChanged();
}
}
}
private void SetTotalPowerReceiverLoad(int totalPowerReceiverLoad)
{
DebugTools.Assert(totalPowerReceiverLoad >= 0, $"Expected load equal to or greater than 0, was {totalPowerReceiverLoad}");
_totalPowerReceiverLoad = totalPowerReceiverLoad;
}
#endregion
private class NullApcNet : IApcNet
{
/// <summary>
/// It is important that this returns false, so <see cref="PowerProviderComponent"/>s with a <see cref="NullApcNet"/> have no power.
/// </summary>
public bool Powered => false;
public GridId? GridId => default;
public void AddApc(ApcComponent apc) { }
public void AddPowerProvider(PowerProviderComponent provider) { }
public void RemoveApc(ApcComponent apc) { }
public void RemovePowerProvider(PowerProviderComponent provider) { }
public void UpdatePowerProviderReceivers(PowerProviderComponent provider, int oldLoad, int newLoad) { }
public void Update(float frameTime) { }
}
}
}