using Content.Shared.Hands.Components;
using Content.Shared.Interaction;
using Content.Shared.Inventory.VirtualItem;
+using Content.Shared.Storage.Components;
using Content.Shared.Tag;
using Robust.Shared.Containers;
using Robust.Shared.Map;
private void InitializeDrop()
{
SubscribeLocalEvent<HandsComponent, EntRemovedFromContainerMessage>(HandleEntityRemoved);
+ SubscribeLocalEvent<HandsComponent, EntityStorageIntoContainerAttemptEvent>(OnEntityStorageDump);
}
protected virtual void HandleEntityRemoved(EntityUid uid, HandsComponent hands, EntRemovedFromContainerMessage args)
_virtualSystem.DeleteVirtualItem((args.Entity, @virtual), uid);
}
+
+ private void OnEntityStorageDump(Entity<HandsComponent> ent, ref EntityStorageIntoContainerAttemptEvent args)
+ {
+ // If you're physically carrying an EntityStroage which tries to dump its contents out,
+ // we want those contents to fall to the floor.
+ args.Cancelled = true;
+ }
+
private bool ShouldIgnoreRestrictions(EntityUid user)
{
//Checks if the Entity is something that shouldn't care about drop distance or walls ie Aghost
using Content.Shared.Movement.Components;
using Content.Shared.Movement.Systems;
using Content.Shared.Popups;
+using Content.Shared.Storage.Components;
using Content.Shared.Weapons.Melee;
using Content.Shared.Whitelist;
using Robust.Shared.Containers;
SubscribeLocalEvent<MechComponent, UserActivateInWorldEvent>(RelayInteractionEvent);
SubscribeLocalEvent<MechComponent, ComponentStartup>(OnStartup);
SubscribeLocalEvent<MechComponent, DestructionEventArgs>(OnDestruction);
+ SubscribeLocalEvent<MechComponent, EntityStorageIntoContainerAttemptEvent>(OnEntityStorageDump);
SubscribeLocalEvent<MechComponent, GetAdditionalAccessEvent>(OnGetAdditionalAccess);
SubscribeLocalEvent<MechComponent, DragDropTargetEvent>(OnDragDrop);
SubscribeLocalEvent<MechComponent, CanDropTargetEvent>(OnCanDragDrop);
BreakMech(uid, component);
}
+ private void OnEntityStorageDump(Entity<MechComponent> entity, ref EntityStorageIntoContainerAttemptEvent args)
+ {
+ // There's no reason we should dump into /any/ of the mech's containers.
+ args.Cancelled = true;
+ }
+
private void OnGetAdditionalAccess(EntityUid uid, MechComponent component, ref GetAdditionalAccessEvent args)
{
var pilot = component.PilotSlot.ContainedEntity;
}
/// <summary>
- /// Destroys the mech, removing the user and ejecting all installed equipment.
+ /// Destroys the mech, removing the user and ejecting anything contained.
/// </summary>
/// <param name="uid"></param>
/// <param name="component"></param>
/// <param name="toRemove"></param>
/// <param name="component"></param>
/// <param name="equipmentComponent"></param>
- /// <param name="forced">Whether or not the removal can be cancelled</param>
+ /// <param name="forced">
+ /// Whether or not the removal can be cancelled, and if non-mech equipment should be ejected.
+ /// </param>
public void RemoveEquipment(EntityUid uid, EntityUid toRemove, MechComponent? component = null,
MechEquipmentComponent? equipmentComponent = null, bool forced = false)
{
if (!Resolve(uid, ref component))
return;
- if (!Resolve(toRemove, ref equipmentComponent))
+ // When forced, we also want to handle the possibility that the "equipment" isn't actually equipment.
+ // This /shouldn't/ be possible thanks to OnEntityStorageDump, but there's been quite a few regressions
+ // with entities being hardlock stuck inside mechs.
+ if (!Resolve(toRemove, ref equipmentComponent) && !forced)
return;
if (!forced)
if (component.CurrentSelectedEquipment == toRemove)
CycleEquipment(uid, component);
- equipmentComponent.EquipmentOwner = null;
+ if (forced && equipmentComponent != null)
+ equipmentComponent.EquipmentOwner = null;
+
_container.Remove(toRemove, component.EquipmentContainer);
UpdateUserInterface(uid, component);
}
_container.Remove(toRemove, component.Contents);
- if (_container.IsEntityInContainer(container))
+ if (_container.IsEntityInContainer(container)
+ && _container.TryGetOuterContainer(container, Transform(container), out var outerContainer))
{
- if (_container.TryGetOuterContainer(container, Transform(container), out var outerContainer) &&
- !HasComp<HandsComponent>(outerContainer.Owner))
+
+ var attemptEvent = new EntityStorageIntoContainerAttemptEvent(outerContainer);
+ RaiseLocalEvent(outerContainer.Owner, ref attemptEvent);
+ if (!attemptEvent.Cancelled)
{
_container.Insert(toRemove, outerContainer);
return true;