Refactor drag and drop to use a shared interface (#2012)

* WIP in progress hours

* Cleanup

* Fix bugle

* Fix nullable error

* Merge fixes

* Merge fixes

* Merge fixes
This commit is contained in:
DrSmugleaf
2020-10-14 15:24:07 +02:00
committed by GitHub
parent f715eed63c
commit cdedaeb12e
37 changed files with 527 additions and 377 deletions

View File

@@ -34,7 +34,7 @@ using Robust.Shared.ViewVariables;
namespace Content.Server.GameObjects.Components.Buckle
{
[RegisterComponent]
public class BuckleComponent : SharedBuckleComponent, IInteractHand, IDragDrop
public class BuckleComponent : SharedBuckleComponent, IInteractHand
{
[Dependency] private readonly IEntityManager _entityManager = default!;
[Dependency] private readonly IEntitySystemManager _entitySystem = default!;
@@ -256,18 +256,7 @@ namespace Content.Server.GameObjects.Components.Buckle
return true;
}
/// <summary>
/// Tries to make an entity buckle the owner of this component to another.
/// </summary>
/// <param name="user">
/// The entity buckling the owner of this component, can be the owner itself.
/// </param>
/// <param name="to">The entity to buckle the owner of this component to.</param>
/// <returns>
/// true if the owner was buckled, otherwise false even if the owner was
/// previously already buckled.
/// </returns>
public bool TryBuckle(IEntity user, IEntity to)
public override bool TryBuckle(IEntity user, IEntity to)
{
if (!CanBuckle(user, to, out var strap))
{
@@ -544,16 +533,6 @@ namespace Content.Server.GameObjects.Components.Buckle
return TryUnbuckle(eventArgs.User);
}
bool IDragDrop.CanDragDrop(DragDropEventArgs eventArgs)
{
return eventArgs.Target.HasComponent<StrapComponent>();
}
bool IDragDrop.DragDrop(DragDropEventArgs eventArgs)
{
return TryBuckle(eventArgs.User, eventArgs.Target);
}
/// <summary>
/// Allows the unbuckling of the owning entity through a verb if
/// anyone right clicks them.

View File

@@ -674,12 +674,12 @@ namespace Content.Server.GameObjects.Components.Disposal
bool IDragDropOn.CanDragDropOn(DragDropEventArgs eventArgs)
{
return CanInsert(eventArgs.Dropped);
return CanInsert(eventArgs.Dragged);
}
bool IDragDropOn.DragDropOn(DragDropEventArgs eventArgs)
{
_ = TryInsert(eventArgs.Dropped, eventArgs.User);
_ = TryInsert(eventArgs.Dragged, eventArgs.User);
return true;
}

View File

@@ -45,7 +45,7 @@ namespace Content.Server.GameObjects.Components.GUI
var itemComponent = entity.GetComponent<ItemComponent>();
// If this item is small enough then it always fits in pockets.
if (itemComponent.ObjectSize <= (int) ReferenceSizes.Pocket)
if (itemComponent.Size <= (int) ReferenceSizes.Pocket)
{
return true;
}

View File

@@ -23,7 +23,7 @@ using static Content.Shared.GameObjects.Components.Inventory.EquipmentSlotDefine
namespace Content.Server.GameObjects.Components.GUI
{
[RegisterComponent]
public sealed class StrippableComponent : SharedStrippableComponent, IDragDrop
public sealed class StrippableComponent : SharedStrippableComponent
{
public const float StripDelay = 2f;
@@ -75,23 +75,9 @@ namespace Content.Server.GameObjects.Components.GUI
UserInterface.SetState(new StrippingBoundUserInterfaceState(inventory, hands, cuffs));
}
public bool CanBeStripped(IEntity by)
public override bool Drop(DragDropEventArgs args)
{
return by != Owner
&& by.HasComponent<HandsComponent>()
&& ActionBlockerSystem.CanInteract(by);
}
public bool CanDragDrop(DragDropEventArgs eventArgs)
{
return eventArgs.Target != eventArgs.Dropped
&& eventArgs.Target == eventArgs.User
&& CanBeStripped(eventArgs.User);
}
public bool DragDrop(DragDropEventArgs eventArgs)
{
if (!eventArgs.User.TryGetComponent(out IActorComponent? actor)) return false;
if (!args.User.TryGetComponent(out IActorComponent? actor)) return false;
OpenUserInterface(actor.playerSession);
return true;

View File

@@ -4,6 +4,7 @@ using Content.Server.GameObjects.Components.GUI;
using Content.Server.GameObjects.Components.Items.Storage;
using Content.Shared.GameObjects;
using Content.Shared.GameObjects.Components.Items;
using Content.Shared.GameObjects.Components.Storage;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;
using Robust.Shared.GameObjects;
@@ -17,6 +18,7 @@ namespace Content.Server.GameObjects.Components.Items.Clothing
[RegisterComponent]
[ComponentReference(typeof(ItemComponent))]
[ComponentReference(typeof(StorableComponent))]
[ComponentReference(typeof(SharedStorableComponent))]
[ComponentReference(typeof(IItemComponent))]
public class ClothingComponent : ItemComponent, IUse
{

View File

@@ -3,6 +3,7 @@ using Content.Server.Interfaces.GameObjects.Components.Items;
using Content.Server.Throw;
using Content.Shared.GameObjects;
using Content.Shared.GameObjects.Components.Items;
using Content.Shared.GameObjects.Components.Storage;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.Verbs;
using Content.Shared.Interfaces.GameObjects.Components;
@@ -19,6 +20,7 @@ namespace Content.Server.GameObjects.Components.Items.Storage
{
[RegisterComponent]
[ComponentReference(typeof(StorableComponent))]
[ComponentReference(typeof(SharedStorableComponent))]
[ComponentReference(typeof(IItemComponent))]
public class ItemComponent : StorableComponent, IInteractHand, IExAct, IEquipped, IUnequipped, IItemComponent
{

View File

@@ -34,8 +34,7 @@ namespace Content.Server.GameObjects.Components.Items.Storage
[RegisterComponent]
[ComponentReference(typeof(IActivate))]
[ComponentReference(typeof(IStorageComponent))]
public class ServerStorageComponent : SharedStorageComponent, IInteractUsing, IUse, IActivate, IStorageComponent, IDestroyAct, IExAct,
IDragDrop
public class ServerStorageComponent : SharedStorageComponent, IInteractUsing, IUse, IActivate, IStorageComponent, IDestroyAct, IExAct
{
[Dependency] private readonly IEntityManager _entityManager = default!;
@@ -50,7 +49,7 @@ namespace Content.Server.GameObjects.Components.Items.Storage
public readonly HashSet<IPlayerSession> SubscribedSessions = new HashSet<IPlayerSession>();
[ViewVariables]
public IReadOnlyCollection<IEntity>? StoredEntities => _storage?.ContainedEntities;
public override IReadOnlyList<IEntity>? StoredEntities => _storage?.ContainedEntities;
[ViewVariables(VVAccess.ReadWrite)]
public bool OccludesLight
@@ -87,7 +86,7 @@ namespace Content.Server.GameObjects.Components.Items.Storage
foreach (var entity in _storage.ContainedEntities)
{
var item = entity.GetComponent<StorableComponent>();
_storageUsed += item.ObjectSize;
_storageUsed += item.Size;
}
}
@@ -107,7 +106,7 @@ namespace Content.Server.GameObjects.Components.Items.Storage
}
if (entity.TryGetComponent(out StorableComponent? store) &&
store.ObjectSize > _storageCapacityMax - _storageUsed)
store.Size > _storageCapacityMax - _storageUsed)
{
return false;
}
@@ -125,12 +124,7 @@ namespace Content.Server.GameObjects.Components.Items.Storage
return CanInsert(entity) && _storage?.Insert(entity) == true;
}
/// <summary>
/// Removes from the storage container and updates the stored value
/// </summary>
/// <param name="entity">The entity to remove</param>
/// <returns>true if no longer in storage, false otherwise</returns>
public bool Remove(IEntity entity)
public override bool Remove(IEntity entity)
{
EnsureInitialCalculated();
return _storage?.Remove(entity) == true;
@@ -147,7 +141,7 @@ namespace Content.Server.GameObjects.Components.Items.Storage
Logger.DebugS(LoggerName, $"Storage (UID {Owner.Uid}) had entity (UID {message.Entity.Uid}) inserted into it.");
_storageUsed += message.Entity.GetComponent<StorableComponent>().ObjectSize;
_storageUsed += message.Entity.GetComponent<StorableComponent>().Size;
UpdateClientInventories();
}
@@ -171,7 +165,7 @@ namespace Content.Server.GameObjects.Components.Items.Storage
return;
}
_storageUsed -= storable.ObjectSize;
_storageUsed -= storable.Size;
UpdateClientInventories();
}
@@ -258,14 +252,16 @@ namespace Content.Server.GameObjects.Components.Items.Storage
return;
}
var storedEntities = new Dictionary<EntityUid, int>();
foreach (var entities in _storage.ContainedEntities)
if (StoredEntities == null)
{
storedEntities.Add(entities.Uid, entities.GetComponent<StorableComponent>().ObjectSize);
Logger.WarningS(LoggerName, $"{nameof(UpdateClientInventory)} called with null {nameof(StoredEntities)}");
return;
}
SendNetworkMessage(new StorageHeldItemsMessage(storedEntities, _storageUsed, _storageCapacityMax), session.ConnectedClient);
var stored = StoredEntities.Select(e => e.Uid).ToArray();
SendNetworkMessage(new StorageHeldItemsMessage(stored, _storageUsed, _storageCapacityMax), session.ConnectedClient);
}
/// <summary>
@@ -500,43 +496,5 @@ namespace Content.Server.GameObjects.Components.Items.Storage
}
}
}
bool IDragDrop.CanDragDrop(DragDropEventArgs eventArgs)
{
return eventArgs.Target.TryGetComponent(out PlaceableSurfaceComponent? placeable) &&
placeable.IsPlaceable;
}
bool IDragDrop.DragDrop(DragDropEventArgs eventArgs)
{
if (!ActionBlockerSystem.CanInteract(eventArgs.User))
{
return false;
}
if (!eventArgs.Target.TryGetComponent<PlaceableSurfaceComponent>(out var placeableSurface) ||
!placeableSurface.IsPlaceable)
{
return false;
}
var storedEntities = StoredEntities?.ToList();
if (storedEntities == null)
{
return false;
}
// empty everything out
foreach (var storedEntity in StoredEntities.ToList())
{
if (Remove(storedEntity))
{
storedEntity.Transform.WorldPosition = eventArgs.DropLocation.Position;
}
}
return true;
}
}
}

