diff --git a/Content.Client/_Sunrise/TTS/TTSSystem.cs b/Content.Client/_Sunrise/TTS/TTSSystem.cs index 7c5173b5463..c25cc059cbe 100644 --- a/Content.Client/_Sunrise/TTS/TTSSystem.cs +++ b/Content.Client/_Sunrise/TTS/TTSSystem.cs @@ -43,6 +43,7 @@ public override void Initialize() _cfg.OnValueChanged(SunriseCCVars.TTSVolume, OnTtsVolumeChanged, true); _cfg.OnValueChanged(SunriseCCVars.TTSRadioVolume, OnTtsRadioVolumeChanged, true); _cfg.OnValueChanged(SunriseCCVars.TTSAnnounceVolume, OnTtsAnnounceVolumeChanged, true); + _cfg.OnValueChanged(SunriseCCVars.TTSClientEnabled, OnTtsClientOptionChanged, true); SubscribeNetworkEvent(OnPlayTTS); SubscribeNetworkEvent(OnAnnounceTTSPlay); } @@ -53,6 +54,7 @@ public override void Shutdown() _cfg.UnsubValueChanged(SunriseCCVars.TTSVolume, OnTtsVolumeChanged); _cfg.UnsubValueChanged(SunriseCCVars.TTSRadioVolume, OnTtsRadioVolumeChanged); _cfg.UnsubValueChanged(SunriseCCVars.TTSAnnounceVolume, OnTtsAnnounceVolumeChanged); + _cfg.UnsubValueChanged(SunriseCCVars.TTSClientEnabled, OnTtsClientOptionChanged); _contentRoot.Dispose(); } @@ -71,6 +73,11 @@ private void OnTtsAnnounceVolumeChanged(float volume) _volumeAnnounce = volume; } + private void OnTtsClientOptionChanged(bool option) + { + RaiseNetworkEvent(new ClientOptionTTSEvent(option)); + } + private void OnAnnounceTTSPlay(AnnounceTtsEvent ev) { if (_volumeAnnounce == 0) diff --git a/Content.Server/_Sunrise/TTS/TTSSystem.cs b/Content.Server/_Sunrise/TTS/TTSSystem.cs index 4f5ece285f8..0d8568c7676 100644 --- a/Content.Server/_Sunrise/TTS/TTSSystem.cs +++ b/Content.Server/_Sunrise/TTS/TTSSystem.cs @@ -40,6 +40,7 @@ public sealed partial class TTSSystem : EntitySystem private const int MaxMessageChars = 100 * 2; // same as SingleBubbleCharLimit * 2 private bool _isEnabled = false; private string _voiceId = "Hanson"; + private List _ignoredRecipients = new(); private string _nukieVoiceId = "Sentrybot"; public const float WhisperVoiceVolumeModifier = 0.6f; // how far whisper goes in world units public const int WhisperVoiceRange = 4; // how far whisper goes in world units @@ -56,6 +57,7 @@ public override void Initialize() SubscribeLocalEvent(OnAnnouncementSpoke); SubscribeNetworkEvent(OnRequestPreviewTTS); + SubscribeNetworkEvent(OnClientOptionTTS); } private async void OnRequestPreviewTTS(RequestPreviewTTSEvent ev, EntitySessionEventArgs args) @@ -72,6 +74,14 @@ private async void OnRequestPreviewTTS(RequestPreviewTTSEvent ev, EntitySessionE RaiseNetworkEvent(new PlayTTSEvent(soundData), Filter.SinglePlayer(args.SenderSession)); } + private async void OnClientOptionTTS(ClientOptionTTSEvent ev, EntitySessionEventArgs args) + { + if (ev.Enabled) + _ignoredRecipients.Remove(args.SenderSession); + else + _ignoredRecipients.Add(args.SenderSession); + } + private void OnRadioReceiveEvent(RadioSpokeEvent args) { if (!_isEnabled || args.Message.Length > MaxMessageChars) @@ -112,13 +122,13 @@ private async void OnAnnouncementSpoke(AnnouncementSpokeEvent args) args.Message.Length > MaxMessageChars * 2 || !GetVoicePrototype(args.Nukie ? _nukieVoiceId : _voiceId, out var protoVoice)) { - RaiseNetworkEvent(new AnnounceTtsEvent(new byte[] { }), args.Source); + RaiseNetworkEvent(new AnnounceTtsEvent(new byte[] { }), args.Source.RemovePlayers(_ignoredRecipients)); return; } var soundData = await GenerateTTS(args.Message, protoVoice.Speaker, isAnnounce: true); soundData ??= new byte[] { }; - RaiseNetworkEvent(new AnnounceTtsEvent(soundData), args.Source); + RaiseNetworkEvent(new AnnounceTtsEvent(soundData), args.Source.RemovePlayers(_ignoredRecipients)); } private async void OnEntitySpoke(EntityUid uid, TTSComponent component, EntitySpokeEvent args) @@ -151,7 +161,7 @@ private async void HandleSay(EntityUid uid, string message, string speaker) { var soundData = await GenerateTTS(message, speaker); if (soundData is null) return; - RaiseNetworkEvent(new PlayTTSEvent(soundData, GetNetEntity(uid)), Filter.Pvs(uid)); + RaiseNetworkEvent(new PlayTTSEvent(soundData, GetNetEntity(uid)), Filter.Pvs(uid).RemovePlayers(_ignoredRecipients)); } private async void HandleWhisper(EntityUid uid, string message, string speaker, bool isRadio) @@ -171,6 +181,9 @@ private async void HandleWhisper(EntityUid uid, string message, string speaker, if (!session.AttachedEntity.HasValue) continue; + if (_ignoredRecipients.Contains(session)) + return; + var xform = xformQuery.GetComponent(session.AttachedEntity.Value); var distance = (sourcePos - _xforms.GetWorldPosition(xform, xformQuery)).LengthSquared(); @@ -194,7 +207,7 @@ private async void HandleRadio(EntityUid[] uids, string message, string speaker) foreach (var uid in uids) { - RaiseNetworkEvent(new PlayTTSEvent(soundData, GetNetEntity(uid), true), Filter.Entities(uid)); + RaiseNetworkEvent(new PlayTTSEvent(soundData, GetNetEntity(uid), true), Filter.Entities(uid).RemovePlayers(_ignoredRecipients)); } } diff --git a/Content.Shared/_Sunrise/SunriseCCVars/SunriseCCVars.cs b/Content.Shared/_Sunrise/SunriseCCVars/SunriseCCVars.cs index 4403b417c84..331d50c9bbb 100644 --- a/Content.Shared/_Sunrise/SunriseCCVars/SunriseCCVars.cs +++ b/Content.Shared/_Sunrise/SunriseCCVars/SunriseCCVars.cs @@ -33,6 +33,13 @@ public sealed class SunriseCCVars public static readonly CVarDef TTSApiTimeout = CVarDef.Create("tts.api_timeout", 5, CVar.SERVERONLY | CVar.ARCHIVE); + /// + /// Option to disable TTS events for client + /// + public static readonly CVarDef TTSClientEnabled = + CVarDef.Create("tts.client_enabled", false, CVar.CLIENTONLY | CVar.ARCHIVE); + + /// /// Default volume setting of TTS sound /// diff --git a/Content.Shared/_Sunrise/TTS/ClientOptionTTSEvent.cs b/Content.Shared/_Sunrise/TTS/ClientOptionTTSEvent.cs new file mode 100644 index 00000000000..e1ce05fc840 --- /dev/null +++ b/Content.Shared/_Sunrise/TTS/ClientOptionTTSEvent.cs @@ -0,0 +1,13 @@ +using Robust.Shared.Serialization; + +namespace Content.Shared._Sunrise.TTS; + +[Serializable, NetSerializable] +public sealed class ClientOptionTTSEvent : EntityEventArgs +{ + public bool Enabled { get; } + public ClientOptionTTSEvent(bool enabled) + { + Enabled = enabled; + } +}