Механика вещания через консоль связи (#3070)

This commit is contained in:
Vigers Ray 2025-09-09 22:15:37 +03:00 committed by GitHub
parent dab2c2e8f5
commit 48bb8fabd7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 272 additions and 32 deletions

View file

@ -27,6 +27,7 @@ namespace Content.Client.Communications.UI
_menu.OnBroadcast += BroadcastButtonPressed;
_menu.OnAlertLevel += AlertLevelSelected;
_menu.OnEmergencyLevel += EmergencyShuttleButtonPressed;
_menu.OnToggleRelay += ToggleRelayPressed; // Sunrise-Edit
}
public void AlertLevelSelected(string level)
@ -58,6 +59,13 @@ namespace Content.Client.Communications.UI
SendMessage(new CommunicationsConsoleBroadcastMessage(message));
}
// Sunrise-Start
private void ToggleRelayPressed()
{
SendMessage(new CommunicationsConsoleToggleRelayMessage());
}
// Sunrise-End
public void CallShuttle()
{
SendMessage(new CommunicationsConsoleCallEmergencyShuttleMessage());
@ -91,6 +99,14 @@ namespace Content.Client.Communications.UI
_menu.EmergencyShuttleButton.Disabled = !_menu.CanCall;
_menu.AnnounceButton.Disabled = !_menu.CanAnnounce;
_menu.BroadcastButton.Disabled = !_menu.CanBroadcast;
// Sunrise-Start
_menu.CanRelay = commsState.CanRelay;
_menu.IsRelaying = commsState.IsRelaying;
_menu.RelayCooldownRemaining = commsState.RelayCooldownRemaining;
_menu.RelayTimeRemaining = commsState.RelayTimeRemaining;
_menu.UpdateRelayUi();
// Sunrise-End
}
}
}

View file

@ -9,23 +9,25 @@
VerticalExpand="True"
Margin="6 6 6 5">
<TextEdit Name="MessageInput"
VerticalExpand="True"
HorizontalExpand="True"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
MinHeight="100"/>
<!-- ButtonsPart -->
<BoxContainer Orientation="Vertical"
VerticalAlignment="Bottom"
SeparationOverride="4">
Margin="0 2">
<!-- AnnouncePart -->
<BoxContainer Orientation="Vertical"
Margin="0 2">
<controls:StripeBack>
<BoxContainer Orientation="Horizontal">
<Label HorizontalExpand="True" Text="{Loc 'comms-console-menu-announcement-header'}"
Name="AnnouncementLabel" VAlign="Center"
StyleClasses="LabelHeading" Align="Center"/>
</BoxContainer>
</controls:StripeBack>
<Button Name="AnnounceButton"
<TextEdit Name="MessageInput"
VerticalExpand="True"
HorizontalExpand="True"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
MinHeight="100"/>
<Button Name="AnnounceButton"
Access="Public"
Text="{Loc 'comms-console-menu-announcement-button'}"
ToolTip="{Loc 'comms-console-menu-announcement-button-tooltip'}"
@ -33,30 +35,66 @@
Margin="0 0 1 0"
Disabled="True"/>
<Button Name="BroadcastButton"
<Button Name="BroadcastButton"
Access="Public"
Text="{Loc 'comms-console-menu-broadcast-button'}"
ToolTip="{Loc 'comms-console-menu-broadcast-button-tooltip'}"
StyleClasses="OpenBoth"/>
</BoxContainer>
<OptionButton Name="AlertLevelButton"
<BoxContainer Orientation="Vertical"
Margin="0 2">
<controls:StripeBack>
<BoxContainer Orientation="Horizontal">
<Label HorizontalExpand="True" Text="{Loc 'comms-console-menu-alert-level-header'}"
Name="AlertLevelLabel" VAlign="Center"
StyleClasses="LabelHeading" Align="Center"/>
</BoxContainer>
</controls:StripeBack>
<OptionButton Name="AlertLevelButton"
Access="Public"
ToolTip="{Loc 'comms-console-menu-alert-level-button-tooltip'}"
StyleClasses="OpenRight"/>
</BoxContainer>
<BoxContainer Orientation="Vertical"
Margin="0 2">
<controls:StripeBack>
<BoxContainer Orientation="Horizontal">
<Label HorizontalExpand="True" Text="{Loc 'comms-console-menu-relay-header'}"
Name="RelayLabel" VAlign="Center"
StyleClasses="LabelHeading" Align="Center"/>
</BoxContainer>
</controls:StripeBack>
<Button Name="RelayButton"
Access="Public"
ToolTip="{Loc 'comms-console-menu-alert-level-button-tooltip'}"
StyleClasses="OpenRight"/>
Text="{Loc 'comms-console-menu-relay-button'}"
ToolTip="{Loc 'comms-console-menu-relay-button-tooltip'}"
StyleClasses="OpenBoth"/>
<RichTextLabel Name="RelayStatusLabel"/>
</BoxContainer>
</BoxContainer>
<BoxContainer Orientation="Vertical"
Margin="0 2">
<!-- EmergencyPart -->
<BoxContainer Orientation="Vertical"
SeparationOverride="6">
<controls:StripeBack>
<BoxContainer Orientation="Horizontal">
<Label HorizontalExpand="True" Text="{Loc 'comms-console-menu-emergency-header'}"
Name="EmergencyLabel" VAlign="Center"
StyleClasses="LabelHeading" Align="Center"/>
</BoxContainer>
</controls:StripeBack>
<RichTextLabel Name="CountdownLabel"/>
<RichTextLabel Name="CountdownLabel"/>
<Button Name="EmergencyShuttleButton"
Access="Public"
<Button Name="EmergencyShuttleButton"
Access="Public"
Text="Placeholder Text"
ToolTip="{Loc 'comms-console-menu-emergency-shuttle-button-tooltip'}"/>
</BoxContainer>
</BoxContainer>
</BoxContainer>
</controls:FancyWindow>