View File

@@ -1,20 +1,33 @@
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization;
using Content.Shared.GameObjects.Components.Storage;
using Robust.Shared.GameObjects;
namespace Content.Server.GameObjects.Components.Items.Storage
{
[RegisterComponent]
public class StorableComponent : Component
[ComponentReference(typeof(SharedStorableComponent))]
public class StorableComponent : SharedStorableComponent
{
public override string Name => "Storable";
private int _size;
public int ObjectSize;
public override void ExposeData(ObjectSerializer serializer)
public override int Size
{
base.ExposeData(serializer);
get => _size;
set
{
if (_size == value)
{
return;
}
serializer.DataField(ref ObjectSize, "size", 1);
_size = value;
Dirty();
}
}
public override ComponentState GetComponentState()
{
return new StorableComponentState(_size);
}
}

View File

@@ -31,6 +31,7 @@ namespace Content.Server.GameObjects.Components.Medical
{
[RegisterComponent]
[ComponentReference(typeof(IActivate))]
[ComponentReference(typeof(SharedMedicalScannerComponent))]
public class MedicalScannerComponent : SharedMedicalScannerComponent, IActivate, IDragDropOn
{
private ContainerSlot _bodyContainer = default!;
@@ -250,12 +251,12 @@ namespace Content.Server.GameObjects.Components.Medical
public bool CanDragDropOn(DragDropEventArgs eventArgs)
{
return eventArgs.Dropped.HasComponent<IBody>();
return eventArgs.Dragged.HasComponent<IBody>();
}
public bool DragDropOn(DragDropEventArgs eventArgs)
{
_bodyContainer.Insert(eventArgs.Dropped);
_bodyContainer.Insert(eventArgs.Dragged);
return true;
}
}

View File

@@ -67,10 +67,10 @@ namespace Content.Server.GameObjects.Components.Movement
string reason;
bool canVault;
if (eventArgs.User == eventArgs.Dropped)
if (eventArgs.User == eventArgs.Dragged)
canVault = CanVault(eventArgs.User, eventArgs.Target, out reason);
else
canVault = CanVault(eventArgs.User, eventArgs.Dropped, eventArgs.Target, out reason);
canVault = CanVault(eventArgs.User, eventArgs.Dragged, eventArgs.Target, out reason);
if (!canVault)
eventArgs.User.PopupMessage(reason);
@@ -154,13 +154,13 @@ namespace Content.Server.GameObjects.Components.Movement
bool IDragDropOn.DragDropOn(DragDropEventArgs eventArgs)
{
if (eventArgs.User == eventArgs.Dropped)
if (eventArgs.User == eventArgs.Dragged)
{
TryClimb(eventArgs.User);
}
else
{
TryMoveEntity(eventArgs.User, eventArgs.Dropped);
TryMoveEntity(eventArgs.User, eventArgs.Dragged);
}
return true;

View File

@@ -1,5 +1,4 @@
using Content.Shared.GameObjects.Components.Movement;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.Physics;
using Robust.Shared.GameObjects;
using Robust.Shared.Maths;
@@ -7,7 +6,7 @@ using Robust.Shared.Maths;
namespace Content.Server.GameObjects.Components.Movement
{
[RegisterComponent]
public class ClimbingComponent : SharedClimbingComponent, IActionBlocker
public class ClimbingComponent : SharedClimbingComponent
{
private bool _isClimbing = false;
private ClimbController _climbController = default;

View File

@@ -9,11 +9,27 @@ using Robust.Shared.ViewVariables;
namespace Content.Server.GameObjects.Components
{
[RegisterComponent]
[ComponentReference(typeof(SharedPlaceableSurfaceComponent))]
public class PlaceableSurfaceComponent : SharedPlaceableSurfaceComponent, IInteractUsing
{
private bool _isPlaceable;
[ViewVariables(VVAccess.ReadWrite)]
public bool IsPlaceable { get => _isPlaceable; set => _isPlaceable = value; }
public override bool IsPlaceable
{
get => _isPlaceable;
set
{
if (_isPlaceable == value)
{
return;
}
_isPlaceable = value;
Dirty();
}
}
[ViewVariables]
int IInteractUsing.Priority => 1;
@@ -25,6 +41,10 @@ namespace Content.Server.GameObjects.Components
serializer.DataField(ref _isPlaceable, "IsPlaceable", true);
}
public override ComponentState GetComponentState()
{
return new PlaceableSurfaceComponentState(_isPlaceable);
}
public async Task<bool> InteractUsing(InteractUsingEventArgs eventArgs)
{

View File

@@ -41,7 +41,7 @@ namespace Content.Server.GameObjects.Components
return false;
}
var size = eventArgs.Using.GetComponent<ItemComponent>().ObjectSize;
var size = eventArgs.Using.GetComponent<ItemComponent>().Size;
// TODO: use proper text macro system for this.

View File

@@ -18,6 +18,7 @@ using Robust.Shared.ViewVariables;
namespace Content.Server.GameObjects.Components.Strap
{
[RegisterComponent]
[ComponentReference(typeof(SharedStrapComponent))]
public class StrapComponent : SharedStrapComponent, IInteractHand
{
[ComponentDependency] public readonly SpriteComponent? SpriteComponent = null;