fix: Block EntityStorage from inserting into mechs (#37942)
This additionally moves the hard-coded check for HandsComp that previously did this, and moves it into an event which now both HandsSystem and MechSystem subscribe to.
This commit is contained in:
@@ -3,6 +3,7 @@ using Content.Shared.Database;
|
||||
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;
|
||||
@@ -20,6 +21,7 @@ public abstract partial class SharedHandsSystem
|
||||
private void InitializeDrop()
|
||||
{
|
||||
SubscribeLocalEvent<HandsComponent, EntRemovedFromContainerMessage>(HandleEntityRemoved);
|
||||
SubscribeLocalEvent<HandsComponent, EntityStorageIntoContainerAttemptEvent>(OnEntityStorageDump);
|
||||
}
|
||||
|
||||
protected virtual void HandleEntityRemoved(EntityUid uid, HandsComponent hands, EntRemovedFromContainerMessage args)
|
||||
@@ -39,6 +41,14 @@ public abstract partial class SharedHandsSystem
|
||||
_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
|
||||
|
||||
@@ -14,6 +14,7 @@ using Content.Shared.Mech.Equipment.Components;
|
||||
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;
|
||||
@@ -48,6 +49,7 @@ public abstract partial class SharedMechSystem : EntitySystem
|
||||
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);
|
||||
@@ -104,6 +106,12 @@ public abstract partial class SharedMechSystem : EntitySystem
|
||||
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;
|
||||
@@ -147,7 +155,7 @@ public abstract partial class SharedMechSystem : EntitySystem
|
||||
}
|
||||
|
||||
/// <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>
|
||||
@@ -237,14 +245,19 @@ public abstract partial class SharedMechSystem : EntitySystem
|
||||
/// <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)
|
||||
@@ -261,7 +274,9 @@ public abstract partial class SharedMechSystem : EntitySystem
|
||||
if (component.CurrentSelectedEquipment == toRemove)
|
||||
CycleEquipment(uid, component);
|
||||
|
||||
if (forced && equipmentComponent != null)
|
||||
equipmentComponent.EquipmentOwner = null;
|
||||
|
||||
_container.Remove(toRemove, component.EquipmentContainer);
|
||||
UpdateUserInterface(uid, component);
|
||||
}
|
||||
|
||||
@@ -166,6 +166,13 @@ public record struct InsertIntoEntityStorageAttemptEvent(EntityUid ItemToInsert,
|
||||
[ByRefEvent]
|
||||
public record struct EntityStorageInsertedIntoAttemptEvent(EntityUid ItemToInsert, bool Cancelled = false);
|
||||
|
||||
/// <summary>
|
||||
/// Raised on the Container's owner whenever an entity storage tries to dump its
|
||||
/// contents while within a container.
|
||||
/// </summary>
|
||||
[ByRefEvent]
|
||||
public record struct EntityStorageIntoContainerAttemptEvent(BaseContainer Container, bool Cancelled = false);
|
||||
|
||||
[ByRefEvent]
|
||||
public record struct StorageOpenAttemptEvent(EntityUid User, bool Silent, bool Cancelled = false);
|
||||
|
||||
|
||||
@@ -305,10 +305,13 @@ public abstract class SharedEntityStorageSystem : EntitySystem
|
||||
|
||||
_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;
|
||||
|
||||
Reference in New Issue
Block a user