View file

@ -19,6 +19,12 @@ namespace Content.Client.Communications.UI
public bool CanAnnounce;
public bool CanBroadcast;
public bool CanCall;
// Sunrise-Start
public bool CanRelay;
public bool IsRelaying;
public float RelayCooldownRemaining;
public float RelayTimeRemaining;
// Sunrise-End
public bool AlertLevelSelectable;
public bool CountdownStarted;
public string CurrentLevel = string.Empty;
@ -28,6 +34,7 @@ namespace Content.Client.Communications.UI
public event Action<string>? OnAlertLevel;
public event Action<string>? OnAnnounce;
public event Action<string>? OnBroadcast;
public event Action? OnToggleRelay; // Sunrise-Edit
public CommunicationsConsoleMenu()
{
@ -58,6 +65,11 @@ namespace Content.Client.Communications.UI
BroadcastButton.OnPressed += _ => OnBroadcast?.Invoke(Rope.Collapse(MessageInput.TextRope));
BroadcastButton.Disabled = !CanBroadcast;
// Sunrise-Start
RelayButton.OnPressed += _ => OnToggleRelay?.Invoke();
RelayButton.Disabled = !CanRelay;
// Sunrise-End
AlertLevelButton.OnItemSelected += args =>
{
var metadata = AlertLevelButton.GetItemMetadata(args.Id);
@ -78,6 +90,7 @@ namespace Content.Client.Communications.UI
{
base.FrameUpdate(args);
UpdateCountdown();
UpdateRelayUi(); // Sunrise-Edit
}
// The current alert could make levels unselectable, so we need to ensure that the UI reacts properly.
@ -122,6 +135,7 @@ namespace Content.Client.Communications.UI
if (!CountdownStarted)
{
CountdownLabel.SetMessage(string.Empty);
CountdownLabel.Visible = false; // Sunrise-Edit
EmergencyShuttleButton.Text = Loc.GetString("comms-console-menu-call-shuttle");
return;
}
@ -132,6 +146,36 @@ namespace Content.Client.Communications.UI
var infoText = Loc.GetString($"comms-console-menu-time-remaining",
("time", diff.ToString(@"hh\:mm\:ss", CultureInfo.CurrentCulture)));
CountdownLabel.SetMessage(infoText);
CountdownLabel.Visible = true; // Sunrise-Edit
}
// Sunrise-Start
public void UpdateRelayUi()
{
RelayButton.Disabled = !CanRelay && !IsRelaying;
if (IsRelaying)
{
RelayButton.Text = Loc.GetString("comms-console-menu-relay-stop");
var remaining = TimeSpan.FromSeconds(Math.Max(0f, RelayTimeRemaining));
var text = Loc.GetString("comms-console-menu-relay-time-left", ("time", remaining.ToString(@"mm\:ss", CultureInfo.CurrentCulture)));
RelayStatusLabel.Visible = true;
RelayStatusLabel.SetMessage(text);
}
else if (RelayCooldownRemaining > 0f)
{
var remaining = TimeSpan.FromSeconds(RelayCooldownRemaining);
RelayButton.Text = Loc.GetString("comms-console-menu-relay-button");
RelayStatusLabel.SetMessage(Loc.GetString("comms-console-menu-relay-cooldown", ("time", remaining.ToString(@"mm\:ss", CultureInfo.CurrentCulture))));
RelayStatusLabel.Visible = true;
RelayButton.Disabled = true;
}
else
{
RelayButton.Text = Loc.GetString("comms-console-menu-relay-button");
RelayStatusLabel.Visible = false;
RelayStatusLabel.SetMessage(string.Empty);
}
}
// Sunrise-End
}
}

View file

