From 207d5136669ffafa53d2a28067b90931d6ef6570 Mon Sep 17 00:00:00 2001 From: lzk <124214523+lzk228@users.noreply.github.com> Date: Tue, 29 Apr 2025 07:24:33 +0200 Subject: [PATCH] SSD sleep take 2 (#34039) * ssd sleep part 2 * forgot this * apply review * yeah * add onmapinit * cache cvar values --------- Co-authored-by: EmoGarbage404 --- Content.Shared/CCVar/CCVars.Ic.cs | 13 ++++ .../SSDIndicator/SSDIndicatorComponent.cs | 17 ++++- .../SSDIndicator/SSDIndicatorSystem.cs | 67 ++++++++++++++++++- 3 files changed, 94 insertions(+), 3 deletions(-) diff --git a/Content.Shared/CCVar/CCVars.Ic.cs b/Content.Shared/CCVar/CCVars.Ic.cs index e149e9f3e1..54ab69b3fa 100644 --- a/Content.Shared/CCVar/CCVars.Ic.cs +++ b/Content.Shared/CCVar/CCVars.Ic.cs @@ -45,4 +45,17 @@ public sealed partial class CCVars /// public static readonly CVarDef ICShowSSDIndicator = CVarDef.Create("ic.show_ssd_indicator", true, CVar.CLIENTONLY); + + /// + /// Forces SSD characters to sleep after ICSSDSleepTime seconds + /// + public static readonly CVarDef ICSSDSleep = + CVarDef.Create("ic.ssd_sleep", true, CVar.SERVER); + + /// + /// Time between character getting SSD status and falling asleep + /// Won't work without ICSSDSleep + /// + public static readonly CVarDef ICSSDSleepTime = + CVarDef.Create("ic.ssd_sleep_time", 600f, CVar.SERVER); } diff --git a/Content.Shared/SSDIndicator/SSDIndicatorComponent.cs b/Content.Shared/SSDIndicator/SSDIndicatorComponent.cs index 634dfc397b..47ac8afe72 100644 --- a/Content.Shared/SSDIndicator/SSDIndicatorComponent.cs +++ b/Content.Shared/SSDIndicator/SSDIndicatorComponent.cs @@ -1,4 +1,4 @@ -using Content.Shared.StatusIcon; +using Content.Shared.StatusIcon; using Robust.Shared.GameStates; using Robust.Shared.Prototypes; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; @@ -9,7 +9,7 @@ namespace Content.Shared.SSDIndicator; /// Shows status icon when player in SSD /// [RegisterComponent, NetworkedComponent] -[AutoGenerateComponentState] +[AutoGenerateComponentState, AutoGenerateComponentPause] public sealed partial class SSDIndicatorComponent : Component { [ViewVariables(VVAccess.ReadWrite)] @@ -19,4 +19,17 @@ public sealed partial class SSDIndicatorComponent : Component [ViewVariables(VVAccess.ReadWrite)] [DataField] public ProtoId Icon = "SSDIcon"; + + /// + /// When the entity should fall asleep + /// + [DataField, AutoPausedField, Access(typeof(SSDIndicatorSystem))] + public TimeSpan FallAsleepTime = TimeSpan.Zero; + + /// + /// Required to don't remove forced sleep from other sources + /// + [ViewVariables(VVAccess.ReadWrite)] + [AutoNetworkedField] + public bool ForcedSleepAdded = false; } diff --git a/Content.Shared/SSDIndicator/SSDIndicatorSystem.cs b/Content.Shared/SSDIndicator/SSDIndicatorSystem.cs index 7fc13d161e..dfba833bcf 100644 --- a/Content.Shared/SSDIndicator/SSDIndicatorSystem.cs +++ b/Content.Shared/SSDIndicator/SSDIndicatorSystem.cs @@ -1,4 +1,8 @@ -using Robust.Shared.Player; +using Content.Shared.Bed.Sleep; +using Content.Shared.CCVar; +using Robust.Shared.Configuration; +using Robust.Shared.Player; +using Robust.Shared.Timing; namespace Content.Shared.SSDIndicator; @@ -7,21 +11,82 @@ namespace Content.Shared.SSDIndicator; /// public sealed class SSDIndicatorSystem : EntitySystem { + [Dependency] private readonly IConfigurationManager _cfg = default!; + [Dependency] private readonly IGameTiming _timing = default!; + + private bool _icSsdSleep; + private float _icSsdSleepTime; + public override void Initialize() { SubscribeLocalEvent(OnPlayerAttached); SubscribeLocalEvent(OnPlayerDetached); + SubscribeLocalEvent(OnMapInit); + + _cfg.OnValueChanged(CCVars.ICSSDSleep, obj => _icSsdSleep = obj, true); + _cfg.OnValueChanged(CCVars.ICSSDSleepTime, obj => _icSsdSleepTime = obj, true); } private void OnPlayerAttached(EntityUid uid, SSDIndicatorComponent component, PlayerAttachedEvent args) { component.IsSSD = false; + + // Removes force sleep and resets the time to zero + if (_icSsdSleep) + { + component.FallAsleepTime = TimeSpan.Zero; + if (component.ForcedSleepAdded) // Remove component only if it has been added by this system + { + EntityManager.RemoveComponent(uid); + component.ForcedSleepAdded = false; + } + } Dirty(uid, component); } private void OnPlayerDetached(EntityUid uid, SSDIndicatorComponent component, PlayerDetachedEvent args) { component.IsSSD = true; + + // Sets the time when the entity should fall asleep + if (_icSsdSleep) + { + component.FallAsleepTime = _timing.CurTime + TimeSpan.FromSeconds(_icSsdSleepTime); + } Dirty(uid, component); } + + // Prevents mapped mobs to go to sleep immediately + private void OnMapInit(EntityUid uid, SSDIndicatorComponent component, MapInitEvent args) + { + if (_icSsdSleep && + component.IsSSD && + component.FallAsleepTime == TimeSpan.Zero) + { + component.FallAsleepTime = _timing.CurTime + TimeSpan.FromSeconds(_icSsdSleepTime); + } + } + + public override void Update(float frameTime) + { + base.Update(frameTime); + + if (!_icSsdSleep) + return; + + var query = EntityQueryEnumerator(); + + while (query.MoveNext(out var uid, out var ssd)) + { + // Forces the entity to sleep when the time has come + if(ssd.IsSSD && + ssd.FallAsleepTime <= _timing.CurTime && + !TerminatingOrDeleted(uid) && + !HasComp(uid)) // Don't add the component if the entity has it from another sources + { + EnsureComp(uid); + ssd.ForcedSleepAdded = true; + } + } + } } -- 2.51.2