diff --git a/Content.Server/Radio/EntitySystems/TelecomSystem.cs b/Content.Server/Radio/EntitySystems/TelecomSystem.cs new file mode 100644 index 0000000000..b4d8897a73 --- /dev/null +++ b/Content.Server/Radio/EntitySystems/TelecomSystem.cs @@ -0,0 +1,5 @@ +namespace Content.Server.Radio.EntitySystems; + +public sealed class TelecomSystem : EntitySystem +{ +} diff --git a/Content.Shared/Radio/Components/TelecomServerComponent.cs b/Content.Shared/Radio/Components/TelecomServerComponent.cs new file mode 100644 index 0000000000..2aa003a1e7 --- /dev/null +++ b/Content.Shared/Radio/Components/TelecomServerComponent.cs @@ -0,0 +1,6 @@ +namespace Content.Shared.Radio.Components; + +[RegisterComponent] +public sealed class TelecomServerComponent : Component +{ +} \ No newline at end of file diff --git a/Content.Shared/Radio/EntitySystems/EncryptionKeySystem.cs b/Content.Shared/Radio/EntitySystems/EncryptionKeySystem.cs index e3c60b99f9..96e7863c86 100644 --- a/Content.Shared/Radio/EntitySystems/EncryptionKeySystem.cs +++ b/Content.Shared/Radio/EntitySystems/EncryptionKeySystem.cs @@ -8,7 +8,6 @@ using Content.Shared.Radio.Components; using Content.Shared.Tools; using Content.Shared.Tools.Components; using Robust.Shared.Containers; -using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Timing; @@ -56,7 +55,7 @@ public sealed class EncryptionKeySystem : EntitySystem } // if tool use ever gets predicted this needs changing. - _popupSystem.PopupEntity(Loc.GetString("headset-encryption-keys-all-extracted"), uid, args.User); + _popupSystem.PopupEntity(Loc.GetString("encryption-keys-all-extracted"), uid, args.User); _audio.PlayPvs(component.KeyExtractionSound, uid); component.Removing = false; } @@ -89,45 +88,55 @@ public sealed class EncryptionKeySystem : EntitySystem private void OnInteractUsing(EntityUid uid, EncryptionKeyHolderComponent component, InteractUsingEvent args) { - if (!TryComp(uid, out var storage) || args.Handled || component.Removing) + if (!TryComp(uid, out var _) || args.Handled || component.Removing) return; - + if (!component.KeysUnlocked) + { + if (_timing.IsFirstTimePredicted) + _popupSystem.PopupEntity(Loc.GetString("encryption-keys-are-locked"), uid, args.User); + return; + } if (TryComp(args.Used, out var key)) { - args.Handled = true; + TryInsertKey(uid, component, args); + } + else + { + TryRemoveKey(uid, component, args); + } + } - if (!component.KeysUnlocked) - { - if (_timing.IsFirstTimePredicted) - _popupSystem.PopupEntity(Loc.GetString("headset-encryption-keys-are-locked"), uid, Filter.Local(), false); - return; - } + private void TryInsertKey(EntityUid uid, EncryptionKeyHolderComponent component, InteractUsingEvent args) + { + args.Handled = true; - if (component.KeySlots <= component.KeyContainer.ContainedEntities.Count) - { - if (_timing.IsFirstTimePredicted) - _popupSystem.PopupEntity(Loc.GetString("headset-encryption-key-slots-already-full"), uid, Filter.Local(), false); - return; - } - - if (component.KeyContainer.Insert(args.Used)) - { - if (_timing.IsFirstTimePredicted) - _popupSystem.PopupEntity(Loc.GetString("headset-encryption-key-successfully-installed"), uid, Filter.Local(), false); - _audio.PlayPredicted(component.KeyInsertionSound, args.Target, args.User); - return; - } + if (component.KeySlots <= component.KeyContainer.ContainedEntities.Count) + { + if (_timing.IsFirstTimePredicted) + _popupSystem.PopupEntity(Loc.GetString("encryption-key-slots-already-full"), uid, args.User); + return; } + if (component.KeyContainer.Insert(args.Used)) + { + if (_timing.IsFirstTimePredicted) + _popupSystem.PopupEntity(Loc.GetString("encryption-key-successfully-installed"), uid, args.User); + _audio.PlayPredicted(component.KeyInsertionSound, args.Target, args.User); + return; + } + } + + private void TryRemoveKey(EntityUid uid, EncryptionKeyHolderComponent component, InteractUsingEvent args) + { if (!TryComp(args.Used, out var tool) || !tool.Qualities.Contains(component.KeysExtractionMethod)) return; - + args.Handled = true; if (component.KeyContainer.ContainedEntities.Count == 0) { if (_timing.IsFirstTimePredicted) - _popupSystem.PopupEntity(Loc.GetString("headset-encryption-keys-no-keys"), uid, Filter.Local(), false); + _popupSystem.PopupEntity(Loc.GetString("encryption-keys-no-keys"), uid, args.User); return; } @@ -136,8 +145,7 @@ public sealed class EncryptionKeySystem : EntitySystem var toolEvData = new ToolEventData(new EncryptionRemovalFinishedEvent(args.User), cancelledEv: new EncryptionRemovalCancelledEvent(), targetEntity: uid); - if(!_toolSystem.UseTool(args.Used, args.User, uid, 1f, new[] { component.KeysExtractionMethod }, toolEvData, toolComponent: tool)) - return; + _toolSystem.UseTool(args.Used, args.User, uid, 1f, new[] { component.KeysExtractionMethod }, toolEvData, toolComponent: tool); } private void OnStartup(EntityUid uid, EncryptionKeyHolderComponent component, ComponentStartup args) @@ -153,14 +161,14 @@ public sealed class EncryptionKeySystem : EntitySystem if (component.KeyContainer.ContainedEntities.Count == 0) { - args.PushMarkup(Loc.GetString("examine-headset-no-keys")); + args.PushMarkup(Loc.GetString("encryption-keys-no-keys")); return; } if (component.Channels.Count > 0) { - args.PushMarkup(Loc.GetString("examine-headset-channels-prefix")); - AddChannelsExamine(component.Channels, component.DefaultChannel, args, _protoManager, "examine-headset-channel"); + args.PushMarkup(Loc.GetString("examine-encryption-channels-prefix")); + AddChannelsExamine(component.Channels, component.DefaultChannel, args, _protoManager, "examine-encryption-channel"); } } @@ -171,8 +179,8 @@ public sealed class EncryptionKeySystem : EntitySystem if(component.Channels.Count > 0) { - args.PushMarkup(Loc.GetString("examine-encryption-key-channels-prefix")); - AddChannelsExamine(component.Channels, component.DefaultChannel, args, _protoManager, "examine-headset-channel"); + args.PushMarkup(Loc.GetString("examine-encryption-channels-prefix")); + AddChannelsExamine(component.Channels, component.DefaultChannel, args, _protoManager, "examine-encryption-channel"); } } @@ -187,7 +195,7 @@ public sealed class EncryptionKeySystem : EntitySystem RadioChannelPrototype? proto; foreach (var id in channels) { - proto = protoManager.Index(id); + proto = _protoManager.Index(id); var key = id == SharedChatSystem.CommonChannel ? SharedChatSystem.RadioCommonPrefix.ToString() @@ -202,11 +210,21 @@ public sealed class EncryptionKeySystem : EntitySystem if (defaultChannel != null && _protoManager.TryIndex(defaultChannel, out proto)) { - var msg = Loc.GetString("examine-default-channel", + if (HasComp(examineEvent.Examined)) + { + var msg = Loc.GetString("examine-headset-default-channel", ("prefix", SharedChatSystem.DefaultChannelPrefix), ("channel", defaultChannel), ("color", proto.Color)); - examineEvent.PushMarkup(msg); + examineEvent.PushMarkup(msg); + } + if (HasComp(examineEvent.Examined)) + { + var msg = Loc.GetString("examine-encryption-default-channel", + ("channel", defaultChannel), + ("color", proto.Color)); + examineEvent.PushMarkup(msg); + } } } diff --git a/Resources/Locale/en-US/headset/headset-component.ftl b/Resources/Locale/en-US/headset/headset-component.ftl index e4706ecad2..7a1637c9d3 100644 --- a/Resources/Locale/en-US/headset/headset-component.ftl +++ b/Resources/Locale/en-US/headset/headset-component.ftl @@ -1,22 +1,7 @@ # Chat window radio wrap (prefix and postfix) chat-radio-message-wrap = [color={$color}]{$channel} {$name} says: "{$message}"[/color] -headset-encryption-key-successfully-installed = You put the key into the headset. -headset-encryption-key-slots-already-full = There is no place for another key. -headset-encryption-keys-all-extracted = You pop out the encryption keys from the headset! -headset-encryption-keys-no-keys = This headset has no encryption keys! -headset-encryption-keys-are-locked = The headset's key slots are locked, you cannot add or remove any keys. - -examine-encryption-key-channels-prefix = It is providing these frequencies to the headset: - -examine-radio-frequency = It's set to broadcast over the {$frequency} frequency. - -examine-headset-channels-prefix = A small screen on the headset displays the following available frequencies: -examine-headset-channel = [color={$color}]{$key} for {$id} ({$freq})[/color] -examine-headset-no-keys = It seems broken. There are no encryption keys in it. -examine-default-channel = Use {$prefix} for the default channel ([color={$color}]{$channel}[/color]). -examine-headset-default-channel = It indicates that the default channel of this headset is [color={$color}]{$channel}[/color]. -examine-encryption-key-default-channel = The default channel is [color={$color}]{$channel}[/color]. +examine-headset-default-channel = Use {$prefix} for the default channel ([color={$color}]{$channel}[/color]). chat-radio-common = Common chat-radio-centcom = CentCom diff --git a/Resources/Locale/en-US/radio/components/encryption-key-component.ftl b/Resources/Locale/en-US/radio/components/encryption-key-component.ftl new file mode 100644 index 0000000000..6d9dc5261c --- /dev/null +++ b/Resources/Locale/en-US/radio/components/encryption-key-component.ftl @@ -0,0 +1,9 @@ +encryption-key-successfully-installed = You put the encryption key inside. +encryption-key-slots-already-full = There is no place for another encryption key. +encryption-keys-all-extracted = You pop out the encryption keys! +encryption-keys-no-keys = This device has no encryption keys! +encryption-keys-are-locked = Encryption key slots are locked! + +examine-encryption-channels-prefix = Available frequencies: +examine-encryption-channel = [color={$color}]{$key} for {$id} ({$freq})[/color] +examine-encryption-default-channel = The default channel is [color={$color}]{$channel}[/color]. diff --git a/Resources/Prototypes/Catalog/Research/technologies.yml b/Resources/Prototypes/Catalog/Research/technologies.yml index 03b1edbb52..08156f9437 100644 --- a/Resources/Prototypes/Catalog/Research/technologies.yml +++ b/Resources/Prototypes/Catalog/Research/technologies.yml @@ -376,6 +376,7 @@ - SignalTrigger - VoiceTrigger - TimerTrigger + - TelecomServerCircuitboard - type: technology name: technologies-electrical-engineering diff --git a/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/Machine/production.yml b/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/Machine/production.yml index 42125ea3e4..616a7293f7 100644 --- a/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/Machine/production.yml +++ b/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/Machine/production.yml @@ -762,3 +762,18 @@ Amount: 1 DefaultPrototype: Beaker ExamineName: Glass Beaker + +- type: entity + id: TelecomServerCircuitboard + parent: BaseMachineCircuitboard + name: telecommunication server machine board + description: A machine printed circuit board for an telecommunication server + components: + - type: MachineBoard + prototype: TelecomServer + requirements: + Capacitor: 1 + ScanningModule: 2 + materialRequirements: + Steel: 1 + Cable: 2 diff --git a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml index 6f7401b449..582b9ce04b 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml @@ -326,6 +326,7 @@ - TraversalDistorterMachineCircuitboard - BoozeDispenserMachineCircuitboard - SodaDispenserMachineCircuitboard + - TelecomServerCircuitboard - type: MaterialStorage whitelist: tags: diff --git a/Resources/Prototypes/Entities/Structures/Machines/telecomms.yml b/Resources/Prototypes/Entities/Structures/Machines/telecomms.yml new file mode 100644 index 0000000000..e3197202d7 --- /dev/null +++ b/Resources/Prototypes/Entities/Structures/Machines/telecomms.yml @@ -0,0 +1,81 @@ +- type: entity + parent: [ BaseMachinePowered, ConstructibleMachine ] + id: TelecomServer + name: telecommunication server + description: When powered and filled with encryption keys it allows radio headset communication + components: + - type: Sprite + sprite: Structures/Machines/telecomms.rsi + snapCardinals: true + netsync: false + layers: + - state: icon + - state: unlit + shader: unshaded + map: ["enum.PowerDeviceVisualLayers.Powered"] + - state: panel + map: ["enum.WiresVisualLayers.MaintenancePanel"] + - type: GenericVisualizer + visuals: + enum.PowerDeviceVisuals.Powered: + enum.PowerDeviceVisualLayers.Powered: + True: { visible: true } + False: { visible: false } + - type: Appearance + - type: WiresVisuals + - type: Physics + bodyType: Static + - type: Fixtures + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.4,-0.4,0.4,0.4" + density: 190 + mask: + - MachineMask + layer: + - MachineLayer + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 100 + behaviors: + - !type:ChangeConstructionNodeBehavior + node: machineFrame + - !type:DoActsBehavior + acts: ["Destruction"] + - type: Machine + board: TelecomServerCircuitboard + - type: Wires + BoardName: "TelecomServer" + LayoutId: TelecomServer + - type: Transform + anchored: true + - type: Pullable + - type: EncryptionKeyHolder + keysExtractionMethod: Prying + keySlots: 10 + - type: TelecomServer + - type: ContainerContainer + containers: + key_slots: !type:Container + machine_board: !type:Container + machine_parts: !type:Container + +- type: entity + parent: TelecomServer + id: TelecomServerFilled + suffix: Filled + components: + - type: ContainerFill + containers: + key_slots: + - EncryptionKeyCommon + - EncryptionKeyCargo + - EncryptionKeyEngineering + - EncryptionKeyMedical + - EncryptionKeyScience + - EncryptionKeySecurity + - EncryptionKeyService + - EncryptionKeyCommand diff --git a/Resources/Prototypes/Recipes/Lathes/electronics.yml b/Resources/Prototypes/Recipes/Lathes/electronics.yml index c2d8d6f1a9..c5aea71800 100644 --- a/Resources/Prototypes/Recipes/Lathes/electronics.yml +++ b/Resources/Prototypes/Recipes/Lathes/electronics.yml @@ -527,3 +527,11 @@ materials: Steel: 100 Glass: 900 + +- type: latheRecipe + id: TelecomServerCircuitboard + result: TelecomServerCircuitboard + completetime: 4 + materials: + Steel: 100 + Glass: 900 diff --git a/Resources/Textures/Structures/Machines/telecomms.rsi/icon.png b/Resources/Textures/Structures/Machines/telecomms.rsi/icon.png new file mode 100644 index 0000000000..0f78e94bdd Binary files /dev/null and b/Resources/Textures/Structures/Machines/telecomms.rsi/icon.png differ diff --git a/Resources/Textures/Structures/Machines/telecomms.rsi/meta.json b/Resources/Textures/Structures/Machines/telecomms.rsi/meta.json new file mode 100644 index 0000000000..d26455cea6 --- /dev/null +++ b/Resources/Textures/Structures/Machines/telecomms.rsi/meta.json @@ -0,0 +1,34 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/blob/9c3494fd79e6bf8dc532300b9de4f688ff276ac9/icons/obj/machines/telecomms.dmi", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "unlit", + "delays": [ + [ + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1 + ] + ] + }, + { + "name": "icon" + }, + { + "name": "panel" + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/Structures/Machines/telecomms.rsi/panel.png b/Resources/Textures/Structures/Machines/telecomms.rsi/panel.png new file mode 100644 index 0000000000..1ab3cfb29c Binary files /dev/null and b/Resources/Textures/Structures/Machines/telecomms.rsi/panel.png differ diff --git a/Resources/Textures/Structures/Machines/telecomms.rsi/unlit.png b/Resources/Textures/Structures/Machines/telecomms.rsi/unlit.png new file mode 100644 index 0000000000..b804f4c6c8 Binary files /dev/null and b/Resources/Textures/Structures/Machines/telecomms.rsi/unlit.png differ