@ -497,7 +497,7 @@ public sealed partial class ChatSystem : SharedChatSystem
// Sunrise-end
// Sunrise-start - Use speaker network for station announcements
if (playTts && (playDefault || announcementSound != null))
if (playTts)
{
if (playDefault && announcementSound == null)
announcementSound = new SoundPathSpecifier(DefaultAnnouncementSound);

View file

@ -80,6 +80,24 @@ namespace Content.Server.Communications
// Sunrise-Start
[DataField("announceVoice", customTypeSerializer:typeof(PrototypeIdSerializer<TTSVoicePrototype>))]
public string AnnounceVoice = "Hanson";
// Sunrise-Start
[ViewVariables]
public bool IsRelaying;
[ViewVariables]
public float RelayTimeRemaining;
[ViewVariables]
public float RelayCooldownRemaining;
[DataField]
public float RelayDuration = 60f;
[DataField]
public float RelayCooldown = 300f;
[DataField]
public float RelayRange = 7f;
// Sunrise-End
}
}

View file

@ -3,11 +3,12 @@ using Content.Server.AlertLevel;
using Content.Server.Chat.Systems;
using Content.Server.DeviceNetwork.Systems;
using Content.Server.Popups;
using Content.Server.Power.EntitySystems;
using Content.Server.RoundEnd;
using Content.Server.Screens.Components;
using Content.Server.Shuttles.Systems;
using Content.Server.Station.Systems;
using Content.Shared._Sunrise.TTS; // Sunrise-edit
using Content.Shared._Sunrise.TTS;
using Content.Shared.Access.Components;
using Content.Shared.Access.Systems;
using Content.Shared.CCVar;
@ -18,6 +19,9 @@ using Content.Shared.DeviceNetwork;
using Content.Shared.DeviceNetwork.Components;
using Content.Shared.IdentityManagement;
using Content.Shared.Popups;
using Content.Shared.Power.EntitySystems;
using Content.Shared.Speech;
using Content.Shared.Speech.Components;
using Robust.Server.GameObjects;
using Robust.Shared.Configuration;
@ -55,6 +59,11 @@ namespace Content.Server.Communications
// On console init, set cooldown
SubscribeLocalEvent<CommunicationsConsoleComponent, MapInitEvent>(OnCommunicationsConsoleMapInit);
// Sunrise-Start
SubscribeLocalEvent<CommunicationsConsoleComponent, CommunicationsConsoleToggleRelayMessage>(OnToggleRelayMessage);
SubscribeLocalEvent<CommunicationsConsoleComponent, ListenEvent>(OnEntitySpokeNearbyRelay);
// Sunrise-End
}
public override void Update(float frameTime)
@ -68,6 +77,23 @@ namespace Content.Server.Communications
comp.AnnouncementCooldownRemaining -= frameTime;
}
// Sunrise-Start
if (comp.RelayCooldownRemaining > 0f)
comp.RelayCooldownRemaining -= frameTime;
if (comp.IsRelaying)
{
if (!this.IsPowered(uid, EntityManager))
StopRelay(uid, comp, announce: true);
else
{
comp.RelayTimeRemaining -= frameTime;
if (comp.RelayTimeRemaining <= 0f)
StopRelay(uid, comp, announce: true);
}
}
// Sunrise-End
comp.UIUpdateAccumulator += frameTime;
if (comp.UIUpdateAccumulator < UIUpdateInterval)
@ -159,13 +185,20 @@ namespace Content.Server.Communications
}
}
var canRelay = comp.RelayCooldownRemaining <= 0f && !comp.IsRelaying && this.IsPowered(uid, EntityManager); // Sunrise-Edit
_uiSystem.SetUiState(uid, CommunicationsConsoleUiKey.Key, new CommunicationsConsoleInterfaceState(
CanAnnounce(comp),
CanCallOrRecall(comp),
levels,
currentLevel,
currentDelay,
_roundEndSystem.ExpectedCountdownEnd
_roundEndSystem.ExpectedCountdownEnd,
// Sunrise-Start
canRelay,
comp.IsRelaying,
MathF.Max(0f, comp.RelayCooldownRemaining),
MathF.Max(0f, comp.RelayTimeRemaining)
// Sunrise-End
));
}
@ -338,6 +371,67 @@ namespace Content.Server.Communications
_roundEndSystem.CancelRoundEndCountdown(uid);
_adminLogger.Add(LogType.Action, LogImpact.High, $"{ToPrettyString(message.Actor):player} has recalled the shuttle.");
}
// Sunrise-Start
private void OnToggleRelayMessage(EntityUid uid, CommunicationsConsoleComponent comp, CommunicationsConsoleToggleRelayMessage message)
{
if (comp.IsRelaying)
{
StopRelay(uid, comp, announce: true);
return;
}
if (comp.RelayCooldownRemaining > 0f)
return;
if (!this.IsPowered(uid, EntityManager))
return;
comp.IsRelaying = true;
comp.RelayTimeRemaining = comp.RelayDuration;
UpdateCommsConsoleInterface(uid, comp);
EnsureComp<ActiveListenerComponent>(uid).Range = comp.RelayRange;
var startText = Loc.GetString("comms-console-relay-started");
var title = Loc.GetString(comp.Title);
_chatSystem.DispatchStationAnnouncement(uid, startText, sender: title, playDefault: true, playTts: true, colorOverride: comp.Color, announceVoice: comp.AnnounceVoice, announcementSound: comp.Sound);
}
private void OnEntitySpokeNearbyRelay(EntityUid uid, CommunicationsConsoleComponent comp, ListenEvent ev)
{
if (!this.IsPowered(uid, EntityManager))
return;
var voice = comp.AnnounceVoice;
if (TryComp<TTSComponent>(ev.Source, out var ttsComponent))
{
voice = ttsComponent.VoicePrototypeId;
}
_chatSystem.DispatchStationAnnouncement(uid, ev.Message, sender: Loc.GetString(comp.Title), playDefault: false, playTts: true, colorOverride: comp.Color, announceVoice: voice);
}
private void StopRelay(EntityUid uid, CommunicationsConsoleComponent comp, bool announce)
{
if (!comp.IsRelaying && comp.RelayCooldownRemaining > 0f)
{
UpdateCommsConsoleInterface(uid, comp);
return;
}
comp.IsRelaying = false;
comp.RelayTimeRemaining = 0f;
comp.RelayCooldownRemaining = comp.RelayCooldown;
UpdateCommsConsoleInterface(uid, comp);
RemCompDeferred<ActiveListenerComponent>(uid);
if (announce)
{
var stopText = Loc.GetString("comms-console-relay-stopped");
var title = Loc.GetString(comp.Title);
_chatSystem.DispatchStationAnnouncement(uid, stopText, sender: title, playDefault: true, playTts: true, colorOverride: comp.Color, announceVoice: comp.AnnounceVoice, announcementSound: comp.Sound);
}
}
// Sunrise-End
}
/// <summary>

