Try fix some mover jank (#13503)
This commit is contained in:
@@ -6,6 +6,7 @@ using Robust.Client.Player;
|
|||||||
using Robust.Shared.Physics;
|
using Robust.Shared.Physics;
|
||||||
using Robust.Shared.Physics.Components;
|
using Robust.Shared.Physics.Components;
|
||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
namespace Content.Client.Physics.Controllers
|
namespace Content.Client.Physics.Controllers
|
||||||
{
|
{
|
||||||
@@ -52,21 +53,11 @@ namespace Content.Client.Physics.Controllers
|
|||||||
if (_playerManager.LocalPlayer?.ControlledEntity is not {Valid: true} player)
|
if (_playerManager.LocalPlayer?.ControlledEntity is not {Valid: true} player)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (TryComp<RelayInputMoverComponent>(player, out var relayMover))
|
if (TryComp<RelayInputMoverComponent>(player, out var relayMover)
|
||||||
|
&& TryComp(relayMover.RelayEntity, out MovementRelayTargetComponent? targetComp))
|
||||||
{
|
{
|
||||||
if (relayMover.RelayEntity != null)
|
DebugTools.Assert(targetComp.Entities.Count <= 1, "Multiple relayed movers are not supported at the moment");
|
||||||
{
|
HandleClientsideMovement(relayMover.RelayEntity.Value, frameTime);
|
||||||
if (TryComp<InputMoverComponent>(player, out var mover) &&
|
|
||||||
TryComp<InputMoverComponent>(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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HandleClientsideMovement(player, frameTime);
|
HandleClientsideMovement(player, frameTime);
|
||||||
@@ -75,6 +66,8 @@ namespace Content.Client.Physics.Controllers
|
|||||||
private void HandleClientsideMovement(EntityUid player, float frameTime)
|
private void HandleClientsideMovement(EntityUid player, float frameTime)
|
||||||
{
|
{
|
||||||
var xformQuery = GetEntityQuery<TransformComponent>();
|
var xformQuery = GetEntityQuery<TransformComponent>();
|
||||||
|
var moverQuery = GetEntityQuery<InputMoverComponent>();
|
||||||
|
var relayTargetQuery = GetEntityQuery<MovementRelayTargetComponent>();
|
||||||
|
|
||||||
if (!TryComp(player, out InputMoverComponent? mover) ||
|
if (!TryComp(player, out InputMoverComponent? mover) ||
|
||||||
!xformQuery.TryGetComponent(player, out var xform))
|
!xformQuery.TryGetComponent(player, out var xform))
|
||||||
@@ -82,7 +75,7 @@ namespace Content.Client.Physics.Controllers
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PhysicsComponent? body = null;
|
PhysicsComponent? body;
|
||||||
TransformComponent? xformMover = xform;
|
TransformComponent? xformMover = xform;
|
||||||
|
|
||||||
if (mover.ToParent && HasComp<RelayInputMoverComponent>(xform.ParentUid))
|
if (mover.ToParent && HasComp<RelayInputMoverComponent>(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
|
// 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()
|
protected override bool CanSound()
|
||||||
|
|||||||
@@ -62,29 +62,22 @@ namespace Content.Server.Physics.Controllers
|
|||||||
|
|
||||||
var bodyQuery = GetEntityQuery<PhysicsComponent>();
|
var bodyQuery = GetEntityQuery<PhysicsComponent>();
|
||||||
var relayQuery = GetEntityQuery<RelayInputMoverComponent>();
|
var relayQuery = GetEntityQuery<RelayInputMoverComponent>();
|
||||||
|
var relayTargetQuery = GetEntityQuery<MovementRelayTargetComponent>();
|
||||||
var xformQuery = GetEntityQuery<TransformComponent>();
|
var xformQuery = GetEntityQuery<TransformComponent>();
|
||||||
var moverQuery = GetEntityQuery<InputMoverComponent>();
|
var moverQuery = GetEntityQuery<InputMoverComponent>();
|
||||||
|
|
||||||
foreach (var mover in EntityQuery<InputMoverComponent>(true))
|
foreach (var mover in EntityQuery<InputMoverComponent>(true))
|
||||||
{
|
{
|
||||||
if (relayQuery.TryGetComponent(mover.Owner, out var relayed) && relayed.RelayEntity != null)
|
var uid = mover.Owner;
|
||||||
{
|
if (relayQuery.HasComponent(uid))
|
||||||
if (moverQuery.TryGetComponent(relayed.RelayEntity, out var relayMover))
|
continue;
|
||||||
{
|
|
||||||
relayMover.CanMove = mover.CanMove;
|
|
||||||
relayMover.RelativeEntity = mover.RelativeEntity;
|
|
||||||
relayMover.RelativeRotation = mover.RelativeRotation;
|
|
||||||
relayMover.TargetRelativeRotation = mover.TargetRelativeRotation;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!xformQuery.TryGetComponent(mover.Owner, out var xform))
|
if (!xformQuery.TryGetComponent(uid, out var xform))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
PhysicsComponent? body = null;
|
PhysicsComponent? body;
|
||||||
var xformMover = xform;
|
var xformMover = xform;
|
||||||
|
|
||||||
if (mover.ToParent && relayQuery.HasComponent(xform.ParentUid))
|
if (mover.ToParent && relayQuery.HasComponent(xform.ParentUid))
|
||||||
@@ -95,12 +88,12 @@ namespace Content.Server.Physics.Controllers
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!bodyQuery.TryGetComponent(mover.Owner, out body))
|
else if (!bodyQuery.TryGetComponent(uid, out body))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
HandleMobMovement(mover, body, xformMover, frameTime, xformQuery);
|
HandleMobMovement(uid, mover, body, xformMover, frameTime, xformQuery, moverQuery, relayTargetQuery);
|
||||||
}
|
}
|
||||||
|
|
||||||
HandleShuttleMovement(frameTime);
|
HandleShuttleMovement(frameTime);
|
||||||
|
|||||||
@@ -5,6 +5,11 @@ namespace Content.Shared.Movement.Components;
|
|||||||
[RegisterComponent, NetworkedComponent]
|
[RegisterComponent, NetworkedComponent]
|
||||||
public sealed class MovementRelayTargetComponent : Component
|
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
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Entities that are relaying to us.
|
/// Entities that are relaying to us.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -192,25 +192,25 @@ namespace Content.Shared.Movement.Systems
|
|||||||
{
|
{
|
||||||
// Relayed movement just uses the same keybinds given we're moving the relayed entity
|
// Relayed movement just uses the same keybinds given we're moving the relayed entity
|
||||||
// the same as us.
|
// the same as us.
|
||||||
TryComp<InputMoverComponent>(entity, out var moverComp);
|
|
||||||
|
|
||||||
// Can't relay inputs if you're dead.
|
if (TryComp<RelayInputMoverComponent>(entity, out var relayMover))
|
||||||
if (TryComp<RelayInputMoverComponent>(entity, out var relayMover) && !_mobState.IsIncapacitated(entity))
|
|
||||||
{
|
{
|
||||||
// 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);
|
DebugTools.Assert(relayMover.RelayEntity != entity);
|
||||||
HandleDirChange(relayMover.RelayEntity.Value, dir, subTick, state);
|
DebugTools.AssertNotNull(relayMover.RelayEntity);
|
||||||
|
|
||||||
|
if (TryComp<InputMoverComponent>(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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (moverComp == null)
|
if (!TryComp<InputMoverComponent>(entity, out var moverComp))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Relay the fact we had any movement event.
|
// Relay the fact we had any movement event.
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ public abstract partial class SharedMoverController
|
|||||||
component.RelayEntity = relayEntity;
|
component.RelayEntity = relayEntity;
|
||||||
targetComp = EnsureComp<MovementRelayTargetComponent>(relayEntity);
|
targetComp = EnsureComp<MovementRelayTargetComponent>(relayEntity);
|
||||||
targetComp.Entities.Add(uid);
|
targetComp.Entities.Add(uid);
|
||||||
|
DebugTools.Assert(targetComp.Entities.Count <= 1, "Multiple relayed movers are not supported at the moment");
|
||||||
Dirty(component);
|
Dirty(component);
|
||||||
Dirty(targetComp);
|
Dirty(targetComp);
|
||||||
}
|
}
|
||||||
@@ -114,6 +115,7 @@ public abstract partial class SharedMoverController
|
|||||||
|
|
||||||
component.Entities.Clear();
|
component.Entities.Clear();
|
||||||
component.Entities.AddRange(state.Entities);
|
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)
|
private void OnTargetRelayGetState(EntityUid uid, MovementRelayTargetComponent component, ref ComponentGetState args)
|
||||||
|
|||||||
@@ -96,13 +96,38 @@ namespace Content.Shared.Movement.Systems
|
|||||||
/// Movement while considering actionblockers, weightlessness, etc.
|
/// Movement while considering actionblockers, weightlessness, etc.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected void HandleMobMovement(
|
protected void HandleMobMovement(
|
||||||
|
EntityUid uid,
|
||||||
InputMoverComponent mover,
|
InputMoverComponent mover,
|
||||||
PhysicsComponent physicsComponent,
|
PhysicsComponent physicsComponent,
|
||||||
TransformComponent xform,
|
TransformComponent xform,
|
||||||
float frameTime,
|
float frameTime,
|
||||||
EntityQuery<TransformComponent> xformQuery)
|
EntityQuery<TransformComponent> xformQuery,
|
||||||
|
EntityQuery<InputMoverComponent> moverQuery,
|
||||||
|
EntityQuery<MovementRelayTargetComponent> 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
|
// Update relative movement
|
||||||
if (mover.LerpAccumulator > 0f)
|
if (mover.LerpAccumulator > 0f)
|
||||||
@@ -191,15 +216,17 @@ namespace Content.Shared.Movement.Systems
|
|||||||
Dirty(mover);
|
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;
|
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.
|
// 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 (walkDir, sprintDir) = GetVelocityInput(mover);
|
||||||
var touching = false;
|
var touching = false;
|
||||||
|
|
||||||
@@ -212,11 +239,11 @@ namespace Content.Shared.Movement.Systems
|
|||||||
if (!touching)
|
if (!touching)
|
||||||
{
|
{
|
||||||
var ev = new CanWeightlessMoveEvent();
|
var ev = new CanWeightlessMoveEvent();
|
||||||
RaiseLocalEvent(xform.Owner, ref ev);
|
RaiseLocalEvent(uid, ref ev);
|
||||||
// No gravity: is our entity touching anything?
|
// No gravity: is our entity touching anything?
|
||||||
touching = ev.CanMove;
|
touching = ev.CanMove;
|
||||||
|
|
||||||
if (!touching && TryComp<MobMoverComponent>(xform.Owner, out var mobMover))
|
if (!touching && TryComp<MobMoverComponent>(uid, out var mobMover))
|
||||||
touching |= IsAroundCollider(PhysicsSystem, xform, mobMover, physicsComponent);
|
touching |= IsAroundCollider(PhysicsSystem, xform, mobMover, physicsComponent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -224,7 +251,7 @@ namespace Content.Shared.Movement.Systems
|
|||||||
// Regular movement.
|
// Regular movement.
|
||||||
// Target velocity.
|
// Target velocity.
|
||||||
// This is relative to the map / grid we're on.
|
// This is relative to the map / grid we're on.
|
||||||
var moveSpeedComponent = CompOrNull<MovementSpeedModifierComponent>(mover.Owner);
|
var moveSpeedComponent = CompOrNull<MovementSpeedModifierComponent>(uid);
|
||||||
|
|
||||||
var walkSpeed = moveSpeedComponent?.CurrentWalkSpeed ?? MovementSpeedModifierComponent.DefaultBaseWalkSpeed;
|
var walkSpeed = moveSpeedComponent?.CurrentWalkSpeed ?? MovementSpeedModifierComponent.DefaultBaseWalkSpeed;
|
||||||
var sprintSpeed = moveSpeedComponent?.CurrentSprintSpeed ?? MovementSpeedModifierComponent.DefaultBaseSprintSpeed;
|
var sprintSpeed = moveSpeedComponent?.CurrentSprintSpeed ?? MovementSpeedModifierComponent.DefaultBaseSprintSpeed;
|
||||||
@@ -286,16 +313,16 @@ namespace Content.Shared.Movement.Systems
|
|||||||
.WithVariation(sound.Params.Variation ?? FootstepVariation);
|
.WithVariation(sound.Params.Variation ?? FootstepVariation);
|
||||||
|
|
||||||
// If we're a relay target then predict the sound for all relays.
|
// If we're a relay target then predict the sound for all relays.
|
||||||
if (TryComp<MovementRelayTargetComponent>(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
|
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)
|
if (!weightless || touching)
|
||||||
Accelerate(ref velocity, in worldTotal, accel, frameTime);
|
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
|
// 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)
|
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;
|
return UsedMobMovement.TryGetValue(uid, out var used) && used;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected bool UseMobMovement(InputMoverComponent mover, PhysicsComponent body)
|
|
||||||
{
|
|
||||||
return mover.CanMove &&
|
|
||||||
body.BodyStatus == BodyStatus.OnGround &&
|
|
||||||
HasComp<InputMoverComponent>(body.Owner) &&
|
|
||||||
// If we're being pulled then don't mess with our velocity.
|
|
||||||
(!TryComp(body.Owner, out SharedPullableComponent? pullable) || !pullable.BeingPulled);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Used for weightlessness to determine if we are near a wall.
|
/// Used for weightlessness to determine if we are near a wall.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
Reference in New Issue
Block a user