diff --git a/Content.Client/SimpleStation14/Holograms/CctvDatabaseUi/CctvDatabaseBoundUserInterface.cs b/Content.Client/SimpleStation14/Holograms/CctvDatabaseUi/CctvDatabaseBoundUserInterface.cs new file mode 100644 index 0000000000..46e3617b35 --- /dev/null +++ b/Content.Client/SimpleStation14/Holograms/CctvDatabaseUi/CctvDatabaseBoundUserInterface.cs @@ -0,0 +1,51 @@ +using Content.Shared.SimpleStation14.Holograms; +using Robust.Client.GameObjects; + +namespace Content.Client.SimpleStation14.Holograms.CctvDatabaseUi; + +public sealed class CctvDatabaseBoundUserInterface : BoundUserInterface +{ + [ViewVariables] + private CctvDatabaseWindow? _menu; + + public CctvDatabaseBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey) + { + } + + protected override void Open() + { + _menu = new CctvDatabaseWindow(); + + _menu.OpenCentered(); + _menu.OnClose += Close; + + _menu.PrintRequested += SendPrintRequest; + } + + private void SendPrintRequest(int index) + { + Logger.Error($"Sending message for index {index}"); + SendMessage(new CctvDatabasePrintRequestMessage(index)); + } + + protected override void UpdateState(BoundUserInterfaceState state) + { + base.UpdateState(state); + + switch (state) + { + case CctvDatabaseState cctvState: + _menu?.UpdateState(cctvState); + break; + } + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) + return; + + _menu?.Dispose(); + } +} diff --git a/Content.Client/SimpleStation14/Holograms/CctvDatabaseUi/CctvDatabaseWindow.xaml b/Content.Client/SimpleStation14/Holograms/CctvDatabaseUi/CctvDatabaseWindow.xaml new file mode 100644 index 0000000000..ced3735356 --- /dev/null +++ b/Content.Client/SimpleStation14/Holograms/CctvDatabaseUi/CctvDatabaseWindow.xaml @@ -0,0 +1,33 @@ + + + + + + + + + + diff --git a/Content.Client/SimpleStation14/Holograms/CctvDatabaseUi/CctvDatabaseWindow.xaml.cs b/Content.Client/SimpleStation14/Holograms/CctvDatabaseUi/CctvDatabaseWindow.xaml.cs new file mode 100644 index 0000000000..691e91e810 --- /dev/null +++ b/Content.Client/SimpleStation14/Holograms/CctvDatabaseUi/CctvDatabaseWindow.xaml.cs @@ -0,0 +1,64 @@ +using Content.Client.UserInterface.Controls; +using Content.Shared.SimpleStation14.Holograms; +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface.Controls; +using Robust.Shared.Timing; + +namespace Content.Client.SimpleStation14.Holograms.CctvDatabaseUi; + +[GenerateTypedNameReferences] +public sealed partial class CctvDatabaseWindow : FancyWindow +{ + [Dependency] private readonly IGameTiming _timing = default!; + + public Action? PrintRequested; + + private const string IdleMessage = "cctv-database-user-interface-message-idle"; + private const string PrintingMessage = "cctv-database-user-interface-message-printing"; + + private TimeSpan? _printTime; + + public void UpdateState(CctvDatabaseState state) + { + var entries = state.CrewManifest; + _printTime = state.FinishedPrintingTime; + + TargetList.RemoveAllChildren(); + + var disabled = state.FinishedPrintingTime != null; + for (var i = 0; i < entries.Count; i++) + { + var label = new Label + { + Text = entries[i], + }; + + var button = new Button + { + Text = "Print", + Disabled = disabled, + }; + + var index = i; + button.OnPressed += _ => PrintRequested?.Invoke(index); + + TargetList.AddChild(label); + TargetList.AddChild(button); + } + + MessageLabel.Text = state.FinishedPrintingTime.ToString() ?? Loc.GetString(IdleMessage); + } + + protected override void FrameUpdate(FrameEventArgs args) + { + base.FrameUpdate(args); + + if (_printTime == null) + return; + + var timeLeft = _printTime.Value - _timing.CurTime; + MessageLabel.Text = timeLeft > TimeSpan.Zero + ? $"{Loc.GetString(PrintingMessage)}: {timeLeft.TotalSeconds:0.0}" + : Loc.GetString(IdleMessage); + } +} diff --git a/Content.Server/SimpleStation14/Holograms/CctvDatabase/CctvDatabaseConsoleActiveComponent.cs b/Content.Server/SimpleStation14/Holograms/CctvDatabase/CctvDatabaseConsoleActiveComponent.cs new file mode 100644 index 0000000000..e456937703 --- /dev/null +++ b/Content.Server/SimpleStation14/Holograms/CctvDatabase/CctvDatabaseConsoleActiveComponent.cs @@ -0,0 +1,20 @@ +namespace Content.Server.SimpleStation14.Holograms.CctvDatabase; + +/// +/// Marks this entity as an active . +/// +[RegisterComponent] +public sealed class CctvDatabaseConsoleActiveComponent : Component +{ + /// + /// The mind currently being printed. + /// + [ViewVariables(VVAccess.ReadWrite)] + public Mind.Mind? PrintingMind; + + /// + /// The time the mind will be printed at. + /// + [ViewVariables(VVAccess.ReadWrite)] + public TimeSpan PrintTime = TimeSpan.Zero; +} diff --git a/Content.Server/SimpleStation14/Holograms/CctvDatabase/CctvDatabaseConsoleComponent.cs b/Content.Server/SimpleStation14/Holograms/CctvDatabase/CctvDatabaseConsoleComponent.cs new file mode 100644 index 0000000000..449780fd31 --- /dev/null +++ b/Content.Server/SimpleStation14/Holograms/CctvDatabase/CctvDatabaseConsoleComponent.cs @@ -0,0 +1,17 @@ +namespace Content.Server.SimpleStation14.Holograms.CctvDatabase; + +/// +/// Marks this entity as a CCTV Database console, allowing it to print CCTV footage onto disks. +/// +/// +/// Mostly a temporary thing for the Hologram system, should be expanded when recordings are actually a thing? +/// +[RegisterComponent] +public sealed class CctvDatabaseConsoleComponent : Component +{ + /// + /// The amount of time it takes this Console to print a disk. + /// + [ViewVariables(VVAccess.ReadWrite)] + public TimeSpan TimeToPrint = TimeSpan.FromMinutes(1.5); +} diff --git a/Content.Server/SimpleStation14/Holograms/CctvDatabase/CctvDatabaseSystem.cs b/Content.Server/SimpleStation14/Holograms/CctvDatabase/CctvDatabaseSystem.cs new file mode 100644 index 0000000000..36bc3c67a9 --- /dev/null +++ b/Content.Server/SimpleStation14/Holograms/CctvDatabase/CctvDatabaseSystem.cs @@ -0,0 +1,110 @@ +//TODO: HOLO In the future the entire CCTV Database system should be completely replaced +// with something that uses station records, requires tracked camera time, +// and a whole bunch of other stuff that'll be fun to use. +// For the time being, this works. + +using Content.Server.GameTicking; +using Content.Server.Mind.Components; +using Content.Server.SimpleStation14.Holograms.Components; +using Content.Server.Station.Systems; +using Content.Shared.SimpleStation14.Holograms; +using Robust.Server.GameObjects; +using Robust.Shared.Timing; + +namespace Content.Server.SimpleStation14.Holograms.CctvDatabase; + +public sealed class CctvDatabaseSystem : EntitySystem +{ + [Dependency] private readonly UserInterfaceSystem _ui = default!; + [Dependency] private readonly StationSystem _station = default!; + [Dependency] private readonly IGameTiming _timing = default!; + + private const string HoloDiskPrototype = "HologramDisk"; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnPlayerSpawn); + + SubscribeLocalEvent(OnUIOpened); + SubscribeLocalEvent(OnPrintRequest); + } + + public override void Update(float delta) + { + while (EntityQueryEnumerator().MoveNext(out var console, out var activeComp)) + { + Log.Error($"{activeComp.PrintTime} >= {_timing.CurTime}"); + if (activeComp.PrintTime >= _timing.CurTime) + FinishPrint(console, activeComp); + } + } + + private void OnPlayerSpawn(EntityUid player, HologramTargetComponent holoTargetComp, PlayerSpawnCompleteEvent args) + { + if (!TryComp(args.Station, out var stationDatabaseComp)) + return; + if (!TryComp(player, out var mindContainerComp) || mindContainerComp.Mind is not { } mind) + return; + + stationDatabaseComp.PotentialsList.Add(mind); + + while (EntityQueryEnumerator().MoveNext(out var console, out _)) + UpdateUserInterface(console); + } + + private void OnUIOpened(EntityUid uid, CctvDatabaseConsoleComponent component, BoundUIOpenedEvent args) + { + if (args.UiKey is not CctvDatabaseUiKey.Key) + return; + + UpdateUserInterface(uid); + } + + private void UpdateUserInterface(EntityUid uid, CctvDatabaseConsoleActiveComponent? activeComp = null) + { + if (!_ui.TryGetUi(uid, CctvDatabaseUiKey.Key, out var bui)) + return; + + if (_station.GetOwningStation(uid) is not { } station || !TryComp(station, out var stationDatabaseComp)) + return; + + TimeSpan? finishTime = null; + + if (Resolve(uid, ref activeComp, false)) + finishTime = activeComp.PrintTime; + + _ui.TrySetUiState(uid, CctvDatabaseUiKey.Key, new CctvDatabaseState(stationDatabaseComp.PotentialsList.ConvertAll(x => x.CharacterName ?? "Unknown"), finishTime)); + } + + private void OnPrintRequest(EntityUid console, CctvDatabaseConsoleComponent consoleComp, CctvDatabasePrintRequestMessage args) + { + if (HasComp(console)) + return; + + if (_station.GetOwningStation(console) is not { } station || !TryComp(station, out var stationDatabaseComp)) + return; + + if (stationDatabaseComp.PotentialsList.Count <= args.Index) // Should never happen. + { + Log.Error($"CCTV Database console {console} tried to print a disk with index {args.Index} but the list only has {stationDatabaseComp.PotentialsList.Count} entries."); + return; + } + + var mind = stationDatabaseComp.PotentialsList[args.Index]; + var activeComp = AddComp(console); + activeComp.PrintingMind = mind; + activeComp.PrintTime = consoleComp.TimeToPrint + _timing.CurTime; + UpdateUserInterface(console, activeComp); + } + + private void FinishPrint(EntityUid console, CctvDatabaseConsoleActiveComponent activeComp) + { + var disk = Spawn(HoloDiskPrototype, Transform(console).Coordinates); + var diskComp = EnsureComp(disk); + diskComp.HoloMind = activeComp.PrintingMind; + RemComp(console); + UpdateUserInterface(console); + } +} diff --git a/Content.Server/SimpleStation14/Holograms/CctvDatabase/StationCctvDatabaseComponent.cs b/Content.Server/SimpleStation14/Holograms/CctvDatabase/StationCctvDatabaseComponent.cs new file mode 100644 index 0000000000..3f87a512f8 --- /dev/null +++ b/Content.Server/SimpleStation14/Holograms/CctvDatabase/StationCctvDatabaseComponent.cs @@ -0,0 +1,7 @@ +namespace Content.Server.SimpleStation14.Holograms.CctvDatabase; + +[RegisterComponent] +public sealed class StationCctvDatabaseComponent : Component +{ + public List PotentialsList = new(); +} diff --git a/Content.Server/SimpleStation14/Holograms/Components/HologramDiskWriterComponent.cs b/Content.Server/SimpleStation14/Holograms/Components/HologramDiskWriterComponent.cs new file mode 100644 index 0000000000..8c72688b41 --- /dev/null +++ b/Content.Server/SimpleStation14/Holograms/Components/HologramDiskWriterComponent.cs @@ -0,0 +1,8 @@ +namespace Content.Server.SimpleStation14.Holograms.Components; + +[RegisterComponent] +public sealed class HologramDiskWriterComponent : Component +{ + [DataField("diskSlot")] + public string DiskSlot = "disk_slot"; +} diff --git a/Content.Server/SimpleStation14/Holograms/Components/HologramTargetComponent.cs b/Content.Server/SimpleStation14/Holograms/Components/HologramTargetComponent.cs new file mode 100644 index 0000000000..a2c8422031 --- /dev/null +++ b/Content.Server/SimpleStation14/Holograms/Components/HologramTargetComponent.cs @@ -0,0 +1,10 @@ +//TODO: HOLO In the future, this and the entire CCTV Database system should be completely replaced +// with something that uses station records, requires tracked camera time, +// and a whole bunch of other stuff that'll be fun to use. +// For the time being, this works. + +namespace Content.Server.SimpleStation14.Holograms.Components; + +[RegisterComponent] +public sealed class HologramTargetComponent : Component +{ } diff --git a/Content.Server/SimpleStation14/Holograms/Components/StationHologramDatabaseComponent.cs b/Content.Server/SimpleStation14/Holograms/Components/StationHologramDatabaseComponent.cs new file mode 100644 index 0000000000..eed181ca1e --- /dev/null +++ b/Content.Server/SimpleStation14/Holograms/Components/StationHologramDatabaseComponent.cs @@ -0,0 +1,6 @@ +namespace Content.Server.SimpleStation14.Holograms.Components; + +[RegisterComponent] +public sealed class StationHologramDatabaseComponent : Component +{ +} diff --git a/Content.Server/SimpleStation14/Holograms/Systems/HologramServerSystem.DiskWriter.cs b/Content.Server/SimpleStation14/Holograms/Systems/HologramServerSystem.DiskWriter.cs new file mode 100644 index 0000000000..d3010c9f9b --- /dev/null +++ b/Content.Server/SimpleStation14/Holograms/Systems/HologramServerSystem.DiskWriter.cs @@ -0,0 +1,15 @@ +using Content.Server.Mind.Components; +using Content.Server.Power.Components; +using Content.Shared.Interaction; +using Content.Shared.SimpleStation14.Holograms; +using Robust.Shared.Containers; + +namespace Content.Server.SimpleStation14.Holograms; + +public sealed partial class HologramServerSystem +{ + public void InitializeDiskWriter() + { + base.Initialize(); + } +} diff --git a/Content.Server/SimpleStation14/Holograms/Systems/HologramServerSystem.Station.cs b/Content.Server/SimpleStation14/Holograms/Systems/HologramServerSystem.Station.cs new file mode 100644 index 0000000000..0cb7ffe3a6 --- /dev/null +++ b/Content.Server/SimpleStation14/Holograms/Systems/HologramServerSystem.Station.cs @@ -0,0 +1,17 @@ +using Content.Server.GameTicking; +using Content.Server.SimpleStation14.Holograms.Components; + +namespace Content.Server.SimpleStation14.Holograms; + +public sealed partial class HologramServerSystem +{ + private void InitializeStation() + { + SubscribeLocalEvent(OnPlayerSpawn); + } + + private void OnPlayerSpawn(EntityUid player, StationHologramDatabaseComponent component, PlayerSpawnCompleteEvent args) + { + } +} + diff --git a/Content.Shared/SimpleStation14/Holograms/CctvDatabaseShared.cs b/Content.Shared/SimpleStation14/Holograms/CctvDatabaseShared.cs new file mode 100644 index 0000000000..4fcb5a915c --- /dev/null +++ b/Content.Shared/SimpleStation14/Holograms/CctvDatabaseShared.cs @@ -0,0 +1,34 @@ +using Content.Shared.CrewManifest; +using Robust.Shared.Serialization; + +namespace Content.Shared.SimpleStation14.Holograms; + +[Serializable, NetSerializable] +public enum CctvDatabaseUiKey +{ + Key +} + +[Serializable, NetSerializable] +public sealed class CctvDatabaseState : BoundUserInterfaceState +{ + public List CrewManifest; + public TimeSpan? FinishedPrintingTime; + + public CctvDatabaseState(List crewManifest, TimeSpan? finishedPrintingTime = null) + { + CrewManifest = crewManifest; + FinishedPrintingTime = finishedPrintingTime; + } +} + +[Serializable, NetSerializable] +public sealed class CctvDatabasePrintRequestMessage : BoundUserInterfaceMessage +{ + public int Index; + + public CctvDatabasePrintRequestMessage(int index) + { + Index = index; + } +} diff --git a/Content.Shared/SimpleStation14/Holograms/HologramEvents.cs b/Content.Shared/SimpleStation14/Holograms/HologramEvents.cs index c19e119a57..afc6ffac6a 100644 --- a/Content.Shared/SimpleStation14/Holograms/HologramEvents.cs +++ b/Content.Shared/SimpleStation14/Holograms/HologramEvents.cs @@ -46,7 +46,7 @@ public record struct HologramGetProjectorEvent(EntityUid? ProjectorOverride = nu /// Allows for manually determining if a projector is valid for a given Hologram. /// /// -/// Valid is nullable, setting it to either value will force that behavior. +/// Setting Valid to either True or False will force that behavior. /// Leaving it null will allow the projector to determine its own validity based on normal rules. /// [ByRefEvent] diff --git a/Resources/Prototypes/Entities/Mobs/Player/diona.yml b/Resources/Prototypes/Entities/Mobs/Player/diona.yml index 63f24b68b0..7cb99149ef 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/diona.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/diona.yml @@ -35,3 +35,4 @@ - type: NpcFactionMember factions: - NanoTrasen + - type: HologramTarget diff --git a/Resources/Prototypes/Entities/Mobs/Player/dwarf.yml b/Resources/Prototypes/Entities/Mobs/Player/dwarf.yml index ee80ea4389..c7b5a3b9d2 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/dwarf.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/dwarf.yml @@ -26,3 +26,4 @@ factions: - NanoTrasen - type: PotentialPsionic + - type: HologramTarget diff --git a/Resources/Prototypes/Entities/Mobs/Player/human.yml b/Resources/Prototypes/Entities/Mobs/Player/human.yml index 980ab7a73a..465ae07568 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/human.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/human.yml @@ -33,6 +33,7 @@ factions: - NanoTrasen - type: PotentialPsionic + - type: HologramTarget #Syndie - type: entity diff --git a/Resources/Prototypes/Entities/Mobs/Player/reptilian.yml b/Resources/Prototypes/Entities/Mobs/Player/reptilian.yml index 21671b3428..27ff04fd63 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/reptilian.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/reptilian.yml @@ -32,3 +32,4 @@ damageRecovery: types: Asphyxiation: -1.0 + - type: HologramTarget diff --git a/Resources/Prototypes/Entities/Mobs/Player/slime.yml b/Resources/Prototypes/Entities/Mobs/Player/slime.yml index 4a090af959..15b03c4192 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/slime.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/slime.yml @@ -27,3 +27,4 @@ - type: PotentialPsionic - type: TypingIndicator proto: slime + - type: HologramTarget diff --git a/Resources/Prototypes/Entities/Stations/nanotrasen.yml b/Resources/Prototypes/Entities/Stations/nanotrasen.yml index 3275c08e5d..929b1af691 100644 --- a/Resources/Prototypes/Entities/Stations/nanotrasen.yml +++ b/Resources/Prototypes/Entities/Stations/nanotrasen.yml @@ -25,6 +25,7 @@ noSpawn: true components: - type: Transform + - type: StationCctvDatabase - type: entity id: NanotrasenCentralCommand diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/arachne.yml b/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/arachne.yml index bebf42f31b..ee79c3463e 100644 --- a/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/arachne.yml +++ b/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/arachne.yml @@ -33,3 +33,4 @@ factions: - NanoTrasen - type: PotentialPsionic + - type: HologramTarget diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/felinid.yml b/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/felinid.yml index 84e653ab1d..e904a034ce 100644 --- a/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/felinid.yml +++ b/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/felinid.yml @@ -33,3 +33,4 @@ factions: - NanoTrasen - type: PotentialPsionic + - type: HologramTarget diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/moth.yml b/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/moth.yml index 537ec17d58..f8b115cfc4 100644 --- a/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/moth.yml +++ b/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/moth.yml @@ -33,3 +33,4 @@ factions: - NanoTrasen - type: PotentialPsionic + - type: HologramTarget diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/oni.yml b/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/oni.yml index 562b9c564e..78cf83e765 100644 --- a/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/oni.yml +++ b/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/oni.yml @@ -33,3 +33,4 @@ factions: - NanoTrasen - type: PotentialPsionic + - type: HologramTarget diff --git a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/shadowkin.yml b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/shadowkin.yml index e560d9eed8..83a47e7bbc 100644 --- a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/shadowkin.yml +++ b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/shadowkin.yml @@ -123,6 +123,7 @@ - type: MovementSpeedModifier baseWalkSpeed : 2.7 baseSprintSpeed : 4.5 + - type: HologramTarget - type: entity diff --git a/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/Computers/computers.yml b/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/Computers/computers.yml new file mode 100644 index 0000000000..1404a2b4ca --- /dev/null +++ b/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/Computers/computers.yml @@ -0,0 +1,34 @@ +- type: entity + parent: BaseComputer + id: ComputerCctvDatabase + name: CCTV database console + description: Used to fard + components: + - type: Sprite + layers: + - map: ["computerLayerBody"] + state: computer + - map: ["computerLayerKeyboard"] + state: generic_keyboard + - map: ["computerLayerScreen"] + state: security + - map: ["computerLayerKeys"] + state: security_key + - type: PointLight + radius: 1.5 + energy: 1.6 + color: "#006400" + # - type: Computer + # board: CrewMonitoringComputerCircuitboard + - type: ActivatableUI + key: enum.CctvDatabaseUiKey.Key + - type: UserInterface + interfaces: + - key: enum.CctvDatabaseUiKey.Key + type: CctvDatabaseBoundUserInterface + - type: CctvDatabaseConsole + # - type: DeviceNetwork + # deviceNetId: Wireless + # receiveFrequencyId: CrewMonitor + # - type: WirelessNetworkConnection + # range: 1200