diff --git a/Content.Client/GameObjects/Components/Body/BodyComponent.cs b/Content.Client/GameObjects/Components/Body/BodyComponent.cs index 524513b372..aa23f069f9 100644 --- a/Content.Client/GameObjects/Components/Body/BodyComponent.cs +++ b/Content.Client/GameObjects/Components/Body/BodyComponent.cs @@ -1,6 +1,4 @@ #nullable enable -using Content.Client.GameObjects.Components.Disposal; -using Content.Client.GameObjects.Components.MedicalScanner; using Content.Shared.GameObjects.Components.Body; using Content.Shared.Interfaces.GameObjects.Components; using Robust.Shared.GameObjects; @@ -11,16 +9,14 @@ namespace Content.Client.GameObjects.Components.Body [ComponentReference(typeof(IBody))] public class BodyComponent : SharedBodyComponent, IDraggable { - public bool CanDrop(CanDropEventArgs eventArgs) + bool IDraggable.CanStartDrag(StartDragDropEventArgs args) { - if (eventArgs.Target.HasComponent() || - eventArgs.Target.HasComponent() || - eventArgs.Target.HasComponent()) - { - return true; - } + return true; + } - return false; + public bool CanDrop(CanDropEventArgs args) + { + return true; } } } diff --git a/Content.Client/GameObjects/Components/Buckle/BuckleComponent.cs b/Content.Client/GameObjects/Components/Buckle/BuckleComponent.cs index a3020c85bc..660d5517a8 100644 --- a/Content.Client/GameObjects/Components/Buckle/BuckleComponent.cs +++ b/Content.Client/GameObjects/Components/Buckle/BuckleComponent.cs @@ -6,6 +6,7 @@ using Robust.Shared.Interfaces.GameObjects; namespace Content.Client.GameObjects.Components.Buckle { [RegisterComponent] + [ComponentReference(typeof(SharedBuckleComponent))] public class BuckleComponent : SharedBuckleComponent { private bool _buckled; diff --git a/Content.Client/GameObjects/Components/Disposal/DisposalMailingUnitComponent.cs b/Content.Client/GameObjects/Components/Disposal/DisposalMailingUnitComponent.cs index fd661f6afa..f3a7376cc3 100644 --- a/Content.Client/GameObjects/Components/Disposal/DisposalMailingUnitComponent.cs +++ b/Content.Client/GameObjects/Components/Disposal/DisposalMailingUnitComponent.cs @@ -1,4 +1,5 @@ using Content.Shared.GameObjects.Components.Disposal; +using Content.Shared.Interfaces.GameObjects.Components; using Robust.Shared.GameObjects; namespace Content.Client.GameObjects.Components.Disposal @@ -7,5 +8,9 @@ namespace Content.Client.GameObjects.Components.Disposal [ComponentReference(typeof(SharedDisposalMailingUnitComponent))] public class DisposalMailingUnitComponent : SharedDisposalMailingUnitComponent { + public override bool DragDropOn(DragDropEventArgs eventArgs) + { + return false; + } } } diff --git a/Content.Client/GameObjects/Components/Disposal/DisposalUnitComponent.cs b/Content.Client/GameObjects/Components/Disposal/DisposalUnitComponent.cs index 1e28af762d..5451edc71d 100644 --- a/Content.Client/GameObjects/Components/Disposal/DisposalUnitComponent.cs +++ b/Content.Client/GameObjects/Components/Disposal/DisposalUnitComponent.cs @@ -1,4 +1,5 @@ using Content.Shared.GameObjects.Components.Disposal; +using Content.Shared.Interfaces.GameObjects.Components; using Robust.Shared.GameObjects; namespace Content.Client.GameObjects.Components.Disposal @@ -7,5 +8,9 @@ namespace Content.Client.GameObjects.Components.Disposal [ComponentReference(typeof(SharedDisposalUnitComponent))] public class DisposalUnitComponent : SharedDisposalUnitComponent { + public override bool DragDropOn(DragDropEventArgs eventArgs) + { + return false; + } } } diff --git a/Content.Client/GameObjects/Components/MedicalScanner/MedicalScannerComponent.cs b/Content.Client/GameObjects/Components/MedicalScanner/MedicalScannerComponent.cs index e48f4cc14b..6ba483832a 100644 --- a/Content.Client/GameObjects/Components/MedicalScanner/MedicalScannerComponent.cs +++ b/Content.Client/GameObjects/Components/MedicalScanner/MedicalScannerComponent.cs @@ -1,4 +1,5 @@ using Content.Shared.GameObjects.Components.Medical; +using Content.Shared.Interfaces.GameObjects.Components; using Robust.Shared.GameObjects; namespace Content.Client.GameObjects.Components.MedicalScanner @@ -7,5 +8,9 @@ namespace Content.Client.GameObjects.Components.MedicalScanner [ComponentReference(typeof(SharedMedicalScannerComponent))] public class MedicalScannerComponent : SharedMedicalScannerComponent { + public override bool DragDropOn(DragDropEventArgs eventArgs) + { + return false; + } } } diff --git a/Content.Client/GameObjects/Components/Movement/ClimbableComponent.cs b/Content.Client/GameObjects/Components/Movement/ClimbableComponent.cs index fe92dc1896..311da1407e 100644 --- a/Content.Client/GameObjects/Components/Movement/ClimbableComponent.cs +++ b/Content.Client/GameObjects/Components/Movement/ClimbableComponent.cs @@ -1,5 +1,8 @@ using Content.Shared.GameObjects.Components.Movement; +using Content.Shared.Interfaces.GameObjects.Components; +using Content.Shared.Utility; using Robust.Shared.GameObjects; +using Robust.Shared.Interfaces.GameObjects; namespace Content.Client.GameObjects.Components.Movement { @@ -7,6 +10,22 @@ namespace Content.Client.GameObjects.Components.Movement [ComponentReference(typeof(IClimbable))] public class ClimbableComponent : SharedClimbableComponent { - + public override bool CanDragDropOn(DragDropEventArgs eventArgs) + { + if (!base.CanDragDropOn(eventArgs)) + return false; + + var user = eventArgs.User; + var target = eventArgs.Target; + var dragged = eventArgs.Dragged; + bool Ignored(IEntity entity) => entity == target || entity == user || entity == dragged; + + return user.InRangeUnobstructed(target, Range, predicate: Ignored) && user.InRangeUnobstructed(dragged, Range, predicate: Ignored); + } + + public override bool DragDropOn(DragDropEventArgs eventArgs) + { + return false; + } } } diff --git a/Content.Client/GameObjects/Components/Movement/ClimbingComponent.cs b/Content.Client/GameObjects/Components/Movement/ClimbingComponent.cs index 7db57f929e..92a76edd1f 100644 --- a/Content.Client/GameObjects/Components/Movement/ClimbingComponent.cs +++ b/Content.Client/GameObjects/Components/Movement/ClimbingComponent.cs @@ -4,6 +4,7 @@ using Robust.Shared.GameObjects; namespace Content.Client.GameObjects.Components.Movement { [RegisterComponent] + [ComponentReference(typeof(SharedClimbingComponent))] public class ClimbingComponent : SharedClimbingComponent { public override void HandleComponentState(ComponentState curState, ComponentState nextState) diff --git a/Content.Client/GameObjects/Components/Strap/StrapComponent.cs b/Content.Client/GameObjects/Components/Strap/StrapComponent.cs index 7da4776258..36e086f560 100644 --- a/Content.Client/GameObjects/Components/Strap/StrapComponent.cs +++ b/Content.Client/GameObjects/Components/Strap/StrapComponent.cs @@ -1,5 +1,6 @@ #nullable enable using Content.Shared.GameObjects.Components.Strap; +using Content.Shared.Interfaces.GameObjects.Components; using Robust.Shared.GameObjects; namespace Content.Client.GameObjects.Components.Strap @@ -8,5 +9,9 @@ namespace Content.Client.GameObjects.Components.Strap [ComponentReference(typeof(SharedStrapComponent))] public class StrapComponent : SharedStrapComponent { + public override bool DragDropOn(DragDropEventArgs eventArgs) + { + return false; + } } } diff --git a/Content.Client/GameObjects/EntitySystems/DragDropSystem.cs b/Content.Client/GameObjects/EntitySystems/DragDropSystem.cs index 97c8aa37dd..ab4e1d601c 100644 --- a/Content.Client/GameObjects/EntitySystems/DragDropSystem.cs +++ b/Content.Client/GameObjects/EntitySystems/DragDropSystem.cs @@ -1,24 +1,32 @@ +#nullable enable using System.Collections.Generic; -using System.Linq; using Content.Client.State; using Content.Client.Utility; -using Content.Shared.GameObjects; using Content.Shared.GameObjects.EntitySystemMessages; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.Interfaces; using Content.Shared.Interfaces.GameObjects.Components; +using Content.Shared.Utility; using JetBrains.Annotations; using Robust.Client.GameObjects; using Robust.Client.GameObjects.EntitySystems; using Robust.Client.Graphics.Shaders; +using Robust.Client.Interfaces.GameObjects.Components; using Robust.Client.Interfaces.Graphics.ClientEye; +using Robust.Client.Interfaces.Input; using Robust.Client.Interfaces.State; +using Robust.Client.Player; +using Robust.Shared.GameObjects; using Robust.Shared.GameObjects.Systems; using Robust.Shared.Input; using Robust.Shared.Input.Binding; using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.IoC; +using Robust.Shared.Localization; using Robust.Shared.Log; +using Robust.Shared.Maths; using Robust.Shared.Prototypes; +using DrawDepth = Content.Shared.GameObjects.DrawDepth; namespace Content.Client.GameObjects.EntitySystems { @@ -29,7 +37,9 @@ namespace Content.Client.GameObjects.EntitySystems public class DragDropSystem : EntitySystem { [Dependency] private readonly IStateManager _stateManager = default!; + [Dependency] private readonly IInputManager _inputManager = default!; [Dependency] private readonly IEyeManager _eyeManager = default!; + [Dependency] private readonly IPlayerManager _playerManager = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!; // how often to recheck possible targets (prevents calling expensive @@ -45,9 +55,11 @@ namespace Content.Client.GameObjects.EntitySystems private const string ShaderDropTargetOutOfRange = "SelectionOutline"; // entity performing the drag action - private IEntity _dragger; + + private IEntity? _dragger; private readonly List _draggables = new(); - private IEntity _dragShadow; + private IEntity? _dragShadow; + // time since mouse down over the dragged entity private float _mouseDownTime; // how much time since last recheck of all possible targets @@ -58,14 +70,14 @@ namespace Content.Client.GameObjects.EntitySystems // can ignore any events sent to this system private bool _isReplaying; - private DragDropHelper _dragDropHelper; + private DragDropHelper _dragDropHelper = default!; - private ShaderInstance _dropTargetInRangeShader; - private ShaderInstance _dropTargetOutOfRangeShader; - private SharedInteractionSystem _interactionSystem; - private InputSystem _inputSystem; + private ShaderInstance? _dropTargetInRangeShader; + private ShaderInstance? _dropTargetOutOfRangeShader; + private SharedInteractionSystem _interactionSystem = default!; + private InputSystem _inputSystem = default!; - private readonly List _highlightedSprites = new(); + private readonly List _highlightedSprites = new(); public override void Initialize() { @@ -112,7 +124,7 @@ namespace Content.Client.GameObjects.EntitySystems private bool OnUseMouseDown(in PointerInputCmdHandler.PointerInputCmdArgs args) { - var dragger = args.Session.AttachedEntity; + var dragger = args.Session?.AttachedEntity; // cancel any current dragging if there is one (shouldn't be because they would've had to have lifted // the mouse, canceling the drag, but just being cautious) _dragDropHelper.EndDrag(); @@ -130,7 +142,7 @@ namespace Content.Client.GameObjects.EntitySystems var canDrag = false; foreach (var draggable in entity.GetAllComponents()) { - var dragEventArgs = new StartDragDropEventArgs(args.Session.AttachedEntity, entity); + var dragEventArgs = new StartDragDropEventArgs(dragger, entity); if (draggable.CanStartDrag(dragEventArgs)) { _draggables.Add(draggable); @@ -156,7 +168,6 @@ namespace Content.Client.GameObjects.EntitySystems return false; } - private bool OnBeginDrag() { if (_dragDropHelper.Dragged == null || _dragDropHelper.Dragged.Deleted) @@ -183,6 +194,7 @@ namespace Content.Client.GameObjects.EntitySystems } HighlightTargets(); + EntityManager.EventBus.RaiseEvent(EventSource.Local, new OutlineToggleMessage(false)); // drag initiated return true; @@ -209,6 +221,9 @@ namespace Content.Client.GameObjects.EntitySystems var mousePos = _eyeManager.ScreenToMap(_dragDropHelper.MouseScreenPosition); // TODO: would use MapPosition instead if it had a setter, but it has no setter. // is that intentional, or should we add a setter for Transform.MapPosition? + if (_dragShadow == null) + return false; + _dragShadow.Transform.WorldPosition = mousePos.Position; _targetRecheckTime += frameTime; @@ -229,6 +244,7 @@ namespace Content.Client.GameObjects.EntitySystems EntityManager.DeleteEntity(_dragShadow); } + EntityManager.EventBus.RaiseEvent(EventSource.Local, new OutlineToggleMessage(true)); _dragShadow = null; _draggables.Clear(); _dragger = null; @@ -238,7 +254,7 @@ namespace Content.Client.GameObjects.EntitySystems private bool OnUseMouseUp(in PointerInputCmdHandler.PointerInputCmdArgs args) { - if (!_dragDropHelper.IsDragging) + if (_dragDropHelper.IsDragging == false) { // haven't started the drag yet, quick mouseup, definitely treat it as a normal click by // replaying the original cmd @@ -251,40 +267,68 @@ namespace Content.Client.GameObjects.EntitySystems var adjustedInputMsg = new FullInputCmdMessage(args.OriginalMessage.Tick, args.OriginalMessage.SubTick, replayMsg.InputFunctionId, replayMsg.State, replayMsg.Coordinates, replayMsg.ScreenCoordinates, replayMsg.Uid); - _inputSystem.HandleInputCommand(savedValue.Session, EngineKeyFunctions.Use, - adjustedInputMsg, true); + if (savedValue.Session != null) + { + _inputSystem.HandleInputCommand(savedValue.Session, EngineKeyFunctions.Use, adjustedInputMsg, true); + } + _isReplaying = false; } _dragDropHelper.EndDrag(); return false; } - // now when ending the drag, we will not replay the click because - // by this time we've determined the input was actually a drag attempt + if (_dragger == null) + { + _dragDropHelper.EndDrag(); + return false; + } + // now when ending the drag, we will not replay the click because + // by this time we've determined the input was actually a drag attempt + var range = (args.Coordinates.ToMapPos(EntityManager) - _dragger.Transform.MapPosition.Position).Length + 0.01f; // tell the server we are dropping if we are over a valid drop target in range. // We don't use args.EntityUid here because drag interactions generally should // work even if there's something "on top" of the drop target if (!_interactionSystem.InRangeUnobstructed(_dragger, - args.Coordinates, ignoreInsideBlocker: true)) + args.Coordinates, range, ignoreInsideBlocker: true)) { _dragDropHelper.EndDrag(); return false; } var entities = GameScreenBase.GetEntitiesUnderPosition(_stateManager, args.Coordinates); + var outOfRange = false; foreach (var entity in entities) { // check if it's able to be dropped on by current dragged entity var dropArgs = new DragDropEventArgs(_dragger, args.Coordinates, _dragDropHelper.Dragged, entity); + var valid = true; + var anyDragDrop = false; + var dragDropOn = new List(); + + foreach (var comp in entity.GetAllComponents()) + { + anyDragDrop = true; + + if (!comp.CanDragDropOn(dropArgs)) + { + valid = false; + dragDropOn.Add(comp); + } + } + + if (!valid || !anyDragDrop) continue; + if (!dropArgs.InRangeUnobstructed(ignoreInsideBlocker: true)) + { + outOfRange = true; + continue; + } foreach (var draggable in _draggables) { - if (!draggable.CanDrop(dropArgs)) - { - continue; - } + if (!draggable.CanDrop(dropArgs)) continue; // tell the server about the drop attempt RaiseNetworkEvent(new DragDropMessage(args.Coordinates, _dragDropHelper.Dragged.Uid, @@ -292,11 +336,22 @@ namespace Content.Client.GameObjects.EntitySystems draggable.Drop(dropArgs); + // Don't fail if it isn't handled as server may do something with it + foreach (var comp in dragDropOn) + { + if (!comp.DragDropOn(dropArgs)) continue; + } + _dragDropHelper.EndDrag(); return true; } } + if (outOfRange) + { + _playerManager.LocalPlayer?.ControlledEntity?.PopupMessage(Loc.GetString("You can't reach there!")); + } + _dragDropHelper.EndDrag(); return false; } @@ -304,7 +359,9 @@ namespace Content.Client.GameObjects.EntitySystems private void HighlightTargets() { if (_dragDropHelper.Dragged == null || - _dragDropHelper.Dragged.Deleted || _dragShadow == null || _dragShadow.Deleted) + _dragDropHelper.Dragged.Deleted || + _dragShadow == null || + _dragShadow.Deleted) { Logger.Warning("Programming error. Can't highlight drag and drop targets, not currently " + "dragging anything or dragged entity / shadow was deleted."); @@ -319,28 +376,42 @@ namespace Content.Client.GameObjects.EntitySystems // find possible targets on screen even if not reachable // TODO: Duplicated in SpriteSystem - var pvsBounds = _eyeManager.GetWorldViewport().Enlarged(5); - var pvsEntities = EntityManager.GetEntitiesIntersecting(_eyeManager.CurrentMap, pvsBounds, true); + var mousePos = _eyeManager.ScreenToMap(_inputManager.MouseScreenPosition).Position; + var bounds = new Box2(mousePos - 1.5f, mousePos + 1.5f); + var pvsEntities = EntityManager.GetEntitiesIntersecting(_eyeManager.CurrentMap, bounds, true); foreach (var pvsEntity in pvsEntities) { - if (pvsEntity.TryGetComponent(out var inRangeSprite)) + if (!pvsEntity.TryGetComponent(out ISpriteComponent? inRangeSprite)) continue; + + // can't highlight if there's no sprite or it's not visible + if (inRangeSprite.Visible == false) continue; + + var valid = (bool?) null; + // check if it's able to be dropped on by current dragged entity + var dropArgs = new DragDropEventArgs(_dragger, pvsEntity.Transform.Coordinates, _dragDropHelper.Dragged, pvsEntity); + + foreach (var comp in pvsEntity.GetAllComponents()) { - // can't highlight if there's no sprite or it's not visible - if (inRangeSprite.Visible == false) continue; + valid = comp.CanDragDropOn(dropArgs); - // check if it's able to be dropped on by current dragged entity - var canDropArgs = new CanDropEventArgs(_dragger, _dragDropHelper.Dragged, pvsEntity); - var anyValidDraggable = _draggables.Any(draggable => draggable.CanDrop(canDropArgs)); - - if (anyValidDraggable) - { - // highlight depending on whether its in or out of range - var inRange = _interactionSystem.InRangeUnobstructed(_dragger, pvsEntity); - inRangeSprite.PostShader = inRange ? _dropTargetInRangeShader : _dropTargetOutOfRangeShader; - inRangeSprite.RenderOrder = EntityManager.CurrentTick.Value; - _highlightedSprites.Add(inRangeSprite); - } + if (valid.Value) + break; } + + // Can't do anything so no highlight + if (!valid.HasValue) + continue; + + // We'll do a final check given server-side does this before any dragdrop can take place. + if (valid.Value) + { + valid = dropArgs.InRangeUnobstructed(ignoreInsideBlocker: true); + } + + // highlight depending on whether its in or out of range + inRangeSprite.PostShader = valid.Value ? _dropTargetInRangeShader : _dropTargetOutOfRangeShader; + inRangeSprite.RenderOrder = EntityManager.CurrentTick.Value; + _highlightedSprites.Add(inRangeSprite); } } @@ -351,6 +422,7 @@ namespace Content.Client.GameObjects.EntitySystems highlightedSprite.PostShader = null; highlightedSprite.RenderOrder = 0; } + _highlightedSprites.Clear(); } diff --git a/Content.Client/State/GameScreenBase.cs b/Content.Client/State/GameScreenBase.cs index 00e836ffd0..3957c5576e 100644 --- a/Content.Client/State/GameScreenBase.cs +++ b/Content.Client/State/GameScreenBase.cs @@ -27,7 +27,7 @@ namespace Content.Client.State // OH GOD. // Ok actually it's fine. // Instantiated dynamically through the StateManager, Dependencies will be resolved. - public partial class GameScreenBase : Robust.Client.State.State + public partial class GameScreenBase : Robust.Client.State.State, IEntityEventSubscriber { [Dependency] protected readonly IClientEntityManager EntityManager = default!; [Dependency] protected readonly IInputManager InputManager = default!; @@ -38,17 +38,29 @@ namespace Content.Client.State [Dependency] protected readonly IMapManager MapManager = default!; [Dependency] protected readonly IUserInterfaceManager UserInterfaceManager = default!; [Dependency] protected readonly IConfigurationManager ConfigurationManager = default!; + [Dependency] private readonly IEntityManager _entityManager = default!; + + private IEventBus _eventBus => _entityManager.EventBus; private IEntity _lastHoveredEntity; + private bool _outlineEnabled = true; + public override void Startup() { InputManager.KeyBindStateChanged += OnKeyBindStateChanged; + _eventBus.SubscribeEvent(EventSource.Local, this, HandleOutlineToggle); } public override void Shutdown() { InputManager.KeyBindStateChanged -= OnKeyBindStateChanged; + _eventBus.UnsubscribeEvent(EventSource.Local, this); + } + + private void HandleOutlineToggle(OutlineToggleMessage message) + { + _outlineEnabled = message.Enabled; } public override void FrameUpdate(FrameEventArgs e) @@ -72,7 +84,7 @@ namespace Content.Client.State } InteractionOutlineComponent outline; - if(!ConfigurationManager.GetCVar(CCVars.OutlineEnabled)) + if(!_outlineEnabled || !ConfigurationManager.GetCVar(CCVars.OutlineEnabled)) { if(entityToClick != null && entityToClick.TryGetComponent(out outline)) { diff --git a/Content.Client/State/OutlineToggleMessage.cs b/Content.Client/State/OutlineToggleMessage.cs new file mode 100644 index 0000000000..bef225fda4 --- /dev/null +++ b/Content.Client/State/OutlineToggleMessage.cs @@ -0,0 +1,14 @@ +using Robust.Shared.GameObjects; + +namespace Content.Client.State +{ + public sealed class OutlineToggleMessage : EntitySystemMessage + { + public bool Enabled { get; } + + public OutlineToggleMessage(bool enabled) + { + Enabled = enabled; + } + } +} diff --git a/Content.Server/GameObjects/Components/Buckle/BuckleComponent.cs b/Content.Server/GameObjects/Components/Buckle/BuckleComponent.cs index f6f4c640f5..61f1539e22 100644 --- a/Content.Server/GameObjects/Components/Buckle/BuckleComponent.cs +++ b/Content.Server/GameObjects/Components/Buckle/BuckleComponent.cs @@ -33,6 +33,7 @@ using Robust.Shared.ViewVariables; namespace Content.Server.GameObjects.Components.Buckle { [RegisterComponent] + [ComponentReference(typeof(SharedBuckleComponent))] public class BuckleComponent : SharedBuckleComponent, IInteractHand { [Dependency] private readonly IGameTiming _gameTiming = default!; @@ -44,11 +45,6 @@ namespace Content.Server.GameObjects.Components.Buckle private int _size; - /// - /// The range from which this entity can buckle to a . - /// - [ViewVariables] - private float _range; /// /// The amount of time that must pass for this entity to /// be able to unbuckle after recently buckling. @@ -184,7 +180,7 @@ namespace Content.Server.GameObjects.Components.Buckle var component = strap; bool Ignored(IEntity entity) => entity == Owner || entity == user || entity == component.Owner; - if (!Owner.InRangeUnobstructed(strap, _range, predicate: Ignored, popup: true)) + if (!Owner.InRangeUnobstructed(strap, Range, predicate: Ignored, popup: true)) { return false; } @@ -319,7 +315,7 @@ namespace Content.Server.GameObjects.Components.Buckle return false; } - if (!user.InRangeUnobstructed(oldBuckledTo, _range, popup: true)) + if (!user.InRangeUnobstructed(oldBuckledTo, Range, popup: true)) { return false; } @@ -385,7 +381,6 @@ namespace Content.Server.GameObjects.Components.Buckle base.ExposeData(serializer); serializer.DataField(ref _size, "size", 100); - serializer.DataField(ref _range, "range", SharedInteractionSystem.InteractionRange / 1.4f); var seconds = 0.25f; serializer.DataField(ref seconds, "cooldown", 0.25f); diff --git a/Content.Server/GameObjects/Components/Disposal/DisposalMailingUnitComponent.cs b/Content.Server/GameObjects/Components/Disposal/DisposalMailingUnitComponent.cs index 0bc3be51b7..072c584b04 100644 --- a/Content.Server/GameObjects/Components/Disposal/DisposalMailingUnitComponent.cs +++ b/Content.Server/GameObjects/Components/Disposal/DisposalMailingUnitComponent.cs @@ -10,13 +10,11 @@ using Content.Server.GameObjects.Components.Items.Storage; using Content.Server.GameObjects.Components.Power.ApcNetComponents; using Content.Server.GameObjects.EntitySystems.DeviceNetwork; using Content.Server.GameObjects.EntitySystems.DoAfter; -using Content.Server.Interfaces; using Content.Server.Interfaces.GameObjects.Components.Items; using Content.Server.Utility; using Content.Shared.GameObjects.Components; using Content.Shared.GameObjects.Components.Body; using Content.Shared.GameObjects.Components.Disposal; -using Content.Shared.GameObjects.EntitySystems; using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.GameObjects.Verbs; using Content.Shared.Interfaces; @@ -47,7 +45,7 @@ namespace Content.Server.GameObjects.Components.Disposal [ComponentReference(typeof(SharedDisposalMailingUnitComponent))] [ComponentReference(typeof(IActivate))] [ComponentReference(typeof(IInteractUsing))] - public class DisposalMailingUnitComponent : SharedDisposalMailingUnitComponent, IInteractHand, IActivate, IInteractUsing, IDragDropOn + public class DisposalMailingUnitComponent : SharedDisposalMailingUnitComponent, IInteractHand, IActivate, IInteractUsing { [Dependency] private readonly IGameTiming _gameTiming = default!; @@ -145,7 +143,7 @@ namespace Content.Server.GameObjects.Components.Disposal /// private (PressureState State, string Localized) _locState; - public bool CanInsert(IEntity entity) + public override bool CanInsert(IEntity entity) { if (!Anchored) { @@ -763,12 +761,12 @@ namespace Content.Server.GameObjects.Components.Disposal return TryDrop(eventArgs.User, eventArgs.Using); } - bool IDragDropOn.CanDragDropOn(DragDropEventArgs eventArgs) + public override bool CanDragDropOn(DragDropEventArgs eventArgs) { return CanInsert(eventArgs.Dragged); } - bool IDragDropOn.DragDropOn(DragDropEventArgs eventArgs) + public override bool DragDropOn(DragDropEventArgs eventArgs) { _ = TryInsert(eventArgs.Dragged, eventArgs.User); return true; diff --git a/Content.Server/GameObjects/Components/Disposal/DisposalUnitComponent.cs b/Content.Server/GameObjects/Components/Disposal/DisposalUnitComponent.cs index d3f1b3230b..d1612da8e5 100644 --- a/Content.Server/GameObjects/Components/Disposal/DisposalUnitComponent.cs +++ b/Content.Server/GameObjects/Components/Disposal/DisposalUnitComponent.cs @@ -6,20 +6,17 @@ using System.Threading; using System.Threading.Tasks; using Content.Server.Atmos; using Content.Server.GameObjects.Components.GUI; -using Content.Server.GameObjects.Components.Items.Storage; using Content.Server.GameObjects.Components.Power.ApcNetComponents; +using Content.Server.GameObjects.Components.Items.Storage; using Content.Server.GameObjects.EntitySystems; using Content.Server.GameObjects.EntitySystems.DoAfter; using Content.Server.Interfaces; using Content.Server.Interfaces.GameObjects.Components.Items; using Content.Server.Utility; +using Content.Shared.GameObjects.Components.Disposal; using Content.Shared.Atmos; using Content.Shared.GameObjects.Components.Body; -using Content.Shared.GameObjects.Components.Damage; -using Content.Shared.GameObjects.Components.Disposal; -using Content.Shared.GameObjects.Components.Items; using Content.Shared.GameObjects.Components.Mobs.State; -using Content.Shared.GameObjects.EntitySystems; using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.GameObjects.Verbs; using Content.Shared.Interfaces; @@ -51,7 +48,7 @@ namespace Content.Server.GameObjects.Components.Disposal [ComponentReference(typeof(SharedDisposalUnitComponent))] [ComponentReference(typeof(IActivate))] [ComponentReference(typeof(IInteractUsing))] - public class DisposalUnitComponent : SharedDisposalUnitComponent, IInteractHand, IActivate, IInteractUsing, IDragDropOn, IThrowCollide, IGasMixtureHolder + public class DisposalUnitComponent : SharedDisposalUnitComponent, IInteractHand, IActivate, IInteractUsing, IThrowCollide, IGasMixtureHolder { [Dependency] private readonly IGameTiming _gameTiming = default!; @@ -137,17 +134,16 @@ namespace Content.Server.GameObjects.Components.Disposal public GasMixture Air { get; set; } = default!; - public bool CanInsert(IEntity entity) + public override bool CanInsert(IEntity entity) { - if (!Anchored) - { + if (!base.CanInsert(entity)) return false; - } if (!entity.TryGetComponent(out IPhysicsComponent? physics) || !physics.CanCollide) { - if (!(entity.TryGetComponent(out IMobStateComponent? state) && state.IsDead())) { + if (entity.TryGetComponent(out IMobStateComponent? state) && state.IsDead()) + { return false; } } @@ -676,12 +672,14 @@ namespace Content.Server.GameObjects.Components.Disposal return TryDrop(eventArgs.User, eventArgs.Using); } - bool IDragDropOn.CanDragDropOn(DragDropEventArgs eventArgs) + public override bool CanDragDropOn(DragDropEventArgs eventArgs) { + // Base is redundant given this already calls the base CanInsert + // If that changes then update this return CanInsert(eventArgs.Dragged); } - bool IDragDropOn.DragDropOn(DragDropEventArgs eventArgs) + public override bool DragDropOn(DragDropEventArgs eventArgs) { _ = TryInsert(eventArgs.Dragged, eventArgs.User); return true; diff --git a/Content.Server/GameObjects/Components/Medical/MedicalScannerComponent.cs b/Content.Server/GameObjects/Components/Medical/MedicalScannerComponent.cs index b5c5f8d9ee..45fe55e65f 100644 --- a/Content.Server/GameObjects/Components/Medical/MedicalScannerComponent.cs +++ b/Content.Server/GameObjects/Components/Medical/MedicalScannerComponent.cs @@ -35,7 +35,7 @@ namespace Content.Server.GameObjects.Components.Medical [RegisterComponent] [ComponentReference(typeof(IActivate))] [ComponentReference(typeof(SharedMedicalScannerComponent))] - public class MedicalScannerComponent : SharedMedicalScannerComponent, IActivate, IDragDropOn, IDestroyAct + public class MedicalScannerComponent : SharedMedicalScannerComponent, IActivate, IDestroyAct { [Dependency] private readonly IGameTiming _gameTiming = default!; @@ -292,12 +292,7 @@ namespace Content.Server.GameObjects.Components.Medical } } - public bool CanDragDropOn(DragDropEventArgs eventArgs) - { - return eventArgs.Dragged.HasComponent(); - } - - public bool DragDropOn(DragDropEventArgs eventArgs) + public override bool DragDropOn(DragDropEventArgs eventArgs) { _bodyContainer.Insert(eventArgs.Dragged); return true; diff --git a/Content.Server/GameObjects/Components/Movement/ClimbableComponent.cs b/Content.Server/GameObjects/Components/Movement/ClimbableComponent.cs index 97f9d4e21d..0b6e78f4f7 100644 --- a/Content.Server/GameObjects/Components/Movement/ClimbableComponent.cs +++ b/Content.Server/GameObjects/Components/Movement/ClimbableComponent.cs @@ -27,41 +27,36 @@ namespace Content.Server.GameObjects.Components.Movement { [RegisterComponent] [ComponentReference(typeof(IClimbable))] - public class ClimbableComponent : SharedClimbableComponent, IDragDropOn + public class ClimbableComponent : SharedClimbableComponent { - /// - /// The range from which this entity can be climbed. - /// - [ViewVariables] - private float _range; - /// /// The time it takes to climb onto the entity. /// [ViewVariables] private float _climbDelay; - private DoAfterSystem _doAfterSystem; - public override void Initialize() { base.Initialize(); - Owner.EnsureComponentWarn(out PhysicsComponent _); - - _doAfterSystem = EntitySystem.Get(); + if (!Owner.EnsureComponent(out PhysicsComponent _)) + { + Logger.Warning($"Entity {Owner.Name} at {Owner.Transform.MapPosition} didn't have a {nameof(PhysicsComponent)}"); + } } public override void ExposeData(ObjectSerializer serializer) { base.ExposeData(serializer); - serializer.DataField(ref _range, "range", SharedInteractionSystem.InteractionRange / 1.4f); serializer.DataField(ref _climbDelay, "delay", 0.8f); } - bool IDragDropOn.CanDragDropOn(DragDropEventArgs eventArgs) + public override bool CanDragDropOn(DragDropEventArgs eventArgs) { + if (!base.CanDragDropOn(eventArgs)) + return false; + string reason; bool canVault; @@ -105,7 +100,7 @@ namespace Content.Server.GameObjects.Components.Movement return false; } - if (!user.InRangeUnobstructed(target, _range)) + if (!user.InRangeUnobstructed(target, Range)) { reason = Loc.GetString("You can't reach there!"); return false; @@ -139,8 +134,8 @@ namespace Content.Server.GameObjects.Components.Movement bool Ignored(IEntity entity) => entity == target || entity == user || entity == dragged; - if (!user.InRangeUnobstructed(target, _range, predicate: Ignored) || - !user.InRangeUnobstructed(dragged, _range, predicate: Ignored)) + if (!user.InRangeUnobstructed(target, Range, predicate: Ignored) || + !user.InRangeUnobstructed(dragged, Range, predicate: Ignored)) { reason = Loc.GetString("You can't reach there!"); return false; @@ -150,7 +145,7 @@ namespace Content.Server.GameObjects.Components.Movement return true; } - bool IDragDropOn.DragDropOn(DragDropEventArgs eventArgs) + public override bool DragDropOn(DragDropEventArgs eventArgs) { if (eventArgs.User == eventArgs.Dragged) { @@ -174,7 +169,7 @@ namespace Content.Server.GameObjects.Components.Movement BreakOnStun = true }; - var result = await _doAfterSystem.DoAfter(doAfterEventArgs); + var result = await EntitySystem.Get().DoAfter(doAfterEventArgs); if (result != DoAfterStatus.Cancelled && entityToMove.TryGetComponent(out IPhysicsComponent body) && body.PhysicsShapes.Count >= 1) { @@ -219,7 +214,7 @@ namespace Content.Server.GameObjects.Components.Movement BreakOnStun = true }; - var result = await _doAfterSystem.DoAfter(doAfterEventArgs); + var result = await EntitySystem.Get().DoAfter(doAfterEventArgs); if (result != DoAfterStatus.Cancelled && user.TryGetComponent(out IPhysicsComponent body) && body.PhysicsShapes.Count >= 1) { diff --git a/Content.Server/GameObjects/Components/Movement/ClimbingComponent.cs b/Content.Server/GameObjects/Components/Movement/ClimbingComponent.cs index 8c3a5e84e2..a924f93d96 100644 --- a/Content.Server/GameObjects/Components/Movement/ClimbingComponent.cs +++ b/Content.Server/GameObjects/Components/Movement/ClimbingComponent.cs @@ -9,6 +9,7 @@ using Robust.Shared.Maths; namespace Content.Server.GameObjects.Components.Movement { [RegisterComponent] + [ComponentReference(typeof(SharedClimbingComponent))] public class ClimbingComponent : SharedClimbingComponent { private bool _isClimbing; diff --git a/Content.Server/GameObjects/Components/Strap/StrapComponent.cs b/Content.Server/GameObjects/Components/Strap/StrapComponent.cs index 253a299ca7..a9a08ec31a 100644 --- a/Content.Server/GameObjects/Components/Strap/StrapComponent.cs +++ b/Content.Server/GameObjects/Components/Strap/StrapComponent.cs @@ -207,9 +207,7 @@ namespace Content.Server.GameObjects.Components.Strap parent = parent.Parent; } - var range = SharedInteractionSystem.InteractionRange / 2; - - if (!user.InRangeUnobstructed(component, range)) + if (!user.InRangeUnobstructed(component, buckle.Range)) { return; } @@ -228,5 +226,11 @@ namespace Content.Server.GameObjects.Components.Strap buckle.ToggleBuckle(user, component.Owner); } } + + public override bool DragDropOn(DragDropEventArgs eventArgs) + { + if (!eventArgs.Dragged.TryGetComponent(out BuckleComponent? buckleComponent)) return false; + return buckleComponent.TryBuckle(eventArgs.User, Owner); + } } } diff --git a/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingSystem.cs b/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingSystem.cs index 0c86d38db0..4c39b8b4fe 100644 --- a/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingSystem.cs @@ -306,7 +306,8 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding // If we've moved to space or the likes then remove us. if (moveEvent.Sender.Deleted || !moveEvent.Sender.TryGetComponent(out IPhysicsComponent physics) || - !PathfindingNode.IsRelevant(moveEvent.Sender, physics)) + !PathfindingNode.IsRelevant(moveEvent.Sender, physics) || + moveEvent.NewPosition.GetGridId(EntityManager) == GridId.Invalid) { HandleEntityRemove(moveEvent.Sender); return; diff --git a/Content.Server/GameObjects/EntitySystems/Click/InteractionSystem.cs b/Content.Server/GameObjects/EntitySystems/Click/InteractionSystem.cs index 5b774388e7..dde99dbddd 100644 --- a/Content.Server/GameObjects/EntitySystems/Click/InteractionSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/Click/InteractionSystem.cs @@ -71,6 +71,7 @@ namespace Content.Server.GameObjects.EntitySystems.Click var interactionArgs = new DragDropEventArgs(performer, msg.DropLocation, dropped, target); // must be in range of both the target and the object they are drag / dropping + // Client also does this check but ya know we gotta validate it. if (!interactionArgs.InRangeUnobstructed(ignoreInsideBlocker: true, popup: true)) return; // trigger dragdrops on the dropped entity diff --git a/Content.Shared/GameObjects/Components/Buckle/SharedBuckleComponent.cs b/Content.Shared/GameObjects/Components/Buckle/SharedBuckleComponent.cs index a78bd4a35c..4d86409a72 100644 --- a/Content.Shared/GameObjects/Components/Buckle/SharedBuckleComponent.cs +++ b/Content.Shared/GameObjects/Components/Buckle/SharedBuckleComponent.cs @@ -11,6 +11,7 @@ using Robust.Shared.GameObjects.Components; using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Physics; using Robust.Shared.Serialization; +using Robust.Shared.ViewVariables; namespace Content.Shared.GameObjects.Components.Buckle { @@ -19,6 +20,18 @@ namespace Content.Shared.GameObjects.Components.Buckle public sealed override string Name => "Buckle"; public sealed override uint? NetID => ContentNetIDs.BUCKLE; + /// + /// The range from which this entity can buckle to a . + /// + [ViewVariables] + public float Range { get; protected set; } + + public override void ExposeData(ObjectSerializer serializer) + { + base.ExposeData(serializer); + serializer.DataReadWriteFunction("range", SharedInteractionSystem.InteractionRange / 1.4f, value => Range = value, () => Range); + } + /// /// True if the entity is buckled, false otherwise. /// diff --git a/Content.Shared/GameObjects/Components/Disposal/SharedDisposalMailingUnitComponent.cs b/Content.Shared/GameObjects/Components/Disposal/SharedDisposalMailingUnitComponent.cs index 5c9def4322..da67e8d4d5 100644 --- a/Content.Shared/GameObjects/Components/Disposal/SharedDisposalMailingUnitComponent.cs +++ b/Content.Shared/GameObjects/Components/Disposal/SharedDisposalMailingUnitComponent.cs @@ -7,7 +7,7 @@ using Robust.Shared.Utility; namespace Content.Shared.GameObjects.Components.Disposal { - public abstract class SharedDisposalMailingUnitComponent : SharedDisposalUnitComponent, ICollideSpecial + public abstract class SharedDisposalMailingUnitComponent : SharedDisposalUnitComponent { public override string Name => "DisposalMailingUnit"; diff --git a/Content.Shared/GameObjects/Components/Disposal/SharedDisposalUnitComponent.cs b/Content.Shared/GameObjects/Components/Disposal/SharedDisposalUnitComponent.cs index d777c2d786..af7a801728 100644 --- a/Content.Shared/GameObjects/Components/Disposal/SharedDisposalUnitComponent.cs +++ b/Content.Shared/GameObjects/Components/Disposal/SharedDisposalUnitComponent.cs @@ -1,6 +1,11 @@ #nullable enable using System; using System.Collections.Generic; +using Content.Shared.GameObjects.Components.Body; +using Content.Shared.GameObjects.Components.Damage; +using Content.Shared.GameObjects.Components.Mobs.State; +using Content.Shared.GameObjects.Components.Storage; +using Content.Shared.Interfaces.GameObjects.Components; using Robust.Shared.GameObjects; using Robust.Shared.GameObjects.Components; using Robust.Shared.GameObjects.Components.UserInterface; @@ -12,7 +17,7 @@ using Robust.Shared.ViewVariables; namespace Content.Shared.GameObjects.Components.Disposal { - public abstract class SharedDisposalUnitComponent : Component, ICollideSpecial + public abstract class SharedDisposalUnitComponent : Component, ICollideSpecial, IDragDropOn { public override string Name => "DisposalUnit"; @@ -160,5 +165,34 @@ namespace Content.Shared.GameObjects.Components.Disposal { Key } + + public virtual bool CanInsert(IEntity entity) + { + if (!Anchored) + return false; + + if (!entity.TryGetComponent(out IPhysicsComponent? physics) || + !physics.CanCollide) + { + if (!(entity.TryGetComponent(out IMobStateComponent? damageState) && damageState.IsDead())) { + return false; + } + } + + if (!entity.HasComponent() && + !entity.HasComponent()) + { + return false; + } + + return true; + } + + public virtual bool CanDragDropOn(DragDropEventArgs eventArgs) + { + return CanInsert(eventArgs.Dragged); + } + + public abstract bool DragDropOn(DragDropEventArgs eventArgs); } } diff --git a/Content.Shared/GameObjects/Components/Medical/SharedMedicalScannerComponent.cs b/Content.Shared/GameObjects/Components/Medical/SharedMedicalScannerComponent.cs index 10262d1fd2..e330d12b93 100644 --- a/Content.Shared/GameObjects/Components/Medical/SharedMedicalScannerComponent.cs +++ b/Content.Shared/GameObjects/Components/Medical/SharedMedicalScannerComponent.cs @@ -1,13 +1,15 @@ using System; using System.Collections.Generic; using Content.Shared.Damage; +using Content.Shared.GameObjects.Components.Body; +using Content.Shared.Interfaces.GameObjects.Components; using Robust.Shared.GameObjects; using Robust.Shared.GameObjects.Components.UserInterface; using Robust.Shared.Serialization; namespace Content.Shared.GameObjects.Components.Medical { - public class SharedMedicalScannerComponent : Component + public abstract class SharedMedicalScannerComponent : Component, IDragDropOn { public override string Name => "MedicalScanner"; @@ -78,5 +80,11 @@ namespace Content.Shared.GameObjects.Components.Medical } + public bool CanDragDropOn(DragDropEventArgs eventArgs) + { + return eventArgs.Dragged.HasComponent(); + } + + public abstract bool DragDropOn(DragDropEventArgs eventArgs); } } diff --git a/Content.Shared/GameObjects/Components/Movement/SharedClimbableComponent.cs b/Content.Shared/GameObjects/Components/Movement/SharedClimbableComponent.cs index 951d051ac1..5aec1e46df 100644 --- a/Content.Shared/GameObjects/Components/Movement/SharedClimbableComponent.cs +++ b/Content.Shared/GameObjects/Components/Movement/SharedClimbableComponent.cs @@ -1,11 +1,34 @@ -using Robust.Shared.GameObjects; +using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.Interfaces.GameObjects.Components; +using Robust.Shared.GameObjects; +using Robust.Shared.Serialization; +using Robust.Shared.ViewVariables; namespace Content.Shared.GameObjects.Components.Movement { public interface IClimbable { }; - public class SharedClimbableComponent : Component, IClimbable + public abstract class SharedClimbableComponent : Component, IClimbable, IDragDropOn { public sealed override string Name => "Climbable"; + + /// + /// The range from which this entity can be climbed. + /// + [ViewVariables] + protected float Range; + + public override void ExposeData(ObjectSerializer serializer) + { + base.ExposeData(serializer); + serializer.DataField(ref Range, "range", SharedInteractionSystem.InteractionRange / 1.4f); + } + + public virtual bool CanDragDropOn(DragDropEventArgs eventArgs) + { + return eventArgs.Dragged.HasComponent(); + } + + public abstract bool DragDropOn(DragDropEventArgs eventArgs); } } diff --git a/Content.Shared/GameObjects/Components/Movement/SharedClimbingComponent.cs b/Content.Shared/GameObjects/Components/Movement/SharedClimbingComponent.cs index e55e599f63..db39b8d368 100644 --- a/Content.Shared/GameObjects/Components/Movement/SharedClimbingComponent.cs +++ b/Content.Shared/GameObjects/Components/Movement/SharedClimbingComponent.cs @@ -6,11 +6,10 @@ using Robust.Shared.GameObjects; using Robust.Shared.GameObjects.Components; using Robust.Shared.Physics; using Robust.Shared.Serialization; -using Content.Shared.Interfaces.GameObjects.Components; namespace Content.Shared.GameObjects.Components.Movement { - public abstract class SharedClimbingComponent : Component, IActionBlocker, ICollideSpecial, IDraggable + public abstract class SharedClimbingComponent : Component, IActionBlocker, ICollideSpecial { public sealed override string Name => "Climbing"; public sealed override uint? NetID => ContentNetIDs.CLIMBING; @@ -47,16 +46,6 @@ namespace Content.Shared.GameObjects.Components.Movement return false; } - bool IDraggable.CanDrop(CanDropEventArgs args) - { - return args.Target.HasComponent(); - } - - bool IDraggable.Drop(DragDropEventArgs args) - { - return false; - } - public override void Initialize() { base.Initialize(); diff --git a/Content.Shared/GameObjects/Components/Strap/SharedStrapComponent.cs b/Content.Shared/GameObjects/Components/Strap/SharedStrapComponent.cs index cd07ec0942..66a5aa73d3 100644 --- a/Content.Shared/GameObjects/Components/Strap/SharedStrapComponent.cs +++ b/Content.Shared/GameObjects/Components/Strap/SharedStrapComponent.cs @@ -1,4 +1,8 @@ using System; +using Content.Shared.GameObjects.Components.Buckle; +using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.Interfaces.GameObjects.Components; +using Content.Shared.Utility; using Robust.Shared.GameObjects; using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Serialization; @@ -23,11 +27,21 @@ namespace Content.Shared.GameObjects.Components.Strap Down } - public abstract class SharedStrapComponent : Component + public abstract class SharedStrapComponent : Component, IDragDropOn { public sealed override string Name => "Strap"; public sealed override uint? NetID => ContentNetIDs.STRAP; + + public virtual bool CanDragDropOn(DragDropEventArgs eventArgs) + { + if (!eventArgs.Dragged.TryGetComponent(out SharedBuckleComponent buckleComponent)) return false; + bool Ignored(IEntity entity) => entity == eventArgs.User || entity == eventArgs.Dragged || entity == eventArgs.Target; + + return eventArgs.Target.InRangeUnobstructed(eventArgs.Dragged, buckleComponent.Range, predicate: Ignored); + } + + public abstract bool DragDropOn(DragDropEventArgs eventArgs); } [Serializable, NetSerializable] diff --git a/Content.Shared/Interfaces/GameObjects/Components/Interaction/IDragDropOn.cs b/Content.Shared/Interfaces/GameObjects/Components/Interaction/IDragDropOn.cs index 1100bdb3d3..761fbe86de 100644 --- a/Content.Shared/Interfaces/GameObjects/Components/Interaction/IDragDropOn.cs +++ b/Content.Shared/Interfaces/GameObjects/Components/Interaction/IDragDropOn.cs @@ -7,7 +7,7 @@ namespace Content.Shared.Interfaces.GameObjects.Components public interface IDragDropOn { /// - /// Invoked server-side when another entity is being dragged and dropped + /// Invoked when another entity is being dragged and dropped /// onto this one before invoking . /// Note that other drag and drop interactions may be attempted if /// this one fails.