Skip to content

Commit

Permalink
Revert "Revert "Prevent stacking pipes (#28308)" (#43)"
Browse files Browse the repository at this point in the history
This reverts commit af626ce
  • Loading branch information
VigersRay committed Jul 1, 2024
1 parent 558750a commit 37a1f5a
Show file tree
Hide file tree
Showing 9 changed files with 147 additions and 9 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using Content.Server.Atmos.EntitySystems;

namespace Content.Server.Atmos.Components;

/// <summary>
/// This is used for restricting anchoring pipes so that they do not overlap.
/// </summary>
[RegisterComponent, Access(typeof(PipeRestrictOverlapSystem))]
public sealed partial class PipeRestrictOverlapComponent : Component;
123 changes: 123 additions & 0 deletions Content.Server/Atmos/EntitySystems/PipeRestrictOverlapSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
using System.Linq;
using Content.Server.Atmos.Components;
using Content.Server.NodeContainer;
using Content.Server.NodeContainer.Nodes;
using Content.Server.Popups;
using Content.Shared.Atmos;
using Content.Shared.Construction.Components;
using JetBrains.Annotations;
using Robust.Server.GameObjects;
using Robust.Shared.Map.Components;

namespace Content.Server.Atmos.EntitySystems;

/// <summary>
/// This handles restricting pipe-based entities from overlapping outlets/inlets with other entities.
/// </summary>
public sealed class PipeRestrictOverlapSystem : EntitySystem
{
[Dependency] private readonly MapSystem _map = default!;
[Dependency] private readonly PopupSystem _popup = default!;
[Dependency] private readonly TransformSystem _xform = default!;

private readonly List<EntityUid> _anchoredEntities = new();
private EntityQuery<NodeContainerComponent> _nodeContainerQuery;

/// <inheritdoc/>
public override void Initialize()
{
SubscribeLocalEvent<PipeRestrictOverlapComponent, AnchorStateChangedEvent>(OnAnchorStateChanged);
SubscribeLocalEvent<PipeRestrictOverlapComponent, AnchorAttemptEvent>(OnAnchorAttempt);

_nodeContainerQuery = GetEntityQuery<NodeContainerComponent>();
}

private void OnAnchorStateChanged(Entity<PipeRestrictOverlapComponent> ent, ref AnchorStateChangedEvent args)
{
if (!args.Anchored)
return;

if (HasComp<AnchorableComponent>(ent) && CheckOverlap(ent))
{
_popup.PopupEntity(Loc.GetString("pipe-restrict-overlap-popup-blocked", ("pipe", ent.Owner)), ent);
_xform.Unanchor(ent, Transform(ent));
}
}

private void OnAnchorAttempt(Entity<PipeRestrictOverlapComponent> ent, ref AnchorAttemptEvent args)
{
if (args.Cancelled)
return;

if (!_nodeContainerQuery.TryComp(ent, out var node))
return;

var xform = Transform(ent);
if (CheckOverlap((ent, node, xform)))
{
_popup.PopupEntity(Loc.GetString("pipe-restrict-overlap-popup-blocked", ("pipe", ent.Owner)), ent, args.User);
args.Cancel();
}
}

[PublicAPI]
public bool CheckOverlap(EntityUid uid)
{
if (!_nodeContainerQuery.TryComp(uid, out var node))
return false;

return CheckOverlap((uid, node, Transform(uid)));
}

public bool CheckOverlap(Entity<NodeContainerComponent, TransformComponent> ent)
{
if (ent.Comp2.GridUid is not { } grid || !TryComp<MapGridComponent>(grid, out var gridComp))
return false;

var indices = _map.TileIndicesFor(grid, gridComp, ent.Comp2.Coordinates);
_anchoredEntities.Clear();
_map.GetAnchoredEntities((grid, gridComp), indices, _anchoredEntities);

foreach (var otherEnt in _anchoredEntities)
{
// this should never actually happen but just for safety
if (otherEnt == ent.Owner)
continue;

if (!_nodeContainerQuery.TryComp(otherEnt, out var otherComp))
continue;

if (PipeNodesOverlap(ent, (otherEnt, otherComp, Transform(otherEnt))))
return true;
}

return false;
}

public bool PipeNodesOverlap(Entity<NodeContainerComponent, TransformComponent> ent, Entity<NodeContainerComponent, TransformComponent> other)
{
var entDirs = GetAllDirections(ent).ToList();
var otherDirs = GetAllDirections(other).ToList();

foreach (var dir in entDirs)
{
foreach (var otherDir in otherDirs)
{
if ((dir & otherDir) != 0)
return true;
}
}

return false;

IEnumerable<PipeDirection> GetAllDirections(Entity<NodeContainerComponent, TransformComponent> pipe)
{
foreach (var node in pipe.Comp1.Nodes.Values)
{
// we need to rotate the pipe manually like this because the rotation doesn't update for pipes that are unanchored.
if (node is PipeNode pipeNode)
yield return pipeNode.OriginalPipeDirection.RotatePipeDirection(pipe.Comp2.LocalRotation);
}
}
}
}
2 changes: 1 addition & 1 deletion Content.Server/Construction/ConstructionSystem.Initial.cs
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ void ShutdownContainers()
}

