Optimize pipe net appearance updating. (#6469)
Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,81 @@
|
|||||||
|
using Content.Server.NodeContainer;
|
||||||
|
using Content.Server.NodeContainer.EntitySystems;
|
||||||
|
using Content.Server.NodeContainer.Nodes;
|
||||||
|
using Content.Shared.Atmos;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.IoC;
|
||||||
|
using Robust.Shared.Map;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Content.Server.Atmos.Piping.EntitySystems;
|
||||||
|
|
||||||
|
public sealed class AtmosPipeNodeAppearanceSystem : EntitySystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
|
||||||
|
// This should probably just be a directed event, but that would require a weird component that exists only to
|
||||||
|
// receive directed events (*cough* *cough* CableVisComponent *cough*).
|
||||||
|
//
|
||||||
|
// Really I want to target any entity with a PipeConnectorVisualizer or a NodeContainerComponent that contains a
|
||||||
|
// pipe-node. But I don't know of nice way of doing that.
|
||||||
|
SubscribeLocalEvent<NodeGroupsRebuilt>(OnNodeUpdate);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnNodeUpdate(ref NodeGroupsRebuilt ev)
|
||||||
|
{
|
||||||
|
UpdateAppearance(ev.NodeOwner);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateAppearance(EntityUid uid, AppearanceComponent? appearance = null, NodeContainerComponent? container = null,
|
||||||
|
TransformComponent? xform = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(uid, ref appearance, ref container, ref xform, false))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!_mapManager.TryGetGrid(xform.GridID, out var grid))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// get connected entities
|
||||||
|
var anyPipeNodes = false;
|
||||||
|
HashSet<EntityUid> connected = new();
|
||||||
|
foreach (var node in container.Nodes.Values)
|
||||||
|
{
|
||||||
|
if (node is not PipeNode)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
anyPipeNodes = true;
|
||||||
|
|
||||||
|
foreach (var connectedNode in node.ReachableNodes)
|
||||||
|
{
|
||||||
|
if (connectedNode is PipeNode)
|
||||||
|
connected.Add(connectedNode.Owner);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!anyPipeNodes)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// find the cardinal directions of any connected entities
|
||||||
|
var netConnectedDirections = PipeDirection.None;
|
||||||
|
var tile = grid.TileIndicesFor(xform.Coordinates);
|
||||||
|
foreach (var neighbour in connected)
|
||||||
|
{
|
||||||
|
var otherTile = grid.TileIndicesFor(Transform(neighbour).Coordinates);
|
||||||
|
|
||||||
|
netConnectedDirections |= (otherTile - tile) switch
|
||||||
|
{
|
||||||
|
(0, 1) => PipeDirection.North,
|
||||||
|
(0, -1) => PipeDirection.South,
|
||||||
|
(1, 0) => PipeDirection.East,
|
||||||
|
(-1, 0) => PipeDirection.West,
|
||||||
|
_ => PipeDirection.None
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
appearance.SetData(PipeVisuals.VisualState, netConnectedDirections);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
using Content.Server.NodeContainer.Nodes;
|
using Content.Server.NodeContainer.Nodes;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.IoC;
|
||||||
|
|
||||||
namespace Content.Server.NodeContainer.EntitySystems
|
namespace Content.Server.NodeContainer.EntitySystems
|
||||||
{
|
{
|
||||||
@@ -9,8 +10,10 @@ namespace Content.Server.NodeContainer.EntitySystems
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <seealso cref="NodeGroupSystem"/>
|
/// <seealso cref="NodeGroupSystem"/>
|
||||||
[UsedImplicitly]
|
[UsedImplicitly]
|
||||||
public class NodeContainerSystem : EntitySystem
|
public sealed class NodeContainerSystem : EntitySystem
|
||||||
{
|
{
|
||||||
|
[Dependency] private readonly NodeGroupSystem _nodeGroupSystem = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
@@ -22,44 +25,50 @@ namespace Content.Server.NodeContainer.EntitySystems
|
|||||||
SubscribeLocalEvent<NodeContainerComponent, RotateEvent>(OnRotateEvent);
|
SubscribeLocalEvent<NodeContainerComponent, RotateEvent>(OnRotateEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void OnInitEvent(EntityUid uid, NodeContainerComponent component, ComponentInit args)
|
private void OnInitEvent(EntityUid uid, NodeContainerComponent component, ComponentInit args)
|
||||||
{
|
{
|
||||||
foreach (var (key, node) in component.Nodes)
|
foreach (var (key, node) in component.Nodes)
|
||||||
{
|
{
|
||||||
node.Name = key;
|
node.Name = key;
|
||||||
node.Initialize(component.Owner);
|
node.Initialize(component.Owner, EntityManager);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void OnStartupEvent(EntityUid uid, NodeContainerComponent component, ComponentStartup args)
|
private void OnStartupEvent(EntityUid uid, NodeContainerComponent component, ComponentStartup args)
|
||||||
{
|
{
|
||||||
foreach (var node in component.Nodes.Values)
|
foreach (var node in component.Nodes.Values)
|
||||||
{
|
{
|
||||||
node.OnContainerStartup();
|
_nodeGroupSystem.QueueReflood(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void OnShutdownEvent(EntityUid uid, NodeContainerComponent component, ComponentShutdown args)
|
private void OnShutdownEvent(EntityUid uid, NodeContainerComponent component, ComponentShutdown args)
|
||||||
{
|
{
|
||||||
foreach (var node in component.Nodes.Values)
|
foreach (var node in component.Nodes.Values)
|
||||||
{
|
{
|
||||||
node.OnContainerShutdown();
|
_nodeGroupSystem.QueueNodeRemove(node);
|
||||||
|
node.Deleting = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void OnAnchorStateChanged(
|
private void OnAnchorStateChanged(
|
||||||
EntityUid uid,
|
EntityUid uid,
|
||||||
NodeContainerComponent component,
|
NodeContainerComponent component,
|
||||||
ref AnchorStateChangedEvent args)
|
ref AnchorStateChangedEvent args)
|
||||||
{
|
{
|
||||||
foreach (var node in component.Nodes.Values)
|
foreach (var node in component.Nodes.Values)
|
||||||
{
|
{
|
||||||
node.AnchorUpdate();
|
if (!node.NeedAnchored)
|
||||||
node.AnchorStateChanged();
|
continue;
|
||||||
|
|
||||||
|
if (args.Anchored)
|
||||||
|
_nodeGroupSystem.QueueReflood(node);
|
||||||
|
else
|
||||||
|
_nodeGroupSystem.QueueNodeRemove(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void OnRotateEvent(EntityUid uid, NodeContainerComponent container, ref RotateEvent ev)
|
private void OnRotateEvent(EntityUid uid, NodeContainerComponent container, ref RotateEvent ev)
|
||||||
{
|
{
|
||||||
if (ev.NewRotation == ev.OldRotation)
|
if (ev.NewRotation == ev.OldRotation)
|
||||||
{
|
{
|
||||||
@@ -68,8 +77,11 @@ namespace Content.Server.NodeContainer.EntitySystems
|
|||||||
|
|
||||||
foreach (var node in container.Nodes.Values)
|
foreach (var node in container.Nodes.Values)
|
||||||
{
|
{
|
||||||
if (node is not IRotatableNode rotatableNode) continue;
|
if (node is not IRotatableNode rotatableNode)
|
||||||
rotatableNode.RotateEvent(ref ev);
|
continue;
|
||||||
|
|
||||||
|
if (rotatableNode.RotateEvent(ref ev))
|
||||||
|
_nodeGroupSystem.QueueReflood(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -245,14 +245,22 @@ namespace Content.Server.NodeContainer.EntitySystems
|
|||||||
_toRemake.Clear();
|
_toRemake.Clear();
|
||||||
_toRemove.Clear();
|
_toRemove.Clear();
|
||||||
|
|
||||||
|
// notify entities that node groups have been updated, so they can do things like update their visuals.
|
||||||
|
HashSet<EntityUid> entities = new();
|
||||||
foreach (var group in newGroups)
|
foreach (var group in newGroups)
|
||||||
{
|
{
|
||||||
foreach (var node in group.Nodes)
|
foreach (var node in group.Nodes)
|
||||||
{
|
{
|
||||||
node.OnPostRebuild();
|
entities.Add(node.Owner);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (var uid in entities)
|
||||||
|
{
|
||||||
|
var ev = new NodeGroupsRebuilt(uid);
|
||||||
|
RaiseLocalEvent(uid, ref ev, true);
|
||||||
|
}
|
||||||
|
|
||||||
_sawmill.Debug($"Updated node groups in {sw.Elapsed.TotalMilliseconds}ms. {newGroups.Count} new groups, {refloodCount} nodes processed.");
|
_sawmill.Debug($"Updated node groups in {sw.Elapsed.TotalMilliseconds}ms. {newGroups.Count} new groups, {refloodCount} nodes processed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -402,4 +410,19 @@ namespace Content.Server.NodeContainer.EntitySystems
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event raised after node groups have been updated. Directed at any entity with a <see
|
||||||
|
/// cref="NodeContainerComponent"/> that had a relevant node.
|
||||||
|
/// </summary>
|
||||||
|
[ByRefEvent]
|
||||||
|
public readonly struct NodeGroupsRebuilt
|
||||||
|
{
|
||||||
|
public readonly EntityUid NodeOwner;
|
||||||
|
|
||||||
|
public NodeGroupsRebuilt(EntityUid nodeOwner)
|
||||||
|
{
|
||||||
|
NodeOwner = nodeOwner;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,7 +54,6 @@ namespace Content.Server.NodeContainer.NodeGroups
|
|||||||
{
|
{
|
||||||
var pipeNode = (PipeNode) node;
|
var pipeNode = (PipeNode) node;
|
||||||
_pipes.Add(pipeNode);
|
_pipes.Add(pipeNode);
|
||||||
pipeNode.JoinPipeNet(this);
|
|
||||||
Air.Volume += pipeNode.Volume;
|
Air.Volume += pipeNode.Volume;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ namespace Content.Server.NodeContainer.Nodes
|
|||||||
public interface IRotatableNode
|
public interface IRotatableNode
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Rotates this <see cref="Node"/>.
|
/// Rotates this <see cref="Node"/>. Returns true if the node's connections need to be updated.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void RotateEvent(ref RotateEvent ev);
|
bool RotateEvent(ref RotateEvent ev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ namespace Content.Server.NodeContainer.Nodes
|
|||||||
|
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
[DataField("needAnchored")]
|
[DataField("needAnchored")]
|
||||||
private bool NeedAnchored { get; } = true;
|
public bool NeedAnchored { get; } = true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Prevents a node from being used by other nodes while midway through removal.
|
/// Prevents a node from being used by other nodes while midway through removal.
|
||||||
@@ -83,70 +83,11 @@ namespace Content.Server.NodeContainer.Nodes
|
|||||||
/// Invoked when the owning <see cref="NodeContainerComponent"/> is initialized.
|
/// Invoked when the owning <see cref="NodeContainerComponent"/> is initialized.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="owner">The owning entity.</param>
|
/// <param name="owner">The owning entity.</param>
|
||||||
public virtual void Initialize(EntityUid owner)
|
public virtual void Initialize(EntityUid owner, IEntityManager entMan)
|
||||||
{
|
{
|
||||||
Owner = owner;
|
Owner = owner;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Invoked when the owning <see cref="NodeContainerComponent"/> is started.
|
|
||||||
/// </summary>
|
|
||||||
public virtual void OnContainerStartup()
|
|
||||||
{
|
|
||||||
EntitySystem.Get<NodeGroupSystem>().QueueReflood(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Immediately create a single-node node group for this node if it does not have one yet.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// This can be useful for nodes like pipes
|
|
||||||
/// that need immediate access to their node group to set parameters like node volume.
|
|
||||||
/// The node group created by this function (if necessary) will still update and form new,
|
|
||||||
/// merged groups later if necessary.
|
|
||||||
/// Set parameters like pipe net volume should then be transferred/merged there.
|
|
||||||
/// </remarks>
|
|
||||||
public void CreateSingleNetImmediate()
|
|
||||||
{
|
|
||||||
EntitySystem.Get<NodeGroupSystem>().CreateSingleNetImmediate(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AnchorUpdate()
|
|
||||||
{
|
|
||||||
if (Anchored)
|
|
||||||
{
|
|
||||||
EntitySystem.Get<NodeGroupSystem>().QueueReflood(this);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
EntitySystem.Get<NodeGroupSystem>().QueueNodeRemove(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Called when the anchored state of the owning entity changes.
|
|
||||||
/// </summary>
|
|
||||||
public virtual void AnchorStateChanged()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Called after the parent node group has been rebuilt.
|
|
||||||
/// </summary>
|
|
||||||
public virtual void OnPostRebuild()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Called when the owning <see cref="NodeContainerComponent"/> is shut down.
|
|
||||||
/// </summary>
|
|
||||||
public virtual void OnContainerShutdown()
|
|
||||||
{
|
|
||||||
Deleting = true;
|
|
||||||
EntitySystem.Get<NodeGroupSystem>().QueueNodeRemove(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// How this node will attempt to find other reachable <see cref="Node"/>s to group with.
|
/// How this node will attempt to find other reachable <see cref="Node"/>s to group with.
|
||||||
/// Returns a set of <see cref="Node"/>s to consider grouping with. Should not return this current <see cref="Node"/>.
|
/// Returns a set of <see cref="Node"/>s to consider grouping with. Should not return this current <see cref="Node"/>.
|
||||||
|
|||||||
@@ -21,8 +21,6 @@ namespace Content.Server.NodeContainer.Nodes
|
|||||||
[DataDefinition]
|
[DataDefinition]
|
||||||
public class PipeNode : Node, IGasMixtureHolder, IRotatableNode
|
public class PipeNode : Node, IGasMixtureHolder, IRotatableNode
|
||||||
{
|
{
|
||||||
private PipeDirection _connectedDirections;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The directions in which this pipe can connect to other pipes around it.
|
/// The directions in which this pipe can connect to other pipes around it.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -56,21 +54,6 @@ namespace Content.Server.NodeContainer.Nodes
|
|||||||
EntitySystem.Get<NodeGroupSystem>().QueueRemakeGroup((BaseNodeGroup) NodeGroup);
|
EntitySystem.Get<NodeGroupSystem>().QueueRemakeGroup((BaseNodeGroup) NodeGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The directions in which this node is connected to other nodes.
|
|
||||||
/// Used by <see cref="PipeVisualState"/>.
|
|
||||||
/// </summary>
|
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
|
||||||
public PipeDirection ConnectedDirections
|
|
||||||
{
|
|
||||||
get => _connectedDirections;
|
|
||||||
private set
|
|
||||||
{
|
|
||||||
_connectedDirections = value;
|
|
||||||
UpdateAppearance();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether this node can connect to others or not.
|
/// Whether this node can connect to others or not.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -124,30 +107,37 @@ namespace Content.Server.NodeContainer.Nodes
|
|||||||
|
|
||||||
private const float DefaultVolume = 200f;
|
private const float DefaultVolume = 200f;
|
||||||
|
|
||||||
public override void OnContainerStartup()
|
public override void Initialize(EntityUid owner, IEntityManager entMan)
|
||||||
{
|
{
|
||||||
base.OnContainerStartup();
|
base.Initialize(owner, entMan);
|
||||||
OnConnectedDirectionsNeedsUpdating();
|
|
||||||
|
if (!RotationsEnabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var xform = entMan.GetComponent<TransformComponent>(owner);
|
||||||
|
CurrentPipeDirection = _originalPipeDirection.RotatePipeDirection(xform.LocalRotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnContainerShutdown()
|
bool IRotatableNode.RotateEvent(ref RotateEvent ev)
|
||||||
{
|
{
|
||||||
base.OnContainerShutdown();
|
if (_originalPipeDirection == PipeDirection.Fourway)
|
||||||
UpdateAdjacentConnectedDirections();
|
return false;
|
||||||
|
|
||||||
|
// update valid pipe direction
|
||||||
|
if (!RotationsEnabled)
|
||||||
|
{
|
||||||
|
if (CurrentPipeDirection == _originalPipeDirection)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
CurrentPipeDirection = _originalPipeDirection;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CurrentPipeDirection = _originalPipeDirection.RotatePipeDirection(ev.NewRotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void JoinPipeNet(IPipeNet pipeNet)
|
// node connections need to be updated
|
||||||
{
|
return true;
|
||||||
OnConnectedDirectionsNeedsUpdating();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Rotates the <see cref="PipeDirection"/> when the entity is rotated, and re-calculates the <see cref="IPipeNet"/>.
|
|
||||||
/// </summary>
|
|
||||||
void IRotatableNode.RotateEvent(ref RotateEvent ev)
|
|
||||||
{
|
|
||||||
OnConnectedDirectionsNeedsUpdating();
|
|
||||||
UpdateAppearance();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override IEnumerable<Node> GetReachableNodes(TransformComponent xform,
|
public override IEnumerable<Node> GetReachableNodes(TransformComponent xform,
|
||||||
@@ -229,104 +219,5 @@ namespace Content.Server.NodeContainer.Nodes
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Updates the <see cref="ConnectedDirections"/> of this and all sorrounding pipes.
|
|
||||||
/// Also updates CurrentPipeDirection.
|
|
||||||
/// </summary>
|
|
||||||
private void OnConnectedDirectionsNeedsUpdating()
|
|
||||||
{
|
|
||||||
if (RotationsEnabled)
|
|
||||||
{
|
|
||||||
CurrentPipeDirection = _originalPipeDirection.RotatePipeDirection(IoCManager.Resolve<IEntityManager>().GetComponent<TransformComponent>(Owner).LocalRotation);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CurrentPipeDirection = _originalPipeDirection;
|
|
||||||
}
|
|
||||||
UpdateConnectedDirections();
|
|
||||||
UpdateAdjacentConnectedDirections();
|
|
||||||
UpdateAppearance();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Checks what directions there are connectable pipes in, to update <see cref="ConnectedDirections"/>.
|
|
||||||
/// </summary>
|
|
||||||
private void UpdateConnectedDirections()
|
|
||||||
{
|
|
||||||
ConnectedDirections = PipeDirection.None;
|
|
||||||
|
|
||||||
var entMan = IoCManager.Resolve<IEntityManager>();
|
|
||||||
var xform = entMan.GetComponent<TransformComponent>(Owner);
|
|
||||||
if (!IoCManager.Resolve<IMapManager>().TryGetGrid(xform.GridID, out var grid))
|
|
||||||
return;
|
|
||||||
var pos = grid.WorldToTile(xform.WorldPosition);
|
|
||||||
var query = entMan.GetEntityQuery<NodeContainerComponent>();
|
|
||||||
|
|
||||||
for (var i = 0; i < PipeDirectionHelpers.AllPipeDirections; i++)
|
|
||||||
{
|
|
||||||
var pipeDir = (PipeDirection) (1 << i);
|
|
||||||
|
|
||||||
if (!CurrentPipeDirection.HasDirection(pipeDir))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
foreach (var pipe in LinkableNodesInDirection(pos, pipeDir, grid, query))
|
|
||||||
{
|
|
||||||
if (pipe.Connectable(entMan) && pipe.NodeGroupID == NodeGroupID)
|
|
||||||
{
|
|
||||||
ConnectedDirections |= pipeDir;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Calls <see cref="UpdateConnectedDirections"/> on all adjacent pipes,
|
|
||||||
/// to update their <see cref="ConnectedDirections"/> when this pipe is changed.
|
|
||||||
/// </summary>
|
|
||||||
private void UpdateAdjacentConnectedDirections()
|
|
||||||
{
|
|
||||||
var entMan = IoCManager.Resolve<IEntityManager>();
|
|
||||||
var xform = entMan.GetComponent<TransformComponent>(Owner);
|
|
||||||
if (!IoCManager.Resolve<IMapManager>().TryGetGrid(xform.GridID, out var grid))
|
|
||||||
return;
|
|
||||||
var pos = grid.WorldToTile(xform.WorldPosition);
|
|
||||||
var query = entMan.GetEntityQuery<NodeContainerComponent>();
|
|
||||||
|
|
||||||
for (var i = 0; i < PipeDirectionHelpers.PipeDirections; i++)
|
|
||||||
{
|
|
||||||
var pipeDir = (PipeDirection) (1 << i);
|
|
||||||
|
|
||||||
foreach (var pipe in LinkableNodesInDirection(pos, pipeDir, grid, query))
|
|
||||||
{
|
|
||||||
pipe.UpdateConnectedDirections();
|
|
||||||
pipe.UpdateAppearance();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Updates the <see cref="AppearanceComponent"/>.
|
|
||||||
/// Gets the combined <see cref="ConnectedDirections"/> of every pipe on this entity, so the visualizer on this entity can draw the pipe connections.
|
|
||||||
/// </summary>
|
|
||||||
private void UpdateAppearance()
|
|
||||||
{
|
|
||||||
if (!IoCManager.Resolve<IEntityManager>().TryGetComponent(Owner, out AppearanceComponent? appearance)
|
|
||||||
|| !IoCManager.Resolve<IEntityManager>().TryGetComponent(Owner, out NodeContainerComponent? container))
|
|
||||||
return;
|
|
||||||
|
|
||||||
var netConnectedDirections = PipeDirection.None;
|
|
||||||
|
|
||||||
foreach (var node in container.Nodes.Values)
|
|
||||||
{
|
|
||||||
if (node is PipeNode pipe)
|
|
||||||
{
|
|
||||||
netConnectedDirections |= pipe.ConnectedDirections;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
appearance.SetData(PipeVisuals.VisualState, netConnectedDirections);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using Content.Server.NodeContainer;
|
using Content.Server.NodeContainer;
|
||||||
using Content.Server.NodeContainer.EntitySystems;
|
using Content.Server.NodeContainer.EntitySystems;
|
||||||
using Content.Server.Power.Components;
|
using Content.Server.Power.Components;
|
||||||
@@ -16,45 +17,26 @@ namespace Content.Server.Power.EntitySystems
|
|||||||
{
|
{
|
||||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||||
|
|
||||||
private readonly HashSet<EntityUid> _toUpdate = new();
|
|
||||||
|
|
||||||
public void QueueUpdate(EntityUid uid)
|
|
||||||
{
|
|
||||||
_toUpdate.Add(uid);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
|
|
||||||
UpdatesAfter.Add(typeof(NodeGroupSystem));
|
SubscribeLocalEvent<CableVisComponent, NodeGroupsRebuilt>(UpdateAppearance);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Update(float frameTime)
|
private void UpdateAppearance(EntityUid uid, CableVisComponent cableVis, ref NodeGroupsRebuilt args)
|
||||||
{
|
{
|
||||||
base.Update(frameTime);
|
|
||||||
|
|
||||||
foreach (var uid in _toUpdate)
|
|
||||||
{
|
|
||||||
if (!EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer)
|
|
||||||
|| !EntityManager.TryGetComponent(uid, out CableVisComponent? cableVis)
|
|
||||||
|| !EntityManager.TryGetComponent(uid, out AppearanceComponent? appearance))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cableVis.Node == null)
|
if (cableVis.Node == null)
|
||||||
continue;
|
return;
|
||||||
|
|
||||||
|
if (!TryComp(uid, out NodeContainerComponent? nodeContainer) || !TryComp(uid, out AppearanceComponent? appearance))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var transform = Transform(uid);
|
||||||
|
if (!_mapManager.TryGetGrid(transform.GridID, out var grid))
|
||||||
|
return;
|
||||||
|
|
||||||
var mask = WireVisDirFlags.None;
|
var mask = WireVisDirFlags.None;
|
||||||
|
|
||||||
var transform = EntityManager.GetComponent<TransformComponent>(uid);
|
|
||||||
|
|
||||||
// Only valid grids allowed.
|
|
||||||
if(!transform.GridID.IsValid())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
var grid = _mapManager.GetGrid(transform.GridID);
|
|
||||||
var tile = grid.TileIndicesFor(transform.Coordinates);
|
var tile = grid.TileIndicesFor(transform.Coordinates);
|
||||||
var node = nodeContainer.GetNode<CableNode>(cableVis.Node);
|
var node = nodeContainer.GetNode<CableNode>(cableVis.Node);
|
||||||
|
|
||||||
@@ -63,10 +45,7 @@ namespace Content.Server.Power.EntitySystems
|
|||||||
if (reachable is not CableNode)
|
if (reachable is not CableNode)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var otherTransform = EntityManager.GetComponent<TransformComponent>(reachable.Owner);
|
var otherTransform = Transform(reachable.Owner);
|
||||||
if (otherTransform.GridID != grid.Index)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
var otherTile = grid.TileIndicesFor(otherTransform.Coordinates);
|
var otherTile = grid.TileIndicesFor(otherTransform.Coordinates);
|
||||||
var diff = otherTile - tile;
|
var diff = otherTile - tile;
|
||||||
|
|
||||||
@@ -82,8 +61,5 @@ namespace Content.Server.Power.EntitySystems
|
|||||||
|
|
||||||
appearance.SetData(WireVisVisuals.ConnectedMask, mask);
|
appearance.SetData(WireVisVisuals.ConnectedMask, mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
_toUpdate.Clear();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Content.Server.NodeContainer;
|
using Content.Server.NodeContainer;
|
||||||
using Content.Server.NodeContainer.Nodes;
|
using Content.Server.NodeContainer.Nodes;
|
||||||
using Content.Server.Power.EntitySystems;
|
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
using Robust.Shared.Maths;
|
using Robust.Shared.Maths;
|
||||||
@@ -70,12 +69,5 @@ namespace Content.Server.Power.Nodes
|
|||||||
yield return node;
|
yield return node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnPostRebuild()
|
|
||||||
{
|
|
||||||
base.OnPostRebuild();
|
|
||||||
|
|
||||||
EntitySystem.Get<CableVisSystem>().QueueUpdate(Owner);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user