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:
Perry Fraser
2025-11-23 15:22:31 -06:00
committed by Vanessa
parent ec7ca3bdea
commit ffe77c6071
4 changed files with 42 additions and 7 deletions
@@ -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;
@@ -64,6 +65,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);
@@ -128,6 +130,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;
@@ -171,7 +179,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>
@@ -261,14 +269,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)
@@ -285,7 +298,9 @@ public abstract partial class SharedMechSystem : EntitySystem
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);
}