From 4b65fb15792ce677bd959bd291883d8084589ac9 Mon Sep 17 00:00:00 2001 From: Leon Friedrich <60421075+ElectroJr@users.noreply.github.com> Date: Mon, 16 Jan 2023 21:20:22 +1300 Subject: [PATCH] Try fix some mover jank (#13503) --- .../Physics/Controllers/MoverController.cs | 25 +++---- .../Physics/Controllers/MoverController.cs | 23 +++---- .../MovementRelayTargetComponent.cs | 5 ++ .../Systems/SharedMoverController.Input.cs | 26 ++++---- .../Systems/SharedMoverController.Relay.cs | 2 + .../Movement/Systems/SharedMoverController.cs | 66 ++++++++++++------- 6 files changed, 79 insertions(+), 68 deletions(-) diff --git a/Content.Client/Physics/Controllers/MoverController.cs b/Content.Client/Physics/Controllers/MoverController.cs index 2baebe1182..926d88fb0c 100644 --- a/Content.Client/Physics/Controllers/MoverController.cs +++ b/Content.Client/Physics/Controllers/MoverController.cs @@ -6,6 +6,7 @@ using Robust.Client.Player; using Robust.Shared.Physics; using Robust.Shared.Physics.Components; using Robust.Shared.Timing; +using Robust.Shared.Utility; namespace Content.Client.Physics.Controllers { @@ -52,21 +53,11 @@ namespace Content.Client.Physics.Controllers if (_playerManager.LocalPlayer?.ControlledEntity is not {Valid: true} player) return; - if (TryComp(player, out var relayMover)) + if (TryComp(player, out var relayMover) + && TryComp(relayMover.RelayEntity, out MovementRelayTargetComponent? targetComp)) { - if (relayMover.RelayEntity != null) - { - if (TryComp(player, out var mover) && - TryComp(relayMover.RelayEntity, out var relayed)) - { - relayed.CanMove = mover.CanMove; - relayed.RelativeEntity = mover.RelativeEntity; - relayed.RelativeRotation = mover.RelativeRotation; - relayed.TargetRelativeRotation = mover.RelativeRotation; - } - - HandleClientsideMovement(relayMover.RelayEntity.Value, frameTime); - } + DebugTools.Assert(targetComp.Entities.Count <= 1, "Multiple relayed movers are not supported at the moment"); + HandleClientsideMovement(relayMover.RelayEntity.Value, frameTime); } HandleClientsideMovement(player, frameTime); @@ -75,6 +66,8 @@ namespace Content.Client.Physics.Controllers private void HandleClientsideMovement(EntityUid player, float frameTime) { var xformQuery = GetEntityQuery(); + var moverQuery = GetEntityQuery(); + var relayTargetQuery = GetEntityQuery(); if (!TryComp(player, out InputMoverComponent? mover) || !xformQuery.TryGetComponent(player, out var xform)) @@ -82,7 +75,7 @@ namespace Content.Client.Physics.Controllers return; } - PhysicsComponent? body = null; + PhysicsComponent? body; TransformComponent? xformMover = xform; if (mover.ToParent && HasComp(xform.ParentUid)) @@ -135,7 +128,7 @@ namespace Content.Client.Physics.Controllers } // Server-side should just be handled on its own so we'll just do this shizznit - HandleMobMovement(mover, body, xformMover, frameTime, xformQuery); + HandleMobMovement(player, mover, body, xformMover, frameTime, xformQuery, moverQuery, relayTargetQuery); } protected override bool CanSound() diff --git a/Content.Server/Physics/Controllers/MoverController.cs b/Content.Server/Physics/Controllers/MoverController.cs index 6098f8fcf4..c27bbdfe53 100644 --- a/Content.Server/Physics/Controllers/MoverController.cs +++ b/Content.Server/Physics/Controllers/MoverController.cs @@ -62,29 +62,22 @@ namespace Content.Server.Physics.Controllers var bodyQuery = GetEntityQuery(); var relayQuery = GetEntityQuery(); + var relayTargetQuery = GetEntityQuery(); var xformQuery = GetEntityQuery(); var moverQuery = GetEntityQuery(); foreach (var mover in EntityQuery(true)) { - if (relayQuery.TryGetComponent(mover.Owner, out var relayed) && relayed.RelayEntity != null) - { - if (moverQuery.TryGetComponent(relayed.RelayEntity, out var relayMover)) - { - relayMover.CanMove = mover.CanMove; - relayMover.RelativeEntity = mover.RelativeEntity; - relayMover.RelativeRotation = mover.RelativeRotation; - relayMover.TargetRelativeRotation = mover.TargetRelativeRotation; - continue; - } - } + var uid = mover.Owner; + if (relayQuery.HasComponent(uid)) + continue; - if (!xformQuery.TryGetComponent(mover.Owner, out var xform)) + if (!xformQuery.TryGetComponent(uid, out var xform)) { continue; } - PhysicsComponent? body = null; + PhysicsComponent? body; var xformMover = xform; if (mover.ToParent && relayQuery.HasComponent(xform.ParentUid)) @@ -95,12 +88,12 @@ namespace Content.Server.Physics.Controllers continue; } } - else if (!bodyQuery.TryGetComponent(mover.Owner, out body)) + else if (!bodyQuery.TryGetComponent(uid, out body)) { continue; } - HandleMobMovement(mover, body, xformMover, frameTime, xformQuery); + HandleMobMovement(uid, mover, body, xformMover, frameTime, xformQuery, moverQuery, relayTargetQuery); } HandleShuttleMovement(frameTime); diff --git a/Content.Shared/Movement/Components/MovementRelayTargetComponent.cs b/Content.Shared/Movement/Components/MovementRelayTargetComponent.cs index 18776ab5b0..80e5c27a5a 100644 --- a/Content.Shared/Movement/Components/MovementRelayTargetComponent.cs +++ b/Content.Shared/Movement/Components/MovementRelayTargetComponent.cs @@ -5,6 +5,11 @@ namespace Content.Shared.Movement.Components; [RegisterComponent, NetworkedComponent] public sealed class MovementRelayTargetComponent : Component { + // This really shouldn't be a list at the moment. Its just not supported. + // Neither movement updating, nor HandleDirChange() support more than one mover. + // Its currently possible for the direction to be set by one mover and the relative rotation to be set by a separate unrelated mover. + // AAAAA + /// /// Entities that are relaying to us. /// diff --git a/Content.Shared/Movement/Systems/SharedMoverController.Input.cs b/Content.Shared/Movement/Systems/SharedMoverController.Input.cs index 167fe2fc0a..d1da217a3d 100644 --- a/Content.Shared/Movement/Systems/SharedMoverController.Input.cs +++ b/Content.Shared/Movement/Systems/SharedMoverController.Input.cs @@ -192,25 +192,25 @@ namespace Content.Shared.Movement.Systems { // Relayed movement just uses the same keybinds given we're moving the relayed entity // the same as us. - TryComp(entity, out var moverComp); - // Can't relay inputs if you're dead. - if (TryComp(entity, out var relayMover) && !_mobState.IsIncapacitated(entity)) + if (TryComp(entity, out var relayMover)) { - // if we swap to relay then stop our existing input if we ever change back. - if (moverComp != null) - { - SetMoveInput(moverComp, MoveButtons.None); - } - - if (relayMover.RelayEntity == null) return; - DebugTools.Assert(relayMover.RelayEntity != entity); - HandleDirChange(relayMover.RelayEntity.Value, dir, subTick, state); + DebugTools.AssertNotNull(relayMover.RelayEntity); + + if (TryComp(entity, out var mover)) + SetMoveInput(mover, MoveButtons.None); + + DebugTools.Assert(TryComp(relayMover.RelayEntity, out MovementRelayTargetComponent? targetComp) && targetComp.Entities.Count == 1, + "Multiple relayed movers are not supported at the moment"); + + if (relayMover.RelayEntity != null && !_mobState.IsIncapacitated(entity)) + HandleDirChange(relayMover.RelayEntity.Value, dir, subTick, state); + return; } - if (moverComp == null) + if (!TryComp(entity, out var moverComp)) return; // Relay the fact we had any movement event. diff --git a/Content.Shared/Movement/Systems/SharedMoverController.Relay.cs b/Content.Shared/Movement/Systems/SharedMoverController.Relay.cs index 67595bbabe..3f73e11431 100644 --- a/Content.Shared/Movement/Systems/SharedMoverController.Relay.cs +++ b/Content.Shared/Movement/Systems/SharedMoverController.Relay.cs @@ -44,6 +44,7 @@ public abstract partial class SharedMoverController component.RelayEntity = relayEntity; targetComp = EnsureComp(relayEntity); targetComp.Entities.Add(uid); + DebugTools.Assert(targetComp.Entities.Count <= 1, "Multiple relayed movers are not supported at the moment"); Dirty(component); Dirty(targetComp); } @@ -114,6 +115,7 @@ public abstract partial class SharedMoverController component.Entities.Clear(); component.Entities.AddRange(state.Entities); + DebugTools.Assert(component.Entities.Count <= 1, "Multiple relayed movers are not supported at the moment"); } private void OnTargetRelayGetState(EntityUid uid, MovementRelayTargetComponent component, ref ComponentGetState args) diff --git a/Content.Shared/Movement/Systems/SharedMoverController.cs b/Content.Shared/Movement/Systems/SharedMoverController.cs index f8c99543da..1239e45b33 100644 --- a/Content.Shared/Movement/Systems/SharedMoverController.cs +++ b/Content.Shared/Movement/Systems/SharedMoverController.cs @@ -96,13 +96,38 @@ namespace Content.Shared.Movement.Systems /// Movement while considering actionblockers, weightlessness, etc. /// protected void HandleMobMovement( + EntityUid uid, InputMoverComponent mover, PhysicsComponent physicsComponent, TransformComponent xform, float frameTime, - EntityQuery xformQuery) + EntityQuery xformQuery, + EntityQuery moverQuery, + EntityQuery relayTargetQuery) { - DebugTools.Assert(!UsedMobMovement.ContainsKey(mover.Owner)); + DebugTools.Assert(!UsedMobMovement.ContainsKey(uid)); + + bool canMove = mover.CanMove; + if (relayTargetQuery.TryGetComponent(uid, out var relayTarget) && relayTarget.Entities.Count > 0) + { + DebugTools.Assert(relayTarget.Entities.Count <= 1, "Multiple relayed movers are not supported at the moment"); + + bool found = false; + foreach (var ent in relayTarget.Entities) + { + if (_mobState.IsIncapacitated(ent) || !moverQuery.TryGetComponent(ent, out var relayedMover)) + continue; + + found = true; + mover.RelativeEntity = relayedMover.RelativeEntity; + mover.RelativeRotation = relayedMover.RelativeRotation; + mover.TargetRelativeRotation = relayedMover.TargetRelativeRotation; + break; + } + + // lets just hope that this is the same entity that set the movement keys/direction. + canMove &= found; + } // Update relative movement if (mover.LerpAccumulator > 0f) @@ -191,15 +216,17 @@ namespace Content.Shared.Movement.Systems Dirty(mover); } - if (!UseMobMovement(mover, physicsComponent)) + if (!canMove + || physicsComponent.BodyStatus != BodyStatus.OnGround + || TryComp(uid, out SharedPullableComponent? pullable) && pullable.BeingPulled) { - UsedMobMovement[mover.Owner] = false; + UsedMobMovement[uid] = false; return; } - UsedMobMovement[mover.Owner] = true; + UsedMobMovement[uid] = true; // Specifically don't use mover.Owner because that may be different to the actual physics body being moved. - var weightless = _gravity.IsWeightless(physicsComponent.Owner, physicsComponent, xform); + var weightless = _gravity.IsWeightless(uid, physicsComponent, xform); var (walkDir, sprintDir) = GetVelocityInput(mover); var touching = false; @@ -212,11 +239,11 @@ namespace Content.Shared.Movement.Systems if (!touching) { var ev = new CanWeightlessMoveEvent(); - RaiseLocalEvent(xform.Owner, ref ev); + RaiseLocalEvent(uid, ref ev); // No gravity: is our entity touching anything? touching = ev.CanMove; - if (!touching && TryComp(xform.Owner, out var mobMover)) + if (!touching && TryComp(uid, out var mobMover)) touching |= IsAroundCollider(PhysicsSystem, xform, mobMover, physicsComponent); } } @@ -224,7 +251,7 @@ namespace Content.Shared.Movement.Systems // Regular movement. // Target velocity. // This is relative to the map / grid we're on. - var moveSpeedComponent = CompOrNull(mover.Owner); + var moveSpeedComponent = CompOrNull(uid); var walkSpeed = moveSpeedComponent?.CurrentWalkSpeed ?? MovementSpeedModifierComponent.DefaultBaseWalkSpeed; var sprintSpeed = moveSpeedComponent?.CurrentSprintSpeed ?? MovementSpeedModifierComponent.DefaultBaseSprintSpeed; @@ -286,16 +313,16 @@ namespace Content.Shared.Movement.Systems .WithVariation(sound.Params.Variation ?? FootstepVariation); // If we're a relay target then predict the sound for all relays. - if (TryComp(mover.Owner, out var targetComp)) + if (relayTarget != null) { - foreach (var ent in targetComp.Entities) + foreach (var ent in relayTarget.Entities) { - _audio.PlayPredicted(sound, mover.Owner, ent, audioParams); + _audio.PlayPredicted(sound, uid, ent, audioParams); } } else { - _audio.PlayPredicted(sound, mover.Owner, mover.Owner, audioParams); + _audio.PlayPredicted(sound, uid, uid, audioParams); } } } @@ -305,10 +332,10 @@ namespace Content.Shared.Movement.Systems if (!weightless || touching) Accelerate(ref velocity, in worldTotal, accel, frameTime); - PhysicsSystem.SetLinearVelocity(physicsComponent.Owner, velocity, body: physicsComponent); + PhysicsSystem.SetLinearVelocity(uid, velocity, body: physicsComponent); // Ensures that players do not spiiiiiiin - PhysicsSystem.SetAngularVelocity(physicsComponent.Owner, 0, body: physicsComponent); + PhysicsSystem.SetAngularVelocity(uid, 0, body: physicsComponent); } private void Friction(float minimumFrictionSpeed, float frameTime, float friction, ref Vector2 velocity) @@ -351,15 +378,6 @@ namespace Content.Shared.Movement.Systems return UsedMobMovement.TryGetValue(uid, out var used) && used; } - protected bool UseMobMovement(InputMoverComponent mover, PhysicsComponent body) - { - return mover.CanMove && - body.BodyStatus == BodyStatus.OnGround && - HasComp(body.Owner) && - // If we're being pulled then don't mess with our velocity. - (!TryComp(body.Owner, out SharedPullableComponent? pullable) || !pullable.BeingPulled); - } - /// /// Used for weightlessness to determine if we are near a wall. ///