From 721a445bbd707d21744ba01220e5ce46eda84e4e Mon Sep 17 00:00:00 2001 From: Leon Friedrich <60421075+ElectroJr@users.noreply.github.com> Date: Mon, 25 Dec 2023 02:33:32 -0500 Subject: [PATCH] Fix pulling mispredicts (#22941) * Fix pulling mispredicts * Make behaviour consistent * Good ol terminating entities --- Content.Server/Hands/Systems/HandsSystem.cs | 19 -------- .../EntitySystems/SharedHandsSystem.Drop.cs | 11 ++++- .../Hands/EntitySystems/SharedHandsSystem.cs | 1 + .../Hands/SharedHandVirtualItemSystem.cs | 11 +++-- .../Pulling/Components/PullableComponent.cs | 15 ++----- .../Components/SharedPullerComponent.cs | 8 ++-- .../SharedPullingStateManagementSystem.cs | 45 +++---------------- .../Systems/SharedPullingSystem.Actions.cs | 9 ++++ 8 files changed, 42 insertions(+), 77 deletions(-) diff --git a/Content.Server/Hands/Systems/HandsSystem.cs b/Content.Server/Hands/Systems/HandsSystem.cs index 15190c81c7..f41298e98d 100644 --- a/Content.Server/Hands/Systems/HandsSystem.cs +++ b/Content.Server/Hands/Systems/HandsSystem.cs @@ -1,25 +1,18 @@ -using System.Linq; using System.Numerics; -using Content.Server.Popups; using Content.Server.Pulling; using Content.Server.Stack; -using Content.Server.Storage.EntitySystems; using Content.Server.Stunnable; using Content.Shared.ActionBlocker; using Content.Shared.Body.Part; using Content.Shared.CombatMode; using Content.Shared.Explosion; -using Content.Shared.Hands; using Content.Shared.Hands.Components; using Content.Shared.Hands.EntitySystems; using Content.Shared.Input; -using Content.Shared.Inventory; using Content.Shared.Physics.Pull; using Content.Shared.Pulling.Components; using Content.Shared.Stacks; -using Content.Shared.Storage; using Content.Shared.Throwing; -using Robust.Shared.Containers; using Robust.Shared.GameStates; using Robust.Shared.Input.Binding; using Robust.Shared.Map; @@ -30,16 +23,12 @@ namespace Content.Server.Hands.Systems { public sealed class HandsSystem : SharedHandsSystem { - [Dependency] private readonly InventorySystem _inventorySystem = default!; [Dependency] private readonly StackSystem _stackSystem = default!; [Dependency] private readonly HandVirtualItemSystem _virtualItemSystem = default!; [Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!; - [Dependency] private readonly SharedHandVirtualItemSystem _virtualSystem = default!; - [Dependency] private readonly PopupSystem _popupSystem = default!; [Dependency] private readonly SharedHandsSystem _handsSystem = default!; [Dependency] private readonly PullingSystem _pullingSystem = default!; [Dependency] private readonly ThrowingSystem _throwingSystem = default!; - [Dependency] private readonly StorageSystem _storageSystem = default!; public override void Initialize() { @@ -98,14 +87,6 @@ namespace Content.Server.Hands.Systems args.Handled = true; // no shove/stun. } - protected override void HandleEntityRemoved(EntityUid uid, HandsComponent hands, EntRemovedFromContainerMessage args) - { - base.HandleEntityRemoved(uid, hands, args); - - if (!Deleted(args.Entity) && TryComp(args.Entity, out HandVirtualItemComponent? @virtual)) - _virtualSystem.Delete((args.Entity, @virtual), uid); - } - private void HandleBodyPartAdded(EntityUid uid, HandsComponent component, ref BodyPartAddedEvent args) { if (args.Part.PartType != BodyPartType.Hand) diff --git a/Content.Shared/Hands/EntitySystems/SharedHandsSystem.Drop.cs b/Content.Shared/Hands/EntitySystems/SharedHandsSystem.Drop.cs index 15b07cb62f..4e24013a50 100644 --- a/Content.Shared/Hands/EntitySystems/SharedHandsSystem.Drop.cs +++ b/Content.Shared/Hands/EntitySystems/SharedHandsSystem.Drop.cs @@ -25,6 +25,9 @@ public abstract partial class SharedHandsSystem var didUnequip = new DidUnequipHandEvent(uid, args.Entity, hand); RaiseLocalEvent(uid, didUnequip); + + if (TryComp(args.Entity, out HandVirtualItemComponent? @virtual)) + _virtualSystem.Delete((args.Entity, @virtual), uid); } /// @@ -100,8 +103,14 @@ public abstract partial class SharedHandsSystem var entity = hand.HeldEntity!.Value; DoDrop(uid, hand, doDropInteraction: doDropInteraction, handsComp); - var userXform = Transform(uid); + if (TerminatingOrDeleted(entity)) + return true; + var itemXform = Transform(entity); + if (itemXform.MapUid == null) + return true; + + var userXform = Transform(uid); var isInContainer = ContainerSystem.IsEntityInContainer(uid); if (targetDropLocation == null || isInContainer) diff --git a/Content.Shared/Hands/EntitySystems/SharedHandsSystem.cs b/Content.Shared/Hands/EntitySystems/SharedHandsSystem.cs index 4f34d6fc54..527ac196b8 100644 --- a/Content.Shared/Hands/EntitySystems/SharedHandsSystem.cs +++ b/Content.Shared/Hands/EntitySystems/SharedHandsSystem.cs @@ -20,6 +20,7 @@ public abstract partial class SharedHandsSystem [Dependency] private readonly SharedItemSystem _items = default!; [Dependency] private readonly SharedStorageSystem _storage = default!; [Dependency] protected readonly SharedTransformSystem TransformSystem = default!; + [Dependency] private readonly SharedHandVirtualItemSystem _virtualSystem = default!; protected event Action?>? OnHandSetActive; diff --git a/Content.Shared/Hands/SharedHandVirtualItemSystem.cs b/Content.Shared/Hands/SharedHandVirtualItemSystem.cs index 2e426020ca..d2fb86f338 100644 --- a/Content.Shared/Hands/SharedHandVirtualItemSystem.cs +++ b/Content.Shared/Hands/SharedHandVirtualItemSystem.cs @@ -11,6 +11,7 @@ public abstract class SharedHandVirtualItemSystem : EntitySystem { [Dependency] private readonly INetManager _net = default!; [Dependency] private readonly SharedHandsSystem _hands = default!; + [Dependency] private readonly SharedTransformSystem _transform = default!; public override void Initialize() { @@ -82,14 +83,16 @@ public abstract class SharedHandVirtualItemSystem : EntitySystem /// public void Delete(Entity item, EntityUid user) { - if (_net.IsClient) - return; - var userEv = new VirtualItemDeletedEvent(item.Comp.BlockingEntity, user); RaiseLocalEvent(user, userEv); var targEv = new VirtualItemDeletedEvent(item.Comp.BlockingEntity, user); RaiseLocalEvent(item.Comp.BlockingEntity, targEv); - QueueDel(item); + if (TerminatingOrDeleted(item)) + return; + + _transform.DetachParentToNull(item, Transform(item)); + if (_net.IsServer) + QueueDel(item); } } diff --git a/Content.Shared/Pulling/Components/PullableComponent.cs b/Content.Shared/Pulling/Components/PullableComponent.cs index 30222c481b..c5c3068869 100644 --- a/Content.Shared/Pulling/Components/PullableComponent.cs +++ b/Content.Shared/Pulling/Components/PullableComponent.cs @@ -5,7 +5,7 @@ using Robust.Shared.Serialization; namespace Content.Shared.Pulling.Components { // Before you try to add another type than SharedPullingStateManagementSystem, consider the can of worms you may be opening! - [NetworkedComponent()] + [NetworkedComponent, AutoGenerateComponentState] [Access(typeof(SharedPullingStateManagementSystem))] [RegisterComponent] public sealed partial class SharedPullableComponent : Component @@ -13,11 +13,13 @@ namespace Content.Shared.Pulling.Components /// /// The current entity pulling this component. /// + [DataField, AutoNetworkedField] public EntityUid? Puller { get; set; } /// /// The pull joint. /// + [DataField, AutoNetworkedField] public string? PullJointId { get; set; } public bool BeingPulled => Puller != null; @@ -40,17 +42,6 @@ namespace Content.Shared.Pulling.Components public bool PrevFixedRotation; } - [Serializable, NetSerializable] - public sealed class PullableComponentState : ComponentState - { - public readonly NetEntity? Puller; - - public PullableComponentState(NetEntity? puller) - { - Puller = puller; - } - } - /// /// Raised when a request is made to stop pulling an entity. /// diff --git a/Content.Shared/Pulling/Components/SharedPullerComponent.cs b/Content.Shared/Pulling/Components/SharedPullerComponent.cs index c21e8a76de..57a86e7f7a 100644 --- a/Content.Shared/Pulling/Components/SharedPullerComponent.cs +++ b/Content.Shared/Pulling/Components/SharedPullerComponent.cs @@ -1,6 +1,8 @@ -namespace Content.Shared.Pulling.Components +using Robust.Shared.GameStates; + +namespace Content.Shared.Pulling.Components { - [RegisterComponent] + [RegisterComponent, NetworkedComponent, AutoGenerateComponentState] [Access(typeof(SharedPullingStateManagementSystem))] public sealed partial class SharedPullerComponent : Component { @@ -9,7 +11,7 @@ public float SprintSpeedModifier => Pulling == default ? 1.0f : 0.95f; - [ViewVariables] + [DataField, AutoNetworkedField] public EntityUid? Pulling { get; set; } /// diff --git a/Content.Shared/Pulling/Systems/SharedPullingStateManagementSystem.cs b/Content.Shared/Pulling/Systems/SharedPullingStateManagementSystem.cs index f2c7518ae2..38ed899889 100644 --- a/Content.Shared/Pulling/Systems/SharedPullingStateManagementSystem.cs +++ b/Content.Shared/Pulling/Systems/SharedPullingStateManagementSystem.cs @@ -1,7 +1,6 @@ using Content.Shared.Physics.Pull; using Content.Shared.Pulling.Components; using JetBrains.Annotations; -using Robust.Shared.GameStates; using Robust.Shared.Map; using Robust.Shared.Physics; using Robust.Shared.Physics.Components; @@ -26,43 +25,6 @@ namespace Content.Shared.Pulling base.Initialize(); SubscribeLocalEvent(OnShutdown); - SubscribeLocalEvent(OnGetState); - SubscribeLocalEvent(OnHandleState); - } - - private void OnGetState(EntityUid uid, SharedPullableComponent component, ref ComponentGetState args) - { - args.State = new PullableComponentState(GetNetEntity(component.Puller)); - } - - private void OnHandleState(EntityUid uid, SharedPullableComponent component, ref ComponentHandleState args) - { - if (args.Current is not PullableComponentState state) - return; - - var puller = EnsureEntity(state.Puller, uid); - - if (!puller.HasValue) - { - ForceDisconnectPullable(component); - return; - } - - if (component.Puller == puller) - { - // don't disconnect and reconnect a puller for no reason - return; - } - - if (!TryComp(puller, out var comp)) - { - Log.Error($"Pullable state for entity {ToPrettyString(uid)} had invalid puller entity {ToPrettyString(puller.Value)}"); - // ensure it disconnects from any different puller, still - ForceDisconnectPullable(component); - return; - } - - ForceRelationship(comp, component); } private void OnShutdown(EntityUid uid, SharedPullableComponent component, ComponentShutdown args) @@ -111,6 +73,9 @@ namespace Content.Shared.Pulling public void ForceRelationship(SharedPullerComponent? puller, SharedPullableComponent? pullable) { + if (_timing.ApplyingState) + return; + ; if (pullable != null && puller != null && (puller.Pulling == pullable.Owner)) { // Already done @@ -187,6 +152,9 @@ namespace Content.Shared.Pulling public void ForceSetMovingTo(SharedPullableComponent pullable, EntityCoordinates? movingTo) { + if (_timing.ApplyingState) + return; + if (pullable.MovingTo == movingTo) { return; @@ -200,6 +168,7 @@ namespace Content.Shared.Pulling } pullable.MovingTo = movingTo; + Dirty(pullable); if (movingTo == null) { diff --git a/Content.Shared/Pulling/Systems/SharedPullingSystem.Actions.cs b/Content.Shared/Pulling/Systems/SharedPullingSystem.Actions.cs index cef527a95c..b3f9c0d1c0 100644 --- a/Content.Shared/Pulling/Systems/SharedPullingSystem.Actions.cs +++ b/Content.Shared/Pulling/Systems/SharedPullingSystem.Actions.cs @@ -12,6 +12,8 @@ using Robust.Shared.Map; using Robust.Shared.Physics; using Robust.Shared.Physics.Components; using Robust.Shared.Physics.Systems; +using Robust.Shared.Timing; +using Robust.Shared.Utility; namespace Content.Shared.Pulling { @@ -23,6 +25,7 @@ namespace Content.Shared.Pulling [Dependency] private readonly SharedInteractionSystem _interaction = default!; [Dependency] private readonly SharedPhysicsSystem _physics = default!; [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!; + [Dependency] private readonly IGameTiming _timing = default!; public bool CanPull(EntityUid puller, EntityUid pulled) { @@ -90,6 +93,9 @@ namespace Content.Shared.Pulling public bool TryStopPull(SharedPullableComponent pullable, EntityUid? user = null) { + if (_timing.ApplyingState) + return false; + if (!pullable.BeingPulled) { return false; @@ -127,6 +133,9 @@ namespace Content.Shared.Pulling // The main "start pulling" function. public bool TryStartPull(SharedPullerComponent puller, SharedPullableComponent pullable) { + if (_timing.ApplyingState) + return false; + if (puller.Pulling == pullable.Owner) return true; -- 2.51.2