diff --git a/Content.Shared/Sound/Components/BaseEmitSoundComponent.cs b/Content.Shared/Sound/Components/BaseEmitSoundComponent.cs
index 870d20457e..7011f72ef0 100644
--- a/Content.Shared/Sound/Components/BaseEmitSoundComponent.cs
+++ b/Content.Shared/Sound/Components/BaseEmitSoundComponent.cs
@@ -1,4 +1,6 @@
using Robust.Shared.Audio;
+using Robust.Shared.GameStates;
+using Robust.Shared.Serialization;
namespace Content.Shared.Sound.Components;
@@ -8,10 +10,9 @@ namespace Content.Shared.Sound.Components;
///
public abstract partial class BaseEmitSoundComponent : Component
{
- public static readonly AudioParams DefaultParams = AudioParams.Default.WithVolume(-2f);
-
- [AutoNetworkedField]
- [ViewVariables(VVAccess.ReadWrite)]
+ ///
+ /// The to play.
+ ///
[DataField(required: true)]
public SoundSpecifier? Sound;
@@ -22,3 +23,15 @@ public abstract partial class BaseEmitSoundComponent : Component
[DataField]
public bool Positional;
}
+
+///
+/// Represents the state of .
+///
+/// This is obviously very cursed, but since the BaseEmitSoundComponent is abstract, we cannot network it.
+/// AutoGenerateComponentState attribute won't work here, and since everything revolves around inheritance for some fucking reason,
+/// there's no better way of doing this.
+[Serializable, NetSerializable]
+public struct EmitSoundComponentState(SoundSpecifier? sound) : IComponentState
+{
+ public SoundSpecifier? Sound { get; } = sound;
+}
diff --git a/Content.Shared/Sound/Components/EmitSoundOnActivateComponent.cs b/Content.Shared/Sound/Components/EmitSoundOnActivateComponent.cs
index 810f132d83..d6aa42177e 100644
--- a/Content.Shared/Sound/Components/EmitSoundOnActivateComponent.cs
+++ b/Content.Shared/Sound/Components/EmitSoundOnActivateComponent.cs
@@ -17,6 +17,6 @@ public sealed partial class EmitSoundOnActivateComponent : BaseEmitSoundComponen
/// otherwise this might enable sound spamming, as use-delays are only initiated if the interaction was
/// handled.
///
- [DataField("handle")]
+ [DataField]
public bool Handle = true;
}
diff --git a/Content.Shared/Sound/Components/EmitSoundOnCollideComponent.cs b/Content.Shared/Sound/Components/EmitSoundOnCollideComponent.cs
index a2cdd63ab7..4cdea05220 100644
--- a/Content.Shared/Sound/Components/EmitSoundOnCollideComponent.cs
+++ b/Content.Shared/Sound/Components/EmitSoundOnCollideComponent.cs
@@ -11,13 +11,12 @@ public sealed partial class EmitSoundOnCollideComponent : BaseEmitSoundComponent
///
/// Minimum velocity required for the sound to play.
///
- [ViewVariables(VVAccess.ReadWrite), DataField("minVelocity")]
+ [DataField("minVelocity")]
public float MinimumVelocity = 3f;
///
/// To avoid sound spam add a cooldown to it.
///
- [ViewVariables(VVAccess.ReadWrite), DataField("nextSound", customTypeSerializer: typeof(TimeOffsetSerializer))]
- [AutoPausedField]
+ [DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), AutoPausedField]
public TimeSpan NextSound;
}
diff --git a/Content.Shared/Sound/Components/EmitSoundOnDropComponent.cs b/Content.Shared/Sound/Components/EmitSoundOnDropComponent.cs
index 5e04295607..64ed5e60dc 100644
--- a/Content.Shared/Sound/Components/EmitSoundOnDropComponent.cs
+++ b/Content.Shared/Sound/Components/EmitSoundOnDropComponent.cs
@@ -6,6 +6,4 @@ namespace Content.Shared.Sound.Components;
/// Simple sound emitter that emits sound on entity drop
///
[RegisterComponent, NetworkedComponent]
-public sealed partial class EmitSoundOnDropComponent : BaseEmitSoundComponent
-{
-}
+public sealed partial class EmitSoundOnDropComponent : BaseEmitSoundComponent;
diff --git a/Content.Shared/Sound/Components/EmitSoundOnInteractUsingComponent.cs b/Content.Shared/Sound/Components/EmitSoundOnInteractUsingComponent.cs
index 49118d9799..d0b16fcec8 100644
--- a/Content.Shared/Sound/Components/EmitSoundOnInteractUsingComponent.cs
+++ b/Content.Shared/Sound/Components/EmitSoundOnInteractUsingComponent.cs
@@ -1,5 +1,4 @@
using Content.Shared.Whitelist;
-using Robust.Shared.Prototypes;
using Robust.Shared.GameStates;
namespace Content.Shared.Sound.Components;
@@ -10,6 +9,9 @@ namespace Content.Shared.Sound.Components;
[RegisterComponent, NetworkedComponent]
public sealed partial class EmitSoundOnInteractUsingComponent : BaseEmitSoundComponent
{
+ ///
+ /// The for the entities that can use this item.
+ ///
[DataField(required: true)]
public EntityWhitelist Whitelist = new();
}
diff --git a/Content.Shared/Sound/Components/EmitSoundOnLandComponent.cs b/Content.Shared/Sound/Components/EmitSoundOnLandComponent.cs
index 2d33a7f5f2..d3fceb85dd 100644
--- a/Content.Shared/Sound/Components/EmitSoundOnLandComponent.cs
+++ b/Content.Shared/Sound/Components/EmitSoundOnLandComponent.cs
@@ -6,6 +6,4 @@ namespace Content.Shared.Sound.Components;
/// Simple sound emitter that emits sound on LandEvent
///
[RegisterComponent, NetworkedComponent]
-public sealed partial class EmitSoundOnLandComponent : BaseEmitSoundComponent
-{
-}
+public sealed partial class EmitSoundOnLandComponent : BaseEmitSoundComponent;
diff --git a/Content.Shared/Sound/Components/EmitSoundOnPickupComponent.cs b/Content.Shared/Sound/Components/EmitSoundOnPickupComponent.cs
index ee4b4b1688..dcf73b7ac2 100644
--- a/Content.Shared/Sound/Components/EmitSoundOnPickupComponent.cs
+++ b/Content.Shared/Sound/Components/EmitSoundOnPickupComponent.cs
@@ -6,6 +6,4 @@ namespace Content.Shared.Sound.Components;
/// Simple sound emitter that emits sound on entity pickup
///
[RegisterComponent, NetworkedComponent]
-public sealed partial class EmitSoundOnPickupComponent : BaseEmitSoundComponent
-{
-}
+public sealed partial class EmitSoundOnPickupComponent : BaseEmitSoundComponent;
diff --git a/Content.Shared/Sound/Components/EmitSoundOnSpawnComponent.cs b/Content.Shared/Sound/Components/EmitSoundOnSpawnComponent.cs
index 49d40ce185..20d39b3460 100644
--- a/Content.Shared/Sound/Components/EmitSoundOnSpawnComponent.cs
+++ b/Content.Shared/Sound/Components/EmitSoundOnSpawnComponent.cs
@@ -6,6 +6,4 @@ namespace Content.Shared.Sound.Components;
/// Simple sound emitter that emits sound on entity spawn.
///
[RegisterComponent, NetworkedComponent]
-public sealed partial class EmitSoundOnSpawnComponent : BaseEmitSoundComponent
-{
-}
+public sealed partial class EmitSoundOnSpawnComponent : BaseEmitSoundComponent;
diff --git a/Content.Shared/Sound/Components/EmitSoundOnThrowComponent.cs b/Content.Shared/Sound/Components/EmitSoundOnThrowComponent.cs
index 5e3650a4a3..f8c0d1181b 100644
--- a/Content.Shared/Sound/Components/EmitSoundOnThrowComponent.cs
+++ b/Content.Shared/Sound/Components/EmitSoundOnThrowComponent.cs
@@ -6,6 +6,4 @@ namespace Content.Shared.Sound.Components;
/// Simple sound emitter that emits sound on ThrowEvent
///
[RegisterComponent, NetworkedComponent]
-public sealed partial class EmitSoundOnThrowComponent : BaseEmitSoundComponent
-{
-}
+public sealed partial class EmitSoundOnThrowComponent : BaseEmitSoundComponent;
diff --git a/Content.Shared/Sound/Components/EmitSoundOnUseComponent.cs b/Content.Shared/Sound/Components/EmitSoundOnUseComponent.cs
index a99a01cec4..ec7a277e92 100644
--- a/Content.Shared/Sound/Components/EmitSoundOnUseComponent.cs
+++ b/Content.Shared/Sound/Components/EmitSoundOnUseComponent.cs
@@ -5,7 +5,7 @@ namespace Content.Shared.Sound.Components;
///
/// Simple sound emitter that emits sound on UseInHand
///
-[RegisterComponent]
+[RegisterComponent, NetworkedComponent]
public sealed partial class EmitSoundOnUseComponent : BaseEmitSoundComponent
{
///
@@ -17,6 +17,6 @@ public sealed partial class EmitSoundOnUseComponent : BaseEmitSoundComponent
/// otherwise this might enable sound spamming, as use-delays are only initiated if the interaction was
/// handled.
///
- [DataField("handle")]
+ [DataField]
public bool Handle = true;
}
diff --git a/Content.Shared/Sound/Components/SpamEmitSoundComponent.cs b/Content.Shared/Sound/Components/SpamEmitSoundComponent.cs
index 149728a5ba..7c1428798c 100644
--- a/Content.Shared/Sound/Components/SpamEmitSoundComponent.cs
+++ b/Content.Shared/Sound/Components/SpamEmitSoundComponent.cs
@@ -1,4 +1,5 @@
using Robust.Shared.GameStates;
+using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
namespace Content.Shared.Sound.Components;
@@ -12,7 +13,7 @@ public sealed partial class SpamEmitSoundComponent : BaseEmitSoundComponent
///
/// The time at which the next sound will play.
///
- [DataField, AutoPausedField, AutoNetworkedField]
+ [DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), AutoPausedField, AutoNetworkedField]
public TimeSpan NextSound;
///
diff --git a/Content.Shared/Sound/Components/SpamEmitSoundRequirePowerComponent.cs b/Content.Shared/Sound/Components/SpamEmitSoundRequirePowerComponent.cs
index b0547ea398..bf5e925e0d 100644
--- a/Content.Shared/Sound/Components/SpamEmitSoundRequirePowerComponent.cs
+++ b/Content.Shared/Sound/Components/SpamEmitSoundRequirePowerComponent.cs
@@ -5,6 +5,4 @@ namespace Content.Shared.Sound.Components;
/// on the powered state of the entity.
///
[RegisterComponent]
-public sealed partial class SpamEmitSoundRequirePowerComponent : Component
-{
-}
+public sealed partial class SpamEmitSoundRequirePowerComponent : Component;
diff --git a/Content.Shared/Sound/SharedEmitSoundSystem.cs b/Content.Shared/Sound/SharedEmitSoundSystem.cs
index 67aabbb74d..58d541e363 100644
--- a/Content.Shared/Sound/SharedEmitSoundSystem.cs
+++ b/Content.Shared/Sound/SharedEmitSoundSystem.cs
@@ -12,6 +12,7 @@ using Content.Shared.Whitelist;
using JetBrains.Annotations;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
+using Robust.Shared.GameStates;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;
using Robust.Shared.Network;
@@ -54,6 +55,47 @@ public abstract class SharedEmitSoundSystem : EntitySystem
SubscribeLocalEvent(OnEmitSoundOnCollide);
SubscribeLocalEvent(OnMobState);
+
+ // We need to handle state manually here
+ // BaseEmitSoundComponent isn't registered so we have to subscribe to each one
+ // TODO: Make it use autonetworking instead of relying on inheritance
+ SubscribeEmitComponent();
+ SubscribeEmitComponent();
+ SubscribeEmitComponent();
+ SubscribeEmitComponent();
+ SubscribeEmitComponent();
+ SubscribeEmitComponent();
+ SubscribeEmitComponent();
+ SubscribeEmitComponent();
+ SubscribeEmitComponent();
+ SubscribeEmitComponent();
+
+ // Helper method so it's a little less ugly
+ void SubscribeEmitComponent() where T : BaseEmitSoundComponent
+ {
+ SubscribeLocalEvent(GetBaseEmitState);
+ SubscribeLocalEvent(HandleBaseEmitState);
+ }
+ }
+
+ private static void GetBaseEmitState(Entity ent, ref ComponentGetState args) where T : BaseEmitSoundComponent
+ {
+ args.State = new EmitSoundComponentState(ent.Comp.Sound);
+ }
+
+ private static void HandleBaseEmitState(Entity ent, ref ComponentHandleState args) where T : BaseEmitSoundComponent
+ {
+ if (args.Current is not EmitSoundComponentState state)
+ return;
+
+ ent.Comp.Sound = state.Sound switch
+ {
+ SoundPathSpecifier pathSpec => new SoundPathSpecifier(pathSpec.Path, pathSpec.Params),
+ SoundCollectionSpecifier collectionSpec => collectionSpec.Collection != null
+ ? new SoundCollectionSpecifier(collectionSpec.Collection, collectionSpec.Params)
+ : null,
+ _ => null,
+ };
}
private void HandleEmitSoundOnUIOpen(EntityUid uid, EmitSoundOnUIOpenComponent component, AfterActivatableUIOpenEvent args)