Deep Space Com

This commit is contained in:
keslik
2025-03-05 11:30:37 +03:00
parent 5ae1b526ed
commit bc5583a128
11 changed files with 361 additions and 4 deletions

View File

@@ -0,0 +1,57 @@
using Content.Shared._White.DeepSpaceCom;
using JetBrains.Annotations;
namespace Content.Client._White.DeepSpaceCom;
[UsedImplicitly]
public sealed class DeepSpaceComBoundUI : BoundUserInterface
{
[ViewVariables]
private DeepSpaceComMenu? _menu;
public DeepSpaceComBoundUI(EntityUid owner, Enum uiKey) : base(owner, uiKey)
{
}
protected override void Open()
{
base.Open();
_menu = new();
_menu.OnMicPressed += enabled =>
{
SendMessage(new ToggleDeepSpaceComMicrophoneMessage(enabled));
};
_menu.OnSpeakerPressed += enabled =>
{
SendMessage(new ToggleDeepSpaceComSpeakerMessage(enabled));
};
_menu.OnChannelSelected += channel =>
{
SendMessage(new SelectDeepSpaceComChannelMessage(channel));
};
_menu.OnClose += Close;
_menu.OpenCentered();
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (!disposing)
return;
_menu?.Close();
}
protected override void UpdateState(BoundUserInterfaceState state)
{
base.UpdateState(state);
if (state is not DeepSpaceComBoundUIState msg)
return;
_menu?.Update(msg);
}
}

View File

@@ -0,0 +1,29 @@
<controls:FancyWindow xmlns="https://spacestation14.io"
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
Title="{Loc 'deepspacecom-menu-title'}"
MinSize="355 150"
SetSize="355 150">
<BoxContainer Orientation="Vertical"
HorizontalExpand="True"
VerticalExpand="True"
Margin="5 0 5 0">
<BoxContainer Orientation="Horizontal" HorizontalExpand="True" VerticalExpand="True">
<BoxContainer Orientation="Vertical" HorizontalExpand="True" VerticalExpand="False" HorizontalAlignment="Left">
<Label Text="{Loc 'deepspacecom-channel-label'}" HorizontalAlignment="Center"/>
<OptionButton Name="ChannelOptions" VerticalExpand="True" MinWidth="125"/>
</BoxContainer>
</BoxContainer>
<Control MinHeight="10"/>
<BoxContainer Orientation="Horizontal" HorizontalExpand="True" HorizontalAlignment="Right" Margin="5 0 5 5">
<Button Name="MicButton" ToggleMode="True" Text="{Loc 'deepspacecom-button-text-mic'}" StyleClasses="OpenRight" MinWidth="70"/>
<Button Name="SpeakerButton" ToggleMode="True" Text="{Loc 'deepspacecom-button-text-speaker'}" StyleClasses="OpenLeft" MinWidth="70"/>
</BoxContainer>
<BoxContainer Orientation="Vertical">
<PanelContainer StyleClasses="LowDivider" />
<BoxContainer Orientation="Horizontal" Margin="10 2 5 0" VerticalAlignment="Bottom">
<Label Text="{Loc 'deepspacecom-flavor-text'}" StyleClasses="WindowFooterText"
HorizontalAlignment="Right" HorizontalExpand="True" Margin="0 0 5 0" />
</BoxContainer>
</BoxContainer>
</BoxContainer>
</controls:FancyWindow>

View File

