ApcNet code improvements (#2876)
* Removes per-frame setting of PowerReceiverComponent.Powered * PowerReceiver.SetLoad Co-authored-by: py01 <pyronetics01@gmail.com>
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using Content.Server.GameObjects.Components.Power;
|
||||
@@ -9,6 +10,8 @@ namespace Content.Server.GameObjects.Components.NodeContainer.NodeGroups
|
||||
{
|
||||
public interface IApcNet
|
||||
{
|
||||
bool Powered { get; }
|
||||
|
||||
void AddApc(ApcComponent apc);
|
||||
|
||||
void RemoveApc(ApcComponent apc);
|
||||
@@ -17,7 +20,7 @@ namespace Content.Server.GameObjects.Components.NodeContainer.NodeGroups
|
||||
|
||||
void RemovePowerProvider(PowerProviderComponent provider);
|
||||
|
||||
void UpdatePowerProviderReceivers(PowerProviderComponent provider);
|
||||
void UpdatePowerProviderReceivers(PowerProviderComponent provider, int oldLoad, int newLoad);
|
||||
|
||||
void Update(float frameTime);
|
||||
}
|
||||
@@ -29,11 +32,19 @@ namespace Content.Server.GameObjects.Components.NodeContainer.NodeGroups
|
||||
private readonly Dictionary<ApcComponent, BatteryComponent> _apcBatteries = new();
|
||||
|
||||
[ViewVariables]
|
||||
private readonly Dictionary<PowerProviderComponent, List<PowerReceiverComponent>> _providerReceivers = new();
|
||||
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 => _providerReceivers.SelectMany(kvp => kvp.Value).Count();
|
||||
private int TotalReceivers => _providers.SelectMany(provider => provider.LinkedReceivers).Count();
|
||||
|
||||
[ViewVariables]
|
||||
private int TotalPowerReceiverLoad { get => _totalPowerReceiverLoad; set => SetTotalPowerReceiverLoad(value); }
|
||||
private int _totalPowerReceiverLoad = 0;
|
||||
|
||||
public static readonly IApcNet NullNet = new NullApcNet();
|
||||
|
||||
@@ -57,80 +68,107 @@ namespace Content.Server.GameObjects.Components.NodeContainer.NodeGroups
|
||||
public void RemoveApc(ApcComponent apc)
|
||||
{
|
||||
_apcBatteries.Remove(apc);
|
||||
if (!_apcBatteries.Any())
|
||||
{
|
||||
foreach (var receiver in _providerReceivers.SelectMany(kvp => kvp.Value))
|
||||
{
|
||||
receiver.HasApcPower = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void AddPowerProvider(PowerProviderComponent provider)
|
||||
{
|
||||
_providerReceivers.Add(provider, provider.LinkedReceivers.ToList());
|
||||
_providers.Add(provider);
|
||||
|
||||
foreach (var receiver in provider.LinkedReceivers)
|
||||
{
|
||||
TotalPowerReceiverLoad += receiver.Load;
|
||||
}
|
||||
}
|
||||
|
||||
public void RemovePowerProvider(PowerProviderComponent provider)
|
||||
{
|
||||
_providerReceivers.Remove(provider);
|
||||
_providers.Remove(provider);
|
||||
|
||||
foreach (var receiver in provider.LinkedReceivers)
|
||||
{
|
||||
TotalPowerReceiverLoad -= receiver.Load;
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdatePowerProviderReceivers(PowerProviderComponent provider)
|
||||
public void UpdatePowerProviderReceivers(PowerProviderComponent provider, int oldLoad, int newLoad)
|
||||
{
|
||||
Debug.Assert(_providerReceivers.ContainsKey(provider));
|
||||
_providerReceivers[provider] = provider.LinkedReceivers.ToList();
|
||||
}
|
||||
Debug.Assert(_providers.Contains(provider));
|
||||
TotalPowerReceiverLoad -= oldLoad;
|
||||
TotalPowerReceiverLoad += newLoad;
|
||||
}
|
||||
|
||||
public void Update(float frameTime)
|
||||
{
|
||||
var totalCharge = 0.0;
|
||||
var totalMaxCharge = 0;
|
||||
foreach (var (apc, battery) in _apcBatteries)
|
||||
var remainingPowerNeeded = TotalPowerReceiverLoad * frameTime;
|
||||
|
||||
foreach (var apcBatteryPair in _apcBatteries)
|
||||
{
|
||||
var apc = apcBatteryPair.Key;
|
||||
|
||||
if (!apc.MainBreakerEnabled)
|
||||
continue;
|
||||
|
||||
totalCharge += battery.CurrentCharge;
|
||||
totalMaxCharge += battery.MaxCharge;
|
||||
var battery = apcBatteryPair.Value;
|
||||
|
||||
if (battery.CurrentCharge < remainingPowerNeeded)
|
||||
{
|
||||
remainingPowerNeeded -= battery.CurrentCharge;
|
||||
battery.CurrentCharge = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
battery.UseCharge(remainingPowerNeeded);
|
||||
remainingPowerNeeded = 0;
|
||||
}
|
||||
|
||||
if (remainingPowerNeeded == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
foreach (var (_, receivers) in _providerReceivers)
|
||||
{
|
||||
foreach (var receiver in receivers)
|
||||
{
|
||||
if (!receiver.NeedsPower || receiver.PowerDisabled)
|
||||
continue;
|
||||
Powered = remainingPowerNeeded == 0;
|
||||
}
|
||||
|
||||
receiver.HasApcPower = TryUsePower(receiver.Load * frameTime);
|
||||
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 bool TryUsePower(float neededCharge)
|
||||
private void SetTotalPowerReceiverLoad(int totalPowerReceiverLoad)
|
||||
{
|
||||
foreach (var (apc, battery) in _apcBatteries)
|
||||
{
|
||||
if (!apc.MainBreakerEnabled)
|
||||
continue;
|
||||
Debug.Assert(totalPowerReceiverLoad >= 0);
|
||||
_totalPowerReceiverLoad = totalPowerReceiverLoad;
|
||||
|
||||
if (battery.TryUseCharge(neededCharge)) //simplification - all power needed must come from one battery
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#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 void AddApc(ApcComponent apc) { }
|
||||
public void AddPowerProvider(PowerProviderComponent provider) { }
|
||||
public void RemoveApc(ApcComponent apc) { }
|
||||
public void RemovePowerProvider(PowerProviderComponent provider) { }
|
||||
public void UpdatePowerProviderReceivers(PowerProviderComponent provider) { }
|
||||
public void UpdatePowerProviderReceivers(PowerProviderComponent provider, int oldLoad, int newLoad) { }
|
||||
public void Update(float frameTime) { }
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user