diff --git a/Content.Client/PDA/Ringer/RingerBoundUserInterface.cs b/Content.Client/PDA/Ringer/RingerBoundUserInterface.cs
index aee8357cdc..a0688523f1 100644
--- a/Content.Client/PDA/Ringer/RingerBoundUserInterface.cs
+++ b/Content.Client/PDA/Ringer/RingerBoundUserInterface.cs
@@ -1,7 +1,7 @@
using Content.Shared.PDA;
using Content.Shared.PDA.Ringer;
using JetBrains.Annotations;
-using Robust.Client.GameObjects;
+using Robust.Shared.Timing;
namespace Content.Client.PDA.Ringer
{
@@ -29,9 +29,17 @@ namespace Content.Client.PDA.Ringer
_menu.SetRingerButton.OnPressed += _ =>
{
- if (!TryGetRingtone(out var ringtone)) return;
+ if (!TryGetRingtone(out var ringtone))
+ return;
SendMessage(new RingerSetRingtoneMessage(ringtone));
+ _menu.SetRingerButton.Disabled = true;
+
+ Timer.Spawn(333, () =>
+ {
+ if (_menu is { Disposed: false, SetRingerButton: { Disposed: false } ringer})
+ ringer.Disabled = false;
+ });
};
}
@@ -74,7 +82,7 @@ namespace Content.Client.PDA.Ringer
}
- _menu.TestRingerButton.Visible = !msg.IsPlaying;
+ _menu.TestRingerButton.Disabled = msg.IsPlaying;
}
diff --git a/Content.Client/PDA/Ringer/RingtoneMenu.xaml b/Content.Client/PDA/Ringer/RingtoneMenu.xaml
index a361a58dd2..2fff0ab1b5 100644
--- a/Content.Client/PDA/Ringer/RingtoneMenu.xaml
+++ b/Content.Client/PDA/Ringer/RingtoneMenu.xaml
@@ -79,12 +79,14 @@
Access="Public"
Text="{Loc 'comp-ringer-ui-test-ringtone-button'}"
HorizontalAlignment="Center"
- VerticalAlignment="Center" />
+ VerticalAlignment="Center"
+ StyleClasses="OpenRight" />
+ VerticalAlignment="Center"
+ StyleClasses="OpenLeft" />
diff --git a/Content.Server/PDA/Ringer/RingerSystem.cs b/Content.Server/PDA/Ringer/RingerSystem.cs
index 2145dae326..a772e76bc4 100644
--- a/Content.Server/PDA/Ringer/RingerSystem.cs
+++ b/Content.Server/PDA/Ringer/RingerSystem.cs
@@ -1,3 +1,5 @@
+using System.Linq;
+using System.Runtime.InteropServices;
using Content.Server.Store.Components;
using Content.Server.Store.Systems;
using Content.Shared.PDA;
@@ -7,21 +9,25 @@ using Content.Shared.Store;
using Robust.Server.GameObjects;
using Robust.Server.Player;
using Robust.Shared.Audio;
+using Robust.Shared.Network;
using Robust.Shared.Player;
using Robust.Shared.Random;
+using Robust.Shared.Timing;
using Robust.Shared.Utility;
-using System.Linq;
namespace Content.Server.PDA.Ringer
{
public sealed class RingerSystem : SharedRingerSystem
{
[Dependency] private readonly PdaSystem _pda = default!;
+ [Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly UserInterfaceSystem _ui = default!;
[Dependency] private readonly AudioSystem _audio = default!;
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
+ private readonly Dictionary _lastSetRingtoneAt = new();
+
public override void Initialize()
{
base.Initialize();
@@ -53,7 +59,7 @@ namespace Content.Server.PDA.Ringer
_popupSystem.PopupEntity(Loc.GetString("comp-ringer-vibration-popup"), uid, Filter.Pvs(uid, 0.05f), false, PopupType.Small);
- UpdateRingerUserInterface(uid, ringer);
+ UpdateRingerUserInterface(uid, ringer, true);
}
public void RingerPlayRingtone(EntityUid uid, RingerComponent ringer)
@@ -62,18 +68,27 @@ namespace Content.Server.PDA.Ringer
_popupSystem.PopupEntity(Loc.GetString("comp-ringer-vibration-popup"), uid, Filter.Pvs(uid, 0.05f), false, PopupType.Small);
- UpdateRingerUserInterface(uid, ringer);
+ UpdateRingerUserInterface(uid, ringer, true);
}
private void UpdateRingerUserInterfaceDriver(EntityUid uid, RingerComponent ringer, RingerRequestUpdateInterfaceMessage args)
{
- UpdateRingerUserInterface(uid, ringer);
+ UpdateRingerUserInterface(uid, ringer, HasComp(uid));
}
private void OnSetRingtone(EntityUid uid, RingerComponent ringer, RingerSetRingtoneMessage args)
{
+ ref var lastSetAt = ref CollectionsMarshal.GetValueRefOrAddDefault(_lastSetRingtoneAt, args.Session.UserId, out var exists);
+
+ // Delay on the client is 0.333, 0.25 is still enough and gives some leeway in case of small time differences
+ if (exists && lastSetAt > _gameTiming.CurTime - TimeSpan.FromMilliseconds(250))
+ return;
+
+ lastSetAt = _gameTiming.CurTime;
+
// Client sent us an updated ringtone so set it to that.
- if (args.Ringtone.Length != RingtoneLength) return;
+ if (args.Ringtone.Length != RingtoneLength)
+ return;
var ev = new BeforeRingtoneSetEvent(args.Ringtone);
RaiseLocalEvent(uid, ref ev);
@@ -156,15 +171,15 @@ namespace Content.Server.PDA.Ringer
{
// Assume validation has already happened.
ringer.Ringtone = ringtone;
- UpdateRingerUserInterface(uid, ringer);
+ UpdateRingerUserInterface(uid, ringer, HasComp(uid));
return true;
}
- private void UpdateRingerUserInterface(EntityUid uid, RingerComponent ringer)
+ private void UpdateRingerUserInterface(EntityUid uid, RingerComponent ringer, bool isPlaying)
{
if (_ui.TryGetUi(uid, RingerUiKey.Key, out var bui))
- _ui.SetUiState(bui, new RingerUpdateState(HasComp(uid), ringer.Ringtone));
+ _ui.SetUiState(bui, new RingerUpdateState(isPlaying, ringer.Ringtone));
}
public bool ToggleRingerUI(EntityUid uid, IPlayerSession session)
@@ -202,7 +217,7 @@ namespace Content.Server.PDA.Ringer
if (ringer.NoteCount > RingtoneLength - 1)
{
remove.Add(uid);
- UpdateRingerUserInterface(uid, ringer);
+ UpdateRingerUserInterface(uid, ringer, false);
ringer.TimeElapsed = 0;
ringer.NoteCount = 0;
break;