From 4e4647bd71164430f3bd4abfccd08ba6e413cb03 Mon Sep 17 00:00:00 2001 From: SkyratBot <59378654+SkyratBot@users.noreply.github.com> Date: Fri, 6 Aug 2021 03:05:37 +0200 Subject: [PATCH] [MIRROR] Add admin panel for viewing circuits (#7389) * Add admin panel for viewing circuits * Update admin_verbs.dm * Update admin_verbs.dm Co-authored-by: Mothblocks <35135081+Mothblocks@users.noreply.github.com> Co-authored-by: Gandalf --- code/modules/admin/admin_verbs.dm | 3 +- code/modules/admin/topic.dm | 13 +-- code/modules/client/client_procs.dm | 14 +++ code/modules/wiremod/admin_panel.dm | 75 ++++++++++++++++ code/modules/wiremod/integrated_circuit.dm | 26 ++++-- tgstation.dme | 1 + .../tgui/interfaces/CircuitAdminPanel.tsx | 85 +++++++++++++++++++ 7 files changed, 196 insertions(+), 21 deletions(-) create mode 100644 code/modules/wiremod/admin_panel.dm create mode 100644 tgui/packages/tgui/interfaces/CircuitAdminPanel.tsx diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index d7c40a58301..548b929b604 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -87,7 +87,8 @@ GLOBAL_PROTECT(admin_verbs_admin) /client/proc/admin_open_event_spawners_menu, //SKYRAT EDIT ADDITION - EVENTS /datum/admins/proc/toggleaooc, //SKYRAT EDIT ADDITION - ADMIN /datum/admins/proc/togglesooc, //SKYRAT EDIT ADDITION - ADMIN - /datum/admins/proc/open_borgopanel + /datum/admins/proc/open_borgopanel, + /datum/admins/proc/view_all_circuits, ) GLOBAL_LIST_INIT(admin_verbs_ban, list(/client/proc/unban_panel, /client/proc/ban_panel, /client/proc/stickybanpanel)) GLOBAL_PROTECT(admin_verbs_ban) diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 98d7c80d354..7e0ab25d118 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -902,18 +902,7 @@ if(!isobserver(usr) && !check_rights(R_ADMIN)) return - var/atom/movable/AM = locate(href_list["adminplayerobservefollow"]) - - var/client/C = usr.client - var/can_ghost = TRUE - if(!isobserver(usr)) - can_ghost = C.admin_ghost() - - if(!can_ghost) - return - var/mob/dead/observer/A = C.mob - A.ManualFollow(AM) - + usr.client?.admin_follow(locate(href_list["adminplayerobservefollow"])) else if(href_list["admingetmovable"]) if(!check_rights(R_ADMIN)) return diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index 40f6ae29946..c136e3195a3 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -1199,3 +1199,17 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( return 0 return max(0, days_needed - player_age) + +/// Attempts to make the client orbit the given object, for administrative purposes. +/// If they are not an observer, will try to aghost them. +/client/proc/admin_follow(atom/movable/target) + var/can_ghost = TRUE + + if (!isobserver(mob)) + can_ghost = admin_ghost() + + if(!can_ghost) + return FALSE + + var/mob/dead/observer/observer = mob + observer.ManualFollow(target) diff --git a/code/modules/wiremod/admin_panel.dm b/code/modules/wiremod/admin_panel.dm new file mode 100644 index 00000000000..33af02f5140 --- /dev/null +++ b/code/modules/wiremod/admin_panel.dm @@ -0,0 +1,75 @@ +/// An admin verb to view all circuits, plus useful information +/datum/admins/proc/view_all_circuits() + set category = "Admin.Game" + set name = "View All Circuits" + + var/static/datum/circuit_admin_panel/circuit_admin_panel = new + circuit_admin_panel.ui_interact(usr) + +/datum/circuit_admin_panel + +/datum/circuit_admin_panel/ui_static_data(mob/user) + var/list/data = list() + data["circuits"] = list() + + for (var/obj/item/integrated_circuit/circuit as anything in GLOB.integrated_circuits) + var/datum/mind/inserter = circuit.inserter_mind?.resolve() + + data["circuits"] += list(list( + "ref" = REF(circuit), + "name" = "[circuit.name] in [loc_name(circuit)]", + "creator" = circuit.get_creator(), + "has_inserter" = !isnull(inserter), + )) + + return data + +/datum/circuit_admin_panel/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) + . = ..() + if (.) + return . + + if (!istext(params["circuit"])) + return FALSE + + var/obj/item/integrated_circuit/circuit = locate(params["circuit"]) + if (!istype(circuit)) + to_chat(usr, span_warning("That circuit no longer exists.")) + return FALSE + + switch (action) + if ("duplicate_circuit") + if (alert(usr, "This will spawn the new circuit at where you are, are you sure?", "Confirm", "Yes", "No") != "Yes") + return FALSE + + var/list/errors = list() + + var/obj/item/integrated_circuit/loaded/new_circuit = new(usr.drop_location()) + new_circuit.load_circuit_data(circuit.convert_to_json(), errors) + + if (length(errors)) + to_chat(usr, span_warning("Somehow, duplicating the circuit failed:")) + for (var/error in errors) + to_chat(usr, span_warning(error)) + if ("follow_circuit") + usr.client?.admin_follow(circuit) + if ("save_circuit") + circuit.attempt_save_to(usr.client) + if ("vv_circuit") + usr.client?.debug_variables(circuit) + if ("open_circuit") + circuit.ui_interact(usr) + if ("open_player_panel") + var/datum/mind/inserter = circuit.inserter_mind?.resolve() + usr.client?.holder?.show_player_panel(inserter?.current) + + return TRUE + +/datum/circuit_admin_panel/ui_state(mob/user) + return GLOB.admin_state + +/datum/circuit_admin_panel/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "CircuitAdminPanel") + ui.open() diff --git a/code/modules/wiremod/integrated_circuit.dm b/code/modules/wiremod/integrated_circuit.dm index c48997ccc2e..8196974eceb 100644 --- a/code/modules/wiremod/integrated_circuit.dm +++ b/code/modules/wiremod/integrated_circuit.dm @@ -1,3 +1,6 @@ +/// A list of all integrated circuits +GLOBAL_LIST_EMPTY_TYPED(integrated_circuits, /obj/item/integrated_circuit) + /** * # Integrated Circuitboard * @@ -53,6 +56,9 @@ /obj/item/integrated_circuit/Initialize() . = ..() + + GLOB.integrated_circuits += src + RegisterSignal(src, COMSIG_ATOM_USB_CABLE_TRY_ATTACH, .proc/on_atom_usb_cable_try_attach) /obj/item/integrated_circuit/loaded/Initialize() @@ -68,6 +74,7 @@ examined_component = null owner_id = null QDEL_NULL(cell) + GLOB.integrated_circuits -= src return ..() /obj/item/integrated_circuit/examine(mob/user) @@ -468,14 +475,7 @@ examined_component = null . = TRUE if("save_circuit") - var/client/saver = usr.client - if(!check_rights_for(saver, R_VAREDIT)) - return - var/temp_file = file("data/CircuitDownloadTempFile") - fdel(temp_file) - WRITE_FILE(temp_file, convert_to_json()) - DIRECT_OUTPUT(saver, ftp(temp_file, "[display_name || "circuit"].json")) - . = TRUE + return attempt_save_to(usr.client) /obj/item/integrated_circuit/proc/on_atom_usb_cable_try_attach(datum/source, obj/item/usb_cable/usb_cable, mob/user) SIGNAL_HANDLER @@ -507,3 +507,13 @@ id_card = owner_id.resolve() return "[src] (Shell: [shell || "*null*"], Inserter: [key_name(inserter, include_link)], Owner ID: [id_card?.name || "*null*"])" + +/// Attempts to save a circuit to a given client +/obj/item/integrated_circuit/proc/attempt_save_to(client/saver) + if(!check_rights_for(saver, R_VAREDIT)) + return FALSE + var/temp_file = file("data/CircuitDownloadTempFile") + fdel(temp_file) + WRITE_FILE(temp_file, convert_to_json()) + DIRECT_OUTPUT(saver, ftp(temp_file, "[display_name || "circuit"].json")) + return TRUE diff --git a/tgstation.dme b/tgstation.dme index e6fccc24da4..027dd342daf 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -3718,6 +3718,7 @@ #include "code\modules\vending\toys.dm" #include "code\modules\vending\wardrobes.dm" #include "code\modules\vending\youtool.dm" +#include "code\modules\wiremod\admin_panel.dm" #include "code\modules\wiremod\component.dm" #include "code\modules\wiremod\component_printer.dm" #include "code\modules\wiremod\datatypes.dm" diff --git a/tgui/packages/tgui/interfaces/CircuitAdminPanel.tsx b/tgui/packages/tgui/interfaces/CircuitAdminPanel.tsx new file mode 100644 index 00000000000..814a147fc10 --- /dev/null +++ b/tgui/packages/tgui/interfaces/CircuitAdminPanel.tsx @@ -0,0 +1,85 @@ +import { BooleanLike } from "common/react"; +import { useBackend } from "../backend"; +import { Button, Table } from "../components"; +import { Window } from "../layouts"; + +type CircuitAdminPanelData = { + circuits: { + ref: string; + name: string; + creator: string; + has_inserter: BooleanLike; + }[] +} + +export const CircuitAdminPanel = (props, context) => { + const { act, data } = useBackend(context); + + return ( + + + + + + Circuit name + + + + Creator + + + + Actions + + + + {data.circuits.map(circuit => { + const createAct = (action: string) => () => { + act(action, { circuit: circuit.ref }); + }; + + return ( + + + {circuit.name} + + + + {circuit.creator} + + + + + + + + + + + + + + {!!circuit.has_inserter && ( + + )} + + + ); + })} +
+
+
+ ); +};