@@ -0,0 +1,59 @@
using Content.Client.UserInterface.Controls;
using Content.Shared._White.DeepSpaceCom;
using Content.Shared.Radio;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Prototypes;
namespace Content.Client._White.DeepSpaceCom;
[GenerateTypedNameReferences]
public sealed partial class DeepSpaceComMenu : FancyWindow
{
[Dependency] private readonly IPrototypeManager _prototype = default!;
public event Action<bool>? OnMicPressed;
public event Action<bool>? OnSpeakerPressed;
public event Action<string>? OnChannelSelected;
private readonly List<string> _channels = new();
public DeepSpaceComMenu()
{
RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this);
MicButton.OnPressed += args => OnMicPressed?.Invoke(args.Button.Pressed);
SpeakerButton.OnPressed += args => OnSpeakerPressed?.Invoke(args.Button.Pressed);
}
public void Update(DeepSpaceComBoundUIState state)
{
MicButton.Pressed = state.MicEnabled;
SpeakerButton.Pressed = state.SpeakerEnabled;
ChannelOptions.Clear();
_channels.Clear();
for (var i = 0; i < state.AvailableChannels.Count; i++)
{
var channel = state.AvailableChannels[i];
if (!_prototype.TryIndex<RadioChannelPrototype>(channel, out var prototype))
continue;
_channels.Add(channel);
ChannelOptions.AddItem(Loc.GetString(prototype.Name), i);
if (channel == state.SelectedChannel)
ChannelOptions.Select(i);
}
ChannelOptions.OnItemSelected += args =>
{
ChannelOptions.SelectId(args.Id);
OnChannelSelected?.Invoke(_channels[args.Id]);
MicButton.Pressed = false;
SpeakerButton.Pressed = false;
OnMicPressed?.Invoke(false);
OnSpeakerPressed?.Invoke(false);
};
}
}

View File

@@ -4,6 +4,7 @@ using Content.Server.Popups;
using Content.Server.Power.Components;
using Content.Server.Power.EntitySystems;
using Content.Server.Radio.Components;
using Content.Shared._White.DeepSpaceCom; // WD
using Content.Server.Speech;
using Content.Server.Speech.Components;
using Content.Shared.UserInterface;
@@ -51,6 +52,11 @@ public sealed class RadioDeviceSystem : EntitySystem
SubscribeLocalEvent<IntercomComponent, ToggleIntercomMicMessage>(OnToggleIntercomMic);
SubscribeLocalEvent<IntercomComponent, ToggleIntercomSpeakerMessage>(OnToggleIntercomSpeaker);
SubscribeLocalEvent<IntercomComponent, SelectIntercomChannelMessage>(OnSelectIntercomChannel);
SubscribeLocalEvent<DeepSpaceComComponent, BeforeActivatableUIOpenEvent>(OnBeforeDeepSpaceComUiOpen); // WD start
SubscribeLocalEvent<DeepSpaceComComponent, ToggleDeepSpaceComMicrophoneMessage>(OnToggleDeepSpaceComMic);
SubscribeLocalEvent<DeepSpaceComComponent, ToggleDeepSpaceComSpeakerMessage>(OnToggleDeepSpaceComSpeaker);
SubscribeLocalEvent<DeepSpaceComComponent, SelectDeepSpaceComChannelMessage>(OnSelectDeepSpaceComChannel); // WD end
}
public override void Update(float frameTime)
@@ -264,4 +270,55 @@ public sealed class RadioDeviceSystem : EntitySystem
var state = new IntercomBoundUIState(micEnabled, speakerEnabled, availableChannels, selectedChannel);
_ui.SetUiState(uid, IntercomUiKey.Key, state);
}
private void OnBeforeDeepSpaceComUiOpen(EntityUid uid, DeepSpaceComComponent component, BeforeActivatableUIOpenEvent args) // WD start
{
UpdateDeepSpaceComUi(uid, component);
}
private void OnToggleDeepSpaceComMic(EntityUid uid, DeepSpaceComComponent component, ToggleDeepSpaceComMicrophoneMessage args)
{
if (component.RequiresPower && !this.IsPowered(uid, EntityManager))
return;
SetMicrophoneEnabled(uid, args.Actor, args.Enabled, true);
UpdateDeepSpaceComUi(uid, component);
}
private void OnToggleDeepSpaceComSpeaker(EntityUid uid, DeepSpaceComComponent component, ToggleDeepSpaceComSpeakerMessage args)
{
if (component.RequiresPower && !this.IsPowered(uid, EntityManager))
return;
SetSpeakerEnabled(uid, args.Actor, args.Enabled, true);
UpdateDeepSpaceComUi(uid, component);
}
private void OnSelectDeepSpaceComChannel(EntityUid uid, DeepSpaceComComponent component, SelectDeepSpaceComChannelMessage args)
{
if (component.RequiresPower && !this.IsPowered(uid, EntityManager))
return;
if (!_protoMan.TryIndex<RadioChannelPrototype>(args.Channel, out _) || !component.SupportedChannels.Contains(args.Channel))
return;
if (TryComp<RadioMicrophoneComponent>(uid, out var mic))
mic.BroadcastChannel = args.Channel;
if (TryComp<RadioSpeakerComponent>(uid, out var speaker))
speaker.Channels = new(){ args.Channel };
UpdateDeepSpaceComUi(uid, component);
}
private void UpdateDeepSpaceComUi(EntityUid uid, DeepSpaceComComponent component)
{
var micComp = CompOrNull<RadioMicrophoneComponent>(uid);
var speakerComp = CompOrNull<RadioSpeakerComponent>(uid);
var micEnabled = micComp?.Enabled ?? false;
var speakerEnabled = speakerComp?.Enabled ?? false;
var availableChannels = component.SupportedChannels;
var selectedChannel = micComp?.BroadcastChannel ?? SharedChatSystem.CommonChannel;
var state = new DeepSpaceComBoundUIState(micEnabled, speakerEnabled, availableChannels, selectedChannel);
_ui.SetUiState(uid, DeepSpaceComUiKey.Key, state);
} // WD end
}

