Apc device network and apc based light switch (#4908)
* Remove WireNet node group from cables Implement extension cable components and system Remove connection over distance logic from ApcPower... components * Add extension cable components to prototypes * Implement ApcNetwork Implement ApcNetSwitch * Fix ignoredComponents.cs * Add friend attribute to new components * Add construction graph for a light switch * Address reviews * Fix broken test * Move ConnectionType enum to DeviceNetworkComponent Change netId data definition to use the ConnectionType enum values Co-authored-by: Julian Giebel <j.giebel@netrocks.info>
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
using Content.Server.DeviceNetwork.Systems;
|
||||
using Content.Server.NodeContainer.Nodes;
|
||||
using Robust.Shared.Analyzers;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Server.DeviceNetwork.Components
|
||||
{
|
||||
[RegisterComponent]
|
||||
[Friend(typeof(ApcNetworkSystem))]
|
||||
public class ApcNetworkComponent : Component
|
||||
{
|
||||
public override string Name => "ApcNetworkConnection";
|
||||
|
||||
/// <summary>
|
||||
/// The node Group the ApcNetworkConnection is connected to
|
||||
/// </summary>
|
||||
[ViewVariables] public Node? ConnectedNode;
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.ViewVariables;
|
||||
@@ -9,16 +10,22 @@ namespace Content.Server.DeviceNetwork.Components
|
||||
{
|
||||
public override string Name => "DeviceNetworkComponent";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The device networks netID this DeviceNetworkComponent connects to.
|
||||
/// The netID is used to seperate device networks that shouldn't interact with each other e.g. wireless and wired.
|
||||
/// The default netID's are_
|
||||
/// 0 -> Private
|
||||
/// 1 -> Wired
|
||||
/// 2 -> Wireless
|
||||
/// Valid device network NetIDs.
|
||||
/// The netID is used to separate device networks that shouldn't interact with each other e.g. wireless and wired.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public enum ConnectionType
|
||||
{
|
||||
Private,
|
||||
Wired,
|
||||
Wireless,
|
||||
Apc
|
||||
}
|
||||
|
||||
[DataField("deviceNetId")]
|
||||
public int DeviceNetId { get; set; } = (int)DeviceNetworkConstants.ConnectionType.Private;
|
||||
public ConnectionType DeviceNetId { get; set; } = ConnectionType.Private;
|
||||
|
||||
[DataField("frequency")]
|
||||
public int Frequency { get; set; } = 0;
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
using Content.Server.DeviceNetwork.Systems.Devices;
|
||||
using Robust.Shared.Analyzers;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Server.DeviceNetwork.Components.Devices
|
||||
{
|
||||
[RegisterComponent]
|
||||
[Friend(typeof(ApcNetSwitchSystem))]
|
||||
public class ApcNetSwitchComponent : Component
|
||||
{
|
||||
public override string Name => "ApcNetSwitch";
|
||||
|
||||
[ViewVariables] public bool State;
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,38 @@
|
||||
namespace Content.Server.DeviceNetwork
|
||||
{
|
||||
/// <summary>
|
||||
/// A collection of utilities to help with using device networks
|
||||
/// A collection of constants to help with using device networks
|
||||
/// </summary>
|
||||
public static class DeviceNetworkConstants
|
||||
{
|
||||
public enum ConnectionType
|
||||
{
|
||||
Private,
|
||||
Wired,
|
||||
Wireless
|
||||
}
|
||||
/// <summary>
|
||||
/// Invalid address used for broadcasting
|
||||
/// </summary>
|
||||
public const string NullAddress = "######";
|
||||
|
||||
#region Commands
|
||||
|
||||
/// <summary>
|
||||
/// The key for command names
|
||||
/// E.g. [DeviceNetworkConstants.Command] = "ping"
|
||||
/// </summary>
|
||||
public const string Command = "command";
|
||||
|
||||
/// <summary>
|
||||
/// The command for setting a devices state
|
||||
/// E.g. to turn a light on or off
|
||||
/// </summary>
|
||||
public const string CmdSetState = "set_state";
|
||||
|
||||
#endregion
|
||||
|
||||
#region SetState
|
||||
|
||||
/// <summary>
|
||||
/// Used with the <see cref="CmdSetState"/> command to turn a device on or off
|
||||
/// </summary>
|
||||
public const string StateEnabled = "state_enabled";
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
56
Content.Server/DeviceNetwork/Systems/ApcNetworkSystem.cs
Normal file
56
Content.Server/DeviceNetwork/Systems/ApcNetworkSystem.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
using Content.Server.DeviceNetwork.Components;
|
||||
using Content.Server.NodeContainer;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Content.Server.Power.EntitySystems;
|
||||
using Content.Server.Power.Nodes;
|
||||
|
||||
namespace Content.Server.DeviceNetwork.Systems
|
||||
{
|
||||
[UsedImplicitly]
|
||||
public class ApcNetworkSystem : EntitySystem
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<ApcNetworkComponent, BeforePacketSentEvent>(OnBeforePacketSent);
|
||||
|
||||
SubscribeLocalEvent<ApcNetworkComponent, ExtensionCableSystem.ProviderConnectedEvent>(OnProviderConnected);
|
||||
SubscribeLocalEvent<ApcNetworkComponent, ExtensionCableSystem.ProviderDisconnectedEvent>(OnProviderDisconnected);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if both devices are connected to the same apc
|
||||
/// </summary>
|
||||
private void OnBeforePacketSent(EntityUid uid, ApcNetworkComponent receiver, BeforePacketSentEvent args)
|
||||
{
|
||||
if (!EntityManager.TryGetComponent(args.Sender, out ApcNetworkComponent? sender)) return;
|
||||
|
||||
if (sender.ConnectedNode?.NodeGroup == null || !sender.ConnectedNode.NodeGroup.Equals(receiver.ConnectedNode?.NodeGroup))
|
||||
{
|
||||
args.Cancel();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnProviderConnected(EntityUid uid, ApcNetworkComponent component, ExtensionCableSystem.ProviderConnectedEvent args)
|
||||
{
|
||||
if (!args.Provider.Owner.TryGetComponent(out NodeContainerComponent? nodeContainer)) return;
|
||||
|
||||
if (nodeContainer.TryGetNode("power", out CableNode? node))
|
||||
{
|
||||
component.ConnectedNode = node;
|
||||
}
|
||||
else if (nodeContainer.TryGetNode("output", out CableDeviceNode? deviceNode))
|
||||
{
|
||||
component.ConnectedNode = deviceNode;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void OnProviderDisconnected(EntityUid uid, ApcNetworkComponent component, ExtensionCableSystem.ProviderDisconnectedEvent args)
|
||||
{
|
||||
component.ConnectedNode = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@ namespace Content.Server.DeviceNetwork.Systems
|
||||
{
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
|
||||
private readonly Dictionary<int, List<DeviceNetworkComponent>> _connections = new();
|
||||
private readonly Dictionary<DeviceNetworkComponent.ConnectionType, List<DeviceNetworkComponent>> _connections = new();
|
||||
private readonly Queue<NetworkPacket> _packets = new();
|
||||
|
||||
public override void Initialize()
|
||||
@@ -139,7 +139,7 @@ namespace Content.Server.DeviceNetwork.Systems
|
||||
/// <summary>
|
||||
/// Generates a valid address by randomly generating one and checking if it already exists on the device network with the given device netId.
|
||||
/// </summary>
|
||||
private string GenerateValidAddress(int netId)
|
||||
private string GenerateValidAddress(DeviceNetworkComponent.ConnectionType netId)
|
||||
{
|
||||
var unique = false;
|
||||
var connections = _connections[netId];
|
||||
@@ -154,7 +154,7 @@ namespace Content.Server.DeviceNetwork.Systems
|
||||
return address;
|
||||
}
|
||||
|
||||
private List<DeviceNetworkComponent> ConnectionsForFrequency(int netId, int frequency)
|
||||
private List<DeviceNetworkComponent> ConnectionsForFrequency(DeviceNetworkComponent.ConnectionType netId, int frequency)
|
||||
{
|
||||
if (!_connections.ContainsKey(netId))
|
||||
return new List<DeviceNetworkComponent>();
|
||||
@@ -164,7 +164,7 @@ namespace Content.Server.DeviceNetwork.Systems
|
||||
return result;
|
||||
}
|
||||
|
||||
private bool TryGetConnectionWithAddress(int netId, int frequency, string address, [NotNullWhen(true)] out DeviceNetworkComponent connection)
|
||||
private bool TryGetConnectionWithAddress(DeviceNetworkComponent.ConnectionType netId, int frequency, string address, [NotNullWhen(true)] out DeviceNetworkComponent connection)
|
||||
{
|
||||
var connections = ConnectionsForFrequency(netId, frequency);
|
||||
|
||||
@@ -180,7 +180,7 @@ namespace Content.Server.DeviceNetwork.Systems
|
||||
return false;
|
||||
}
|
||||
|
||||
private List<DeviceNetworkComponent> ConnectionsWithReceiveAll(int netId, int frequency)
|
||||
private List<DeviceNetworkComponent> ConnectionsWithReceiveAll(DeviceNetworkComponent.ConnectionType netId, int frequency)
|
||||
{
|
||||
if (!_connections.ContainsKey(netId))
|
||||
return new List<DeviceNetworkComponent>();
|
||||
@@ -195,7 +195,7 @@ namespace Content.Server.DeviceNetwork.Systems
|
||||
if (!TryGetConnectionWithAddress(packet.NetId, packet.Frequency, packet.Address, out var connection))
|
||||
return;
|
||||
|
||||
var receivers = ConnectionsWithReceiveAll(packet.Frequency, packet.NetId);
|
||||
var receivers = ConnectionsWithReceiveAll(packet.NetId, packet.Frequency);
|
||||
receivers.Add(connection);
|
||||
|
||||
SendToConnections(receivers, packet);
|
||||
@@ -203,7 +203,7 @@ namespace Content.Server.DeviceNetwork.Systems
|
||||
|
||||
private void BroadcastPacket(NetworkPacket packet)
|
||||
{
|
||||
var receivers = ConnectionsForFrequency(packet.Frequency, packet.NetId);
|
||||
var receivers = ConnectionsForFrequency(packet.NetId, packet.Frequency);
|
||||
SendToConnections(receivers, packet);
|
||||
}
|
||||
|
||||
@@ -223,7 +223,7 @@ namespace Content.Server.DeviceNetwork.Systems
|
||||
|
||||
internal struct NetworkPacket
|
||||
{
|
||||
public int NetId;
|
||||
public DeviceNetworkComponent.ConnectionType NetId;
|
||||
public int Frequency;
|
||||
public string Address;
|
||||
public bool Broadcast;
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
using Content.Server.DeviceNetwork.Components;
|
||||
using Content.Server.DeviceNetwork.Components.Devices;
|
||||
using Content.Shared.Interaction;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
|
||||
namespace Content.Server.DeviceNetwork.Systems.Devices
|
||||
{
|
||||
public sealed class ApcNetSwitchSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly DeviceNetworkSystem _deviceNetworkSystem = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<ApcNetSwitchComponent, InteractHandEvent>(OnInteracted);
|
||||
SubscribeLocalEvent<ApcNetSwitchComponent, PacketSentEvent>(OnPackedReceived);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Toggles the state of the switch and sents a <see cref="DeviceNetworkConstants.CmdSetState"/> command with the
|
||||
/// <see cref="DeviceNetworkConstants.StateEnabled"/> value set to state.
|
||||
/// </summary>
|
||||
private void OnInteracted(EntityUid uid, ApcNetSwitchComponent component, InteractHandEvent args)
|
||||
{
|
||||
if (!EntityManager.TryGetComponent(uid, out DeviceNetworkComponent? networkComponent)) return;
|
||||
|
||||
component.State = !component.State;
|
||||
|
||||
var payload = new NetworkPayload
|
||||
{
|
||||
[DeviceNetworkConstants.Command] = DeviceNetworkConstants.CmdSetState,
|
||||
[DeviceNetworkConstants.StateEnabled] = component.State,
|
||||
};
|
||||
|
||||
_deviceNetworkSystem.QueuePacket(uid, DeviceNetworkConstants.NullAddress, networkComponent.Frequency, payload, true);
|
||||
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Listens to the <see cref="DeviceNetworkConstants.CmdSetState"/> command of other switches to sync state
|
||||
/// </summary>
|
||||
private void OnPackedReceived(EntityUid uid, ApcNetSwitchComponent component, PacketSentEvent args)
|
||||
{
|
||||
if (!EntityManager.TryGetComponent(uid, out DeviceNetworkComponent? networkComponent) || args.SenderAddress == networkComponent.Address) return;
|
||||
if (!args.Data.TryGetValue(DeviceNetworkConstants.Command, out string? command) || command != DeviceNetworkConstants.CmdSetState) return;
|
||||
if (!args.Data.TryGetValue(DeviceNetworkConstants.StateEnabled, out bool enabled)) return;
|
||||
|
||||
component.State = enabled;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user