using Content.Server.GameObjects.Components.NodeContainer.NodeGroups; using Robust.Server.Interfaces.GameObjects; using Robust.Shared.GameObjects; using Robust.Shared.Interfaces.Map; using Robust.Shared.IoC; using Robust.Shared.Serialization; using Robust.Shared.ViewVariables; using System; using System.Collections.Generic; using System.Linq; namespace Content.Server.GameObjects.Components.Power.ApcNetComponents { /// /// Relays s in an area to a so they can receive power. /// public interface IPowerProvider { void AddReceiver(PowerReceiverComponent receiver); void RemoveReceiver(PowerReceiverComponent receiver); } [RegisterComponent] public class PowerProviderComponent : BaseApcNetComponent, IPowerProvider { public override string Name => "PowerProvider"; /// /// The max distance this can transmit power to s from. /// [ViewVariables(VVAccess.ReadWrite)] public int PowerTransferRange { get => _powerTransferRange; set => SetPowerTransferRange(value); } private int _powerTransferRange; [ViewVariables] public IReadOnlyList LinkedReceivers => _linkedReceivers; private List _linkedReceivers = new List(); /// /// If s should consider connecting to this. /// [ViewVariables(VVAccess.ReadWrite)] public bool Connectable { get; private set; } = true; public static readonly IPowerProvider NullProvider = new NullPowerProvider(); public void AddReceiver(PowerReceiverComponent receiver) { _linkedReceivers.Add(receiver); Net.UpdatePowerProviderReceivers(this); } public void RemoveReceiver(PowerReceiverComponent receiver) { _linkedReceivers.Remove(receiver); Net.UpdatePowerProviderReceivers(this); } public override void ExposeData(ObjectSerializer serializer) { base.ExposeData(serializer); serializer.DataField(ref _powerTransferRange, "powerTransferRange", 3); } protected override void Startup() { base.Startup(); foreach (var receiver in FindAvailableReceivers()) { receiver.Provider = this; } } public override void OnRemove() { Connectable = false; var receivers = _linkedReceivers.ToArray(); foreach (var receiver in receivers) { receiver.ClearProvider(); } _linkedReceivers = new List(); Net.UpdatePowerProviderReceivers(this); foreach (var receiver in receivers) { receiver.TryFindAndSetProvider(); } base.OnRemove(); } private List FindAvailableReceivers() { var mapManager = IoCManager.Resolve(); var nearbyEntities = IoCManager.Resolve() .GetEntitiesInRange(Owner, PowerTransferRange); return nearbyEntities.Select(entity => entity.TryGetComponent(out var receiver) ? receiver : null) .Where(receiver => receiver != null) .Where(receiver => receiver.Connectable) .Where(receiver => receiver.NeedsProvider) .Where(receiver => receiver.Owner.Transform.GridPosition.Distance(mapManager, Owner.Transform.GridPosition) < Math.Min(PowerTransferRange, receiver.PowerReceptionRange)) .ToList(); } protected override void AddSelfToNet(IApcNet apcNet) { apcNet.AddPowerProvider(this); } protected override void RemoveSelfFromNet(IApcNet apcNet) { apcNet.RemovePowerProvider(this); } private void SetPowerTransferRange(int newPowerTransferRange) { foreach (var receiver in _linkedReceivers) { receiver.ClearProvider(); } _powerTransferRange = newPowerTransferRange; _linkedReceivers = FindAvailableReceivers(); Net.UpdatePowerProviderReceivers(this); } private class NullPowerProvider : IPowerProvider { public void AddReceiver(PowerReceiverComponent receiver) { } public void RemoveReceiver(PowerReceiverComponent receiver) { } } } }