Add small cooldown to NukeKeypadEnterMessages (#41831)

* cooldown

* d

* time offset serializer

* undo button disabling according to feedback

* Update Content.Client/Nuke/NukeBoundUserInterface.cs
This commit is contained in:
slarticodefast 2025-12-12 01:58:51 +01:00 committed by BarryNorfolk
parent 87dd6de9dd
commit f967c76f12
3 changed files with 23 additions and 2 deletions

View File

@ -5,6 +5,7 @@ using Content.Shared.Explosion;
using Content.Shared.Nuke; using Content.Shared.Nuke;
using Robust.Shared.Audio; using Robust.Shared.Audio;
using Robust.Shared.Map; using Robust.Shared.Map;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Server.Nuke namespace Content.Server.Nuke
@ -164,6 +165,14 @@ namespace Content.Server.Nuke
[DataField] [DataField]
public string EnteredCode = ""; public string EnteredCode = "";
/// <summary>
/// Time at which the last nuke code was entered.
/// Used to apply a cooldown to prevent clients from attempting to brute force the nuke code by sending keypad messages every tick.
/// <seealso cref="SharedNukeComponent.EnterCodeCooldown"/>
/// </summary>
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer))]
public TimeSpan LastCodeEnteredAt = TimeSpan.Zero;
/// <summary> /// <summary>
/// Current status of a nuclear bomb. /// Current status of a nuclear bomb.
/// </summary> /// </summary>

View File

@ -18,11 +18,10 @@ using Robust.Server.GameObjects;
using Robust.Shared.Audio; using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems; using Robust.Shared.Audio.Systems;
using Robust.Shared.Containers; using Robust.Shared.Containers;
using Robust.Shared.Map;
using Robust.Shared.Map.Components; using Robust.Shared.Map.Components;
using Robust.Shared.Player;
using Robust.Shared.Random; using Robust.Shared.Random;
using Robust.Shared.Utility; using Robust.Shared.Utility;
using Robust.Shared.Timing;
namespace Content.Server.Nuke; namespace Content.Server.Nuke;
@ -45,6 +44,7 @@ public sealed class NukeSystem : EntitySystem
[Dependency] private readonly UserInterfaceSystem _ui = default!; [Dependency] private readonly UserInterfaceSystem _ui = default!;
[Dependency] private readonly AppearanceSystem _appearance = default!; [Dependency] private readonly AppearanceSystem _appearance = default!;
[Dependency] private readonly TurfSystem _turf = default!; [Dependency] private readonly TurfSystem _turf = default!;
[Dependency] private readonly IGameTiming _timing = default!;
/// <summary> /// <summary>
/// Used to calculate when the nuke song should start playing for maximum kino with the nuke sfx /// Used to calculate when the nuke song should start playing for maximum kino with the nuke sfx
@ -232,6 +232,12 @@ public sealed class NukeSystem : EntitySystem
if (component.Status != NukeStatus.AWAIT_CODE) if (component.Status != NukeStatus.AWAIT_CODE)
return; return;
var curTime = _timing.CurTime;
if (curTime < component.LastCodeEnteredAt + SharedNukeComponent.EnterCodeCooldown)
return; // Validate that they are not entering codes faster than the cooldown.
component.LastCodeEnteredAt = curTime;
UpdateStatus(uid, component); UpdateStatus(uid, component);
UpdateUserInterface(uid, component); UpdateUserInterface(uid, component);
} }

View File

@ -5,6 +5,12 @@ namespace Content.Shared.Nuke
public abstract partial class SharedNukeComponent : Component public abstract partial class SharedNukeComponent : Component
{ {
public const string NukeDiskSlotId = "Nuke"; public const string NukeDiskSlotId = "Nuke";
/// <summary>
/// Cooldown time between attempts to enter the nuke code.
/// Used to prevent clients from trying to brute force it.
/// </summary>
public static readonly TimeSpan EnterCodeCooldown = TimeSpan.FromSeconds(1);
} }
[Serializable, NetSerializable] [Serializable, NetSerializable]