Try fix some mover jank (#13503)

This commit is contained in:
Leon Friedrich
2023-01-16 21:20:22 +13:00
committed by GitHub
parent 450dfd5074
commit 4b65fb1579
6 changed files with 79 additions and 68 deletions

View File

@@ -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,22 +53,12 @@ namespace Content.Client.Physics.Controllers
if (_playerManager.LocalPlayer?.ControlledEntity is not {Valid: true} player)
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)
{
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;
}
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<TransformComponent>();
var moverQuery = GetEntityQuery<InputMoverComponent>();
var relayTargetQuery = GetEntityQuery<MovementRelayTargetComponent>();
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<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
HandleMobMovement(mover, body, xformMover, frameTime, xformQuery);
HandleMobMovement(player, mover, body, xformMover, frameTime, xformQuery, moverQuery, relayTargetQuery);
}
protected override bool CanSound()

View File

@@ -62,29 +62,22 @@ namespace Content.Server.Physics.Controllers
var bodyQuery = GetEntityQuery<PhysicsComponent>();
var relayQuery = GetEntityQuery<RelayInputMoverComponent>();
var relayTargetQuery = GetEntityQuery<MovementRelayTargetComponent>();
var xformQuery = GetEntityQuery<TransformComponent>();
var moverQuery = GetEntityQuery<InputMoverComponent>();
foreach (var mover in EntityQuery<InputMoverComponent>(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;
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);

View File

@@ -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
/// <summary>
/// Entities that are relaying to us.
/// </summary>

View File

@@ -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<InputMoverComponent>(entity, out var moverComp);
// Can't relay inputs if you're dead.
if (TryComp<RelayInputMoverComponent>(entity, out var relayMover) && !_mobState.IsIncapacitated(entity))
if (TryComp<RelayInputMoverComponent>(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);
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;
}
if (moverComp == null)
if (!TryComp<InputMoverComponent>(entity, out var moverComp))
return;
// Relay the fact we had any movement event.

View File

@@ -44,6 +44,7 @@ public abstract partial class SharedMoverController
component.RelayEntity = relayEntity;
targetComp = EnsureComp<MovementRelayTargetComponent>(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)

View File

@@ -96,13 +96,38 @@ namespace Content.Shared.Movement.Systems
/// Movement while considering actionblockers, weightlessness, etc.
/// </summary>
protected void HandleMobMovement(
EntityUid uid,
InputMoverComponent mover,
PhysicsComponent physicsComponent,
TransformComponent xform,
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
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<MobMoverComponent>(xform.Owner, out var mobMover))
if (!touching && TryComp<MobMoverComponent>(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<MovementSpeedModifierComponent>(mover.Owner);
var moveSpeedComponent = CompOrNull<MovementSpeedModifierComponent>(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<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
{
_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<InputMoverComponent>(body.Owner) &&
// If we're being pulled then don't mess with our velocity.
(!TryComp(body.Owner, out SharedPullableComponent? pullable) || !pullable.BeingPulled);
}
/// <summary>
/// Used for weightlessness to determine if we are near a wall.
/// </summary>