using JetBrains.Annotations;
using Robust.Shared.Map;
using Robust.Shared.Network;
+using Robust.Shared.Physics.Components;
+using Robust.Shared.Physics.Events;
using Robust.Shared.Random;
+using Robust.Shared.Timing;
-namespace Content.Shared.Sound
+namespace Content.Shared.Sound;
+
+/// <summary>
+/// Will play a sound on various events if the affected entity has a component derived from BaseEmitSoundComponent
+/// </summary>
+[UsedImplicitly]
+public abstract class SharedEmitSoundSystem : EntitySystem
{
- /// <summary>
- /// Will play a sound on various events if the affected entity has a component derived from BaseEmitSoundComponent
- /// </summary>
- [UsedImplicitly]
- public abstract class SharedEmitSoundSystem : EntitySystem
+ [Dependency] private readonly IGameTiming _timing = default!;
+ [Dependency] private readonly INetManager _netMan = default!;
+ [Dependency] private readonly IMapManager _mapManager = default!;
+ [Dependency] private readonly ITileDefinitionManager _tileDefMan = default!;
+ [Dependency] protected readonly IRobustRandom Random = default!;
+ [Dependency] private readonly SharedAudioSystem _audioSystem = default!;
+ [Dependency] protected readonly SharedPopupSystem Popup = default!;
+
+ public override void Initialize()
{
- [Dependency] private readonly INetManager _netMan = default!;
- [Dependency] private readonly IMapManager _mapManager = default!;
- [Dependency] private readonly ITileDefinitionManager _tileDefMan = default!;
- [Dependency] protected readonly IRobustRandom Random = default!;
- [Dependency] private readonly SharedAudioSystem _audioSystem = default!;
- [Dependency] protected readonly SharedPopupSystem Popup = default!;
-
- public override void Initialize()
- {
- base.Initialize();
- SubscribeLocalEvent<EmitSoundOnSpawnComponent, ComponentInit>(HandleEmitSpawnOnInit);
- SubscribeLocalEvent<EmitSoundOnLandComponent, LandEvent>(OnEmitSoundOnLand);
- SubscribeLocalEvent<EmitSoundOnUseComponent, UseInHandEvent>(HandleEmitSoundOnUseInHand);
- SubscribeLocalEvent<EmitSoundOnThrowComponent, ThrownEvent>(HandleEmitSoundOnThrown);
- SubscribeLocalEvent<EmitSoundOnActivateComponent, ActivateInWorldEvent>(HandleEmitSoundOnActivateInWorld);
- SubscribeLocalEvent<EmitSoundOnPickupComponent, GotEquippedHandEvent>(HandleEmitSoundOnPickup);
- SubscribeLocalEvent<EmitSoundOnDropComponent, DroppedEvent>(HandleEmitSoundOnDrop);
- }
+ base.Initialize();
+ SubscribeLocalEvent<EmitSoundOnSpawnComponent, ComponentInit>(OnEmitSpawnOnInit);
+ SubscribeLocalEvent<EmitSoundOnLandComponent, LandEvent>(OnEmitSoundOnLand);
+ SubscribeLocalEvent<EmitSoundOnUseComponent, UseInHandEvent>(OnEmitSoundOnUseInHand);
+ SubscribeLocalEvent<EmitSoundOnThrowComponent, ThrownEvent>(OnEmitSoundOnThrown);
+ SubscribeLocalEvent<EmitSoundOnActivateComponent, ActivateInWorldEvent>(OnEmitSoundOnActivateInWorld);
+ SubscribeLocalEvent<EmitSoundOnPickupComponent, GotEquippedHandEvent>(OnEmitSoundOnPickup);
+ SubscribeLocalEvent<EmitSoundOnDropComponent, DroppedEvent>(OnEmitSoundOnDrop);
+ SubscribeLocalEvent<EmitSoundOnCollideComponent, StartCollideEvent>(OnEmitSoundOnCollide);
+ }
- private void HandleEmitSpawnOnInit(EntityUid uid, EmitSoundOnSpawnComponent component, ComponentInit args)
- {
- TryEmitSound(component, predict: false);
- }
+ private void OnEmitSpawnOnInit(EntityUid uid, EmitSoundOnSpawnComponent component, ComponentInit args)
+ {
+ TryEmitSound(uid, component, predict: false);
+ }
- private void OnEmitSoundOnLand(EntityUid uid, BaseEmitSoundComponent component, ref LandEvent args)
- {
- if (!TryComp<TransformComponent>(uid, out var xform) ||
- !_mapManager.TryGetGrid(xform.GridUid, out var grid))
- return;
+ private void OnEmitSoundOnLand(EntityUid uid, BaseEmitSoundComponent component, ref LandEvent args)
+ {
+ if (!TryComp<TransformComponent>(uid, out var xform) ||
+ !_mapManager.TryGetGrid(xform.GridUid, out var grid))
+ return;
- var tile = grid.GetTileRef(xform.Coordinates);
+ var tile = grid.GetTileRef(xform.Coordinates);
- // Handle maps being grids (we'll still emit the sound).
- if (xform.GridUid != xform.MapUid && tile.IsSpace(_tileDefMan))
- return;
+ // Handle maps being grids (we'll still emit the sound).
+ if (xform.GridUid != xform.MapUid && tile.IsSpace(_tileDefMan))
+ return;
- // hand throwing not predicted sadly
- TryEmitSound(component, args.User, false);
- }
+ // hand throwing not predicted sadly
+ TryEmitSound(uid, component, args.User, false);
+ }
- private void HandleEmitSoundOnUseInHand(EntityUid eUI, EmitSoundOnUseComponent component, UseInHandEvent args)
- {
- // Intentionally not checking whether the interaction has already been handled.
- TryEmitSound(component, args.User);
+ private void OnEmitSoundOnUseInHand(EntityUid uid, EmitSoundOnUseComponent component, UseInHandEvent args)
+ {
+ // Intentionally not checking whether the interaction has already been handled.
+ TryEmitSound(uid, component, args.User);
- if (component.Handle)
- args.Handled = true;
- }
+ if (component.Handle)
+ args.Handled = true;
+ }
- private void HandleEmitSoundOnThrown(EntityUid eUI, BaseEmitSoundComponent component, ThrownEvent args)
- {
- TryEmitSound(component, args.User, false);
- }
+ private void OnEmitSoundOnThrown(EntityUid uid, BaseEmitSoundComponent component, ThrownEvent args)
+ {
+ TryEmitSound(uid, component, args.User, false);
+ }
- private void HandleEmitSoundOnActivateInWorld(EntityUid eUI, EmitSoundOnActivateComponent component, ActivateInWorldEvent args)
- {
- // Intentionally not checking whether the interaction has already been handled.
- TryEmitSound(component, args.User);
+ private void OnEmitSoundOnActivateInWorld(EntityUid uid, EmitSoundOnActivateComponent component, ActivateInWorldEvent args)
+ {
+ // Intentionally not checking whether the interaction has already been handled.
+ TryEmitSound(uid, component, args.User);
- if (component.Handle)
- args.Handled = true;
- }
+ if (component.Handle)
+ args.Handled = true;
+ }
+
+ private void OnEmitSoundOnPickup(EntityUid uid, EmitSoundOnPickupComponent component, GotEquippedHandEvent args)
+ {
+ TryEmitSound(uid, component, args.User);
+ }
+
+ private void OnEmitSoundOnDrop(EntityUid uid, EmitSoundOnDropComponent component, DroppedEvent args)
+ {
+ TryEmitSound(uid, component, args.User);
+ }
- private void HandleEmitSoundOnPickup(EntityUid uid, EmitSoundOnPickupComponent component, GotEquippedHandEvent args)
+ protected void TryEmitSound(EntityUid uid, BaseEmitSoundComponent component, EntityUid? user=null, bool predict=true)
+ {
+ if (component.Sound == null)
+ return;
+
+ if (predict)
{
- TryEmitSound(component, args.User);
+ _audioSystem.PlayPredicted(component.Sound, uid, user);
}
-
- private void HandleEmitSoundOnDrop(EntityUid uid, EmitSoundOnDropComponent component, DroppedEvent args)
+ else if (_netMan.IsServer)
{
- TryEmitSound(component, args.User);
+ // don't predict sounds that client couldn't have played already
+ _audioSystem.PlayPvs(component.Sound, uid);
}
+ }
- protected void TryEmitSound(BaseEmitSoundComponent component, EntityUid? user=null, bool predict=true)
+ private void OnEmitSoundOnCollide(EntityUid uid, EmitSoundOnCollideComponent component, ref StartCollideEvent args)
+ {
+ if (!args.OurFixture.Hard ||
+ !args.OtherFixture.Hard ||
+ !TryComp<PhysicsComponent>(uid, out var physics) ||
+ physics.LinearVelocity.Length < component.MinimumVelocity ||
+ _timing.CurTime < component.NextSound)
{
- if (component.Sound == null)
- return;
-
- if (predict)
- {
- _audioSystem.PlayPredicted(component.Sound, component.Owner, user);
- }
- else if (_netMan.IsServer)
- {
- // don't predict sounds that client couldn't have played already
- _audioSystem.PlayPvs(component.Sound, component.Owner);
- }
+ return;
}
+
+ component.NextSound = _timing.CurTime + EmitSoundOnCollideComponent.CollideCooldown;
+ TryEmitSound(uid, component, predict: false);
}
}
-