using Content.Client._DV.Tips.UI; using Content.Shared._DV.CCVars; using Content.Shared._DV.Tips; using JetBrains.Annotations; using Robust.Client.UserInterface; using Robust.Shared.Audio.Systems; using Robust.Shared.Configuration; using Robust.Shared.Player; using Robust.Shared.Prototypes; namespace Content.Client._DV.Tips; /// /// Client-side system that receives tip events from the server and displays the tip popup UI. /// public sealed class TipSystem : SharedTipSystem { [Dependency] private readonly IUserInterfaceManager _ui = default!; [Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly IConfigurationManager _cfg = default!; /// /// Queue of tips waiting to be shown. Only one tip is displayed at a time. /// private readonly Queue _tipQueue = new(); /// /// Currently displayed tip popup, if any. /// private TipPopup? _currentPopup; /// /// The tip ID of the currently displayed popup, used for dismiss events. /// private ProtoId? _currentTipId; public override void Initialize() { base.Initialize(); SubscribeNetworkEvent(OnShowTip); } private void OnShowTip(ShowTipEvent ev) { // Return if tips are disabled globally if (_cfg.GetCVar(DCCVars.DisableTipsGlobal)) return; // Return if tips are disabled locally and IgnoreCvar is the default value if (_cfg.GetCVar(DCCVars.DisableTips) && !ev.IgnoreCvar) return; _tipQueue.Enqueue(ev); TryShowNextTip(); } private void TryShowNextTip() { while (true) { if (_currentPopup != null) return; if (_tipQueue.Count == 0) return; var tipEvent = _tipQueue.Dequeue(); if (!Prototype.TryIndex(tipEvent.TipId, out var tipProto)) { Log.Warning($"Received tip event for unknown prototype: {tipEvent.TipId}"); continue; } ShowTipPopup(tipProto, tipEvent); break; } } private void ShowTipPopup(TipPrototype tip, ShowTipEvent ev) { _currentPopup = new TipPopup(tip); _currentPopup.OnClose += OnPopupClosed; _currentTipId = tip.ID; _ui.RootControl.AddChild(_currentPopup); // Play the sound _audio.PlayGlobal(ev.Sound, Filter.Local(), false); } private void OnPopupClosed(bool dontShowAgain) { if (_currentPopup != null && _currentTipId != null) { // Send dismiss event to server RaiseNetworkEvent(new TipDismissedEvent(_currentTipId.Value, dontShowAgain)); _currentPopup.OnClose -= OnPopupClosed; _currentPopup?.Close(); _currentPopup = null; _currentTipId = null; } TryShowNextTip(); } /// /// Closes the current tip popup if one is open. /// [PublicAPI] public void CloseCurrentTip() { _currentPopup?.Close(); } /// /// Clears all queued tips without showing them. /// [PublicAPI] public void ClearTipQueue() { _tipQueue.Clear(); } }