var newEntityProto = graph.Nodes[edge.Target].Entity.GetId(null, user, new(EntityManager));
var newEntity = EntityManager.SpawnAttachedTo(newEntityProto, coords, rotation: angle);
var newEntity = Spawn(newEntityProto, _transformSystem.ToMapCoordinates(coords), rotation: angle);

if (!TryComp(newEntity, out ConstructionComponent? construction))
{
Expand Down
16 changes: 8 additions & 8 deletions Content.Server/NodeContainer/Nodes/PipeNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public partial class PipeNode : Node, IGasMixtureHolder, IRotatableNode
/// The directions in which this pipe can connect to other pipes around it.
/// </summary>
[DataField("pipeDirection")]
private PipeDirection _originalPipeDirection;
public PipeDirection OriginalPipeDirection;

/// <summary>
/// The *current* pipe directions (accounting for rotation)
Expand Down Expand Up @@ -110,26 +110,26 @@ public override void Initialize(EntityUid owner, IEntityManager entMan)
return;

var xform = entMan.GetComponent<TransformComponent>(owner);
CurrentPipeDirection = _originalPipeDirection.RotatePipeDirection(xform.LocalRotation);
CurrentPipeDirection = OriginalPipeDirection.RotatePipeDirection(xform.LocalRotation);
}

bool IRotatableNode.RotateNode(in MoveEvent ev)
{
if (_originalPipeDirection == PipeDirection.Fourway)
if (OriginalPipeDirection == PipeDirection.Fourway)
return false;

// update valid pipe direction
if (!RotationsEnabled)
{
if (CurrentPipeDirection == _originalPipeDirection)
if (CurrentPipeDirection == OriginalPipeDirection)
return false;

CurrentPipeDirection = _originalPipeDirection;
CurrentPipeDirection = OriginalPipeDirection;
return true;
}

var oldDirection = CurrentPipeDirection;
CurrentPipeDirection = _originalPipeDirection.RotatePipeDirection(ev.NewRotation);
CurrentPipeDirection = OriginalPipeDirection.RotatePipeDirection(ev.NewRotation);
return oldDirection != CurrentPipeDirection;
}

Expand All @@ -142,12 +142,12 @@ public override void OnAnchorStateChanged(IEntityManager entityManager, bool anc

if (!RotationsEnabled)
{
CurrentPipeDirection = _originalPipeDirection;
CurrentPipeDirection = OriginalPipeDirection;
return;
}

var xform = entityManager.GetComponent<TransformComponent>(Owner);
CurrentPipeDirection = _originalPipeDirection.RotatePipeDirection(xform.LocalRotation);
CurrentPipeDirection = OriginalPipeDirection.RotatePipeDirection(xform.LocalRotation);
}

public override IEnumerable<Node> GetReachableNodes(TransformComponent xform,
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
construction-step-condition-no-unstackable-in-tile = You cannot make a stack of similar devices.
pipe-restrict-overlap-popup-blocked = { CAPITALIZE(THE($pipe))} doesn't fit over the other pipes!
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,7 @@
- type: PipeColorVisuals
- type: Rotatable
- type: GasRecycler
- type: PipeRestrictOverlap
- type: NodeContainer
nodes:
inlet:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
- type: Appearance
- type: PipeColorVisuals
- type: NodeContainer
- type: PipeRestrictOverlap
- type: AtmosUnsafeUnanchor
- type: AtmosPipeColor
- type: Tag
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@
key: enum.ThermomachineUiKey.Key
- type: WiresPanel
- type: WiresVisuals
- type: PipeRestrictOverlap
- type: NodeContainer
nodes:
pipe:
Expand Down Expand Up @@ -381,6 +382,7 @@
- type: GasCondenser
- type: AtmosPipeColor
- type: AtmosDevice
- type: PipeRestrictOverlap
- type: ApcPowerReceiver
powerLoad: 10000
- type: Machine
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@
nodeGroupID: Teg

- type: AtmosUnsafeUnanchor
- type: PipeRestrictOverlap
- type: TegCirculator
- type: StealTarget
stealGroup: Teg
Expand Down

0 comments on commit 37a1f5a

Please sign in to comment.