View file

@ -18,8 +18,14 @@ namespace Content.Shared.Communications
public List<string>? AlertLevels;
public string CurrentAlert;
public float CurrentAlertDelay;
// Sunrise-Start
public readonly bool CanRelay;
public readonly bool IsRelaying;
public readonly float RelayCooldownRemaining;
public readonly float RelayTimeRemaining;
// Sunrise-End
public CommunicationsConsoleInterfaceState(bool canAnnounce, bool canCall, List<string>? alertLevels, string currentAlert, float currentAlertDelay, TimeSpan? expectedCountdownEnd = null)
public CommunicationsConsoleInterfaceState(bool canAnnounce, bool canCall, List<string>? alertLevels, string currentAlert, float currentAlertDelay, TimeSpan? expectedCountdownEnd = null, bool canRelay = false, bool isRelaying = false, float relayCooldownRemaining = 0f, float relayTimeRemaining = 0f) // Sunrise-Edit
{
CanAnnounce = canAnnounce;
CanCall = canCall;
@ -28,6 +34,12 @@ namespace Content.Shared.Communications
AlertLevels = alertLevels;
CurrentAlert = currentAlert;
CurrentAlertDelay = currentAlertDelay;
// Sunrise-Start
CanRelay = canRelay;
IsRelaying = isRelaying;
RelayCooldownRemaining = relayCooldownRemaining;
RelayTimeRemaining = relayTimeRemaining;
// Sunrise-End
}
}
@ -63,6 +75,13 @@ namespace Content.Shared.Communications
}
}
// Sunrise-Start
[Serializable, NetSerializable]
public sealed class CommunicationsConsoleToggleRelayMessage : BoundUserInterfaceMessage
{
}
// Sunrise-End
[Serializable, NetSerializable]
public sealed class CommunicationsConsoleCallEmergencyShuttleMessage : BoundUserInterfaceMessage
{

View file

@ -1 +1,12 @@
comms-console-announcement-title-prison = Космическая тюрьма
comms-console-announcement-title-prison = Космическая тюрьма
comms-console-menu-relay-button = Включить
comms-console-menu-relay-button-tooltip = Включить или выключить вещание голоса на динамики.
comms-console-menu-relay-stop = Выключить
comms-console-menu-relay-cooldown = Перезарядка: { $time }.
comms-console-menu-announcement-header = Оповещения
comms-console-menu-relay-header = Вещание
comms-console-menu-relay-time-left = Осталось: { $time }
comms-console-menu-emergency-header = Эвакуация
comms-console-menu-alert-level-header = Код угрозы
comms-console-relay-started = Начато вещание через консоль связи.
comms-console-relay-stopped = Вещание через консоль связи остановлено.