From 9b31c2a92990065e68513f73bfaaff0e320cbcee Mon Sep 17 00:00:00 2001 From: Centronias Date: Sat, 19 Sep 2026 19:58:53 +0000 Subject: [PATCH] Parcel wrap bugfix + multihandedness enhancement (#43956) * parcel wrap enhancements: - bugfix: can't wrap stuff that can't be picked up because it's static (ie. usually anchored, maybe other cases, idk) - enhancement: multi-handedness is inherited by the parcel from its contents - technical: migrate to `EntityQuery` dependencies for all component lookups. * Apply suggestion from @Centronias * Update Content.Shared/ParcelWrap/Systems/ParcelWrappingSystem.cs * Update ParcelWrappingSystem.cs --------- Co-authored-by: Pok <113675512+Pok27@users.noreply.github.com> --- .../Components/WrappedParcelComponent.cs | 7 +++++ .../ParcelWrappingSystem.ParcelWrap.cs | 2 +- .../ParcelWrappingSystem.WrappedParcel.cs | 27 ++++++++++++------- .../Systems/ParcelWrappingSystem.cs | 14 +++++++++- 4 files changed, 38 insertions(+), 12 deletions(-) diff --git a/Content.Shared/ParcelWrap/Components/WrappedParcelComponent.cs b/Content.Shared/ParcelWrap/Components/WrappedParcelComponent.cs index 17c6ef46cb..6d597c64d1 100644 --- a/Content.Shared/ParcelWrap/Components/WrappedParcelComponent.cs +++ b/Content.Shared/ParcelWrap/Components/WrappedParcelComponent.cs @@ -61,6 +61,13 @@ public sealed partial class WrappedParcelComponent : Component [DataField, AutoNetworkedField] public bool GetsShapeFromContent; + /// + /// If true, the owner of this entity has added if any item inserted into + /// has that component. + /// + [DataField, AutoNetworkedField] + public bool GetsMultiHandednessFromContent = true; + /// /// If a player trapped inside this parcel can escape from it by unwrapping it. /// This is set by the used to create the parcel. diff --git a/Content.Shared/ParcelWrap/Systems/ParcelWrappingSystem.ParcelWrap.cs b/Content.Shared/ParcelWrap/Systems/ParcelWrappingSystem.ParcelWrap.cs index a2d47f9f59..a95de6794a 100644 --- a/Content.Shared/ParcelWrap/Systems/ParcelWrappingSystem.ParcelWrap.cs +++ b/Content.Shared/ParcelWrap/Systems/ParcelWrappingSystem.ParcelWrap.cs @@ -88,7 +88,7 @@ public sealed partial class ParcelWrappingSystem { var duration = wrapper.Comp.WrapDelay; - if (TryComp(target, out var overrideComp) && + if (_parcelWrapOverrideQuery.TryComp(target, out var overrideComp) && overrideComp.WrapDelay is { } wrapDelayOverride) duration = wrapDelayOverride; diff --git a/Content.Shared/ParcelWrap/Systems/ParcelWrappingSystem.WrappedParcel.cs b/Content.Shared/ParcelWrap/Systems/ParcelWrappingSystem.WrappedParcel.cs index 8a5a8f4fc3..7374fdd682 100644 --- a/Content.Shared/ParcelWrap/Systems/ParcelWrappingSystem.WrappedParcel.cs +++ b/Content.Shared/ParcelWrap/Systems/ParcelWrappingSystem.WrappedParcel.cs @@ -32,7 +32,10 @@ public sealed partial class ParcelWrappingSystem entity.Comp.Contents = _container.EnsureContainer(entity, entity.Comp.ContainerId); } - private void OnEntInsertedIntoContainer(Entity entity, ref EntInsertedIntoContainerMessage args) + private void OnEntInsertedIntoContainer( + Entity entity, + ref EntInsertedIntoContainerMessage args + ) { // If the entity was inserted because of a server state application, assume that the item's state is applied // correctly as well and that deriving them from the contents is unneeded. @@ -40,12 +43,10 @@ public sealed partial class ParcelWrappingSystem return; if (args.Container != entity.Comp.Contents || - !TryComp(entity, out var parcelItemComp)) + !_itemQuery.TryComp(entity, out var parcelItemComp)) return; - // If this wrap maintains the size when wrapping, set the parcel's size to the target's size, or the fallback - // size if the target does not have a size. - var targetItemComp = CompOrNull(args.Entity); + var targetItemComp = _itemQuery.CompOrNull(args.Entity); if (entity.Comp.GetsSizeFromContent) { var size = targetItemComp?.Size ?? _fallbackParcelSize; @@ -53,12 +54,16 @@ public sealed partial class ParcelWrappingSystem _appearance.SetData(entity, WrappedParcelVisuals.Size, size.Id); } - // If this wrap maintains the shape when wrapping and the item has a shape override, copy the shape override to - // the parcel. if (entity.Comp.GetsShapeFromContent) { _item.SetShape(entity, targetItemComp?.Shape, parcelItemComp); } + + if (entity.Comp.GetsMultiHandednessFromContent && + _multiHandedItemQuery.TryComp(args.Entity, out var multiHandedItemComp)) + { + EnsureComp(entity).HandsNeeded = multiHandedItemComp.HandsNeeded; + } } private void OnUseInHand(Entity entity, ref UseInHandEvent args) @@ -69,8 +74,10 @@ public sealed partial class ParcelWrappingSystem args.Handled = TryStartUnwrapDoAfter(args.User, entity); } - private void OnGetVerbsForWrappedParcel(Entity entity, - ref GetVerbsEvent args) + private void OnGetVerbsForWrappedParcel( + Entity entity, + ref GetVerbsEvent args + ) { if (!args.CanAccess || !args.CanComplexInteract) return; @@ -93,7 +100,7 @@ public sealed partial class ParcelWrappingSystem if (args.Handled || args.Cancelled) return; - if (args.Target is { } target && TryComp(target, out var parcel)) + if (args.Target is { } target && _wrappedParcelQuery.TryComp(target, out var parcel)) { UnwrapInternal(args.User, (target, parcel)); args.Handled = true; diff --git a/Content.Shared/ParcelWrap/Systems/ParcelWrappingSystem.cs b/Content.Shared/ParcelWrap/Systems/ParcelWrappingSystem.cs index 84856ac73d..ea9fa0d8a1 100644 --- a/Content.Shared/ParcelWrap/Systems/ParcelWrappingSystem.cs +++ b/Content.Shared/ParcelWrap/Systems/ParcelWrappingSystem.cs @@ -4,8 +4,11 @@ using Content.Shared.Item; using Content.Shared.ParcelWrap.Components; using Content.Shared.Popups; using Content.Shared.Whitelist; +using JetBrains.Annotations; using Robust.Shared.Audio.Systems; using Robust.Shared.Containers; +using Robust.Shared.Physics; +using Robust.Shared.Physics.Components; namespace Content.Shared.ParcelWrap.Systems; @@ -27,6 +30,12 @@ public sealed partial class ParcelWrappingSystem : EntitySystem [Dependency] private SharedTransformSystem _transform = default!; [Dependency] private EntityWhitelistSystem _whitelist = default!; + [Dependency] private EntityQuery _itemQuery = default!; + [Dependency] private EntityQuery _multiHandedItemQuery = default!; + [Dependency] private EntityQuery _parcelWrapOverrideQuery = default!; + [Dependency] private EntityQuery _physicsQuery = default!; + [Dependency] private EntityQuery _wrappedParcelQuery = default!; + /// public override void Initialize() { @@ -42,6 +51,7 @@ public sealed partial class ParcelWrappingSystem : EntitySystem /// The entity doing the wrapping. /// The entity to be wrapped. /// True if can be used to wrap , false otherwise. + [PublicAPI] public bool IsWrappable(Entity wrapper, EntityUid target) { return @@ -49,6 +59,8 @@ public sealed partial class ParcelWrappingSystem : EntitySystem wrapper.Owner != target && // Wrapper should never be empty, but may as well make sure. !_charges.IsEmpty(wrapper.Owner) && - _whitelist.CheckBoth(target, wrapper.Comp.Blacklist, wrapper.Comp.Whitelist); + _whitelist.CheckBoth(target, wrapper.Comp.Blacklist, wrapper.Comp.Whitelist) && + // If it can't be moved, it shouldn't be able to go into a parcel and picked up. + _physicsQuery.TryComp(target, out var physics) && physics.BodyType != BodyType.Static; } }