Communications Console: The ECSining (#8374)
Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>
This commit is contained in:
@@ -1,157 +1,59 @@
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using Content.Server.Access.Systems;
|
||||
using Content.Server.AlertLevel;
|
||||
using Content.Server.Chat.Managers;
|
||||
using Content.Server.Power.Components;
|
||||
using Content.Server.RoundEnd;
|
||||
using Content.Server.Station.Systems;
|
||||
using Content.Server.UserInterface;
|
||||
using Content.Shared.Communications;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Timing;
|
||||
using Timer = Robust.Shared.Timing.Timer;
|
||||
|
||||
namespace Content.Server.Communications
|
||||
{
|
||||
// TODO: ECS
|
||||
[RegisterComponent]
|
||||
public sealed class CommunicationsConsoleComponent : SharedCommunicationsConsoleComponent, IEntityEventSubscriber
|
||||
public sealed class CommunicationsConsoleComponent : SharedCommunicationsConsoleComponent
|
||||
{
|
||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||
[Dependency] private readonly IChatManager _chatManager = default!;
|
||||
[Dependency] private readonly IEntityManager _entities = default!;
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
[Dependency] private readonly IEntitySystemManager _sysMan = default!;
|
||||
/// <summary>
|
||||
/// Remaining cooldown between making announcements.
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
public float AnnouncementCooldownRemaining;
|
||||
|
||||
private bool Powered => !_entities.TryGetComponent(Owner, out ApcPowerReceiverComponent? receiver) || receiver.Powered;
|
||||
/// <summary>
|
||||
/// Has the UI already been refreshed after the announcement
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
public bool AlreadyRefreshed = false;
|
||||
|
||||
private RoundEndSystem RoundEndSystem => EntitySystem.Get<RoundEndSystem>();
|
||||
private AlertLevelSystem AlertLevelSystem => EntitySystem.Get<AlertLevelSystem>();
|
||||
private StationSystem StationSystem => EntitySystem.Get<StationSystem>();
|
||||
/// <summary>
|
||||
/// Fluent ID for the announcement title
|
||||
/// If a Fluent ID isn't found, just uses the raw string
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField("title", required: true)]
|
||||
public string AnnouncementDisplayName = "comms-console-announcement-title-station";
|
||||
|
||||
[ViewVariables] private BoundUserInterface? UserInterface => Owner.GetUIOrNull(CommunicationsConsoleUiKey.Key);
|
||||
/// <summary>
|
||||
/// Announcement color
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField("color")]
|
||||
public Color AnnouncementColor = Color.Gold;
|
||||
|
||||
public TimeSpan LastAnnounceTime { get; private set; } = TimeSpan.Zero;
|
||||
public TimeSpan AnnounceCooldown { get; } = TimeSpan.FromSeconds(90);
|
||||
private CancellationTokenSource _announceCooldownEndedTokenSource = new();
|
||||
/// <summary>
|
||||
/// Time in seconds between announcement delays on a per-console basis
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField("delay")]
|
||||
public int DelayBetweenAnnouncements = 90;
|
||||
|
||||
protected override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
/// <summary>
|
||||
/// Can call or recall the shuttle
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField("canShuttle")]
|
||||
public bool CanCallShuttle = true;
|
||||
|
||||
if (UserInterface != null)
|
||||
{
|
||||
UserInterface.OnReceiveMessage += UserInterfaceOnOnReceiveMessage;
|
||||
}
|
||||
/// <summary>
|
||||
/// Announce on all grids (for nukies)
|
||||
/// </summary>
|
||||
[DataField("global")]
|
||||
public bool AnnounceGlobal = false;
|
||||
|
||||
_entityManager.EventBus.SubscribeEvent<RoundEndSystemChangedEvent>(EventSource.Local, this, (s) => UpdateBoundInterface());
|
||||
_entityManager.EventBus.SubscribeEvent<AlertLevelChangedEvent>(EventSource.Local, this, _ => UpdateBoundInterface());
|
||||
_entityManager.EventBus.SubscribeEvent<AlertLevelDelayFinishedEvent>(EventSource.Local, this, _ => UpdateBoundInterface());
|
||||
}
|
||||
|
||||
protected override void Startup()
|
||||
{
|
||||
base.Startup();
|
||||
|
||||
UpdateBoundInterface();
|
||||
}
|
||||
|
||||
private void UpdateBoundInterface()
|
||||
{
|
||||
if (!Deleted)
|
||||
{
|
||||
var system = RoundEndSystem;
|
||||
|
||||
List<string>? levels = null;
|
||||
string currentLevel = default!;
|
||||
float currentDelay = 0;
|
||||
var stationUid = StationSystem.GetOwningStation(Owner);
|
||||
if (stationUid != null)
|
||||
{
|
||||
if (_entityManager.TryGetComponent(stationUid.Value, out AlertLevelComponent? alerts)
|
||||
&& alerts.AlertLevels != null)
|
||||
{
|
||||
if (alerts.IsSelectable)
|
||||
{
|
||||
levels = new();
|
||||
foreach (var (id, detail) in alerts.AlertLevels.Levels)
|
||||
{
|
||||
if (detail.Selectable)
|
||||
{
|
||||
levels.Add(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
currentLevel = alerts.CurrentLevel;
|
||||
currentDelay = AlertLevelSystem.GetAlertLevelDelay(stationUid.Value, alerts);
|
||||
}
|
||||
}
|
||||
|
||||
UserInterface?.SetState(new CommunicationsConsoleInterfaceState(CanAnnounce(), system.CanCall(), levels, currentLevel, currentDelay, system.ExpectedCountdownEnd));
|
||||
}
|
||||
}
|
||||
|
||||
public bool CanAnnounce()
|
||||
{
|
||||
if (LastAnnounceTime == TimeSpan.Zero)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return _gameTiming.CurTime >= LastAnnounceTime + AnnounceCooldown;
|
||||
}
|
||||
|
||||
protected override void OnRemove()
|
||||
{
|
||||
_entityManager.EventBus.UnsubscribeEvent<RoundEndSystemChangedEvent>(EventSource.Local, this);
|
||||
base.OnRemove();
|
||||
}
|
||||
|
||||
private void UserInterfaceOnOnReceiveMessage(ServerBoundUserInterfaceMessage obj)
|
||||
{
|
||||
switch (obj.Message)
|
||||
{
|
||||
case CommunicationsConsoleCallEmergencyShuttleMessage _:
|
||||
RoundEndSystem.RequestRoundEnd(obj.Session.AttachedEntity);
|
||||
break;
|
||||
|
||||
case CommunicationsConsoleRecallEmergencyShuttleMessage _:
|
||||
RoundEndSystem.CancelRoundEndCountdown(obj.Session.AttachedEntity);
|
||||
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 sys = _sysMan.GetEntitySystem<IdCardSystem>();
|
||||
|
||||
var author = "Unknown";
|
||||
if (obj.Session.AttachedEntity is {Valid: true} mob && sys.TryFindIdCard(mob, out var id))
|
||||
{
|
||||
author = $"{id.FullName} ({CultureInfo.CurrentCulture.TextInfo.ToTitleCase(id.JobTitle ?? string.Empty)})".Trim();
|
||||
}
|
||||
|
||||
message += $"\nSent by {author}";
|
||||
_chatManager.DispatchStationAnnouncement(message, "Communications Console", colorOverride: Color.Gold);
|
||||
break;
|
||||
case CommunicationsConsoleSelectAlertLevelMessage alertMsg:
|
||||
var stationUid = StationSystem.GetOwningStation(Owner);
|
||||
if (stationUid != null)
|
||||
{
|
||||
AlertLevelSystem.SetLevel(stationUid.Value, alertMsg.Level, true, true);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
public BoundUserInterface? UserInterface => Owner.GetUIOrNull(CommunicationsConsoleUiKey.Key);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user