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;
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()

View File

@@ -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);

View File

@@ -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>

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 // 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.

View File

@@ -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)

View File

@@ -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>