From 1347aed0b2b156714281ba6a44c0832990a508db Mon Sep 17 00:00:00 2001 From: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Date: Thu, 11 Aug 2022 12:11:29 +1000 Subject: [PATCH] Don't allow anchorable overlap (#10461) * Don't allow anchorable overlap Should significantly reduce incidents of wall pushing. * woops --- .../Construction/AnchorableSystem.cs | 56 +++++++++++++++++-- .../EntitySystems/SharedAnchorableSystem.cs | 1 - .../en-US/anchorable/anchorable-component.ftl | 3 +- 3 files changed, 53 insertions(+), 7 deletions(-) diff --git a/Content.Server/Construction/AnchorableSystem.cs b/Content.Server/Construction/AnchorableSystem.cs index 61499a63f9..8172e5cab0 100644 --- a/Content.Server/Construction/AnchorableSystem.cs +++ b/Content.Server/Construction/AnchorableSystem.cs @@ -1,5 +1,4 @@ using System.Threading; -using System.Threading.Tasks; using Content.Server.Administration.Logs; using Content.Server.Coordinates.Helpers; using Content.Server.Popups; @@ -11,6 +10,7 @@ using Content.Shared.Database; using Content.Shared.Examine; using Content.Shared.Pulling.Components; using Content.Shared.Tools.Components; +using Robust.Shared.Map; using Robust.Shared.Player; namespace Content.Server.Construction @@ -18,6 +18,7 @@ namespace Content.Server.Construction public sealed class AnchorableSystem : SharedAnchorableSystem { [Dependency] private readonly IAdminLogManager _adminLogger = default!; + [Dependency] private readonly IMapManager _mapManager = default!; [Dependency] private readonly PopupSystem _popup = default!; [Dependency] private readonly ToolSystem _toolSystem = default!; [Dependency] private readonly PullingSystem _pullingSystem = default!; @@ -71,6 +72,12 @@ namespace Content.Server.Construction { component.CancelToken = null; var xform = Transform(uid); + if (TryComp(uid, out var anchorBody) && + !TileFree(xform.Coordinates, anchorBody)) + { + _popup.PopupEntity(Loc.GetString("anchorable-occupied"), uid, Filter.Entities(args.User)); + return; + } // Snap rotation to cardinal (multiple of 90) var rot = xform.LocalRotation; @@ -81,8 +88,9 @@ namespace Content.Server.Construction _pullingSystem.TryStopPull(pullable); } + // TODO: Anchoring snaps rn anyway! if (component.Snap) - xform.Coordinates = xform.Coordinates.SnapToGrid(); + xform.Coordinates = xform.Coordinates.SnapToGrid(EntityManager, _mapManager); RaiseLocalEvent(uid, new BeforeAnchoredEvent(args.User, args.Using), false); xform.Anchored = true; @@ -97,6 +105,34 @@ namespace Content.Server.Construction ); } + private bool TileFree(EntityCoordinates coordinates, PhysicsComponent anchorBody) + { + // Probably ignore CanCollide on the anchoring body? + var gridUid = coordinates.GetGridUid(EntityManager); + + if (!_mapManager.TryGetGrid(gridUid, out var grid)) + return false; + + var tileIndices = grid.TileIndicesFor(coordinates); + var enumerator = grid.GetAnchoredEntitiesEnumerator(tileIndices); + var bodyQuery = GetEntityQuery(); + + while (enumerator.MoveNext(out var ent)) + { + if (!bodyQuery.TryGetComponent(ent, out var body) || + !body.CanCollide) + continue; + + if ((body.CollisionMask & anchorBody.CollisionLayer) != 0x0 || + (body.CollisionLayer & anchorBody.CollisionMask) != 0x0) + { + return false; + } + } + + return true; + } + /// /// Checks if a tool can change the anchored status. /// @@ -135,14 +171,24 @@ namespace Content.Server.Construction SharedPullableComponent? pullable = null, ToolComponent? usingTool = null) { - if (!Resolve(uid, ref anchorable, ref transform)) return; + if (!Resolve(uid, ref anchorable, ref transform)) + return; // Optional resolves. Resolve(uid, ref pullable, false); - if (!Resolve(usingUid, ref usingTool)) return; + if (!Resolve(usingUid, ref usingTool)) + return; - if (!Valid(uid, userUid, usingUid, true, anchorable, usingTool)) return; + if (!Valid(uid, userUid, usingUid, true, anchorable, usingTool)) + return; + + if (TryComp(uid, out var anchorBody) && + !TileFree(transform.Coordinates, anchorBody)) + { + _popup.PopupEntity(Loc.GetString("anchorable-occupied"), uid, Filter.Entities(userUid)); + return; + } anchorable.CancelToken = new CancellationTokenSource(); diff --git a/Content.Shared/Construction/EntitySystems/SharedAnchorableSystem.cs b/Content.Shared/Construction/EntitySystems/SharedAnchorableSystem.cs index b0e9329fd4..398a8c51d5 100644 --- a/Content.Shared/Construction/EntitySystems/SharedAnchorableSystem.cs +++ b/Content.Shared/Construction/EntitySystems/SharedAnchorableSystem.cs @@ -1,4 +1,3 @@ -using System.Threading.Tasks; using Content.Shared.Construction.Components; using Content.Shared.Containers.ItemSlots; using Content.Shared.Interaction; diff --git a/Resources/Locale/en-US/anchorable/anchorable-component.ftl b/Resources/Locale/en-US/anchorable/anchorable-component.ftl index 9cc3b3c86c..fdac0aa741 100644 --- a/Resources/Locale/en-US/anchorable/anchorable-component.ftl +++ b/Resources/Locale/en-US/anchorable/anchorable-component.ftl @@ -1,2 +1,3 @@ anchorable-anchored = Anchored -anchorable-unanchored = Unanchored \ No newline at end of file +anchorable-unanchored = Unanchored +anchorable-occupied = Tile occupied