Drag changes (#2487)
* Drag changes * Higlights only show near cursor * Don't highlight un-droppable entities * Fixes invalid highlights issue * Also the scanner * 2 months fix * Address reviews Co-authored-by: Metal Gear Sloth <metalgearsloth@gmail.com>
This commit is contained in:
@@ -1,6 +1,4 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
using Content.Client.GameObjects.Components.Disposal;
|
|
||||||
using Content.Client.GameObjects.Components.MedicalScanner;
|
|
||||||
using Content.Shared.GameObjects.Components.Body;
|
using Content.Shared.GameObjects.Components.Body;
|
||||||
using Content.Shared.Interfaces.GameObjects.Components;
|
using Content.Shared.Interfaces.GameObjects.Components;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
@@ -11,16 +9,14 @@ namespace Content.Client.GameObjects.Components.Body
|
|||||||
[ComponentReference(typeof(IBody))]
|
[ComponentReference(typeof(IBody))]
|
||||||
public class BodyComponent : SharedBodyComponent, IDraggable
|
public class BodyComponent : SharedBodyComponent, IDraggable
|
||||||
{
|
{
|
||||||
public bool CanDrop(CanDropEventArgs eventArgs)
|
bool IDraggable.CanStartDrag(StartDragDropEventArgs args)
|
||||||
{
|
{
|
||||||
if (eventArgs.Target.HasComponent<DisposalUnitComponent>() ||
|
return true;
|
||||||
eventArgs.Target.HasComponent<MedicalScannerComponent>() ||
|
}
|
||||||
eventArgs.Target.HasComponent<DisposalMailingUnitComponent>())
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
public bool CanDrop(CanDropEventArgs args)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using Robust.Shared.Interfaces.GameObjects;
|
|||||||
namespace Content.Client.GameObjects.Components.Buckle
|
namespace Content.Client.GameObjects.Components.Buckle
|
||||||
{
|
{
|
||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
|
[ComponentReference(typeof(SharedBuckleComponent))]
|
||||||
public class BuckleComponent : SharedBuckleComponent
|
public class BuckleComponent : SharedBuckleComponent
|
||||||
{
|
{
|
||||||
private bool _buckled;
|
private bool _buckled;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Content.Shared.GameObjects.Components.Disposal;
|
using Content.Shared.GameObjects.Components.Disposal;
|
||||||
|
using Content.Shared.Interfaces.GameObjects.Components;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
|
|
||||||
namespace Content.Client.GameObjects.Components.Disposal
|
namespace Content.Client.GameObjects.Components.Disposal
|
||||||
@@ -7,5 +8,9 @@ namespace Content.Client.GameObjects.Components.Disposal
|
|||||||
[ComponentReference(typeof(SharedDisposalMailingUnitComponent))]
|
[ComponentReference(typeof(SharedDisposalMailingUnitComponent))]
|
||||||
public class DisposalMailingUnitComponent : SharedDisposalMailingUnitComponent
|
public class DisposalMailingUnitComponent : SharedDisposalMailingUnitComponent
|
||||||
{
|
{
|
||||||
|
public override bool DragDropOn(DragDropEventArgs eventArgs)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Content.Shared.GameObjects.Components.Disposal;
|
using Content.Shared.GameObjects.Components.Disposal;
|
||||||
|
using Content.Shared.Interfaces.GameObjects.Components;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
|
|
||||||
namespace Content.Client.GameObjects.Components.Disposal
|
namespace Content.Client.GameObjects.Components.Disposal
|
||||||
@@ -7,5 +8,9 @@ namespace Content.Client.GameObjects.Components.Disposal
|
|||||||
[ComponentReference(typeof(SharedDisposalUnitComponent))]
|
[ComponentReference(typeof(SharedDisposalUnitComponent))]
|
||||||
public class DisposalUnitComponent : SharedDisposalUnitComponent
|
public class DisposalUnitComponent : SharedDisposalUnitComponent
|
||||||
{
|
{
|
||||||
|
public override bool DragDropOn(DragDropEventArgs eventArgs)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Content.Shared.GameObjects.Components.Medical;
|
using Content.Shared.GameObjects.Components.Medical;
|
||||||
|
using Content.Shared.Interfaces.GameObjects.Components;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
|
|
||||||
namespace Content.Client.GameObjects.Components.MedicalScanner
|
namespace Content.Client.GameObjects.Components.MedicalScanner
|
||||||
@@ -7,5 +8,9 @@ namespace Content.Client.GameObjects.Components.MedicalScanner
|
|||||||
[ComponentReference(typeof(SharedMedicalScannerComponent))]
|
[ComponentReference(typeof(SharedMedicalScannerComponent))]
|
||||||
public class MedicalScannerComponent : SharedMedicalScannerComponent
|
public class MedicalScannerComponent : SharedMedicalScannerComponent
|
||||||
{
|
{
|
||||||
|
public override bool DragDropOn(DragDropEventArgs eventArgs)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
using Content.Shared.GameObjects.Components.Movement;
|
using Content.Shared.GameObjects.Components.Movement;
|
||||||
|
using Content.Shared.Interfaces.GameObjects.Components;
|
||||||
|
using Content.Shared.Utility;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
|
|
||||||
namespace Content.Client.GameObjects.Components.Movement
|
namespace Content.Client.GameObjects.Components.Movement
|
||||||
{
|
{
|
||||||
@@ -7,6 +10,22 @@ namespace Content.Client.GameObjects.Components.Movement
|
|||||||
[ComponentReference(typeof(IClimbable))]
|
[ComponentReference(typeof(IClimbable))]
|
||||||
public class ClimbableComponent : SharedClimbableComponent
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using Robust.Shared.GameObjects;
|
|||||||
namespace Content.Client.GameObjects.Components.Movement
|
namespace Content.Client.GameObjects.Components.Movement
|
||||||
{
|
{
|
||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
|
[ComponentReference(typeof(SharedClimbingComponent))]
|
||||||
public class ClimbingComponent : SharedClimbingComponent
|
public class ClimbingComponent : SharedClimbingComponent
|
||||||
{
|
{
|
||||||
public override void HandleComponentState(ComponentState curState, ComponentState nextState)
|
public override void HandleComponentState(ComponentState curState, ComponentState nextState)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
using Content.Shared.GameObjects.Components.Strap;
|
using Content.Shared.GameObjects.Components.Strap;
|
||||||
|
using Content.Shared.Interfaces.GameObjects.Components;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
|
|
||||||
namespace Content.Client.GameObjects.Components.Strap
|
namespace Content.Client.GameObjects.Components.Strap
|
||||||
@@ -8,5 +9,9 @@ namespace Content.Client.GameObjects.Components.Strap
|
|||||||
[ComponentReference(typeof(SharedStrapComponent))]
|
[ComponentReference(typeof(SharedStrapComponent))]
|
||||||
public class StrapComponent : SharedStrapComponent
|
public class StrapComponent : SharedStrapComponent
|
||||||
{
|
{
|
||||||
|
public override bool DragDropOn(DragDropEventArgs eventArgs)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,24 +1,32 @@
|
|||||||
|
#nullable enable
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using Content.Client.State;
|
using Content.Client.State;
|
||||||
using Content.Client.Utility;
|
using Content.Client.Utility;
|
||||||
using Content.Shared.GameObjects;
|
|
||||||
using Content.Shared.GameObjects.EntitySystemMessages;
|
using Content.Shared.GameObjects.EntitySystemMessages;
|
||||||
using Content.Shared.GameObjects.EntitySystems;
|
using Content.Shared.GameObjects.EntitySystems;
|
||||||
|
using Content.Shared.Interfaces;
|
||||||
using Content.Shared.Interfaces.GameObjects.Components;
|
using Content.Shared.Interfaces.GameObjects.Components;
|
||||||
|
using Content.Shared.Utility;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Client.GameObjects;
|
using Robust.Client.GameObjects;
|
||||||
using Robust.Client.GameObjects.EntitySystems;
|
using Robust.Client.GameObjects.EntitySystems;
|
||||||
using Robust.Client.Graphics.Shaders;
|
using Robust.Client.Graphics.Shaders;
|
||||||
|
using Robust.Client.Interfaces.GameObjects.Components;
|
||||||
using Robust.Client.Interfaces.Graphics.ClientEye;
|
using Robust.Client.Interfaces.Graphics.ClientEye;
|
||||||
|
using Robust.Client.Interfaces.Input;
|
||||||
using Robust.Client.Interfaces.State;
|
using Robust.Client.Interfaces.State;
|
||||||
|
using Robust.Client.Player;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.GameObjects.Systems;
|
using Robust.Shared.GameObjects.Systems;
|
||||||
using Robust.Shared.Input;
|
using Robust.Shared.Input;
|
||||||
using Robust.Shared.Input.Binding;
|
using Robust.Shared.Input.Binding;
|
||||||
using Robust.Shared.Interfaces.GameObjects;
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
|
using Robust.Shared.Localization;
|
||||||
using Robust.Shared.Log;
|
using Robust.Shared.Log;
|
||||||
|
using Robust.Shared.Maths;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
|
using DrawDepth = Content.Shared.GameObjects.DrawDepth;
|
||||||
|
|
||||||
namespace Content.Client.GameObjects.EntitySystems
|
namespace Content.Client.GameObjects.EntitySystems
|
||||||
{
|
{
|
||||||
@@ -29,7 +37,9 @@ namespace Content.Client.GameObjects.EntitySystems
|
|||||||
public class DragDropSystem : EntitySystem
|
public class DragDropSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IStateManager _stateManager = default!;
|
[Dependency] private readonly IStateManager _stateManager = default!;
|
||||||
|
[Dependency] private readonly IInputManager _inputManager = default!;
|
||||||
[Dependency] private readonly IEyeManager _eyeManager = default!;
|
[Dependency] private readonly IEyeManager _eyeManager = default!;
|
||||||
|
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||||
|
|
||||||
// how often to recheck possible targets (prevents calling expensive
|
// how often to recheck possible targets (prevents calling expensive
|
||||||
@@ -45,9 +55,11 @@ namespace Content.Client.GameObjects.EntitySystems
|
|||||||
private const string ShaderDropTargetOutOfRange = "SelectionOutline";
|
private const string ShaderDropTargetOutOfRange = "SelectionOutline";
|
||||||
|
|
||||||
// entity performing the drag action
|
// entity performing the drag action
|
||||||
private IEntity _dragger;
|
|
||||||
|
private IEntity? _dragger;
|
||||||
private readonly List<IDraggable> _draggables = new();
|
private readonly List<IDraggable> _draggables = new();
|
||||||
private IEntity _dragShadow;
|
private IEntity? _dragShadow;
|
||||||
|
|
||||||
// time since mouse down over the dragged entity
|
// time since mouse down over the dragged entity
|
||||||
private float _mouseDownTime;
|
private float _mouseDownTime;
|
||||||
// how much time since last recheck of all possible targets
|
// 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
|
// can ignore any events sent to this system
|
||||||
private bool _isReplaying;
|
private bool _isReplaying;
|
||||||
|
|
||||||
private DragDropHelper<IEntity> _dragDropHelper;
|
private DragDropHelper<IEntity> _dragDropHelper = default!;
|
||||||
|
|
||||||
private ShaderInstance _dropTargetInRangeShader;
|
private ShaderInstance? _dropTargetInRangeShader;
|
||||||
private ShaderInstance _dropTargetOutOfRangeShader;
|
private ShaderInstance? _dropTargetOutOfRangeShader;
|
||||||
private SharedInteractionSystem _interactionSystem;
|
private SharedInteractionSystem _interactionSystem = default!;
|
||||||
private InputSystem _inputSystem;
|
private InputSystem _inputSystem = default!;
|
||||||
|
|
||||||
private readonly List<SpriteComponent> _highlightedSprites = new();
|
private readonly List<ISpriteComponent> _highlightedSprites = new();
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
@@ -112,7 +124,7 @@ namespace Content.Client.GameObjects.EntitySystems
|
|||||||
|
|
||||||
private bool OnUseMouseDown(in PointerInputCmdHandler.PointerInputCmdArgs args)
|
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
|
// 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)
|
// the mouse, canceling the drag, but just being cautious)
|
||||||
_dragDropHelper.EndDrag();
|
_dragDropHelper.EndDrag();
|
||||||
@@ -130,7 +142,7 @@ namespace Content.Client.GameObjects.EntitySystems
|
|||||||
var canDrag = false;
|
var canDrag = false;
|
||||||
foreach (var draggable in entity.GetAllComponents<IDraggable>())
|
foreach (var draggable in entity.GetAllComponents<IDraggable>())
|
||||||
{
|
{
|
||||||
var dragEventArgs = new StartDragDropEventArgs(args.Session.AttachedEntity, entity);
|
var dragEventArgs = new StartDragDropEventArgs(dragger, entity);
|
||||||
if (draggable.CanStartDrag(dragEventArgs))
|
if (draggable.CanStartDrag(dragEventArgs))
|
||||||
{
|
{
|
||||||
_draggables.Add(draggable);
|
_draggables.Add(draggable);
|
||||||
@@ -156,7 +168,6 @@ namespace Content.Client.GameObjects.EntitySystems
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private bool OnBeginDrag()
|
private bool OnBeginDrag()
|
||||||
{
|
{
|
||||||
if (_dragDropHelper.Dragged == null || _dragDropHelper.Dragged.Deleted)
|
if (_dragDropHelper.Dragged == null || _dragDropHelper.Dragged.Deleted)
|
||||||
@@ -183,6 +194,7 @@ namespace Content.Client.GameObjects.EntitySystems
|
|||||||
}
|
}
|
||||||
|
|
||||||
HighlightTargets();
|
HighlightTargets();
|
||||||
|
EntityManager.EventBus.RaiseEvent(EventSource.Local, new OutlineToggleMessage(false));
|
||||||
|
|
||||||
// drag initiated
|
// drag initiated
|
||||||
return true;
|
return true;
|
||||||
@@ -209,6 +221,9 @@ namespace Content.Client.GameObjects.EntitySystems
|
|||||||
var mousePos = _eyeManager.ScreenToMap(_dragDropHelper.MouseScreenPosition);
|
var mousePos = _eyeManager.ScreenToMap(_dragDropHelper.MouseScreenPosition);
|
||||||
// TODO: would use MapPosition instead if it had a setter, but it has no setter.
|
// 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?
|
// is that intentional, or should we add a setter for Transform.MapPosition?
|
||||||
|
if (_dragShadow == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
_dragShadow.Transform.WorldPosition = mousePos.Position;
|
_dragShadow.Transform.WorldPosition = mousePos.Position;
|
||||||
|
|
||||||
_targetRecheckTime += frameTime;
|
_targetRecheckTime += frameTime;
|
||||||
@@ -229,6 +244,7 @@ namespace Content.Client.GameObjects.EntitySystems
|
|||||||
EntityManager.DeleteEntity(_dragShadow);
|
EntityManager.DeleteEntity(_dragShadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EntityManager.EventBus.RaiseEvent(EventSource.Local, new OutlineToggleMessage(true));
|
||||||
_dragShadow = null;
|
_dragShadow = null;
|
||||||
_draggables.Clear();
|
_draggables.Clear();
|
||||||
_dragger = null;
|
_dragger = null;
|
||||||
@@ -238,7 +254,7 @@ namespace Content.Client.GameObjects.EntitySystems
|
|||||||
|
|
||||||
private bool OnUseMouseUp(in PointerInputCmdHandler.PointerInputCmdArgs args)
|
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
|
// haven't started the drag yet, quick mouseup, definitely treat it as a normal click by
|
||||||
// replaying the original cmd
|
// replaying the original cmd
|
||||||
@@ -251,40 +267,68 @@ namespace Content.Client.GameObjects.EntitySystems
|
|||||||
var adjustedInputMsg = new FullInputCmdMessage(args.OriginalMessage.Tick, args.OriginalMessage.SubTick,
|
var adjustedInputMsg = new FullInputCmdMessage(args.OriginalMessage.Tick, args.OriginalMessage.SubTick,
|
||||||
replayMsg.InputFunctionId, replayMsg.State, replayMsg.Coordinates, replayMsg.ScreenCoordinates, replayMsg.Uid);
|
replayMsg.InputFunctionId, replayMsg.State, replayMsg.Coordinates, replayMsg.ScreenCoordinates, replayMsg.Uid);
|
||||||
|
|
||||||
_inputSystem.HandleInputCommand(savedValue.Session, EngineKeyFunctions.Use,
|
if (savedValue.Session != null)
|
||||||
adjustedInputMsg, true);
|
{
|
||||||
|
_inputSystem.HandleInputCommand(savedValue.Session, EngineKeyFunctions.Use, adjustedInputMsg, true);
|
||||||
|
}
|
||||||
|
|
||||||
_isReplaying = false;
|
_isReplaying = false;
|
||||||
}
|
}
|
||||||
_dragDropHelper.EndDrag();
|
_dragDropHelper.EndDrag();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// now when ending the drag, we will not replay the click because
|
if (_dragger == null)
|
||||||
// by this time we've determined the input was actually a drag attempt
|
{
|
||||||
|
_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.
|
// 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
|
// We don't use args.EntityUid here because drag interactions generally should
|
||||||
// work even if there's something "on top" of the drop target
|
// work even if there's something "on top" of the drop target
|
||||||
if (!_interactionSystem.InRangeUnobstructed(_dragger,
|
if (!_interactionSystem.InRangeUnobstructed(_dragger,
|
||||||
args.Coordinates, ignoreInsideBlocker: true))
|
args.Coordinates, range, ignoreInsideBlocker: true))
|
||||||
{
|
{
|
||||||
_dragDropHelper.EndDrag();
|
_dragDropHelper.EndDrag();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var entities = GameScreenBase.GetEntitiesUnderPosition(_stateManager, args.Coordinates);
|
var entities = GameScreenBase.GetEntitiesUnderPosition(_stateManager, args.Coordinates);
|
||||||
|
var outOfRange = false;
|
||||||
|
|
||||||
foreach (var entity in entities)
|
foreach (var entity in entities)
|
||||||
{
|
{
|
||||||
// check if it's able to be dropped on by current dragged entity
|
// check if it's able to be dropped on by current dragged entity
|
||||||
var dropArgs = new DragDropEventArgs(_dragger, args.Coordinates, _dragDropHelper.Dragged, entity);
|
var dropArgs = new DragDropEventArgs(_dragger, args.Coordinates, _dragDropHelper.Dragged, entity);
|
||||||
|
var valid = true;
|
||||||
|
var anyDragDrop = false;
|
||||||
|
var dragDropOn = new List<IDragDropOn>();
|
||||||
|
|
||||||
|
foreach (var comp in entity.GetAllComponents<IDragDropOn>())
|
||||||
|
{
|
||||||
|
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)
|
foreach (var draggable in _draggables)
|
||||||
{
|
{
|
||||||
if (!draggable.CanDrop(dropArgs))
|
if (!draggable.CanDrop(dropArgs)) continue;
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// tell the server about the drop attempt
|
// tell the server about the drop attempt
|
||||||
RaiseNetworkEvent(new DragDropMessage(args.Coordinates, _dragDropHelper.Dragged.Uid,
|
RaiseNetworkEvent(new DragDropMessage(args.Coordinates, _dragDropHelper.Dragged.Uid,
|
||||||
@@ -292,11 +336,22 @@ namespace Content.Client.GameObjects.EntitySystems
|
|||||||
|
|
||||||
draggable.Drop(dropArgs);
|
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();
|
_dragDropHelper.EndDrag();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (outOfRange)
|
||||||
|
{
|
||||||
|
_playerManager.LocalPlayer?.ControlledEntity?.PopupMessage(Loc.GetString("You can't reach there!"));
|
||||||
|
}
|
||||||
|
|
||||||
_dragDropHelper.EndDrag();
|
_dragDropHelper.EndDrag();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -304,7 +359,9 @@ namespace Content.Client.GameObjects.EntitySystems
|
|||||||
private void HighlightTargets()
|
private void HighlightTargets()
|
||||||
{
|
{
|
||||||
if (_dragDropHelper.Dragged == null ||
|
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 " +
|
Logger.Warning("Programming error. Can't highlight drag and drop targets, not currently " +
|
||||||
"dragging anything or dragged entity / shadow was deleted.");
|
"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
|
// find possible targets on screen even if not reachable
|
||||||
// TODO: Duplicated in SpriteSystem
|
// TODO: Duplicated in SpriteSystem
|
||||||
var pvsBounds = _eyeManager.GetWorldViewport().Enlarged(5);
|
var mousePos = _eyeManager.ScreenToMap(_inputManager.MouseScreenPosition).Position;
|
||||||
var pvsEntities = EntityManager.GetEntitiesIntersecting(_eyeManager.CurrentMap, pvsBounds, true);
|
var bounds = new Box2(mousePos - 1.5f, mousePos + 1.5f);
|
||||||
|
var pvsEntities = EntityManager.GetEntitiesIntersecting(_eyeManager.CurrentMap, bounds, true);
|
||||||
foreach (var pvsEntity in pvsEntities)
|
foreach (var pvsEntity in pvsEntities)
|
||||||
{
|
{
|
||||||
if (pvsEntity.TryGetComponent<SpriteComponent>(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<IDragDropOn>())
|
||||||
{
|
{
|
||||||
// can't highlight if there's no sprite or it's not visible
|
valid = comp.CanDragDropOn(dropArgs);
|
||||||
if (inRangeSprite.Visible == false) continue;
|
|
||||||
|
|
||||||
// check if it's able to be dropped on by current dragged entity
|
if (valid.Value)
|
||||||
var canDropArgs = new CanDropEventArgs(_dragger, _dragDropHelper.Dragged, pvsEntity);
|
break;
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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.PostShader = null;
|
||||||
highlightedSprite.RenderOrder = 0;
|
highlightedSprite.RenderOrder = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
_highlightedSprites.Clear();
|
_highlightedSprites.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ namespace Content.Client.State
|
|||||||
// OH GOD.
|
// OH GOD.
|
||||||
// Ok actually it's fine.
|
// Ok actually it's fine.
|
||||||
// Instantiated dynamically through the StateManager, Dependencies will be resolved.
|
// 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 IClientEntityManager EntityManager = default!;
|
||||||
[Dependency] protected readonly IInputManager InputManager = default!;
|
[Dependency] protected readonly IInputManager InputManager = default!;
|
||||||
@@ -38,17 +38,29 @@ namespace Content.Client.State
|
|||||||
[Dependency] protected readonly IMapManager MapManager = default!;
|
[Dependency] protected readonly IMapManager MapManager = default!;
|
||||||
[Dependency] protected readonly IUserInterfaceManager UserInterfaceManager = default!;
|
[Dependency] protected readonly IUserInterfaceManager UserInterfaceManager = default!;
|
||||||
[Dependency] protected readonly IConfigurationManager ConfigurationManager = default!;
|
[Dependency] protected readonly IConfigurationManager ConfigurationManager = default!;
|
||||||
|
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||||
|
|
||||||
|
private IEventBus _eventBus => _entityManager.EventBus;
|
||||||
|
|
||||||
private IEntity _lastHoveredEntity;
|
private IEntity _lastHoveredEntity;
|
||||||
|
|
||||||
|
private bool _outlineEnabled = true;
|
||||||
|
|
||||||
public override void Startup()
|
public override void Startup()
|
||||||
{
|
{
|
||||||
InputManager.KeyBindStateChanged += OnKeyBindStateChanged;
|
InputManager.KeyBindStateChanged += OnKeyBindStateChanged;
|
||||||
|
_eventBus.SubscribeEvent<OutlineToggleMessage>(EventSource.Local, this, HandleOutlineToggle);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Shutdown()
|
public override void Shutdown()
|
||||||
{
|
{
|
||||||
InputManager.KeyBindStateChanged -= OnKeyBindStateChanged;
|
InputManager.KeyBindStateChanged -= OnKeyBindStateChanged;
|
||||||
|
_eventBus.UnsubscribeEvent<OutlineToggleMessage>(EventSource.Local, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleOutlineToggle(OutlineToggleMessage message)
|
||||||
|
{
|
||||||
|
_outlineEnabled = message.Enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void FrameUpdate(FrameEventArgs e)
|
public override void FrameUpdate(FrameEventArgs e)
|
||||||
@@ -72,7 +84,7 @@ namespace Content.Client.State
|
|||||||
}
|
}
|
||||||
|
|
||||||
InteractionOutlineComponent outline;
|
InteractionOutlineComponent outline;
|
||||||
if(!ConfigurationManager.GetCVar(CCVars.OutlineEnabled))
|
if(!_outlineEnabled || !ConfigurationManager.GetCVar(CCVars.OutlineEnabled))
|
||||||
{
|
{
|
||||||
if(entityToClick != null && entityToClick.TryGetComponent(out outline))
|
if(entityToClick != null && entityToClick.TryGetComponent(out outline))
|
||||||
{
|
{
|
||||||
|
|||||||
14
Content.Client/State/OutlineToggleMessage.cs
Normal file
14
Content.Client/State/OutlineToggleMessage.cs
Normal file
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -33,6 +33,7 @@ using Robust.Shared.ViewVariables;
|
|||||||
namespace Content.Server.GameObjects.Components.Buckle
|
namespace Content.Server.GameObjects.Components.Buckle
|
||||||
{
|
{
|
||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
|
[ComponentReference(typeof(SharedBuckleComponent))]
|
||||||
public class BuckleComponent : SharedBuckleComponent, IInteractHand
|
public class BuckleComponent : SharedBuckleComponent, IInteractHand
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||||
@@ -44,11 +45,6 @@ namespace Content.Server.GameObjects.Components.Buckle
|
|||||||
|
|
||||||
private int _size;
|
private int _size;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The range from which this entity can buckle to a <see cref="StrapComponent"/>.
|
|
||||||
/// </summary>
|
|
||||||
[ViewVariables]
|
|
||||||
private float _range;
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The amount of time that must pass for this entity to
|
/// The amount of time that must pass for this entity to
|
||||||
/// be able to unbuckle after recently buckling.
|
/// be able to unbuckle after recently buckling.
|
||||||
@@ -184,7 +180,7 @@ namespace Content.Server.GameObjects.Components.Buckle
|
|||||||
var component = strap;
|
var component = strap;
|
||||||
bool Ignored(IEntity entity) => entity == Owner || entity == user || entity == component.Owner;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -319,7 +315,7 @@ namespace Content.Server.GameObjects.Components.Buckle
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!user.InRangeUnobstructed(oldBuckledTo, _range, popup: true))
|
if (!user.InRangeUnobstructed(oldBuckledTo, Range, popup: true))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -385,7 +381,6 @@ namespace Content.Server.GameObjects.Components.Buckle
|
|||||||
base.ExposeData(serializer);
|
base.ExposeData(serializer);
|
||||||
|
|
||||||
serializer.DataField(ref _size, "size", 100);
|
serializer.DataField(ref _size, "size", 100);
|
||||||
serializer.DataField(ref _range, "range", SharedInteractionSystem.InteractionRange / 1.4f);
|
|
||||||
|
|
||||||
var seconds = 0.25f;
|
var seconds = 0.25f;
|
||||||
serializer.DataField(ref seconds, "cooldown", 0.25f);
|
serializer.DataField(ref seconds, "cooldown", 0.25f);
|
||||||
|
|||||||
@@ -10,13 +10,11 @@ using Content.Server.GameObjects.Components.Items.Storage;
|
|||||||
using Content.Server.GameObjects.Components.Power.ApcNetComponents;
|
using Content.Server.GameObjects.Components.Power.ApcNetComponents;
|
||||||
using Content.Server.GameObjects.EntitySystems.DeviceNetwork;
|
using Content.Server.GameObjects.EntitySystems.DeviceNetwork;
|
||||||
using Content.Server.GameObjects.EntitySystems.DoAfter;
|
using Content.Server.GameObjects.EntitySystems.DoAfter;
|
||||||
using Content.Server.Interfaces;
|
|
||||||
using Content.Server.Interfaces.GameObjects.Components.Items;
|
using Content.Server.Interfaces.GameObjects.Components.Items;
|
||||||
using Content.Server.Utility;
|
using Content.Server.Utility;
|
||||||
using Content.Shared.GameObjects.Components;
|
using Content.Shared.GameObjects.Components;
|
||||||
using Content.Shared.GameObjects.Components.Body;
|
using Content.Shared.GameObjects.Components.Body;
|
||||||
using Content.Shared.GameObjects.Components.Disposal;
|
using Content.Shared.GameObjects.Components.Disposal;
|
||||||
using Content.Shared.GameObjects.EntitySystems;
|
|
||||||
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
|
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
|
||||||
using Content.Shared.GameObjects.Verbs;
|
using Content.Shared.GameObjects.Verbs;
|
||||||
using Content.Shared.Interfaces;
|
using Content.Shared.Interfaces;
|
||||||
@@ -47,7 +45,7 @@ namespace Content.Server.GameObjects.Components.Disposal
|
|||||||
[ComponentReference(typeof(SharedDisposalMailingUnitComponent))]
|
[ComponentReference(typeof(SharedDisposalMailingUnitComponent))]
|
||||||
[ComponentReference(typeof(IActivate))]
|
[ComponentReference(typeof(IActivate))]
|
||||||
[ComponentReference(typeof(IInteractUsing))]
|
[ComponentReference(typeof(IInteractUsing))]
|
||||||
public class DisposalMailingUnitComponent : SharedDisposalMailingUnitComponent, IInteractHand, IActivate, IInteractUsing, IDragDropOn
|
public class DisposalMailingUnitComponent : SharedDisposalMailingUnitComponent, IInteractHand, IActivate, IInteractUsing
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||||
|
|
||||||
@@ -145,7 +143,7 @@ namespace Content.Server.GameObjects.Components.Disposal
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private (PressureState State, string Localized) _locState;
|
private (PressureState State, string Localized) _locState;
|
||||||
|
|
||||||
public bool CanInsert(IEntity entity)
|
public override bool CanInsert(IEntity entity)
|
||||||
{
|
{
|
||||||
if (!Anchored)
|
if (!Anchored)
|
||||||
{
|
{
|
||||||
@@ -763,12 +761,12 @@ namespace Content.Server.GameObjects.Components.Disposal
|
|||||||
return TryDrop(eventArgs.User, eventArgs.Using);
|
return TryDrop(eventArgs.User, eventArgs.Using);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IDragDropOn.CanDragDropOn(DragDropEventArgs eventArgs)
|
public override bool CanDragDropOn(DragDropEventArgs eventArgs)
|
||||||
{
|
{
|
||||||
return CanInsert(eventArgs.Dragged);
|
return CanInsert(eventArgs.Dragged);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IDragDropOn.DragDropOn(DragDropEventArgs eventArgs)
|
public override bool DragDropOn(DragDropEventArgs eventArgs)
|
||||||
{
|
{
|
||||||
_ = TryInsert(eventArgs.Dragged, eventArgs.User);
|
_ = TryInsert(eventArgs.Dragged, eventArgs.User);
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -6,20 +6,17 @@ using System.Threading;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Content.Server.Atmos;
|
using Content.Server.Atmos;
|
||||||
using Content.Server.GameObjects.Components.GUI;
|
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.Power.ApcNetComponents;
|
||||||
|
using Content.Server.GameObjects.Components.Items.Storage;
|
||||||
using Content.Server.GameObjects.EntitySystems;
|
using Content.Server.GameObjects.EntitySystems;
|
||||||
using Content.Server.GameObjects.EntitySystems.DoAfter;
|
using Content.Server.GameObjects.EntitySystems.DoAfter;
|
||||||
using Content.Server.Interfaces;
|
using Content.Server.Interfaces;
|
||||||
using Content.Server.Interfaces.GameObjects.Components.Items;
|
using Content.Server.Interfaces.GameObjects.Components.Items;
|
||||||
using Content.Server.Utility;
|
using Content.Server.Utility;
|
||||||
|
using Content.Shared.GameObjects.Components.Disposal;
|
||||||
using Content.Shared.Atmos;
|
using Content.Shared.Atmos;
|
||||||
using Content.Shared.GameObjects.Components.Body;
|
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.Components.Mobs.State;
|
||||||
using Content.Shared.GameObjects.EntitySystems;
|
|
||||||
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
|
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
|
||||||
using Content.Shared.GameObjects.Verbs;
|
using Content.Shared.GameObjects.Verbs;
|
||||||
using Content.Shared.Interfaces;
|
using Content.Shared.Interfaces;
|
||||||
@@ -51,7 +48,7 @@ namespace Content.Server.GameObjects.Components.Disposal
|
|||||||
[ComponentReference(typeof(SharedDisposalUnitComponent))]
|
[ComponentReference(typeof(SharedDisposalUnitComponent))]
|
||||||
[ComponentReference(typeof(IActivate))]
|
[ComponentReference(typeof(IActivate))]
|
||||||
[ComponentReference(typeof(IInteractUsing))]
|
[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!;
|
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||||
|
|
||||||
@@ -137,17 +134,16 @@ namespace Content.Server.GameObjects.Components.Disposal
|
|||||||
|
|
||||||
public GasMixture Air { get; set; } = default!;
|
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;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
if (!entity.TryGetComponent(out IPhysicsComponent? physics) ||
|
if (!entity.TryGetComponent(out IPhysicsComponent? physics) ||
|
||||||
!physics.CanCollide)
|
!physics.CanCollide)
|
||||||
{
|
{
|
||||||
if (!(entity.TryGetComponent(out IMobStateComponent? state) && state.IsDead())) {
|
if (entity.TryGetComponent(out IMobStateComponent? state) && state.IsDead())
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -676,12 +672,14 @@ namespace Content.Server.GameObjects.Components.Disposal
|
|||||||
return TryDrop(eventArgs.User, eventArgs.Using);
|
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);
|
return CanInsert(eventArgs.Dragged);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IDragDropOn.DragDropOn(DragDropEventArgs eventArgs)
|
public override bool DragDropOn(DragDropEventArgs eventArgs)
|
||||||
{
|
{
|
||||||
_ = TryInsert(eventArgs.Dragged, eventArgs.User);
|
_ = TryInsert(eventArgs.Dragged, eventArgs.User);
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ namespace Content.Server.GameObjects.Components.Medical
|
|||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
[ComponentReference(typeof(IActivate))]
|
[ComponentReference(typeof(IActivate))]
|
||||||
[ComponentReference(typeof(SharedMedicalScannerComponent))]
|
[ComponentReference(typeof(SharedMedicalScannerComponent))]
|
||||||
public class MedicalScannerComponent : SharedMedicalScannerComponent, IActivate, IDragDropOn, IDestroyAct
|
public class MedicalScannerComponent : SharedMedicalScannerComponent, IActivate, IDestroyAct
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||||
|
|
||||||
@@ -292,12 +292,7 @@ namespace Content.Server.GameObjects.Components.Medical
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool CanDragDropOn(DragDropEventArgs eventArgs)
|
public override bool DragDropOn(DragDropEventArgs eventArgs)
|
||||||
{
|
|
||||||
return eventArgs.Dragged.HasComponent<IBody>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool DragDropOn(DragDropEventArgs eventArgs)
|
|
||||||
{
|
{
|
||||||
_bodyContainer.Insert(eventArgs.Dragged);
|
_bodyContainer.Insert(eventArgs.Dragged);
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -27,41 +27,36 @@ namespace Content.Server.GameObjects.Components.Movement
|
|||||||
{
|
{
|
||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
[ComponentReference(typeof(IClimbable))]
|
[ComponentReference(typeof(IClimbable))]
|
||||||
public class ClimbableComponent : SharedClimbableComponent, IDragDropOn
|
public class ClimbableComponent : SharedClimbableComponent
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// The range from which this entity can be climbed.
|
|
||||||
/// </summary>
|
|
||||||
[ViewVariables]
|
|
||||||
private float _range;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The time it takes to climb onto the entity.
|
/// The time it takes to climb onto the entity.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
private float _climbDelay;
|
private float _climbDelay;
|
||||||
|
|
||||||
private DoAfterSystem _doAfterSystem;
|
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
|
|
||||||
Owner.EnsureComponentWarn(out PhysicsComponent _);
|
if (!Owner.EnsureComponent(out PhysicsComponent _))
|
||||||
|
{
|
||||||
_doAfterSystem = EntitySystem.Get<DoAfterSystem>();
|
Logger.Warning($"Entity {Owner.Name} at {Owner.Transform.MapPosition} didn't have a {nameof(PhysicsComponent)}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void ExposeData(ObjectSerializer serializer)
|
public override void ExposeData(ObjectSerializer serializer)
|
||||||
{
|
{
|
||||||
base.ExposeData(serializer);
|
base.ExposeData(serializer);
|
||||||
|
|
||||||
serializer.DataField(ref _range, "range", SharedInteractionSystem.InteractionRange / 1.4f);
|
|
||||||
serializer.DataField(ref _climbDelay, "delay", 0.8f);
|
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;
|
string reason;
|
||||||
bool canVault;
|
bool canVault;
|
||||||
|
|
||||||
@@ -105,7 +100,7 @@ namespace Content.Server.GameObjects.Components.Movement
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!user.InRangeUnobstructed(target, _range))
|
if (!user.InRangeUnobstructed(target, Range))
|
||||||
{
|
{
|
||||||
reason = Loc.GetString("You can't reach there!");
|
reason = Loc.GetString("You can't reach there!");
|
||||||
return false;
|
return false;
|
||||||
@@ -139,8 +134,8 @@ namespace Content.Server.GameObjects.Components.Movement
|
|||||||
|
|
||||||
bool Ignored(IEntity entity) => entity == target || entity == user || entity == dragged;
|
bool Ignored(IEntity entity) => entity == target || entity == user || entity == dragged;
|
||||||
|
|
||||||
if (!user.InRangeUnobstructed(target, _range, predicate: Ignored) ||
|
if (!user.InRangeUnobstructed(target, Range, predicate: Ignored) ||
|
||||||
!user.InRangeUnobstructed(dragged, _range, predicate: Ignored))
|
!user.InRangeUnobstructed(dragged, Range, predicate: Ignored))
|
||||||
{
|
{
|
||||||
reason = Loc.GetString("You can't reach there!");
|
reason = Loc.GetString("You can't reach there!");
|
||||||
return false;
|
return false;
|
||||||
@@ -150,7 +145,7 @@ namespace Content.Server.GameObjects.Components.Movement
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IDragDropOn.DragDropOn(DragDropEventArgs eventArgs)
|
public override bool DragDropOn(DragDropEventArgs eventArgs)
|
||||||
{
|
{
|
||||||
if (eventArgs.User == eventArgs.Dragged)
|
if (eventArgs.User == eventArgs.Dragged)
|
||||||
{
|
{
|
||||||
@@ -174,7 +169,7 @@ namespace Content.Server.GameObjects.Components.Movement
|
|||||||
BreakOnStun = true
|
BreakOnStun = true
|
||||||
};
|
};
|
||||||
|
|
||||||
var result = await _doAfterSystem.DoAfter(doAfterEventArgs);
|
var result = await EntitySystem.Get<DoAfterSystem>().DoAfter(doAfterEventArgs);
|
||||||
|
|
||||||
if (result != DoAfterStatus.Cancelled && entityToMove.TryGetComponent(out IPhysicsComponent body) && body.PhysicsShapes.Count >= 1)
|
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
|
BreakOnStun = true
|
||||||
};
|
};
|
||||||
|
|
||||||
var result = await _doAfterSystem.DoAfter(doAfterEventArgs);
|
var result = await EntitySystem.Get<DoAfterSystem>().DoAfter(doAfterEventArgs);
|
||||||
|
|
||||||
if (result != DoAfterStatus.Cancelled && user.TryGetComponent(out IPhysicsComponent body) && body.PhysicsShapes.Count >= 1)
|
if (result != DoAfterStatus.Cancelled && user.TryGetComponent(out IPhysicsComponent body) && body.PhysicsShapes.Count >= 1)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ using Robust.Shared.Maths;
|
|||||||
namespace Content.Server.GameObjects.Components.Movement
|
namespace Content.Server.GameObjects.Components.Movement
|
||||||
{
|
{
|
||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
|
[ComponentReference(typeof(SharedClimbingComponent))]
|
||||||
public class ClimbingComponent : SharedClimbingComponent
|
public class ClimbingComponent : SharedClimbingComponent
|
||||||
{
|
{
|
||||||
private bool _isClimbing;
|
private bool _isClimbing;
|
||||||
|
|||||||
@@ -207,9 +207,7 @@ namespace Content.Server.GameObjects.Components.Strap
|
|||||||
parent = parent.Parent;
|
parent = parent.Parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
var range = SharedInteractionSystem.InteractionRange / 2;
|
if (!user.InRangeUnobstructed(component, buckle.Range))
|
||||||
|
|
||||||
if (!user.InRangeUnobstructed(component, range))
|
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -228,5 +226,11 @@ namespace Content.Server.GameObjects.Components.Strap
|
|||||||
buckle.ToggleBuckle(user, component.Owner);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -306,7 +306,8 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding
|
|||||||
// If we've moved to space or the likes then remove us.
|
// If we've moved to space or the likes then remove us.
|
||||||
if (moveEvent.Sender.Deleted ||
|
if (moveEvent.Sender.Deleted ||
|
||||||
!moveEvent.Sender.TryGetComponent(out IPhysicsComponent physics) ||
|
!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);
|
HandleEntityRemove(moveEvent.Sender);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ namespace Content.Server.GameObjects.EntitySystems.Click
|
|||||||
var interactionArgs = new DragDropEventArgs(performer, msg.DropLocation, dropped, target);
|
var interactionArgs = new DragDropEventArgs(performer, msg.DropLocation, dropped, target);
|
||||||
|
|
||||||
// must be in range of both the target and the object they are drag / dropping
|
// 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;
|
if (!interactionArgs.InRangeUnobstructed(ignoreInsideBlocker: true, popup: true)) return;
|
||||||
|
|
||||||
// trigger dragdrops on the dropped entity
|
// trigger dragdrops on the dropped entity
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ using Robust.Shared.GameObjects.Components;
|
|||||||
using Robust.Shared.Interfaces.GameObjects;
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
using Robust.Shared.Physics;
|
using Robust.Shared.Physics;
|
||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
|
using Robust.Shared.ViewVariables;
|
||||||
|
|
||||||
namespace Content.Shared.GameObjects.Components.Buckle
|
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 string Name => "Buckle";
|
||||||
|
|
||||||
public sealed override uint? NetID => ContentNetIDs.BUCKLE;
|
public sealed override uint? NetID => ContentNetIDs.BUCKLE;
|
||||||
|
/// <summary>
|
||||||
|
/// The range from which this entity can buckle to a <see cref="StrapComponent"/>.
|
||||||
|
/// </summary>
|
||||||
|
[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);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// True if the entity is buckled, false otherwise.
|
/// True if the entity is buckled, false otherwise.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ using Robust.Shared.Utility;
|
|||||||
|
|
||||||
namespace Content.Shared.GameObjects.Components.Disposal
|
namespace Content.Shared.GameObjects.Components.Disposal
|
||||||
{
|
{
|
||||||
public abstract class SharedDisposalMailingUnitComponent : SharedDisposalUnitComponent, ICollideSpecial
|
public abstract class SharedDisposalMailingUnitComponent : SharedDisposalUnitComponent
|
||||||
{
|
{
|
||||||
public override string Name => "DisposalMailingUnit";
|
public override string Name => "DisposalMailingUnit";
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
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;
|
||||||
using Robust.Shared.GameObjects.Components;
|
using Robust.Shared.GameObjects.Components;
|
||||||
using Robust.Shared.GameObjects.Components.UserInterface;
|
using Robust.Shared.GameObjects.Components.UserInterface;
|
||||||
@@ -12,7 +17,7 @@ using Robust.Shared.ViewVariables;
|
|||||||
|
|
||||||
namespace Content.Shared.GameObjects.Components.Disposal
|
namespace Content.Shared.GameObjects.Components.Disposal
|
||||||
{
|
{
|
||||||
public abstract class SharedDisposalUnitComponent : Component, ICollideSpecial
|
public abstract class SharedDisposalUnitComponent : Component, ICollideSpecial, IDragDropOn
|
||||||
{
|
{
|
||||||
public override string Name => "DisposalUnit";
|
public override string Name => "DisposalUnit";
|
||||||
|
|
||||||
@@ -160,5 +165,34 @@ namespace Content.Shared.GameObjects.Components.Disposal
|
|||||||
{
|
{
|
||||||
Key
|
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<SharedStorableComponent>() &&
|
||||||
|
!entity.HasComponent<IBody>())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual bool CanDragDropOn(DragDropEventArgs eventArgs)
|
||||||
|
{
|
||||||
|
return CanInsert(eventArgs.Dragged);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract bool DragDropOn(DragDropEventArgs eventArgs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Content.Shared.Damage;
|
using Content.Shared.Damage;
|
||||||
|
using Content.Shared.GameObjects.Components.Body;
|
||||||
|
using Content.Shared.Interfaces.GameObjects.Components;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.GameObjects.Components.UserInterface;
|
using Robust.Shared.GameObjects.Components.UserInterface;
|
||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
namespace Content.Shared.GameObjects.Components.Medical
|
namespace Content.Shared.GameObjects.Components.Medical
|
||||||
{
|
{
|
||||||
public class SharedMedicalScannerComponent : Component
|
public abstract class SharedMedicalScannerComponent : Component, IDragDropOn
|
||||||
{
|
{
|
||||||
public override string Name => "MedicalScanner";
|
public override string Name => "MedicalScanner";
|
||||||
|
|
||||||
@@ -78,5 +80,11 @@ namespace Content.Shared.GameObjects.Components.Medical
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public bool CanDragDropOn(DragDropEventArgs eventArgs)
|
||||||
|
{
|
||||||
|
return eventArgs.Dragged.HasComponent<IBody>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract bool DragDropOn(DragDropEventArgs eventArgs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
namespace Content.Shared.GameObjects.Components.Movement
|
||||||
{
|
{
|
||||||
public interface IClimbable { };
|
public interface IClimbable { };
|
||||||
|
|
||||||
public class SharedClimbableComponent : Component, IClimbable
|
public abstract class SharedClimbableComponent : Component, IClimbable, IDragDropOn
|
||||||
{
|
{
|
||||||
public sealed override string Name => "Climbable";
|
public sealed override string Name => "Climbable";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The range from which this entity can be climbed.
|
||||||
|
/// </summary>
|
||||||
|
[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<SharedClimbingComponent>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract bool DragDropOn(DragDropEventArgs eventArgs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,11 +6,10 @@ using Robust.Shared.GameObjects;
|
|||||||
using Robust.Shared.GameObjects.Components;
|
using Robust.Shared.GameObjects.Components;
|
||||||
using Robust.Shared.Physics;
|
using Robust.Shared.Physics;
|
||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
using Content.Shared.Interfaces.GameObjects.Components;
|
|
||||||
|
|
||||||
namespace Content.Shared.GameObjects.Components.Movement
|
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 string Name => "Climbing";
|
||||||
public sealed override uint? NetID => ContentNetIDs.CLIMBING;
|
public sealed override uint? NetID => ContentNetIDs.CLIMBING;
|
||||||
@@ -47,16 +46,6 @@ namespace Content.Shared.GameObjects.Components.Movement
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IDraggable.CanDrop(CanDropEventArgs args)
|
|
||||||
{
|
|
||||||
return args.Target.HasComponent<IClimbable>();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IDraggable.Drop(DragDropEventArgs args)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
using System;
|
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.GameObjects;
|
||||||
using Robust.Shared.Interfaces.GameObjects;
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
@@ -23,11 +27,21 @@ namespace Content.Shared.GameObjects.Components.Strap
|
|||||||
Down
|
Down
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract class SharedStrapComponent : Component
|
public abstract class SharedStrapComponent : Component, IDragDropOn
|
||||||
{
|
{
|
||||||
public sealed override string Name => "Strap";
|
public sealed override string Name => "Strap";
|
||||||
|
|
||||||
public sealed override uint? NetID => ContentNetIDs.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]
|
[Serializable, NetSerializable]
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace Content.Shared.Interfaces.GameObjects.Components
|
|||||||
public interface IDragDropOn
|
public interface IDragDropOn
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 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 <see cref="DragDropOn"/>.
|
/// onto this one before invoking <see cref="DragDropOn"/>.
|
||||||
/// Note that other drag and drop interactions may be attempted if
|
/// Note that other drag and drop interactions may be attempted if
|
||||||
/// this one fails.
|
/// this one fails.
|
||||||
|
|||||||
Reference in New Issue
Block a user