2021-02-12 01:31:19 -08:00
#nullable enable
2021-03-08 04:09:59 +11:00
using System.Collections.Generic ;
2021-04-21 20:14:40 +10:00
using Content.Server.Actions ;
2021-06-09 22:19:39 +02:00
using Content.Server.Inventory.Components ;
using Content.Server.Items ;
using Content.Server.Movement.Components ;
using Content.Server.Shuttle ;
2019-04-05 02:04:34 +02:00
using Content.Shared.Audio ;
2021-06-09 22:19:39 +02:00
using Content.Shared.Inventory ;
2019-04-05 02:04:34 +02:00
using Content.Shared.Maps ;
2021-06-09 22:19:39 +02:00
using Content.Shared.Movement.Components ;
2021-03-08 04:09:59 +11:00
using Content.Shared.Physics.Controllers ;
2021-06-09 22:19:39 +02:00
using Content.Shared.Tag ;
2019-04-15 21:11:38 -06:00
using Robust.Server.GameObjects ;
2021-02-12 01:31:19 -08:00
using Robust.Shared.Audio ;
2021-02-11 01:13:03 -08:00
using Robust.Shared.GameObjects ;
2019-04-15 21:11:38 -06:00
using Robust.Shared.IoC ;
2019-11-13 17:37:46 -05:00
using Robust.Shared.Log ;
2019-04-15 21:11:38 -06:00
using Robust.Shared.Map ;
2021-03-08 04:09:59 +11:00
using Robust.Shared.Maths ;
2021-03-30 21:43:03 +11:00
using Robust.Shared.Physics.Collision.Shapes ;
2021-03-08 04:09:59 +11:00
using Robust.Shared.Physics.Dynamics ;
2021-03-21 09:12:03 -07:00
using Robust.Shared.Player ;
2019-04-15 21:11:38 -06:00
using Robust.Shared.Prototypes ;
2019-08-17 21:09:09 +02:00
using Robust.Shared.Random ;
2021-04-21 20:14:40 +10:00
using Robust.Shared.Utility ;
2019-04-04 16:18:43 +02:00
2021-03-08 04:09:59 +11:00
namespace Content.Server.Physics.Controllers
2019-04-04 16:18:43 +02:00
{
2021-03-08 04:09:59 +11:00
public class MoverController : SharedMoverController
2019-04-04 16:18:43 +02:00
{
2020-06-24 02:21:20 +02:00
[Dependency] private readonly IPrototypeManager _prototypeManager = default ! ;
[Dependency] private readonly ITileDefinitionManager _tileDefinitionManager = default ! ;
[Dependency] private readonly IMapManager _mapManager = default ! ;
[Dependency] private readonly IRobustRandom _robustRandom = default ! ;
2019-04-04 16:18:43 +02:00
2020-06-24 02:21:20 +02:00
private AudioSystem _audioSystem = default ! ;
2019-04-05 02:04:34 +02:00
private const float StepSoundMoveDistanceRunning = 2 ;
private const float StepSoundMoveDistanceWalking = 1.5f ;
2021-03-08 04:09:59 +11:00
private HashSet < EntityUid > _excludedMobs = new ( ) ;
2019-04-04 16:18:43 +02:00
public override void Initialize ( )
{
2020-06-24 02:21:20 +02:00
base . Initialize ( ) ;
2021-03-08 04:09:59 +11:00
_audioSystem = EntitySystem . Get < AudioSystem > ( ) ;
2021-02-28 18:49:48 +01:00
}
2021-03-01 03:11:29 +11:00
2021-03-08 04:09:59 +11:00
public override void UpdateBeforeSolve ( bool prediction , float frameTime )
2021-02-28 18:49:48 +01:00
{
2021-03-08 04:09:59 +11:00
base . UpdateBeforeSolve ( prediction , frameTime ) ;
_excludedMobs . Clear ( ) ;
foreach ( var ( mobMover , mover , physics ) in ComponentManager . EntityQuery < IMobMoverComponent , IMoverComponent , PhysicsComponent > ( ) )
2021-03-01 03:11:29 +11:00
{
2021-03-08 04:09:59 +11:00
_excludedMobs . Add ( mover . Owner . Uid ) ;
HandleMobMovement ( mover , physics , mobMover ) ;
}
foreach ( var mover in ComponentManager . EntityQuery < ShuttleControllerComponent > ( ) )
{
_excludedMobs . Add ( mover . Owner . Uid ) ;
HandleShuttleMovement ( mover ) ;
}
foreach ( var ( mover , physics ) in ComponentManager . EntityQuery < IMoverComponent , PhysicsComponent > ( true ) )
{
if ( _excludedMobs . Contains ( mover . Owner . Uid ) ) continue ;
HandleKinematicMovement ( mover , physics ) ;
2019-04-04 16:18:43 +02:00
}
}
2021-03-08 04:09:59 +11:00
/ *
* Some thoughts :
* Unreal actually doesn ' t predict vehicle movement at all , it ' s purely server - side which I thought was interesting
* The reason for this is that vehicles change direction very slowly compared to players so you don ' t really have the requirement for quick movement anyway
* As such could probably just look at applying a force / impulse to the shuttle server - side only so it controls like the titanic .
* /
private void HandleShuttleMovement ( ShuttleControllerComponent mover )
2020-06-24 02:21:20 +02:00
{
2021-03-08 04:09:59 +11:00
var gridId = mover . Owner . Transform . GridID ;
if ( ! _mapManager . TryGetGrid ( gridId , out var grid ) | | ! EntityManager . TryGetEntity ( grid . GridEntityId , out var gridEntity ) ) return ;
//TODO: Switch to shuttle component
if ( ! gridEntity . TryGetComponent ( out PhysicsComponent ? physics ) )
2020-07-03 23:32:41 +02:00
{
2021-03-08 04:09:59 +11:00
physics = gridEntity . AddComponent < PhysicsComponent > ( ) ;
physics . BodyStatus = BodyStatus . InAir ;
physics . CanCollide = true ;
physics . AddFixture ( new Fixture ( physics , new PhysShapeGrid ( grid ) ) ) ;
2020-07-03 23:32:41 +02:00
}
2021-03-08 04:09:59 +11:00
// TODO: Uhh this probably doesn't work but I still need to rip out the entity tree and make RenderingTreeSystem use grids so I'm not overly concerned about breaking shuttles.
physics . ApplyForce ( mover . VelocityDir . walking + mover . VelocityDir . sprinting ) ;
mover . VelocityDir = ( Vector2 . Zero , Vector2 . Zero ) ;
2020-06-24 02:21:20 +02:00
}
2020-05-23 01:23:36 +02:00
2021-03-08 04:09:59 +11:00
protected override void HandleFootsteps ( IMoverComponent mover , IMobMoverComponent mobMover )
2020-06-24 02:21:20 +02:00
{
2021-04-21 20:14:40 +10:00
if ( ! mover . Owner . HasTag ( "FootstepSound" ) ) return ;
2020-06-24 02:21:20 +02:00
var transform = mover . Owner . Transform ;
2021-04-21 20:14:40 +10:00
var coordinates = transform . Coordinates ;
var gridId = coordinates . GetGridId ( EntityManager ) ;
var distanceNeeded = mover . Sprinting ? StepSoundMoveDistanceRunning : StepSoundMoveDistanceWalking ;
2020-06-24 02:21:20 +02:00
// Handle footsteps.
2021-04-21 20:14:40 +10:00
if ( _mapManager . GridExists ( gridId ) )
2020-06-24 02:21:20 +02:00
{
// Can happen when teleporting between grids.
2021-04-21 20:14:40 +10:00
if ( ! coordinates . TryDistance ( EntityManager , mobMover . LastPosition , out var distance ) | |
distance > distanceNeeded )
2020-09-06 16:11:53 +02:00
{
2021-04-21 20:14:40 +10:00
mobMover . StepSoundDistance = distanceNeeded ;
}
else
{
mobMover . StepSoundDistance + = distance ;
2020-09-06 16:11:53 +02:00
}
2019-04-04 16:18:43 +02:00
}
else
{
2021-04-21 20:14:40 +10:00
// In space no one can hear you squeak
return ;
2019-04-04 16:18:43 +02:00
}
2021-04-21 20:14:40 +10:00
DebugTools . Assert ( gridId ! = GridId . Invalid ) ;
mobMover . LastPosition = coordinates ;
2020-05-23 17:18:32 +02:00
2021-04-21 20:14:40 +10:00
if ( mobMover . StepSoundDistance < distanceNeeded ) return ;
2020-05-23 17:18:32 +02:00
2021-04-21 20:14:40 +10:00
mobMover . StepSoundDistance - = distanceNeeded ;
if ( mover . Owner . TryGetComponent < InventoryComponent > ( out var inventory )
& & inventory . TryGetSlotItem < ItemComponent > ( EquipmentSlotDefines . Slots . SHOES , out var item )
& & item . Owner . TryGetComponent < FootstepModifierComponent > ( out var modifier ) )
{
modifier . PlayFootstep ( ) ;
}
else
{
PlayFootstepSound ( mover . Owner , gridId , coordinates , mover . Sprinting ) ;
2020-04-18 12:10:50 +02:00
}
2019-04-04 16:18:43 +02:00
}
2019-04-05 02:04:34 +02:00
2021-04-21 20:14:40 +10:00
private void PlayFootstepSound ( IEntity mover , GridId gridId , EntityCoordinates coordinates , bool sprinting )
2019-04-05 02:04:34 +02:00
{
2021-04-21 20:14:40 +10:00
var grid = _mapManager . GetGrid ( gridId ) ;
2019-04-28 22:08:27 -07:00
var tile = grid . GetTileRef ( coordinates ) ;
2019-04-05 02:04:34 +02:00
2021-04-21 20:14:40 +10:00
if ( tile . IsSpace ( _tileDefinitionManager ) ) return ;
2020-11-22 15:02:39 +01:00
// If the coordinates have a FootstepModifier component
// i.e. component that emit sound on footsteps emit that sound
string? soundCollectionName = null ;
2021-04-28 10:49:37 -07:00
foreach ( var maybeFootstep in grid . GetAnchoredEntities ( tile . GridIndices ) )
2019-04-05 02:04:34 +02:00
{
2021-04-28 10:49:37 -07:00
if ( EntityManager . ComponentManager . TryGetComponent ( maybeFootstep , out FootstepModifierComponent ? footstep ) )
2019-04-05 02:04:34 +02:00
{
2020-11-22 15:02:39 +01:00
soundCollectionName = footstep . _soundCollectionName ;
2019-04-05 02:04:34 +02:00
break ;
}
}
2020-11-22 15:02:39 +01:00
// if there is no FootstepModifierComponent, determine sound based on tiles
if ( soundCollectionName = = null )
2019-04-05 02:04:34 +02:00
{
// Walking on a tile.
2020-06-24 02:21:20 +02:00
var def = ( ContentTileDefinition ) _tileDefinitionManager [ tile . Tile . TypeId ] ;
2021-04-01 18:22:26 -07:00
if ( string . IsNullOrEmpty ( def . FootstepSounds ) )
2019-04-05 02:04:34 +02:00
{
// Nothing to play, oh well.
return ;
}
2020-06-24 02:21:20 +02:00
2019-04-05 02:04:34 +02:00
soundCollectionName = def . FootstepSounds ;
}
2021-04-21 20:14:40 +10:00
if ( ! _prototypeManager . TryIndex ( soundCollectionName , out SoundCollectionPrototype ? soundCollection ) )
2019-08-10 22:17:49 +10:00
{
Logger . ErrorS ( "sound" , $"Unable to find sound collection for {soundCollectionName}" ) ;
2021-04-21 20:14:40 +10:00
return ;
2019-08-10 22:17:49 +10:00
}
2021-03-08 04:09:59 +11:00
2021-04-21 20:14:40 +10:00
SoundSystem . Play (
Filter . Pvs ( coordinates ) ,
_robustRandom . Pick ( soundCollection . PickFiles ) ,
2021-05-12 14:50:02 +02:00
mover . Transform . Coordinates ,
2021-04-21 20:14:40 +10:00
sprinting ? AudioParams . Default . WithVolume ( 0.75f ) : null ) ;
}
2019-04-04 16:18:43 +02:00
}
}