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:
Veritius
2022-06-03 21:37:35 +10:00
committed by GitHub
parent c6d20e6ccf
commit 237cb3d0b4
33 changed files with 608 additions and 249 deletions

View File

@@ -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);
}
}