View File

@@ -3,6 +3,7 @@ using Content.Server.Chat.Systems;
using Content.Server.Power.Components;
using Content.Server.Radio.Components;
using Content.Server.VoiceMask;
using Content.Shared._White.DeepSpaceCom; // WD
using Content.Shared.Chat;
using Content.Shared.Database;
using Content.Shared.Radio;
@@ -127,12 +128,13 @@ public sealed class RadioSystem : EntitySystem
var radioQuery = EntityQueryEnumerator<ActiveRadioComponent, TransformComponent>();
while (canSend && radioQuery.MoveNext(out var receiver, out var radio, out var transform))
{
if (!radio.ReceiveAllChannels)
if (!radio.ReceiveAllChannels) // WD start
{
if (!radio.Channels.Contains(channel.ID) || (TryComp<IntercomComponent>(receiver, out var intercom) &&
!intercom.SupportedChannels.Contains(channel.ID)))
if (!radio.Channels.Contains(channel.ID) ||
(TryComp<DeepSpaceComComponent>(receiver, out var deepSpaceCom) && !deepSpaceCom.SupportedChannels.Contains(channel.ID)) ||
(TryComp<IntercomComponent>(receiver, out var intercom) && !intercom.SupportedChannels.Contains(channel.ID)))
continue;
}
} // WD end
if (!channel.LongRange && transform.MapID != sourceMapId && !radio.GlobalReceive)
continue;

View File

@@ -0,0 +1,15 @@
using Content.Shared.Radio;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
using Robust.Shared.GameStates;
namespace Content.Shared._White.DeepSpaceCom;
[RegisterComponent, NetworkedComponent]
public sealed partial class DeepSpaceComComponent : Component
{
[DataField("requiresPower"), ViewVariables(VVAccess.ReadWrite)]
public bool RequiresPower = true;
[DataField("supportedChannels", customTypeSerializer: typeof(PrototypeIdListSerializer<RadioChannelPrototype>))]
public List<string> SupportedChannels = new();
}

View File

