Re-organize all projects (#4166)

This commit is contained in:
DrSmugleaf
2021-06-09 22:19:39 +02:00
committed by GitHub
parent 9f50e4061b
commit ff1a2d97ea
1773 changed files with 5258 additions and 5508 deletions

View File

@@ -0,0 +1,22 @@
using Robust.Shared.GameObjects;
using Robust.Shared.Map;
namespace Content.Shared.Movement.Components
{
public interface IMobMoverComponent : IComponent
{
const float GrabRangeDefault = 0.6f;
const float PushStrengthDefault = 600.0f;
const float WeightlessStrengthDefault = 0.4f;
EntityCoordinates LastPosition { get; set; }
public float StepSoundDistance { get; set; }
float GrabRange { get; set; }
float PushStrength { get; set; }
float WeightlessStrength { get; set; }
}
}

View File

@@ -0,0 +1,43 @@
#nullable enable
using Robust.Shared.GameObjects;
using Robust.Shared.Maths;
namespace Content.Shared.Movement.Components
{
// Does nothing except ensure uniqueness between mover components.
// There can only be one.
public interface IMoverComponent : IComponent
{
/// <summary>
/// Movement speed (m/s) that the entity walks.
/// </summary>
float CurrentWalkSpeed { get; }
/// <summary>
/// Movement speed (m/s) that the entity sprints.
/// </summary>
float CurrentSprintSpeed { get; }
/// <summary>
/// Is the entity Sprinting (running)?
/// </summary>
bool Sprinting { get; }
/// <summary>
/// Calculated linear velocity direction of the entity.
/// </summary>
(Vector2 walking, Vector2 sprinting) VelocityDir { get; }
/// <summary>
/// Toggles one of the four cardinal directions. Each of the four directions are
/// composed into a single direction vector, <see cref="SharedPlayerInputMoverComponent.VelocityDir"/>. Enabling
/// opposite directions will cancel each other out, resulting in no direction.
/// </summary>
/// <param name="direction">Direction to toggle.</param>
/// <param name="subTick"></param>
/// <param name="enabled">If the direction is active.</param>
void SetVelocityDirection(Direction direction, ushort subTick, bool enabled);
void SetSprinting(ushort subTick, bool walking);
}
}

View File

@@ -0,0 +1,10 @@
#nullable enable
using Robust.Shared.Players;
namespace Content.Shared.Movement.Components
{
public interface IRelayMoveInput
{
void MoveInputPressed(ICommonSession session);
}
}

View File

@@ -0,0 +1,54 @@
#nullable enable
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Map;
using Robust.Shared.Physics;
namespace Content.Shared.Movement.Components
{
[RegisterComponent]
public sealed class MovementIgnoreGravityComponent : Component
{
public override string Name => "MovementIgnoreGravity";
}
public static class GravityExtensions
{
public static bool IsWeightless(this IEntity entity, PhysicsComponent? body = null, EntityCoordinates? coords = null, IMapManager? mapManager = null)
{
if (body == null)
entity.TryGetComponent(out body);
if (entity.HasComponent<MovementIgnoreGravityComponent>() ||
(body?.BodyType & (BodyType.Static | BodyType.Kinematic)) != 0) return false;
var transform = entity.Transform;
var gridId = transform.GridID;
if (!gridId.IsValid())
{
// Not on a grid = no gravity for now.
// In the future, may want to allow maps to override to always have gravity instead.
return true;
}
mapManager ??= IoCManager.Resolve<IMapManager>();
var grid = mapManager.GetGrid(gridId);
if (!grid.HasGravity)
{
return true;
}
coords ??= transform.Coordinates;
if (!coords.Value.IsValid(entity.EntityManager))
{
return true;
}
var tile = grid.GetTileRef(coords.Value).Tile;
return tile.IsEmpty;
}
}
}

View File

@@ -0,0 +1,99 @@
#nullable enable
using Robust.Shared.Containers;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables;
namespace Content.Shared.Movement.Components
{
[RegisterComponent]
public class MovementSpeedModifierComponent : Component
{
public const float DefaultBaseWalkSpeed = 4.0f;
public const float DefaultBaseSprintSpeed = 7.0f;
public override string Name => "MovementSpeedModifier";
private float _cachedWalkSpeedModifier = 1.0f;
[ViewVariables]
public float WalkSpeedModifier
{
get
{
RecalculateMovementSpeedModifiers();
return _cachedWalkSpeedModifier;
}
}
private float _cachedSprintSpeedModifier;
[ViewVariables]
public float SprintSpeedModifier
{
get
{
RecalculateMovementSpeedModifiers();
return _cachedSprintSpeedModifier;
}
}
[ViewVariables(VVAccess.ReadWrite)]
[DataField("baseWalkSpeed")]
public float BaseWalkSpeed { get; set; } = 4;
[ViewVariables(VVAccess.ReadWrite)]
[DataField("baseSprintSpeed")]
public float BaseSprintSpeed { get; set; } = 7;
[ViewVariables]
public float CurrentWalkSpeed => WalkSpeedModifier * BaseWalkSpeed;
[ViewVariables]
public float CurrentSprintSpeed => SprintSpeedModifier * BaseSprintSpeed;
/// <summary>
/// set to warn us that a component's movespeed modifier has changed
/// </summary>
private bool _movespeedModifiersNeedRefresh = true;
public void RefreshMovementSpeedModifiers()
{
_movespeedModifiersNeedRefresh = true;
}
public static void RefreshItemModifiers(IEntity item)
{
if (item.TryGetContainer(out var container) &&
container.Owner.TryGetComponent(out MovementSpeedModifierComponent? mod))
{
mod.RefreshMovementSpeedModifiers();
}
}
/// <summary>
/// Recalculate movement speed with current modifiers, or return early if no change
/// </summary>
private void RecalculateMovementSpeedModifiers()
{
{
if (!_movespeedModifiersNeedRefresh)
return;
var movespeedModifiers = Owner.GetAllComponents<IMoveSpeedModifier>();
float walkSpeedModifier = 1.0f;
float sprintSpeedModifier = 1.0f;
foreach (var component in movespeedModifiers)
{
walkSpeedModifier *= component.WalkSpeedModifier;
sprintSpeedModifier *= component.SprintSpeedModifier;
}
_cachedWalkSpeedModifier = walkSpeedModifier;
_cachedSprintSpeedModifier = sprintSpeedModifier;
}
_movespeedModifiersNeedRefresh = false;
}
}
public interface IMoveSpeedModifier
{
float WalkSpeedModifier { get; }
float SprintSpeedModifier { get; }
}
}

View File

@@ -0,0 +1,27 @@
#nullable enable
using Robust.Shared.GameObjects;
using Robust.Shared.Maths;
namespace Content.Shared.Movement.Components
{
[RegisterComponent]
[ComponentReference(typeof(IMoverComponent))]
public class SharedDummyInputMoverComponent : Component, IMoverComponent
{
public override string Name => "DummyInputMover";
public bool IgnorePaused => false;
public float CurrentWalkSpeed => 0f;
public float CurrentSprintSpeed => 0f;
public bool Sprinting => false;
public (Vector2 walking, Vector2 sprinting) VelocityDir => (Vector2.Zero, Vector2.Zero);
public void SetVelocityDirection(Direction direction, ushort subTick, bool enabled)
{
}
public void SetSprinting(ushort subTick, bool walking)
{
}
}
}

View File

@@ -0,0 +1,263 @@
#nullable enable
using System;
using Content.Shared.NetIDs;
using Robust.Shared.Configuration;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Maths;
using Robust.Shared.Players;
using Robust.Shared.Serialization;
using Robust.Shared.Timing;
using Robust.Shared.ViewVariables;
namespace Content.Shared.Movement.Components
{
[RegisterComponent]
[ComponentReference(typeof(IMoverComponent))]
public class SharedPlayerInputMoverComponent : Component, IMoverComponent
{
// This class has to be able to handle server TPS being lower than client FPS.
// While still having perfectly responsive movement client side.
// We do this by keeping track of the exact sub-tick values that inputs are pressed on the client,
// and then building a total movement vector based on those sub-tick steps.
//
// We keep track of the last sub-tick a movement input came in,
// Then when a new input comes in, we calculate the fraction of the tick the LAST input was active for
// (new sub-tick - last sub-tick)
// and then add to the total-this-tick movement vector
// by multiplying that fraction by the movement direction for the last input.
// This allows us to incrementally build the movement vector for the current tick,
// without having to keep track of some kind of list of inputs and calculating it later.
//
// We have to keep track of a separate movement vector for walking and sprinting,
// since we don't actually know our current movement speed while processing inputs.
// We change which vector we write into based on whether we were sprinting after the previous input.
// (well maybe we do but the code is designed such that MoverSystem applies movement speed)
// (and I'm not changing that)
[Dependency] private readonly IConfigurationManager _configurationManager = default!;
[Dependency] private readonly IGameTiming _gameTiming = default!;
[ComponentDependency] private readonly MovementSpeedModifierComponent? _movementSpeed = default!;
public override string Name => "PlayerInputMover";
public override uint? NetID => ContentNetIDs.PLAYER_INPUT_MOVER;
private GameTick _lastInputTick;
private ushort _lastInputSubTick;
private Vector2 _curTickWalkMovement;
private Vector2 _curTickSprintMovement;
private MoveButtons _heldMoveButtons = MoveButtons.None;
public float CurrentWalkSpeed => _movementSpeed?.CurrentWalkSpeed ?? MovementSpeedModifierComponent.DefaultBaseWalkSpeed;
public float CurrentSprintSpeed => _movementSpeed?.CurrentSprintSpeed ?? MovementSpeedModifierComponent.DefaultBaseSprintSpeed;
public bool Sprinting => !HasFlag(_heldMoveButtons, MoveButtons.Walk);
/// <summary>
/// Calculated linear velocity direction of the entity.
/// </summary>
[ViewVariables]
public (Vector2 walking, Vector2 sprinting) VelocityDir
{
get
{
if (!_gameTiming.InSimulation)
{
// Outside of simulation we'll be running client predicted movement per-frame.
// So return a full-length vector as if it's a full tick.
// Physics system will have the correct time step anyways.
var immediateDir = DirVecForButtons(_heldMoveButtons);
return Sprinting ? (Vector2.Zero, immediateDir) : (immediateDir, Vector2.Zero);
}
Vector2 walk;
Vector2 sprint;
float remainingFraction;
if (_gameTiming.CurTick > _lastInputTick)
{
walk = Vector2.Zero;
sprint = Vector2.Zero;
remainingFraction = 1;
}
else
{
walk = _curTickWalkMovement;
sprint = _curTickSprintMovement;
remainingFraction = (ushort.MaxValue - _lastInputSubTick) / (float) ushort.MaxValue;
}
var curDir = DirVecForButtons(_heldMoveButtons) * remainingFraction;
if (Sprinting)
{
sprint += curDir;
}
else
{
walk += curDir;
}
// Logger.Info($"{curDir}{walk}{sprint}");
return (walk, sprint);
}
}
/// <summary>
/// Whether or not the player can move diagonally.
/// </summary>
[ViewVariables]
public bool DiagonalMovementEnabled => _configurationManager.GetCVar<bool>(CCVars.GameDiagonalMovement);
/// <inheritdoc />
public override void Initialize()
{
base.Initialize();
Owner.EnsureComponentWarn<PhysicsComponent>();
}
/// <summary>
/// Toggles one of the four cardinal directions. Each of the four directions are
/// composed into a single direction vector, <see cref="VelocityDir"/>. Enabling
/// opposite directions will cancel each other out, resulting in no direction.
/// </summary>
/// <param name="direction">Direction to toggle.</param>
/// <param name="subTick"></param>
/// <param name="enabled">If the direction is active.</param>
public void SetVelocityDirection(Direction direction, ushort subTick, bool enabled)
{
// Logger.Info($"[{_gameTiming.CurTick}/{subTick}] {direction}: {enabled}");
var bit = direction switch
{
Direction.East => MoveButtons.Right,
Direction.North => MoveButtons.Up,
Direction.West => MoveButtons.Left,
Direction.South => MoveButtons.Down,
_ => throw new ArgumentException(nameof(direction))
};
SetMoveInput(subTick, enabled, bit);
}
private void SetMoveInput(ushort subTick, bool enabled, MoveButtons bit)
{
// Modifies held state of a movement button at a certain sub tick and updates current tick movement vectors.
if (_gameTiming.CurTick > _lastInputTick)
{
_curTickWalkMovement = Vector2.Zero;
_curTickSprintMovement = Vector2.Zero;
_lastInputTick = _gameTiming.CurTick;
_lastInputSubTick = 0;
}
if (subTick >= _lastInputSubTick)
{
var fraction = (subTick - _lastInputSubTick) / (float) ushort.MaxValue;
ref var lastMoveAmount = ref Sprinting ? ref _curTickSprintMovement : ref _curTickWalkMovement;
lastMoveAmount += DirVecForButtons(_heldMoveButtons) * fraction;
_lastInputSubTick = subTick;
}
if (enabled)
{
_heldMoveButtons |= bit;
}
else
{
_heldMoveButtons &= ~bit;
}
Dirty();
}
public void SetSprinting(ushort subTick, bool walking)
{
// Logger.Info($"[{_gameTiming.CurTick}/{subTick}] Sprint: {enabled}");
SetMoveInput(subTick, walking, MoveButtons.Walk);
}
public override void HandleComponentState(ComponentState? curState, ComponentState? nextState)
{
if (curState is MoverComponentState state)
{
_heldMoveButtons = state.Buttons;
_lastInputTick = GameTick.Zero;
_lastInputSubTick = 0;
}
}
public override ComponentState GetComponentState(ICommonSession player)
{
return new MoverComponentState(_heldMoveButtons);
}
/// <summary>
/// Retrieves the normalized direction vector for a specified combination of movement keys.
/// </summary>
private Vector2 DirVecForButtons(MoveButtons buttons)
{
// key directions are in screen coordinates
// _moveDir is in world coordinates
// if the camera is moved, this needs to be changed
var x = 0;
x -= HasFlag(buttons, MoveButtons.Left) ? 1 : 0;
x += HasFlag(buttons, MoveButtons.Right) ? 1 : 0;
var y = 0;
if (DiagonalMovementEnabled || x == 0)
{
y -= HasFlag(buttons, MoveButtons.Down) ? 1 : 0;
y += HasFlag(buttons, MoveButtons.Up) ? 1 : 0;
}
var vec = new Vector2(x, y);
// can't normalize zero length vector
if (vec.LengthSquared > 1.0e-6)
{
// Normalize so that diagonals aren't faster or something.
vec = vec.Normalized;
}
return vec;
}
[Serializable, NetSerializable]
private sealed class MoverComponentState : ComponentState
{
public MoveButtons Buttons { get; }
public MoverComponentState(MoveButtons buttons) : base(ContentNetIDs
.PLAYER_INPUT_MOVER)
{
Buttons = buttons;
}
}
[Flags]
private enum MoveButtons : byte
{
None = 0,
Up = 1,
Down = 2,
Left = 4,
Right = 8,
Walk = 16,
}
private static bool HasFlag(MoveButtons buttons, MoveButtons flag)
{
return (buttons & flag) == flag;
}
}
}

View File

@@ -0,0 +1,123 @@
#nullable enable
using System;
using Content.Shared.NetIDs;
using Robust.Shared.GameObjects;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Players;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables;
namespace Content.Shared.Movement.Components
{
/// <summary>
/// The basic player mover with footsteps and grabbing
/// </summary>
[RegisterComponent]
[ComponentReference(typeof(IMobMoverComponent))]
public class SharedPlayerMobMoverComponent : Component, IMobMoverComponent
{
public override string Name => "PlayerMobMover";
public override uint? NetID => ContentNetIDs.PLAYER_MOB_MOVER;
private float _stepSoundDistance;
[DataField("grabRange")]
private float _grabRange = IMobMoverComponent.GrabRangeDefault;
[DataField("pushStrength")]
private float _pushStrength = IMobMoverComponent.PushStrengthDefault;
[DataField("weightlessStrength")]
private float _weightlessStrength = IMobMoverComponent.WeightlessStrengthDefault;
[ViewVariables(VVAccess.ReadWrite)]
public EntityCoordinates LastPosition { get; set; }
/// <summary>
/// Used to keep track of how far we have moved before playing a step sound
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
public float StepSoundDistance
{
get => _stepSoundDistance;
set
{
if (MathHelper.CloseTo(_stepSoundDistance, value)) return;
_stepSoundDistance = value;
}
}
[ViewVariables(VVAccess.ReadWrite)]
public float GrabRange
{
get => _grabRange;
set
{
if (MathHelper.CloseTo(_grabRange, value)) return;
_grabRange = value;
Dirty();
}
}
[ViewVariables(VVAccess.ReadWrite)]
public float PushStrength
{
get => _pushStrength;
set
{
if (MathHelper.CloseTo(_pushStrength, value)) return;
_pushStrength = value;
Dirty();
}
}
[ViewVariables(VVAccess.ReadWrite)]
public float WeightlessStrength
{
get => _weightlessStrength;
set
{
if (MathHelper.CloseTo(_weightlessStrength, value)) return;
_weightlessStrength = value;
Dirty();
}
}
public override void Initialize()
{
base.Initialize();
if (!Owner.HasComponent<IMoverComponent>())
{
Owner.EnsureComponentWarn<SharedPlayerInputMoverComponent>();
}
}
public override ComponentState GetComponentState(ICommonSession session)
{
return new PlayerMobMoverComponentState(_grabRange, _pushStrength, _weightlessStrength);
}
public override void HandleComponentState(ComponentState? curState, ComponentState? nextState)
{
base.HandleComponentState(curState, nextState);
if (curState is not PlayerMobMoverComponentState playerMoverState) return;
GrabRange = playerMoverState.GrabRange;
PushStrength = playerMoverState.PushStrength;
}
[Serializable, NetSerializable]
private sealed class PlayerMobMoverComponentState : ComponentState
{
public float GrabRange;
public float PushStrength;
public float WeightlessStrength;
public PlayerMobMoverComponentState(float grabRange, float pushStrength, float weightlessStrength) : base(ContentNetIDs.PLAYER_MOB_MOVER)
{
GrabRange = grabRange;
PushStrength = pushStrength;
WeightlessStrength = weightlessStrength;
}
}
}
}

View File

@@ -0,0 +1,59 @@
#nullable enable
using System;
using Content.Shared.NetIDs;
using Robust.Shared.GameObjects;
using Robust.Shared.Maths;
using Robust.Shared.Players;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables;
namespace Content.Shared.Movement.Components
{
[RegisterComponent]
public class SharedTileFrictionModifier : Component
{
public override string Name => "TileFrictionModifier";
/// <summary>
/// Multiply the tilefriction cvar by this to get the body's actual tilefriction.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
public float Modifier
{
get => _modifier;
set
{
if (MathHelper.CloseTo(_modifier, value)) return;
_modifier = value;
}
}
[DataField("modifier")]
private float _modifier = 1.0f;
public override ComponentState GetComponentState(ICommonSession session)
{
return new TileFrictionComponentState(_modifier);
}
public override void HandleComponentState(ComponentState? curState, ComponentState? nextState)
{
base.HandleComponentState(curState, nextState);
if (curState is not TileFrictionComponentState tileState) return;
_modifier = tileState.Modifier;
}
[NetSerializable, Serializable]
protected class TileFrictionComponentState : ComponentState
{
public float Modifier;
public TileFrictionComponentState(float modifier) : base(ContentNetIDs.TILE_FRICTION)
{
Modifier = modifier;
}
}
}
}