Reduce node resolves (#6435)

This commit is contained in:
Leon Friedrich
2022-02-07 01:10:33 +13:00
committed by GitHub
parent b82926e324
commit 1e10314900
12 changed files with 195 additions and 147 deletions

View File

@@ -1,9 +1,8 @@
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.Nodes;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.Map;
using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Server.Electrocution namespace Content.Server.Electrocution
@@ -16,10 +15,13 @@ namespace Content.Server.Electrocution
[DataField("node")] [DataField("node")]
public string NodeName = default!; public string NodeName = default!;
public override IEnumerable<Node> GetReachableNodes() public override IEnumerable<Node> GetReachableNodes(TransformComponent xform,
EntityQuery<NodeContainerComponent> nodeQuery,
EntityQuery<TransformComponent> xformQuery,
IMapGrid? grid,
IEntityManager entMan)
{ {
var ent = IoCManager.Resolve<IEntityManager>(); if (!nodeQuery.TryGetComponent(CableEntity, out var nodeContainer))
if (!ent.TryGetComponent(CableEntity, out NodeContainerComponent? nodeContainer))
yield break; yield break;
if (nodeContainer.TryGetNode(NodeName, out Node? node)) if (nodeContainer.TryGetNode(NodeName, out Node? node))

View File

@@ -12,6 +12,7 @@ using Robust.Shared.Enums;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Log; using Robust.Shared.Log;
using Robust.Shared.Map;
using Robust.Shared.Maths; using Robust.Shared.Maths;
using Robust.Shared.Utility; using Robust.Shared.Utility;
@@ -28,6 +29,7 @@ namespace Content.Server.NodeContainer.EntitySystems
[Dependency] private readonly IAdminManager _adminManager = default!; [Dependency] private readonly IAdminManager _adminManager = default!;
[Dependency] private readonly INodeGroupFactory _nodeGroupFactory = default!; [Dependency] private readonly INodeGroupFactory _nodeGroupFactory = default!;
[Dependency] private readonly ILogManager _logManager = default!; [Dependency] private readonly ILogManager _logManager = default!;
[Dependency] private readonly IMapManager _mapManager = default!;
private readonly List<int> _visDeletes = new(); private readonly List<int> _visDeletes = new();
private readonly List<BaseNodeGroup> _visSends = new(); private readonly List<BaseNodeGroup> _visSends = new();
@@ -141,6 +143,9 @@ namespace Content.Server.NodeContainer.EntitySystems
var sw = Stopwatch.StartNew(); var sw = Stopwatch.StartNew();
var xformQuery = EntityManager.GetEntityQuery<TransformComponent>();
var nodeQuery = EntityManager.GetEntityQuery<NodeContainerComponent>();
foreach (var toRemove in _toRemove) foreach (var toRemove in _toRemove)
{ {
if (toRemove.NodeGroup == null) if (toRemove.NodeGroup == null)
@@ -182,7 +187,11 @@ namespace Content.Server.NodeContainer.EntitySystems
QueueRemakeGroup((BaseNodeGroup) node.NodeGroup); QueueRemakeGroup((BaseNodeGroup) node.NodeGroup);
} }
foreach (var compatible in GetCompatibleNodes(node)) // GetCompatibleNodes will involve getting the transform & grid as most connection requirements are
// based on position & anchored neighbours However, here more than one node could be attached to the
// same parent. So there is probably a better way of doing this.
foreach (var compatible in GetCompatibleNodes(node, xformQuery, nodeQuery))
{ {
ClearReachableIfNecessary(compatible); ClearReachableIfNecessary(compatible);
@@ -303,14 +312,23 @@ namespace Content.Server.NodeContainer.EntitySystems
return allNodes; return allNodes;
} }
private static IEnumerable<Node> GetCompatibleNodes(Node node) private IEnumerable<Node> GetCompatibleNodes(Node node, EntityQuery<TransformComponent> xformQuery, EntityQuery<NodeContainerComponent> nodeQuery)
{ {
foreach (var reachable in node.GetReachableNodes()) var xform = xformQuery.GetComponent(node.Owner);
_mapManager.TryGetGrid(xform.GridID, out var grid);
if (!node.Connectable(EntityManager, xform))
yield break;
foreach (var reachable in node.GetReachableNodes(xform, nodeQuery, xformQuery, grid, EntityManager))
{ {
DebugTools.Assert(reachable != node, "GetReachableNodes() should not include self."); DebugTools.Assert(reachable != node, "GetReachableNodes() should not include self.");
if (reachable.Connectable && reachable.NodeGroupID == node.NodeGroupID) if (reachable.NodeGroupID == node.NodeGroupID
&& reachable.Connectable(EntityManager, xformQuery.GetComponent(reachable.Owner)))
{
yield return reachable; yield return reachable;
}
} }
} }

View File

@@ -12,16 +12,18 @@ namespace Content.Server.NodeContainer.Nodes
[DataDefinition] [DataDefinition]
public class AdjacentNode : Node public class AdjacentNode : Node
{ {
public override IEnumerable<Node> GetReachableNodes() public override IEnumerable<Node> GetReachableNodes(TransformComponent xform,
EntityQuery<NodeContainerComponent> nodeQuery,
EntityQuery<TransformComponent> xformQuery,
IMapGrid? grid,
IEntityManager entMan)
{ {
if (!IoCManager.Resolve<IEntityManager>().GetComponent<TransformComponent>(Owner).Anchored) if (!xform.Anchored || grid == null)
yield break; yield break;
var entMan = IoCManager.Resolve<IEntityManager>(); var gridIndex = grid.TileIndicesFor(xform.Coordinates);
var grid = IoCManager.Resolve<IMapManager>().GetGrid(IoCManager.Resolve<IEntityManager>().GetComponent<TransformComponent>(Owner).GridID);
var gridIndex = grid.TileIndicesFor(IoCManager.Resolve<IEntityManager>().GetComponent<TransformComponent>(Owner).Coordinates);
foreach (var (_, node) in NodeHelpers.GetCardinalNeighborNodes(entMan, grid, gridIndex)) foreach (var (_, node) in NodeHelpers.GetCardinalNeighborNodes(nodeQuery, grid, gridIndex))
{ {
if (node != this) if (node != this)
yield return node; yield return node;

View File

@@ -3,6 +3,7 @@ using Content.Server.NodeContainer.EntitySystems;
using Content.Server.NodeContainer.NodeGroups; using Content.Server.NodeContainer.NodeGroups;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Map;
using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables; using Robust.Shared.ViewVariables;
@@ -36,7 +37,20 @@ namespace Content.Server.NodeContainer.Nodes
/// <summary> /// <summary>
/// If this node should be considered for connection by other nodes. /// If this node should be considered for connection by other nodes.
/// </summary> /// </summary>
public bool Connectable => !Deleting && Anchored; public virtual bool Connectable(IEntityManager entMan, TransformComponent? xform = null)
{
if (Deleting)
return false;
if (entMan.IsQueuedForDeletion(Owner))
return false;
if (!NeedAnchored)
return true;
xform ??= entMan.GetComponent<TransformComponent>(Owner);
return xform.Anchored;
}
protected bool Anchored => !NeedAnchored || IoCManager.Resolve<IEntityManager>().GetComponent<TransformComponent>(Owner).Anchored; protected bool Anchored => !NeedAnchored || IoCManager.Resolve<IEntityManager>().GetComponent<TransformComponent>(Owner).Anchored;
@@ -145,6 +159,10 @@ namespace Content.Server.NodeContainer.Nodes
/// of this asymmetric relation are made to manually update with <see cref="NodeGroupSystem.QueueReflood"/>. /// of this asymmetric relation are made to manually update with <see cref="NodeGroupSystem.QueueReflood"/>.
/// </para> /// </para>
/// </remarks> /// </remarks>
public abstract IEnumerable<Node> GetReachableNodes(); public abstract IEnumerable<Node> GetReachableNodes(TransformComponent xform,
EntityQuery<NodeContainerComponent> nodeQuery,
EntityQuery<TransformComponent> xformQuery,
IMapGrid? grid,
IEntityManager entMan);
} }
} }

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
@@ -12,11 +12,11 @@ namespace Content.Server.NodeContainer.Nodes
/// </summary> /// </summary>
public static class NodeHelpers public static class NodeHelpers
{ {
public static IEnumerable<Node> GetNodesInTile(IEntityManager entMan, IMapGrid grid, Vector2i coords) public static IEnumerable<Node> GetNodesInTile(EntityQuery<NodeContainerComponent> nodeQuery, IMapGrid grid, Vector2i coords)
{ {
foreach (var entityUid in grid.GetAnchoredEntities(coords)) foreach (var entityUid in grid.GetAnchoredEntities(coords))
{ {
if (!entMan.TryGetComponent(entityUid, out NodeContainerComponent? container)) if (!nodeQuery.TryGetComponent(entityUid, out var container))
continue; continue;
foreach (var node in container.Nodes.Values) foreach (var node in container.Nodes.Values)
@@ -27,14 +27,14 @@ namespace Content.Server.NodeContainer.Nodes
} }
public static IEnumerable<(Direction dir, Node node)> GetCardinalNeighborNodes( public static IEnumerable<(Direction dir, Node node)> GetCardinalNeighborNodes(
IEntityManager entMan, EntityQuery<NodeContainerComponent> nodeQuery,
IMapGrid grid, IMapGrid grid,
Vector2i coords, Vector2i coords,
bool includeSameTile = true) bool includeSameTile = true)
{ {
foreach (var (dir, entityUid) in GetCardinalNeighborCells(grid, coords, includeSameTile)) foreach (var (dir, entityUid) in GetCardinalNeighborCells(grid, coords, includeSameTile))
{ {
if (!entMan.TryGetComponent(entityUid, out NodeContainerComponent? container)) if (!nodeQuery.TryGetComponent(entityUid, out var container))
continue; continue;
foreach (var node in container.Nodes.Values) foreach (var node in container.Nodes.Values)
@@ -68,22 +68,5 @@ namespace Content.Server.NodeContainer.Nodes
foreach (var uid in grid.GetAnchoredEntities(coords + (-1, 0))) foreach (var uid in grid.GetAnchoredEntities(coords + (-1, 0)))
yield return (Direction.West, uid); yield return (Direction.West, uid);
} }
public static Vector2i TileOffsetForDir(Direction dir)
{
return dir switch
{
Direction.Invalid => (0, 0),
Direction.South => (0, -1),
Direction.SouthEast => (1, -1),
Direction.East => (1, 0),
Direction.NorthEast => (1, 1),
Direction.North => (0, 1),
Direction.NorthWest => (-1, 1),
Direction.West => (-1, 0),
Direction.SouthWest => (-1, -1),
_ => throw new ArgumentOutOfRangeException(nameof(dir), dir, null)
};
}
} }
} }

View File

@@ -7,6 +7,7 @@ using Content.Shared.Atmos;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Map; using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.Utility; using Robust.Shared.Utility;
using Robust.Shared.ViewVariables; using Robust.Shared.ViewVariables;
@@ -89,6 +90,11 @@ namespace Content.Server.NodeContainer.Nodes
[DataField("connectionsEnabled")] [DataField("connectionsEnabled")]
private bool _connectionsEnabled = true; private bool _connectionsEnabled = true;
public override bool Connectable(IEntityManager entMan, TransformComponent? xform = null)
{
return _connectionsEnabled && base.Connectable(entMan, xform);
}
[DataField("rotationsEnabled")] [DataField("rotationsEnabled")]
public bool RotationsEnabled { get; set; } = true; public bool RotationsEnabled { get; set; } = true;
@@ -144,25 +150,16 @@ namespace Content.Server.NodeContainer.Nodes
UpdateAppearance(); UpdateAppearance();
} }
public override IEnumerable<Node> GetReachableNodes() public override IEnumerable<Node> GetReachableNodes(TransformComponent xform,
EntityQuery<NodeContainerComponent> nodeQuery,
EntityQuery<TransformComponent> xformQuery,
IMapGrid? grid,
IEntityManager entMan)
{ {
for (var i = 0; i < PipeDirectionHelpers.AllPipeDirections; i++) if (_alwaysReachable != null)
{
var pipeDir = (PipeDirection) (1 << i);
if (!CurrentPipeDirection.HasDirection(pipeDir))
continue;
foreach (var pipe in LinkableNodesInDirection(pipeDir))
{
yield return pipe;
}
}
if(_alwaysReachable != null)
{ {
var remQ = new RemQueue<PipeNode>(); var remQ = new RemQueue<PipeNode>();
foreach(var pipe in _alwaysReachable) foreach (var pipe in _alwaysReachable)
{ {
if (pipe.Deleting) if (pipe.Deleting)
{ {
@@ -171,64 +168,58 @@ namespace Content.Server.NodeContainer.Nodes
yield return pipe; yield return pipe;
} }
foreach(var pipe in remQ) foreach (var pipe in remQ)
{ {
_alwaysReachable.Remove(pipe); _alwaysReachable.Remove(pipe);
} }
} }
if (!xform.Anchored || grid == null)
yield break;
var pos = grid.TileIndicesFor(xform.Coordinates);
for (var i = 0; i < PipeDirectionHelpers.PipeDirections; i++)
{
var pipeDir = (PipeDirection) (1 << i);
if (!CurrentPipeDirection.HasDirection(pipeDir))
continue;
foreach (var pipe in LinkableNodesInDirection(pos, pipeDir, grid, nodeQuery))
{
yield return pipe;
}
}
} }
/// <summary> /// <summary>
/// Gets the pipes that can connect to us from entities on the tile or adjacent in a direction. /// Gets the pipes that can connect to us from entities on the tile or adjacent in a direction.
/// </summary> /// </summary>
private IEnumerable<PipeNode> LinkableNodesInDirection(PipeDirection pipeDir) private IEnumerable<PipeNode> LinkableNodesInDirection(Vector2i pos, PipeDirection pipeDir, IMapGrid grid,
EntityQuery<NodeContainerComponent> nodeQuery)
{ {
if (!Anchored) foreach (var pipe in PipesInDirection(pos, pipeDir, grid, nodeQuery))
yield break;
foreach (var pipe in PipesInDirection(pipeDir))
{ {
if (pipe.ConnectionsEnabled && pipe.CurrentPipeDirection.HasDirection(pipeDir.GetOpposite())) if (pipe.NodeGroupID == NodeGroupID
&& pipe.CurrentPipeDirection.HasDirection(pipeDir.GetOpposite()))
{
yield return pipe; yield return pipe;
}
} }
} }
/// <summary> /// <summary>
/// Gets the pipes from entities on the tile adjacent in a direction. /// Gets the pipes from entities on the tile adjacent in a direction.
/// </summary> /// </summary>
protected IEnumerable<PipeNode> PipesInDirection(PipeDirection pipeDir) protected IEnumerable<PipeNode> PipesInDirection(Vector2i pos, PipeDirection pipeDir, IMapGrid grid,
EntityQuery<NodeContainerComponent> nodeQuery)
{ {
if (!IoCManager.Resolve<IEntityManager>().GetComponent<TransformComponent>(Owner).Anchored) var offsetPos = pos.Offset(pipeDir.ToDirection());
yield break;
var grid = IoCManager.Resolve<IMapManager>().GetGrid(IoCManager.Resolve<IEntityManager>().GetComponent<TransformComponent>(Owner).GridID); foreach (var entity in grid.GetAnchoredEntities(offsetPos))
var position = IoCManager.Resolve<IEntityManager>().GetComponent<TransformComponent>(Owner).Coordinates;
foreach (var entity in grid.GetInDir(position, pipeDir.ToDirection()))
{ {
if (!IoCManager.Resolve<IEntityManager>().TryGetComponent<NodeContainerComponent>(entity, out var container)) if (!nodeQuery.TryGetComponent(entity, out var container))
continue;
foreach (var node in container.Nodes.Values)
{
if (node is PipeNode pipe)
yield return pipe;
}
}
}
/// <summary>
/// Gets the pipes from entities on the same tile.
/// </summary>
protected IEnumerable<PipeNode> PipesInTile()
{
if (!IoCManager.Resolve<IEntityManager>().GetComponent<TransformComponent>(Owner).Anchored)
yield break;
var grid = IoCManager.Resolve<IMapManager>().GetGrid(IoCManager.Resolve<IEntityManager>().GetComponent<TransformComponent>(Owner).GridID);
var position = IoCManager.Resolve<IEntityManager>().GetComponent<TransformComponent>(Owner).Coordinates;
foreach (var entity in grid.GetLocal(position))
{
if (!IoCManager.Resolve<IEntityManager>().TryGetComponent<NodeContainerComponent>(entity, out var container))
continue; continue;
foreach (var node in container.Nodes.Values) foreach (var node in container.Nodes.Values)
@@ -265,6 +256,13 @@ namespace Content.Server.NodeContainer.Nodes
{ {
ConnectedDirections = PipeDirection.None; 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++) for (var i = 0; i < PipeDirectionHelpers.AllPipeDirections; i++)
{ {
var pipeDir = (PipeDirection) (1 << i); var pipeDir = (PipeDirection) (1 << i);
@@ -272,9 +270,9 @@ namespace Content.Server.NodeContainer.Nodes
if (!CurrentPipeDirection.HasDirection(pipeDir)) if (!CurrentPipeDirection.HasDirection(pipeDir))
continue; continue;
foreach (var pipe in LinkableNodesInDirection(pipeDir)) foreach (var pipe in LinkableNodesInDirection(pos, pipeDir, grid, query))
{ {
if (pipe.Connectable && pipe.NodeGroupID == NodeGroupID) if (pipe.Connectable(entMan) && pipe.NodeGroupID == NodeGroupID)
{ {
ConnectedDirections |= pipeDir; ConnectedDirections |= pipeDir;
break; break;
@@ -289,11 +287,18 @@ namespace Content.Server.NodeContainer.Nodes
/// </summary> /// </summary>
private void UpdateAdjacentConnectedDirections() 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++) for (var i = 0; i < PipeDirectionHelpers.PipeDirections; i++)
{ {
var pipeDir = (PipeDirection) (1 << i); var pipeDir = (PipeDirection) (1 << i);
foreach (var pipe in LinkableNodesInDirection(pipeDir)) foreach (var pipe in LinkableNodesInDirection(pos, pipeDir, grid, query))
{ {
pipe.UpdateConnectedDirections(); pipe.UpdateConnectedDirections();
pipe.UpdateAppearance(); pipe.UpdateAppearance();

View File

@@ -1,4 +1,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using Robust.Shared.GameObjects;
using Robust.Shared.Map;
using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Server.NodeContainer.Nodes namespace Content.Server.NodeContainer.Nodes
@@ -6,15 +8,24 @@ namespace Content.Server.NodeContainer.Nodes
[DataDefinition] [DataDefinition]
public class PortPipeNode : PipeNode public class PortPipeNode : PipeNode
{ {
public override IEnumerable<Node> GetReachableNodes() public override IEnumerable<Node> GetReachableNodes(TransformComponent xform,
EntityQuery<NodeContainerComponent> nodeQuery,
EntityQuery<TransformComponent> xformQuery,
IMapGrid? grid,
IEntityManager entMan)
{ {
foreach (var node in PipesInTile()) if (!xform.Anchored || grid == null)
yield break;
var gridIndex = grid.TileIndicesFor(xform.Coordinates);
foreach (var node in NodeHelpers.GetNodesInTile(nodeQuery, grid, gridIndex))
{ {
if (node is PortablePipeNode) if (node is PortablePipeNode)
yield return node; yield return node;
} }
foreach (var node in base.GetReachableNodes()) foreach (var node in base.GetReachableNodes(xform, nodeQuery, xformQuery, grid, entMan))
{ {
yield return node; yield return node;
} }

View File

@@ -1,4 +1,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using Robust.Shared.GameObjects;
using Robust.Shared.Map;
using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Server.NodeContainer.Nodes namespace Content.Server.NodeContainer.Nodes
@@ -6,15 +8,24 @@ namespace Content.Server.NodeContainer.Nodes
[DataDefinition] [DataDefinition]
public class PortablePipeNode : PipeNode public class PortablePipeNode : PipeNode
{ {
public override IEnumerable<Node> GetReachableNodes() public override IEnumerable<Node> GetReachableNodes(TransformComponent xform,
EntityQuery<NodeContainerComponent> nodeQuery,
EntityQuery<TransformComponent> xformQuery,
IMapGrid? grid,
IEntityManager entMan)
{ {
foreach (var node in PipesInTile()) if (!xform.Anchored || grid == null)
yield break;
var gridIndex = grid.TileIndicesFor(xform.Coordinates);
foreach (var node in NodeHelpers.GetNodesInTile(nodeQuery, grid, gridIndex))
{ {
if (node is PortPipeNode) if (node is PortPipeNode)
yield return node; yield return node;
} }
foreach (var node in base.GetReachableNodes()) foreach (var node in base.GetReachableNodes(xform, nodeQuery, xformQuery, grid, entMan))
{ {
yield return node; yield return node;
} }

View File

@@ -1,7 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using Content.Server.NodeContainer;
using Content.Server.NodeContainer.Nodes; using Content.Server.NodeContainer.Nodes;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Map; using Robust.Shared.Map;
using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.Serialization.Manager.Attributes;
@@ -13,20 +13,18 @@ namespace Content.Server.Power.Nodes
[DataDefinition] [DataDefinition]
public class CableDeviceNode : Node public class CableDeviceNode : Node
{ {
public override IEnumerable<Node> GetReachableNodes() public override IEnumerable<Node> GetReachableNodes(TransformComponent xform,
EntityQuery<NodeContainerComponent> nodeQuery,
EntityQuery<TransformComponent> xformQuery,
IMapGrid? grid,
IEntityManager entMan)
{ {
if (!Anchored) if (!xform.Anchored || grid == null)
yield break; yield break;
var entMan = IoCManager.Resolve<IEntityManager>(); var gridIndex = grid.TileIndicesFor(xform.Coordinates);
// If we're in an invalid grid, such as grid 0, we cannot connect to anything. foreach (var node in NodeHelpers.GetNodesInTile(nodeQuery, grid, gridIndex))
if(!IoCManager.Resolve<IMapManager>().TryGetGrid(IoCManager.Resolve<IEntityManager>().GetComponent<TransformComponent>(Owner).GridID, out var grid))
yield break;
var gridIndex = grid.TileIndicesFor(IoCManager.Resolve<IEntityManager>().GetComponent<TransformComponent>(Owner).Coordinates);
foreach (var node in NodeHelpers.GetNodesInTile(entMan, grid, gridIndex))
{ {
if (node is CableNode) if (node is CableNode)
yield return node; yield return node;

View File

@@ -1,8 +1,8 @@
using System.Collections.Generic; using System.Collections.Generic;
using Content.Server.NodeContainer;
using Content.Server.NodeContainer.Nodes; using Content.Server.NodeContainer.Nodes;
using Content.Server.Power.EntitySystems; using Content.Server.Power.EntitySystems;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Map; using Robust.Shared.Map;
using Robust.Shared.Maths; using Robust.Shared.Maths;
using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.Serialization.Manager.Attributes;
@@ -12,21 +12,23 @@ namespace Content.Server.Power.Nodes
[DataDefinition] [DataDefinition]
public class CableNode : Node public class CableNode : Node
{ {
public override IEnumerable<Node> GetReachableNodes() public override IEnumerable<Node> GetReachableNodes(TransformComponent xform,
EntityQuery<NodeContainerComponent> nodeQuery,
EntityQuery<TransformComponent> xformQuery,
IMapGrid? grid,
IEntityManager entMan)
{ {
if (!Anchored) if (!xform.Anchored || grid == null)
yield break; yield break;
var entMan = IoCManager.Resolve<IEntityManager>(); var gridIndex = grid.TileIndicesFor(xform.Coordinates);
var grid = IoCManager.Resolve<IMapManager>().GetGrid(IoCManager.Resolve<IEntityManager>().GetComponent<TransformComponent>(Owner).GridID);
var gridIndex = grid.TileIndicesFor(IoCManager.Resolve<IEntityManager>().GetComponent<TransformComponent>(Owner).Coordinates);
// While we go over adjacent nodes, we build a list of blocked directions due to // While we go over adjacent nodes, we build a list of blocked directions due to
// incoming or outgoing wire terminals. // incoming or outgoing wire terminals.
var terminalDirs = 0; var terminalDirs = 0;
List<(Direction, Node)> nodeDirs = new(); List<(Direction, Node)> nodeDirs = new();
foreach (var (dir, node) in NodeHelpers.GetCardinalNeighborNodes(entMan, grid, gridIndex)) foreach (var (dir, node) in NodeHelpers.GetCardinalNeighborNodes(nodeQuery, grid, gridIndex))
{ {
if (node is CableNode && node != this) if (node is CableNode && node != this)
{ {
@@ -44,11 +46,11 @@ namespace Content.Server.Power.Nodes
if (dir == Direction.Invalid) if (dir == Direction.Invalid)
{ {
// On own tile, block direction it faces // On own tile, block direction it faces
terminalDirs |= 1 << (int) IoCManager.Resolve<IEntityManager>().GetComponent<TransformComponent>(node.Owner).LocalRotation.GetCardinalDir(); terminalDirs |= 1 << (int) xformQuery.GetComponent(node.Owner).LocalRotation.GetCardinalDir();
} }
else else
{ {
var terminalDir = IoCManager.Resolve<IEntityManager>().GetComponent<TransformComponent>(node.Owner).LocalRotation.GetCardinalDir(); var terminalDir = xformQuery.GetComponent(node.Owner).LocalRotation.GetCardinalDir();
if (terminalDir.GetOpposite() == dir) if (terminalDir.GetOpposite() == dir)
{ {
// Target tile has a terminal towards us, block the direction. // Target tile has a terminal towards us, block the direction.

View File

@@ -1,8 +1,9 @@
using System.Collections.Generic; using System.Collections.Generic;
using Content.Server.NodeContainer;
using Content.Server.NodeContainer.Nodes; using Content.Server.NodeContainer.Nodes;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Map; using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Server.Power.Nodes namespace Content.Server.Power.Nodes
@@ -10,29 +11,27 @@ namespace Content.Server.Power.Nodes
[DataDefinition] [DataDefinition]
public class CableTerminalNode : CableDeviceNode public class CableTerminalNode : CableDeviceNode
{ {
public override IEnumerable<Node> GetReachableNodes() public override IEnumerable<Node> GetReachableNodes(TransformComponent xform,
EntityQuery<NodeContainerComponent> nodeQuery,
EntityQuery<TransformComponent> xformQuery,
IMapGrid? grid,
IEntityManager entMan)
{ {
if (!Anchored) if (!xform.Anchored || grid == null)
yield break; yield break;
if (IoCManager.Resolve<IEntityManager>().GetComponent<TransformComponent>(Owner).GridID == GridId.Invalid) var gridIndex = grid.TileIndicesFor(xform.Coordinates);
yield break; // No funny nodes in spess.
var dir = xform.LocalRotation.GetDir();
var targetIdx = gridIndex.Offset(dir);
var entMan = IoCManager.Resolve<IEntityManager>(); foreach (var node in NodeHelpers.GetNodesInTile(nodeQuery, grid, targetIdx))
var grid = IoCManager.Resolve<IMapManager>().GetGrid(IoCManager.Resolve<IEntityManager>().GetComponent<TransformComponent>(Owner).GridID);
var gridIndex = grid.TileIndicesFor(IoCManager.Resolve<IEntityManager>().GetComponent<TransformComponent>(Owner).Coordinates);
var dir = IoCManager.Resolve<IEntityManager>().GetComponent<TransformComponent>(Owner).LocalRotation.GetDir();
var targetIdx = gridIndex + NodeHelpers.TileOffsetForDir(dir);
foreach (var node in NodeHelpers.GetNodesInTile(entMan, grid, targetIdx))
{ {
if (node is CableTerminalPortNode) if (node is CableTerminalPortNode)
yield return node; yield return node;
} }
foreach (var node in base.GetReachableNodes()) foreach (var node in base.GetReachableNodes(xform, nodeQuery, xformQuery, grid, entMan))
{ {
yield return node; yield return node;
} }

View File

@@ -1,7 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using Content.Server.NodeContainer;
using Content.Server.NodeContainer.Nodes; using Content.Server.NodeContainer.Nodes;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Map; using Robust.Shared.Map;
using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.Serialization.Manager.Attributes;
@@ -10,19 +10,18 @@ namespace Content.Server.Power.Nodes
[DataDefinition] [DataDefinition]
public class CableTerminalPortNode : Node public class CableTerminalPortNode : Node
{ {
public override IEnumerable<Node> GetReachableNodes() public override IEnumerable<Node> GetReachableNodes(TransformComponent xform,
EntityQuery<NodeContainerComponent> nodeQuery,
EntityQuery<TransformComponent> xformQuery,
IMapGrid? grid,
IEntityManager entMan)
{ {
if (!Anchored) if (!xform.Anchored || grid == null)
yield break; yield break;
if (IoCManager.Resolve<IEntityManager>().GetComponent<TransformComponent>(Owner).GridID == GridId.Invalid) var gridIndex = grid.TileIndicesFor(xform.Coordinates);
yield break; // No funny nodes in spess.
var entMan = IoCManager.Resolve<IEntityManager>(); var nodes = NodeHelpers.GetCardinalNeighborNodes(nodeQuery, grid, gridIndex, includeSameTile: false);
var grid = IoCManager.Resolve<IMapManager>().GetGrid(IoCManager.Resolve<IEntityManager>().GetComponent<TransformComponent>(Owner).GridID);
var gridIndex = grid.TileIndicesFor(IoCManager.Resolve<IEntityManager>().GetComponent<TransformComponent>(Owner).Coordinates);
var nodes = NodeHelpers.GetCardinalNeighborNodes(entMan, grid, gridIndex, includeSameTile: false);
foreach (var (_, node) in nodes) foreach (var (_, node) in nodes)
{ {
if (node is CableTerminalNode) if (node is CableTerminalNode)