@@ -0,0 +1,59 @@
using Robust.Shared.Serialization;
namespace Content.Shared._White.DeepSpaceCom;
[Serializable, NetSerializable]
public enum DeepSpaceComUiKey
{
Key
}
[Serializable, NetSerializable]
public sealed class DeepSpaceComBoundUIState : BoundUserInterfaceState
{
public bool MicEnabled;
public bool SpeakerEnabled;
public List<string> AvailableChannels;
public string SelectedChannel;
public DeepSpaceComBoundUIState(bool micEnabled, bool speakerEnabled, List<string> availableChannels, string selectedChannel)
{
MicEnabled = micEnabled;
SpeakerEnabled = speakerEnabled;
AvailableChannels = availableChannels;
SelectedChannel = selectedChannel;
}
}
[Serializable, NetSerializable]
public sealed class ToggleDeepSpaceComMicrophoneMessage : BoundUserInterfaceMessage
{
public bool Enabled;
public ToggleDeepSpaceComMicrophoneMessage(bool enabled)
{
Enabled = enabled;
}
}
[Serializable, NetSerializable]
public sealed class ToggleDeepSpaceComSpeakerMessage : BoundUserInterfaceMessage
{
public bool Enabled;
public ToggleDeepSpaceComSpeakerMessage(bool enabled)
{
Enabled = enabled;
}
}
[Serializable, NetSerializable]
public sealed class SelectDeepSpaceComChannelMessage : BoundUserInterfaceMessage
{
public string Channel;
public SelectDeepSpaceComChannelMessage(string channel)
{
Channel = channel;
}
}

View File

@@ -0,0 +1,7 @@
ent-ComputerDeepSpaceCom = консоль дальней связи
.desc = Дальняя космическая связь обеспечивает быстрый обмен сообщениями почти на любом расстоянии. Корпорация слышит!
ent-DeepSpaceComComputerCircuitboard = печатная плата пульта дальней связи
.desc = Печатная плата для пульта дальней космической связи.
chat-radio-deepspace = Дальняя связь

View File

@@ -0,0 +1,5 @@
deepspacecom-menu-title = Пульт дальней космической связи
deepspacecom-channel-label = Частота:
deepspacecom-button-text-mic = Микрофон
deepspacecom-button-text-speaker = Динамик
deepspacecom-flavor-text = Поиск сигналов...

View File

@@ -0,0 +1,61 @@
- type: entity
parent: BaseComputer
id: ComputerDeepSpaceCom
name: deep space communications desk
description: A computer.
components:
- type: ApcPowerReceiver
- type: Electrified
enabled: false
usesApcPower: true
- type: RadioMicrophone
powerRequired: true
unobstructedRequired: true
listenRange: 2
toggleOnInteract: false
- type: RadioSpeaker
toggleOnInteract: false
- type: DeepSpaceCom
supportedChannels:
- DeepSpace
- Common
- type: TTS # check tts work
id: Sentrybot
- type: Speech
speechVerb: Robotic
- type: Sprite # replace sprites in future
layers:
- map: ["computerLayerBody"]
state: computer
- map: ["computerLayerKeyboard"]
state: generic_keyboard
- map: ["computerLayerScreen"]
state: comm
- map: ["computerLayerKeys"]
state: generic_keys
- type: ActivatableUI
key: enum.DeepSpaceComUiKey.Key
- type: UserInterface
interfaces:
enum.DeepSpaceComUiKey.Key:
type: DeepSpaceComBoundUI
- type: Computer
board: DeepSpaceComComputerCircuitboard
- type: PointLight
radius: 1.5
energy: 1.6
color: "#3c5eb5"
- type: Damageable
damageContainer: StructuralInorganic
damageModifierSet: StrongMetallic
- type: entity
parent: BaseComputerCircuitboard
id: DeepSpaceComComputerCircuitboard
name: deepspacecom computer board
description: A computer printed circuit board for a DeepSpaceCom desk.
components:
- type: Sprite
state: cpu_command
- type: ComputerBoard
prototype: ComputerDeepSpaceCom

View File

@@ -118,3 +118,9 @@
color: "#f6ce64"
# long range since otherwise it'd defeat the point of a handheld radio independent of telecomms
longRange: true
- type: radioChannel # WD start
id: DeepSpace
name: chat-radio-deepspace
frequency: 1501
longRange: true # WD end