From 366738c503969c9c7838a4388450c57eb9cc218d Mon Sep 17 00:00:00 2001 From: NovaBot <154629622+NovaBot13@users.noreply.github.com> Date: Sat, 27 Jan 2024 10:44:47 -0500 Subject: [PATCH] [MIRROR] New Telecommunications Monitoring Console UI (#639) * New Telecommunications Monitoring Console UI (#81111) I've made a new UI for Telecommunications Monitoring Console. New features include: more useful information, search bar, icons and smaller window. This PR also includes a new sprite sheet, be warned! Additionally, I've removed `updateUsrDialog` because it makes no sense here and UI updates are handled by TGUI. * New Telecommunications Monitoring Console UI --------- Co-authored-by: Interception&? <137328283+intercepti0n@users.noreply.github.com> --- .../telecomms/computers/telemonitor.dm | 202 +++++++------ code/modules/asset_cache/assets/tcomms.dm | 12 + tgstation.dme | 1 + .../tgui/interfaces/TelecommsMonitor.tsx | 276 +++++++++++------- 4 files changed, 292 insertions(+), 199 deletions(-) create mode 100644 code/modules/asset_cache/assets/tcomms.dm diff --git a/code/game/machinery/telecomms/computers/telemonitor.dm b/code/game/machinery/telecomms/computers/telemonitor.dm index 400d827f618..6cf18323105 100644 --- a/code/game/machinery/telecomms/computers/telemonitor.dm +++ b/code/game/machinery/telecomms/computers/telemonitor.dm @@ -1,126 +1,156 @@ -/* - Telecomms monitor tracks the overall trafficing of a telecommunications network - and displays a heirarchy of linked machines. -*/ - #define MAIN_VIEW 0 #define MACHINE_VIEW 1 #define MAX_NETWORK_ID_LENGTH 15 /obj/machinery/computer/telecomms/monitor name = "telecommunications monitoring console" - icon_screen = "comm_monitor" desc = "Monitors the details of the telecommunications network it's synced with." - /// Current screen the user is viewing - var/screen = MAIN_VIEW - /// Weakrefs of the machines located by the computer - var/list/machine_list = list() + circuit = /obj/item/circuitboard/computer/comm_monitor + + icon_screen = "comm_monitor" + /// Weakref of the currently selected tcomms machine - var/datum/weakref/selected_machine_ref + var/datum/weakref/selected_machine_ref = null + /// Weakrefs of the machines located by the computer + var/list/datum/weakref/machine_refs + + /// Currently displayed "tab" + var/screen = MAIN_VIEW /// The network to probe var/network = "NULL" /// Error message to show - var/error_message = "" - circuit = /obj/item/circuitboard/computer/comm_monitor + var/status_message = null -/obj/machinery/computer/telecomms/monitor/ui_data(mob/user) - var/list/data = list( - "screen" = screen, - "network" = network, - "error_message" = error_message, +/obj/machinery/computer/telecomms/monitor/Initialize(mapload, obj/item/circuitboard/C) + . = ..() + LAZYINITLIST(machine_refs) + +/obj/machinery/computer/telecomms/monitor/ui_assets(mob/user) + return list( + get_asset_datum(/datum/asset/spritesheet/telecomms), ) +/obj/machinery/computer/telecomms/monitor/ui_interact(mob/user, datum/tgui/ui) + . = ..() + + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "TelecommsMonitor") + ui.open() + +/obj/machinery/computer/telecomms/monitor/ui_data(mob/user) + var/list/data = list() + + data["screen"] = screen + data["statusMessage"] = status_message + switch(screen) - // --- Main Menu --- if(MAIN_VIEW) - var/list/found_machinery = list() - for(var/datum/weakref/tcomms_ref in machine_list) - var/obj/machinery/telecomms/telecomms = tcomms_ref.resolve() - if(!telecomms) - machine_list -= tcomms_ref + data["network"] = network + + data["machines"] = list() + for(var/datum/weakref/machine_ref in machine_refs) + var/obj/machinery/telecomms/machine = machine_ref.resolve() + if(isnull(machine)) + machine_refs -= machine_ref continue - found_machinery += list(list("ref" = REF(telecomms), "name" = telecomms.name, "id" = telecomms.id)) - data["machinery"] = found_machinery - // --- Viewing Machine --- + + data["machines"] += list(list( + "id" = machine.id, + "name" = machine.name, + "icon" = initial(machine.icon_state), + )) + if(MACHINE_VIEW) - // Send selected machinery data - var/list/machine_out = list() - var/obj/machinery/telecomms/selected = selected_machine_ref.resolve() - if(selected) - machine_out["name"] = selected.name - // Get the linked machinery - var/list/linked_machinery = list() - for(var/obj/machinery/telecomms/T in selected.links) - linked_machinery += list(list("ref" = REF(T.id), "name" = T.name, "id" = T.id)) - machine_out["linked_machinery"] = linked_machinery - data["machine"] = machine_out + var/obj/machinery/telecomms/selected = selected_machine_ref?.resolve() + if(!isnull(selected)) + var/list/linked_machines = list() + for(var/obj/machinery/telecomms/machine as anything in selected.links) + linked_machines += list(list( + "id" = machine.id, + "name" = machine.name, + "icon" = initial(machine.icon_state), + )) + + data["machine"] = list( + "id" = selected.id, + "name" = selected.name, + "network" = selected.network, + "linkedMachines" = linked_machines, + ) + return data /obj/machinery/computer/telecomms/monitor/ui_act(action, params) . = ..() if(.) - return . + return - error_message = "" + status_message = null switch(action) - // Scan for a network - if("probe_network") - var/new_network = params["network_id"] + if("flush") + machine_refs = list() + network = "" + return TRUE - if(length(new_network) > MAX_NETWORK_ID_LENGTH) - error_message = "OPERATION FAILED: NETWORK ID TOO LONG." - return TRUE + if("home") + selected_machine_ref = null + screen = MAIN_VIEW + return TRUE + + if("view") + var/machine_id = params["id"] + if(isnull(machine_id)) + return + + for(var/datum/weakref/machine_ref as anything in machine_refs) + var/obj/machinery/telecomms/machine = machine_ref.resolve() + if(isnull(machine)) + machine_refs -= machine_ref + continue + + if(machine.id != machine_id) + continue - list_clear_empty_weakrefs(machine_list) + selected_machine_ref = machine_ref + screen = MACHINE_VIEW - if(machine_list.len > 0) - error_message = "OPERATION FAILED: CANNOT PROBE WHEN BUFFER FULL." + if(isnull(selected_machine_ref)) + status_message = "OPERATION FAILED: UNABLE TO LOCATE MACHINERY." + + return TRUE + + if("probe") + var/network_id = params["id"] + if(length(network_id) > MAX_NETWORK_ID_LENGTH) + status_message = "OPERATION FAILED: NETWORK ID TOO LONG." return TRUE - network = new_network + list_clear_empty_weakrefs(machine_refs) - for(var/obj/machinery/telecomms/T in urange(25, src)) - if(T.network == network) - machine_list += WEAKREF(T) - if(machine_list.len == 0) - error_message = "OPERATION FAILED: UNABLE TO LOCATE NETWORK ENTITIES IN [network]." + if(length(machine_refs) > 0) + status_message = "OPERATION FAILED: CANNOT PROBE WHEN BUFFER FULL." return TRUE - error_message = "[machine_list.len] ENTITIES LOCATED & BUFFERED"; - return TRUE - if("flush_buffer") - machine_list = list() - network = "" - return TRUE - if("view_machine") - for(var/datum/weakref/tcomms_ref in machine_list) - var/obj/machinery/telecomms/tcomms = tcomms_ref.resolve() - if(!tcomms) - machine_list -= tcomms_ref + + network = network_id + + var/list/telecomms_machines = SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/telecomms) + for(var/obj/machinery/telecomms/machine as anything in telecomms_machines) + if(machine.network != network) continue - if(tcomms.id == params["id"]) - selected_machine_ref = tcomms_ref - if(!selected_machine_ref) - error_message = "OPERATION FAILED: UNABLE TO LOCATE MACHINERY." - screen = MACHINE_VIEW - return TRUE - if("return_home") - selected_machine_ref = null - screen = MAIN_VIEW - return TRUE - return TRUE -/obj/machinery/computer/telecomms/monitor/attackby() - . = ..() - updateUsrDialog() + machine_refs += WEAKREF(machine) -/obj/machinery/computer/telecomms/monitor/ui_interact(mob/user, datum/tgui/ui) - . = ..() - ui = SStgui.try_update_ui(user, src, ui) - if (!ui) - ui = new(user, src, "TelecommsMonitor", name) - ui.open() + if(length(machine_refs) == 0) + status_message = "OPERATION FAILED: UNABLE TO LOCATE NETWORK ENTITIES IN [network]." + return TRUE + + status_message = "[length(machine_refs)] ENTITIES LOCATED & BUFFERED" + return TRUE + + return TRUE #undef MAIN_VIEW #undef MACHINE_VIEW diff --git a/code/modules/asset_cache/assets/tcomms.dm b/code/modules/asset_cache/assets/tcomms.dm new file mode 100644 index 00000000000..ecfdb4a498c --- /dev/null +++ b/code/modules/asset_cache/assets/tcomms.dm @@ -0,0 +1,12 @@ +/datum/asset/spritesheet/telecomms + name="tcomms" + +/datum/asset/spritesheet/telecomms/create_spritesheets() + var/list/inserted_states = list() // No need to send entire `telecomms.dmi`. + for(var/obj/machinery/telecomms/machine as anything in subtypesof(/obj/machinery/telecomms)) + var/icon_state = machine::icon_state + if(icon_state in inserted_states) + continue + + Insert(icon_state, machine::icon, icon_state) + inserted_states += icon_state diff --git a/tgstation.dme b/tgstation.dme index 47ec0507cd0..52651da3645 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -3372,6 +3372,7 @@ #include "code\modules\asset_cache\assets\seeds.dm" #include "code\modules\asset_cache\assets\sheetmaterials.dm" #include "code\modules\asset_cache\assets\supplypods.dm" +#include "code\modules\asset_cache\assets\tcomms.dm" #include "code\modules\asset_cache\assets\tgfont.dm" #include "code\modules\asset_cache\assets\tgui.dm" #include "code\modules\asset_cache\assets\uplink.dm" diff --git a/tgui/packages/tgui/interfaces/TelecommsMonitor.tsx b/tgui/packages/tgui/interfaces/TelecommsMonitor.tsx index 8a1ecdd64d6..722df7f022b 100644 --- a/tgui/packages/tgui/interfaces/TelecommsMonitor.tsx +++ b/tgui/packages/tgui/interfaces/TelecommsMonitor.tsx @@ -1,14 +1,16 @@ -import { useState } from 'react'; +import { classes } from 'common/react'; +import { toTitleCase } from 'common/string'; +import { useMemo, useState } from 'react'; import { useBackend } from '../backend'; import { + Box, Button, Input, LabeledList, NoticeBox, Section, Stack, - Table, } from '../components'; import { Window } from '../layouts'; @@ -17,157 +19,205 @@ enum Screen { Machine, } +type Machine = { + id: string; + name: string; + icon: string; +}; + +type BaseMachine = { network: string; linkedMachines: Machine[] } & Machine; + type Data = { screen: Screen; + statusMessage: string; + machine?: BaseMachine; network: string; - error_message: string; - machinery: Machine[]; - machine: Machine; + machines?: Machine[]; }; -type Machine = { - ref: string; - id: string; - name: string; - linked_machinery: LinkedMachinery[]; -}; +export const TelecommsMonitor = (props: any) => { + const { data } = useBackend(); + const { screen, statusMessage } = data; -type LinkedMachinery = { - ref: string; - id: string; - name: string; + return ( + + + + + {!!statusMessage && {statusMessage}} + + + {(screen === Screen.Main && ) || + (screen === Screen.Machine && )} + + + + + ); }; -const MachineScreen = (props) => { +const MainScreen = (props: any) => { const { act, data } = useBackend(); - const { network, machine } = data; - const { linked_machinery = [] } = machine; + const { network, machines = [] } = data; + + const [networkId, setNetworkId] = useState(network); return ( -
+ + + setNetworkId(value)} + placeholder="Enter Network ID..." + /> + + + + + +
+
+ + act('return_home')} + icon="trash" + color="red" + tooltip="Flush Buffer" + disabled={machines.length === 0} + onClick={() => act('flush')} /> } - > - - {network} - - {machine.name} - - - - - -
- - - Address - Name - Machine - - {linked_machinery?.map((lm) => ( - - {lm.ref} - {lm.id} - -
-
+ machines={machines} + onSelect={(machine) => act('view', { id: machine.id })} + />
); }; -const MainScreen = (props) => { +const MachineScreen = (props: any) => { const { act, data } = useBackend(); - const { machinery = [], network } = data; - const [networkId, setNetworkId] = useState(network); + const { id, name, network, linkedMachines } = data.machine!; return ( -
- setNetworkId(value)} - placeholder="Network ID" - /> - -
-
-
act('flush_buffer')} - /> + } > - - - Address - Name - Machine - - {machinery?.map((machine) => ( - - {machine.ref} - {machine.id} - -
+ + {network} + {id} + + {toTitleCase(name)} + +
+ + act('view', { id: machine.id })} + /> +
); }; -export const TelecommsMonitor = (props) => { - const { act, data } = useBackend(); - const { screen, error_message } = data; +type MachineListProps = { + title: string; + buttons?: React.ReactNode; + machines: Machine[]; + onSelect: (machine: Machine) => void; +}; + +const MachineList = (props: MachineListProps) => { + const { title, buttons, machines, onSelect } = props; + + const [searching, setSearching] = useState(false); + const [search, setSearch] = useState(''); + + const sortedMachines = useMemo( + () => + machines.filter((machine) => + machine.id.toLowerCase().includes(search.toLowerCase()), + ), + [search, machines.length], + ); + return ( - - - - - {!!error_message && {error_message}} - +
+ + + ))} + + {searching && ( + + setSearch(value)} + /> + + )} - - + ) : ( + No machines connected! + )} +
); };