#nullable enable using System; using System.Globalization; using System.Threading; using Content.Server.GameObjects.Components.PDA; using Content.Server.GameObjects.Components.Power.ApcNetComponents; using Content.Server.GameObjects.EntitySystems; using Content.Server.Interfaces.Chat; using Content.Server.Utility; using Content.Shared.GameObjects.Components.Command; using Content.Shared.Interfaces.GameObjects.Components; using Robust.Server.GameObjects; using Robust.Server.Player; using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Timing; using Robust.Shared.ViewVariables; using Timer = Robust.Shared.Timing.Timer; namespace Content.Server.GameObjects.Components.Command { [RegisterComponent] [ComponentReference(typeof(IActivate))] public class CommunicationsConsoleComponent : SharedCommunicationsConsoleComponent, IActivate { [Dependency] private readonly IGameTiming _gameTiming = default!; [Dependency] private readonly IChatManager _chatManager = default!; private bool Powered => !Owner.TryGetComponent(out PowerReceiverComponent? receiver) || receiver.Powered; private RoundEndSystem RoundEndSystem => EntitySystem.Get(); [ViewVariables] private BoundUserInterface? UserInterface => Owner.GetUIOrNull(CommunicationsConsoleUiKey.Key); public TimeSpan LastAnnounceTime { get; private set; } = TimeSpan.Zero; public TimeSpan AnnounceCooldown { get; } = TimeSpan.FromSeconds(90); private CancellationTokenSource _announceCooldownEndedTokenSource = new(); public override void Initialize() { base.Initialize(); if (UserInterface != null) { UserInterface.OnReceiveMessage += UserInterfaceOnOnReceiveMessage; } RoundEndSystem.OnRoundEndCountdownStarted += UpdateBoundInterface; RoundEndSystem.OnRoundEndCountdownCancelled += UpdateBoundInterface; RoundEndSystem.OnRoundEndCountdownFinished += UpdateBoundInterface; RoundEndSystem.OnCallCooldownEnded += UpdateBoundInterface; } protected override void Startup() { base.Startup(); UpdateBoundInterface(); } private void UpdateBoundInterface() { if (!Deleted) { var system = RoundEndSystem; UserInterface?.SetState(new CommunicationsConsoleInterfaceState(CanAnnounce(), system.CanCall(), system.ExpectedCountdownEnd)); } } public bool CanAnnounce() { if (LastAnnounceTime == TimeSpan.Zero) { return true; } return _gameTiming.CurTime >= LastAnnounceTime + AnnounceCooldown; } public override void OnRemove() { RoundEndSystem.OnRoundEndCountdownStarted -= UpdateBoundInterface; RoundEndSystem.OnRoundEndCountdownCancelled -= UpdateBoundInterface; RoundEndSystem.OnRoundEndCountdownFinished -= UpdateBoundInterface; base.OnRemove(); } private void UserInterfaceOnOnReceiveMessage(ServerBoundUserInterfaceMessage obj) { switch (obj.Message) { case CommunicationsConsoleCallEmergencyShuttleMessage _: RoundEndSystem.RequestRoundEnd(); break; case CommunicationsConsoleRecallEmergencyShuttleMessage _: RoundEndSystem.CancelRoundEndCountdown(); break; case CommunicationsConsoleAnnounceMessage msg: if (!CanAnnounce()) { return; } _announceCooldownEndedTokenSource.Cancel(); _announceCooldownEndedTokenSource = new CancellationTokenSource(); LastAnnounceTime = _gameTiming.CurTime; Timer.Spawn(AnnounceCooldown, () => UpdateBoundInterface(), _announceCooldownEndedTokenSource.Token); UpdateBoundInterface(); var message = msg.Message.Length <= 256 ? msg.Message.Trim() : $"{msg.Message.Trim().Substring(0, 256)}..."; var author = "Unknown"; var mob = obj.Session.AttachedEntity; if (mob != null && mob.TryGetHeldId(out var id)) { author = $"{id.FullName} ({CultureInfo.CurrentCulture.TextInfo.ToTitleCase(id.JobTitle ?? string.Empty)})".Trim(); } message += $"\nSent by {author}"; _chatManager.DispatchStationAnnouncement(message, "Communications Console"); break; } } public void OpenUserInterface(IPlayerSession session) { UserInterface?.Open(session); } void IActivate.Activate(ActivateEventArgs eventArgs) { if (!eventArgs.User.TryGetComponent(out ActorComponent? actor)) return; /* if (!Powered) { return; } */ OpenUserInterface(actor.PlayerSession); } } }