use manual component state for BaseEmitSoundComponent (#35030)
* why * cursed
This commit is contained in:
@@ -1,4 +1,6 @@
|
|||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
|
using Robust.Shared.GameStates;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
namespace Content.Shared.Sound.Components;
|
namespace Content.Shared.Sound.Components;
|
||||||
|
|
||||||
@@ -8,10 +10,9 @@ namespace Content.Shared.Sound.Components;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract partial class BaseEmitSoundComponent : Component
|
public abstract partial class BaseEmitSoundComponent : Component
|
||||||
{
|
{
|
||||||
public static readonly AudioParams DefaultParams = AudioParams.Default.WithVolume(-2f);
|
/// <summary>
|
||||||
|
/// The <see cref="SoundSpecifier"/> to play.
|
||||||
[AutoNetworkedField]
|
/// </summary>
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
|
||||||
[DataField(required: true)]
|
[DataField(required: true)]
|
||||||
public SoundSpecifier? Sound;
|
public SoundSpecifier? Sound;
|
||||||
|
|
||||||
@@ -22,3 +23,15 @@ public abstract partial class BaseEmitSoundComponent : Component
|
|||||||
[DataField]
|
[DataField]
|
||||||
public bool Positional;
|
public bool Positional;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the state of <see cref="BaseEmitSoundComponent"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>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.</remarks>
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public struct EmitSoundComponentState(SoundSpecifier? sound) : IComponentState
|
||||||
|
{
|
||||||
|
public SoundSpecifier? Sound { get; } = sound;
|
||||||
|
}
|
||||||
|
|||||||
@@ -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
|
/// otherwise this might enable sound spamming, as use-delays are only initiated if the interaction was
|
||||||
/// handled.
|
/// handled.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
[DataField("handle")]
|
[DataField]
|
||||||
public bool Handle = true;
|
public bool Handle = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,13 +11,12 @@ public sealed partial class EmitSoundOnCollideComponent : BaseEmitSoundComponent
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Minimum velocity required for the sound to play.
|
/// Minimum velocity required for the sound to play.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ViewVariables(VVAccess.ReadWrite), DataField("minVelocity")]
|
[DataField("minVelocity")]
|
||||||
public float MinimumVelocity = 3f;
|
public float MinimumVelocity = 3f;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// To avoid sound spam add a cooldown to it.
|
/// To avoid sound spam add a cooldown to it.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ViewVariables(VVAccess.ReadWrite), DataField("nextSound", customTypeSerializer: typeof(TimeOffsetSerializer))]
|
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), AutoPausedField]
|
||||||
[AutoPausedField]
|
|
||||||
public TimeSpan NextSound;
|
public TimeSpan NextSound;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,4 @@ namespace Content.Shared.Sound.Components;
|
|||||||
/// Simple sound emitter that emits sound on entity drop
|
/// Simple sound emitter that emits sound on entity drop
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[RegisterComponent, NetworkedComponent]
|
[RegisterComponent, NetworkedComponent]
|
||||||
public sealed partial class EmitSoundOnDropComponent : BaseEmitSoundComponent
|
public sealed partial class EmitSoundOnDropComponent : BaseEmitSoundComponent;
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Content.Shared.Whitelist;
|
using Content.Shared.Whitelist;
|
||||||
using Robust.Shared.Prototypes;
|
|
||||||
using Robust.Shared.GameStates;
|
using Robust.Shared.GameStates;
|
||||||
|
|
||||||
namespace Content.Shared.Sound.Components;
|
namespace Content.Shared.Sound.Components;
|
||||||
@@ -10,6 +9,9 @@ namespace Content.Shared.Sound.Components;
|
|||||||
[RegisterComponent, NetworkedComponent]
|
[RegisterComponent, NetworkedComponent]
|
||||||
public sealed partial class EmitSoundOnInteractUsingComponent : BaseEmitSoundComponent
|
public sealed partial class EmitSoundOnInteractUsingComponent : BaseEmitSoundComponent
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The <see cref="EntityWhitelist"/> for the entities that can use this item.
|
||||||
|
/// </summary>
|
||||||
[DataField(required: true)]
|
[DataField(required: true)]
|
||||||
public EntityWhitelist Whitelist = new();
|
public EntityWhitelist Whitelist = new();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,4 @@ namespace Content.Shared.Sound.Components;
|
|||||||
/// Simple sound emitter that emits sound on LandEvent
|
/// Simple sound emitter that emits sound on LandEvent
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[RegisterComponent, NetworkedComponent]
|
[RegisterComponent, NetworkedComponent]
|
||||||
public sealed partial class EmitSoundOnLandComponent : BaseEmitSoundComponent
|
public sealed partial class EmitSoundOnLandComponent : BaseEmitSoundComponent;
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -6,6 +6,4 @@ namespace Content.Shared.Sound.Components;
|
|||||||
/// Simple sound emitter that emits sound on entity pickup
|
/// Simple sound emitter that emits sound on entity pickup
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[RegisterComponent, NetworkedComponent]
|
[RegisterComponent, NetworkedComponent]
|
||||||
public sealed partial class EmitSoundOnPickupComponent : BaseEmitSoundComponent
|
public sealed partial class EmitSoundOnPickupComponent : BaseEmitSoundComponent;
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -6,6 +6,4 @@ namespace Content.Shared.Sound.Components;
|
|||||||
/// Simple sound emitter that emits sound on entity spawn.
|
/// Simple sound emitter that emits sound on entity spawn.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[RegisterComponent, NetworkedComponent]
|
[RegisterComponent, NetworkedComponent]
|
||||||
public sealed partial class EmitSoundOnSpawnComponent : BaseEmitSoundComponent
|
public sealed partial class EmitSoundOnSpawnComponent : BaseEmitSoundComponent;
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -6,6 +6,4 @@ namespace Content.Shared.Sound.Components;
|
|||||||
/// Simple sound emitter that emits sound on ThrowEvent
|
/// Simple sound emitter that emits sound on ThrowEvent
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[RegisterComponent, NetworkedComponent]
|
[RegisterComponent, NetworkedComponent]
|
||||||
public sealed partial class EmitSoundOnThrowComponent : BaseEmitSoundComponent
|
public sealed partial class EmitSoundOnThrowComponent : BaseEmitSoundComponent;
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ namespace Content.Shared.Sound.Components;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Simple sound emitter that emits sound on UseInHand
|
/// Simple sound emitter that emits sound on UseInHand
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[RegisterComponent]
|
[RegisterComponent, NetworkedComponent]
|
||||||
public sealed partial class EmitSoundOnUseComponent : BaseEmitSoundComponent
|
public sealed partial class EmitSoundOnUseComponent : BaseEmitSoundComponent
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -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
|
/// otherwise this might enable sound spamming, as use-delays are only initiated if the interaction was
|
||||||
/// handled.
|
/// handled.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
[DataField("handle")]
|
[DataField]
|
||||||
public bool Handle = true;
|
public bool Handle = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Robust.Shared.GameStates;
|
using Robust.Shared.GameStates;
|
||||||
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
||||||
|
|
||||||
namespace Content.Shared.Sound.Components;
|
namespace Content.Shared.Sound.Components;
|
||||||
|
|
||||||
@@ -12,7 +13,7 @@ public sealed partial class SpamEmitSoundComponent : BaseEmitSoundComponent
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The time at which the next sound will play.
|
/// The time at which the next sound will play.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField, AutoPausedField, AutoNetworkedField]
|
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), AutoPausedField, AutoNetworkedField]
|
||||||
public TimeSpan NextSound;
|
public TimeSpan NextSound;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -5,6 +5,4 @@ namespace Content.Shared.Sound.Components;
|
|||||||
/// on the powered state of the entity.
|
/// on the powered state of the entity.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
public sealed partial class SpamEmitSoundRequirePowerComponent : Component
|
public sealed partial class SpamEmitSoundRequirePowerComponent : Component;
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ using Content.Shared.Whitelist;
|
|||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
using Robust.Shared.Audio.Systems;
|
using Robust.Shared.Audio.Systems;
|
||||||
|
using Robust.Shared.GameStates;
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
using Robust.Shared.Map.Components;
|
using Robust.Shared.Map.Components;
|
||||||
using Robust.Shared.Network;
|
using Robust.Shared.Network;
|
||||||
@@ -54,6 +55,47 @@ public abstract class SharedEmitSoundSystem : EntitySystem
|
|||||||
SubscribeLocalEvent<EmitSoundOnCollideComponent, StartCollideEvent>(OnEmitSoundOnCollide);
|
SubscribeLocalEvent<EmitSoundOnCollideComponent, StartCollideEvent>(OnEmitSoundOnCollide);
|
||||||
|
|
||||||
SubscribeLocalEvent<SoundWhileAliveComponent, MobStateChangedEvent>(OnMobState);
|
SubscribeLocalEvent<SoundWhileAliveComponent, MobStateChangedEvent>(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<EmitSoundOnActivateComponent>();
|
||||||
|
SubscribeEmitComponent<EmitSoundOnCollideComponent>();
|
||||||
|
SubscribeEmitComponent<EmitSoundOnDropComponent>();
|
||||||
|
SubscribeEmitComponent<EmitSoundOnInteractUsingComponent>();
|
||||||
|
SubscribeEmitComponent<EmitSoundOnLandComponent>();
|
||||||
|
SubscribeEmitComponent<EmitSoundOnPickupComponent>();
|
||||||
|
SubscribeEmitComponent<EmitSoundOnSpawnComponent>();
|
||||||
|
SubscribeEmitComponent<EmitSoundOnThrowComponent>();
|
||||||
|
SubscribeEmitComponent<EmitSoundOnUIOpenComponent>();
|
||||||
|
SubscribeEmitComponent<EmitSoundOnUseComponent>();
|
||||||
|
|
||||||
|
// Helper method so it's a little less ugly
|
||||||
|
void SubscribeEmitComponent<T>() where T : BaseEmitSoundComponent
|
||||||
|
{
|
||||||
|
SubscribeLocalEvent<T, ComponentGetState>(GetBaseEmitState);
|
||||||
|
SubscribeLocalEvent<T, ComponentHandleState>(HandleBaseEmitState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GetBaseEmitState<T>(Entity<T> ent, ref ComponentGetState args) where T : BaseEmitSoundComponent
|
||||||
|
{
|
||||||
|
args.State = new EmitSoundComponentState(ent.Comp.Sound);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void HandleBaseEmitState<T>(Entity<T> 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)
|
private void HandleEmitSoundOnUIOpen(EntityUid uid, EmitSoundOnUIOpenComponent component, AfterActivatableUIOpenEvent args)
|
||||||
|
|||||||
Reference in New Issue
Block a user