From d538100ceb2a45cc80230cbc9a0d84ae02cbbbec Mon Sep 17 00:00:00 2001
From: AffectedArc07 <25063394+AffectedArc07@users.noreply.github.com>
Date: Sun, 26 Jun 2022 20:10:09 +0100
Subject: [PATCH] Shift+F3 debug menu (#18065)
* F3 debug menu
* Some tweaks
* So that escalated
* Update code/controllers/subsystem.dm
* Update code/controllers/subsystem/debugview.dm
* Charlie tweaks
---
code/__DEFINES/layers.dm | 4 +-
code/controllers/subsystem.dm | 11 ++-
code/controllers/subsystem/acid.dm | 4 +-
code/controllers/subsystem/air.dm | 5 +-
code/controllers/subsystem/chat_pings.dm | 4 +-
code/controllers/subsystem/dbcore.dm | 4 +-
code/controllers/subsystem/debugview.dm | 81 +++++++++++++++++++
code/controllers/subsystem/fires.dm | 4 +-
code/controllers/subsystem/garbage.dm | 17 ++--
code/controllers/subsystem/ghost_spawns.dm | 5 +-
code/controllers/subsystem/http.dm | 4 +-
code/controllers/subsystem/idlenpcpool.dm | 6 +-
code/controllers/subsystem/lighting.dm | 4 +-
code/controllers/subsystem/machinery.dm | 4 +-
code/controllers/subsystem/mobs.dm | 4 +-
code/controllers/subsystem/npcpool.dm | 5 +-
code/controllers/subsystem/overlays.dm | 4 +-
.../subsystem/processing/processing.dm | 4 +-
code/controllers/subsystem/profiler.dm | 4 +-
code/controllers/subsystem/redis.dm | 4 +-
code/controllers/subsystem/runechat.dm | 4 +-
code/controllers/subsystem/shuttles.dm | 4 +-
code/controllers/subsystem/spacedrift.dm | 4 +-
code/controllers/subsystem/sun.dm | 4 +-
code/controllers/subsystem/tgui.dm | 4 +-
code/controllers/subsystem/throwing.dm | 4 +-
code/controllers/subsystem/tickets/tickets.dm | 4 +-
code/controllers/subsystem/timer.dm | 4 +-
code/modules/admin/admin_verbs.dm | 2 +
code/modules/client/client_defines.dm | 3 +
code/modules/client/client_procs.dm | 1 +
code/modules/keybindings/bindings_admin.dm | 9 +++
code/modules/keybindings/bindings_client.dm | 8 +-
paradise.dme | 1 +
34 files changed, 172 insertions(+), 66 deletions(-)
create mode 100644 code/controllers/subsystem/debugview.dm
diff --git a/code/__DEFINES/layers.dm b/code/__DEFINES/layers.dm
index 00e6ae1bb80..515739088e9 100644
--- a/code/__DEFINES/layers.dm
+++ b/code/__DEFINES/layers.dm
@@ -126,8 +126,10 @@
#define SPLASHSCREEN_LAYER 23
#define SPLASHSCREEN_PLANE 23
-// This should always be on top.
#define HUD_PLANE_BUILDMODE 30
+// This should always be on top. No exceptions.
+#define HUD_PLANE_DEBUGVIEW 40
+
///Plane master controller keys
#define PLANE_MASTERS_GAME "plane_masters_game"
diff --git a/code/controllers/subsystem.dm b/code/controllers/subsystem.dm
index d37597d190d..a3ae69cfa2b 100644
--- a/code/controllers/subsystem.dm
+++ b/code/controllers/subsystem.dm
@@ -159,6 +159,9 @@
if(SS_SLEEPING)
state = SS_PAUSING
+// Gets extra details for the subsystem stat panes
+/datum/controller/subsystem/proc/get_stat_details()
+ return
//used to initialize the subsystem AFTER the map has loaded
/datum/controller/subsystem/Initialize(start_timeofday)
@@ -172,16 +175,18 @@
if(!statclick)
statclick = new/obj/effect/statclick/debug(null, "Initializing...", src)
-
+ var/ss_info = get_stat_details()
if(can_fire && !(SS_NO_FIRE & flags))
- msg = "[round(cost, 1)]ms | [round(tick_usage, 1)]%([round(tick_overrun, 1)]%) | [round(ticks, 0.1)]\t[msg]"
+ msg = "[round(cost, 1)]ms | [round(tick_usage, 1)]%([round(tick_overrun, 1)]%) | [round(ticks, 0.1)]\t[ss_info]"
else
- msg = "OFFLINE\t[msg]"
+ msg = "OFFLINE\t[ss_info]"
var/title = name
if(can_fire)
title = "[state_colour()]\[[state_letter()]][title]"
+ else
+ title = "\[O][title]"
stat(title, statclick.update(msg))
diff --git a/code/controllers/subsystem/acid.dm b/code/controllers/subsystem/acid.dm
index 3dbea1c3c15..f6933f10e8c 100644
--- a/code/controllers/subsystem/acid.dm
+++ b/code/controllers/subsystem/acid.dm
@@ -8,8 +8,8 @@ SUBSYSTEM_DEF(acid)
var/list/currentrun = list()
var/list/processing = list()
-/datum/controller/subsystem/acid/stat_entry()
- ..("P:[processing.len]")
+/datum/controller/subsystem/acid/get_stat_details()
+ return "P:[length(processing)]"
/datum/controller/subsystem/acid/get_metrics()
. = ..()
diff --git a/code/controllers/subsystem/air.dm b/code/controllers/subsystem/air.dm
index c5886bac18a..60969b9a840 100644
--- a/code/controllers/subsystem/air.dm
+++ b/code/controllers/subsystem/air.dm
@@ -46,7 +46,8 @@ SUBSYSTEM_DEF(air)
var/list/currentrun = list()
var/currentpart = SSAIR_DEFERREDPIPENETS
-/datum/controller/subsystem/air/stat_entry(msg)
+/datum/controller/subsystem/air/get_stat_details()
+ var/list/msg = list()
msg += "C:{"
msg += "AT:[round(cost_turfs,1)]|"
msg += "EG:[round(cost_groups,1)]|"
@@ -64,7 +65,7 @@ SUBSYSTEM_DEF(air)
msg += "HP:[high_pressure_delta.len]|"
msg += "AS:[active_super_conductivity.len]|"
msg += "AT/MS:[round((cost ? active_turfs.len/cost : 0),0.1)]"
- ..(msg)
+ return msg.Join("")
/datum/controller/subsystem/air/get_metrics()
. = ..()
diff --git a/code/controllers/subsystem/chat_pings.dm b/code/controllers/subsystem/chat_pings.dm
index ad013cab3d6..eda9a006c01 100644
--- a/code/controllers/subsystem/chat_pings.dm
+++ b/code/controllers/subsystem/chat_pings.dm
@@ -12,5 +12,5 @@ SUBSYSTEM_DEF(chat_pings)
if(MC_TICK_CHECK)
return
-/datum/controller/subsystem/chat_pings/stat_entry()
- ..("P: [length(chat_datums)]")
+/datum/controller/subsystem/chat_pings/get_stat_details()
+ return "P: [length(chat_datums)]"
diff --git a/code/controllers/subsystem/dbcore.dm b/code/controllers/subsystem/dbcore.dm
index ed7e8c25596..b9ac3673404 100644
--- a/code/controllers/subsystem/dbcore.dm
+++ b/code/controllers/subsystem/dbcore.dm
@@ -24,8 +24,8 @@ SUBSYSTEM_DEF(dbcore)
offline_implications = "The server will no longer check for undeleted SQL Queries. No immediate action is needed."
-/datum/controller/subsystem/dbcore/stat_entry()
- ..("A: [length(active_queries)]")
+/datum/controller/subsystem/dbcore/get_stat_details()
+ return "A: [length(active_queries)]"
// This is in Initialize() so that its actually seen in chat
/datum/controller/subsystem/dbcore/Initialize()
diff --git a/code/controllers/subsystem/debugview.dm b/code/controllers/subsystem/debugview.dm
new file mode 100644
index 00000000000..2326eb0776d
--- /dev/null
+++ b/code/controllers/subsystem/debugview.dm
@@ -0,0 +1,81 @@
+SUBSYSTEM_DEF(debugview)
+ name = "Debug View"
+ wait = 1 // SS_TICKER subsystem, so wait is in ticks
+ flags = SS_TICKER|SS_NO_INIT
+ offline_implications = "Shift+F3 will no longer show a debug view. No immediate action is needed."
+ /// List of clients currently processing
+ var/list/client/processing = list()
+
+/datum/controller/subsystem/debugview/fire(resumed)
+ // Generate debug text
+ var/list/entries = list()
+ entries += "CPU: [round(world.cpu, 1)] | MCPU: [round(world.map_cpu, 1)] | FPS/TPS: [world.fps] | Clients: [length(GLOB.clients)] | BYOND: [world.byond_version].[world.byond_build]"
+ entries += "\[Air] Cost: [round(SSair.cost, 1)]ms | AT: [length(SSair.active_turfs)]"
+ entries += "\[Debug] Cost: [round(SSdebugview.cost, 1)]ms | P: [length(SSdebugview.processing)]" // meta af (tbf we need to know how much were using)
+ entries += "\[FP] Cost: [round(SSfastprocess.cost, 1)]ms | P: [length(SSfastprocess.processing)]"
+ // Snowflakery for SSgarbage
+ var/list/counts = list()
+ for(var/list/L in SSgarbage.queues)
+ counts += length(L)
+ entries += "\[GC] Cost: [round(SSgarbage.cost, 1)]ms | Q: [counts.Join(",")] H: [SSgarbage.delslasttick] | S: [SSgarbage.gcedlasttick]"
+ entries += "\[Input] Cost: [round(SSinput.cost, 1)]ms"
+ entries += "\[Lighting] Cost: [round(SSlighting.cost, 1)]ms | SQ: [length(SSlighting.sources_queue)] | CQ: [length(SSlighting.corners_queue)] | OQ: [length(SSlighting.objects_queue)]"
+ entries += "\[Machines] Cost: [round(SSmachines.cost, 1)]ms | M: [length(SSmachines.processing)] | P: [length(SSmachines.powernets)]"
+ entries += "\[Mobs] Cost: [round(SSmobs.cost, 1)]ms | P: [length(GLOB.mob_living_list)]"
+ entries += "\[Objects] Cost: [round(SSobj.cost, 1)]ms | P: [length(SSobj.processing)]"
+ entries += "\[Processing] Cost: [round(SSprocessing.cost, 1)]ms | P: [length(SSprocessing.processing)]"
+ entries += "\[Projectiles] Cost: [round(SSprojectiles.cost, 1)]ms | P: [length(SSprojectiles.processing)]"
+ entries += "\[Runechat] Cost: [round(SSrunechat.cost, 1)]ms | AM: [SSrunechat.bucket_count] | SQ: [length(SSrunechat.second_queue)]"
+ entries += "\[TGUI] Cost: [round(SStgui.cost, 1)]ms | P: [length(SStgui.processing_uis)]"
+ entries += "\[Timer] Cost: [round(SStimer.cost, 1)]ms | B: [SStimer.bucket_count] | P: [length(SStimer.second_queue)] | RST: [SStimer.bucket_reset_count]"
+
+ // Do some parsing to format it properly
+ var/out_text = entries.Join("\n")
+ var/mty = 480 - 9 * length(entries)
+
+ // And update the clients
+ for(var/client/C as anything in processing)
+ C.debug_text_overlay.maptext_y = mty
+ C.debug_text_overlay.maptext = "[out_text]"
+
+/datum/controller/subsystem/debugview/proc/start_processing(client/C)
+ C.debug_text_overlay = new /obj/screen/debugtextholder
+ C.screen |= C.debug_text_overlay
+ processing |= C
+
+/datum/controller/subsystem/debugview/proc/stop_processing(client/C)
+ processing -= C
+ C.screen -= C.debug_text_overlay
+ qdel(C.debug_text_overlay)
+
+/obj/screen/debugtextholder
+ icon = 'icons/mob/screen_full.dmi'
+ icon_state = "default"
+ screen_loc = "CENTER-7,CENTER-7"
+ plane = HUD_PLANE_DEBUGVIEW
+ maptext_height = 480 // If we ever change view size, increase this
+ maptext_width = 480
+
+
+// Make a verb for dumping full SS stats
+/client/proc/ss_breakdown()
+ set name = "SS Info Breakdown"
+ set category = "Debug"
+
+ if(!check_rights(R_DEBUG|R_VIEWRUNTIMES))
+ return
+
+ var/datum/browser/popup = new(usr, "ss_breakdown", "Subsystem Breakdown", 1100, 850)
+
+ var/list/html = list()
+ html += "CPU: [round(world.cpu, 1)] | MCPU: [round(world.map_cpu, 1)] | FPS/TPS: [world.fps] | Clients: [length(GLOB.clients)] | BYOND: [world.byond_version].[world.byond_build]"
+ html += "--- SS BREAKDOWN ---"
+ for(var/datum/controller/subsystem/SS as anything in Master.subsystems)
+ // We dont care about subsystems that arent firing (or are unable to)
+ if((SS.flags & SS_NO_FIRE) || !SS.can_fire)
+ continue
+
+ html += "[SS.state_colour()]\[[SS.state_letter()]][SS.ss_id]\t[round(SS.cost, 1)]ms | [round(SS.tick_usage, 1)]% | [SS.get_stat_details()]"
+
+ popup.set_content(html.Join("
"))
+ popup.open(FALSE)
diff --git a/code/controllers/subsystem/fires.dm b/code/controllers/subsystem/fires.dm
index 4ae71f72841..f261158b269 100644
--- a/code/controllers/subsystem/fires.dm
+++ b/code/controllers/subsystem/fires.dm
@@ -8,8 +8,8 @@ SUBSYSTEM_DEF(fires)
var/list/currentrun = list()
var/list/processing = list()
-/datum/controller/subsystem/fires/stat_entry()
- ..("P:[processing.len]")
+/datum/controller/subsystem/fires/get_stat_details()
+ return "P:[length(processing)]"
/datum/controller/subsystem/fires/get_metrics()
diff --git a/code/controllers/subsystem/garbage.dm b/code/controllers/subsystem/garbage.dm
index 03f630148e0..a8a673aac1e 100644
--- a/code/controllers/subsystem/garbage.dm
+++ b/code/controllers/subsystem/garbage.dm
@@ -41,25 +41,26 @@ SUBSYSTEM_DEF(garbage)
pass_counts[i] = 0
fail_counts[i] = 0
-/datum/controller/subsystem/garbage/stat_entry(msg)
+/datum/controller/subsystem/garbage/get_stat_details()
+ var/list/msg = list()
var/list/counts = list()
for(var/list/L in queues)
counts += length(L)
- msg += "Queue:[counts.Join(",")] | Del's:[delslasttick] | Soft:[gcedlasttick] |"
- msg += "GR:"
+ msg += "Q:[counts.Join(", ")] | D:[delslasttick] | S:[gcedlasttick] |"
+ msg += "GCR:"
if(!(delslasttick + gcedlasttick))
msg += "n/a|"
else
msg += "[round((gcedlasttick / (delslasttick + gcedlasttick)) * 100, 0.01)]% |"
- msg += "Total Dels:[totaldels] | Soft:[totalgcs] |"
+ msg += "TD:[totaldels] | TS:[totalgcs] |"
if(!(totaldels + totalgcs))
msg += "n/a|"
else
- msg += "TGR:[round((totalgcs / (totaldels + totalgcs)) * 100, 0.01)]% |"
- msg += " Pass:[pass_counts.Join(",")]"
- msg += " | Fail:[fail_counts.Join(",")]"
- ..(msg)
+ msg += "TGCR:[round((totalgcs / (totaldels + totalgcs)) * 100, 0.01)]% |"
+ msg += " P:[pass_counts.Join(",")]"
+ msg += " | F:[fail_counts.Join(",")]"
+ return msg.Join("")
/datum/controller/subsystem/garbage/get_metrics()
. = ..()
diff --git a/code/controllers/subsystem/ghost_spawns.dm b/code/controllers/subsystem/ghost_spawns.dm
index e9b2c2a8809..4d0c1e97f61 100644
--- a/code/controllers/subsystem/ghost_spawns.dm
+++ b/code/controllers/subsystem/ghost_spawns.dm
@@ -201,11 +201,12 @@ SUBSYSTEM_DEF(ghost_spawns)
if(!next_poll_to_finish || P2.time_left() < next_poll_to_finish.time_left())
next_poll_to_finish = P2
-/datum/controller/subsystem/ghost_spawns/stat_entry(msg)
+/datum/controller/subsystem/ghost_spawns/get_stat_details()
+ var/list/msg = list()
msg += "Active: [length(currently_polling)] | Total: [total_polls]"
if(next_poll_to_finish)
msg += " | Next: [DisplayTimeText(next_poll_to_finish.time_left())] ([length(next_poll_to_finish.signed_up)] candidates)"
- ..(msg)
+ return msg.Join("")
// The datum that describes one instance of candidate polling
/datum/candidate_poll
diff --git a/code/controllers/subsystem/http.dm b/code/controllers/subsystem/http.dm
index 6c7178a69fa..3ec168124ba 100644
--- a/code/controllers/subsystem/http.dm
+++ b/code/controllers/subsystem/http.dm
@@ -20,8 +20,8 @@ SUBSYSTEM_DEF(http)
active_async_requests = list()
return ..()
-/datum/controller/subsystem/http/stat_entry()
- ..("P: [length(active_async_requests)] | T: [total_requests]")
+/datum/controller/subsystem/http/get_stat_details()
+ return "P: [length(active_async_requests)] | T: [total_requests]"
/datum/controller/subsystem/http/fire(resumed)
for(var/r in active_async_requests)
diff --git a/code/controllers/subsystem/idlenpcpool.dm b/code/controllers/subsystem/idlenpcpool.dm
index d61b90f1239..bdaed1c2877 100644
--- a/code/controllers/subsystem/idlenpcpool.dm
+++ b/code/controllers/subsystem/idlenpcpool.dm
@@ -9,10 +9,8 @@ SUBSYSTEM_DEF(idlenpcpool)
var/list/currentrun = list()
var/static/list/idle_mobs_by_zlevel[][]
-/datum/controller/subsystem/idlenpcpool/stat_entry()
- var/list/idlelist = GLOB.simple_animals[AI_IDLE]
- var/list/zlist = GLOB.simple_animals[AI_Z_OFF]
- ..("IdleNPCS:[idlelist.len]|Z:[zlist.len]")
+/datum/controller/subsystem/idlenpcpool/get_stat_details()
+ return "IdleNPCS:[length(GLOB.simple_animals[AI_IDLE])]|Z:[length(GLOB.simple_animals[AI_Z_OFF])]"
/datum/controller/subsystem/idlenpcpool/Initialize(start_timeofday)
idle_mobs_by_zlevel = new /list(world.maxz,0)
diff --git a/code/controllers/subsystem/lighting.dm b/code/controllers/subsystem/lighting.dm
index f197fbc735e..293cb0a36ed 100644
--- a/code/controllers/subsystem/lighting.dm
+++ b/code/controllers/subsystem/lighting.dm
@@ -8,8 +8,8 @@ SUBSYSTEM_DEF(lighting)
var/static/list/corners_queue = list() // List of lighting corners queued for update.
var/static/list/objects_queue = list() // List of lighting objects queued for update.
-/datum/controller/subsystem/lighting/stat_entry()
- ..("L:[length(sources_queue)]|C:[length(corners_queue)]|O:[length(objects_queue)]")
+/datum/controller/subsystem/lighting/get_stat_details()
+ return "L:[length(sources_queue)]|C:[length(corners_queue)]|O:[length(objects_queue)]"
/datum/controller/subsystem/lighting/get_metrics()
. = ..()
diff --git a/code/controllers/subsystem/machinery.dm b/code/controllers/subsystem/machinery.dm
index 96eac799ae0..4f2152b3ace 100644
--- a/code/controllers/subsystem/machinery.dm
+++ b/code/controllers/subsystem/machinery.dm
@@ -37,8 +37,8 @@ SUBSYSTEM_DEF(machines)
NewPN.add_cable(PC)
propagate_network(PC,PC.powernet)
-/datum/controller/subsystem/machines/stat_entry()
- ..("Machines: [processing.len]\nPowernets: [powernets.len]\tDeferred: [deferred_powernet_rebuilds.len]")
+/datum/controller/subsystem/machines/get_stat_details()
+ return "Machines: [processing.len] | Powernets: [powernets.len] | Deferred: [deferred_powernet_rebuilds.len]"
/datum/controller/subsystem/machines/proc/process_defered_powernets(resumed = 0)
if(!resumed)
diff --git a/code/controllers/subsystem/mobs.dm b/code/controllers/subsystem/mobs.dm
index ebd37383e35..5fb354d9157 100644
--- a/code/controllers/subsystem/mobs.dm
+++ b/code/controllers/subsystem/mobs.dm
@@ -18,8 +18,8 @@ SUBSYSTEM_DEF(mobs)
cust["processing"] = length(GLOB.mob_living_list)
.["custom"] = cust
-/datum/controller/subsystem/mobs/stat_entry()
- ..("P:[GLOB.mob_living_list.len]")
+/datum/controller/subsystem/mobs/get_stat_details()
+ return "P:[length(GLOB.mob_living_list.len)]"
/datum/controller/subsystem/mobs/Initialize(start_timeofday)
clients_by_zlevel = new /list(world.maxz,0)
diff --git a/code/controllers/subsystem/npcpool.dm b/code/controllers/subsystem/npcpool.dm
index 79541c199a4..fcac095489e 100644
--- a/code/controllers/subsystem/npcpool.dm
+++ b/code/controllers/subsystem/npcpool.dm
@@ -7,9 +7,8 @@ SUBSYSTEM_DEF(npcpool)
var/list/currentrun = list()
-/datum/controller/subsystem/npcpool/stat_entry()
- var/list/activelist = GLOB.simple_animals[AI_ON]
- ..("SimpleAnimals:[activelist.len]")
+/datum/controller/subsystem/npcpool/get_stat_details()
+ return "SimpleAnimals: [length(GLOB.simple_animals[AI_ON])]"
/datum/controller/subsystem/npcpool/fire(resumed = FALSE)
diff --git a/code/controllers/subsystem/overlays.dm b/code/controllers/subsystem/overlays.dm
index 95b9e925b5d..e4178284f7f 100644
--- a/code/controllers/subsystem/overlays.dm
+++ b/code/controllers/subsystem/overlays.dm
@@ -23,8 +23,8 @@ SUBSYSTEM_DEF(overlays)
return ..()
-/datum/controller/subsystem/overlays/stat_entry()
- ..("Ov:[length(queue)]")
+/datum/controller/subsystem/overlays/get_stat_details()
+ return "Ov:[length(queue)]"
/datum/controller/subsystem/overlays/Recover()
overlay_icon_state_caches = SSoverlays.overlay_icon_state_caches
diff --git a/code/controllers/subsystem/processing/processing.dm b/code/controllers/subsystem/processing/processing.dm
index b08aae88a23..4ec3beb5c6f 100644
--- a/code/controllers/subsystem/processing/processing.dm
+++ b/code/controllers/subsystem/processing/processing.dm
@@ -11,8 +11,8 @@ SUBSYSTEM_DEF(processing)
var/list/currentrun = list()
offline_implications = "Objects using the default processor will no longer process. Shuttle call recommended."
-/datum/controller/subsystem/processing/stat_entry()
- ..("[stat_tag]:[processing.len]")
+/datum/controller/subsystem/processing/get_stat_details()
+ return "[stat_tag]:[length(processing)]"
/datum/controller/subsystem/processing/get_metrics()
. = ..()
diff --git a/code/controllers/subsystem/profiler.dm b/code/controllers/subsystem/profiler.dm
index 324dcaf4cad..d44489c5ca3 100644
--- a/code/controllers/subsystem/profiler.dm
+++ b/code/controllers/subsystem/profiler.dm
@@ -13,8 +13,8 @@ SUBSYSTEM_DEF(profiler)
/// Time it took to send the stuff down FFI for redis (ms)
var/send_ffi_cost = 0
-/datum/controller/subsystem/profiler/stat_entry()
- ..("F:[round(fetch_cost, 1)]ms | W:[round(write_cost, 1)]ms | SE:[round(send_encode_cost, 1)]ms | SF:[round(send_ffi_cost, 1)]ms")
+/datum/controller/subsystem/profiler/get_stat_details()
+ return "F:[round(fetch_cost, 1)]ms | W:[round(write_cost, 1)]ms | SE:[round(send_encode_cost, 1)]ms | SF:[round(send_ffi_cost, 1)]ms"
/datum/controller/subsystem/profiler/Initialize()
if(!GLOB.configuration.general.enable_auto_profiler)
diff --git a/code/controllers/subsystem/redis.dm b/code/controllers/subsystem/redis.dm
index df8ce561595..d2e49fd2289 100644
--- a/code/controllers/subsystem/redis.dm
+++ b/code/controllers/subsystem/redis.dm
@@ -13,8 +13,8 @@ SUBSYSTEM_DEF(redis)
offline_implications = "The server will no longer be able to send or receive redis messages. Shuttle call recommended (Potential server crash inbound)."
// SS meta procs
-/datum/controller/subsystem/redis/stat_entry()
- ..("S:[length(subbed_channels)] | Q:[length(queue)] | C:[connected ? "Y" : "N"]")
+/datum/controller/subsystem/redis/get_stat_details()
+ return "S:[length(subbed_channels)] | Q:[length(queue)] | C:[connected ? "Y" : "N"]"
/datum/controller/subsystem/redis/Initialize()
// Connect to cappuccino
diff --git a/code/controllers/subsystem/runechat.dm b/code/controllers/subsystem/runechat.dm
index 960e56048b1..4602b970383 100644
--- a/code/controllers/subsystem/runechat.dm
+++ b/code/controllers/subsystem/runechat.dm
@@ -46,8 +46,8 @@ SUBSYSTEM_DEF(runechat)
head_offset = world.time
bucket_resolution = world.tick_lag
-/datum/controller/subsystem/runechat/stat_entry(msg)
- ..("ActMsgs:[bucket_count] SecQueue:[length(second_queue)]")
+/datum/controller/subsystem/runechat/get_stat_details()
+ return "ActMsgs:[bucket_count] SecQueue:[length(second_queue)]"
/datum/controller/subsystem/runechat/fire(resumed = FALSE)
// Store local references to datum vars as it is faster to access them this way
diff --git a/code/controllers/subsystem/shuttles.dm b/code/controllers/subsystem/shuttles.dm
index 65bbd26a808..aa690ef03d0 100644
--- a/code/controllers/subsystem/shuttles.dm
+++ b/code/controllers/subsystem/shuttles.dm
@@ -65,8 +65,8 @@ SUBSYSTEM_DEF(shuttle)
return ..()
-/datum/controller/subsystem/shuttle/stat_entry(msg)
- ..("M:[mobile.len] S:[stationary.len] T:[transit.len]")
+/datum/controller/subsystem/shuttle/get_stat_details()
+ return "M:[length(mobile)] S:[length(stationary)] T:[length(transit)]"
/datum/controller/subsystem/shuttle/proc/initial_load()
for(var/obj/docking_port/D in world)
diff --git a/code/controllers/subsystem/spacedrift.dm b/code/controllers/subsystem/spacedrift.dm
index 8dd64dced5f..e684ced3d8f 100644
--- a/code/controllers/subsystem/spacedrift.dm
+++ b/code/controllers/subsystem/spacedrift.dm
@@ -9,8 +9,8 @@ SUBSYSTEM_DEF(spacedrift)
var/list/currentrun = list()
var/list/processing = list()
-/datum/controller/subsystem/spacedrift/stat_entry()
- ..("P:[processing.len]")
+/datum/controller/subsystem/spacedrift/get_stat_details()
+ return "P:[length(processing)]"
/datum/controller/subsystem/spacedrift/get_metrics()
. = ..()
diff --git a/code/controllers/subsystem/sun.dm b/code/controllers/subsystem/sun.dm
index fc691c3a0c0..74b5679893e 100644
--- a/code/controllers/subsystem/sun.dm
+++ b/code/controllers/subsystem/sun.dm
@@ -25,8 +25,8 @@ SUBSYSTEM_DEF(sun)
return ..()
-/datum/controller/subsystem/sun/stat_entry(msg)
- ..("P:[solars.len]")
+/datum/controller/subsystem/sun/get_stat_details()
+ return "P:[length(solars)]"
/datum/controller/subsystem/sun/fire()
angle = (360 + angle + rate * 6) % 360 // increase/decrease the angle to the sun, adjusted by the rate
diff --git a/code/controllers/subsystem/tgui.dm b/code/controllers/subsystem/tgui.dm
index 5eb4d09aa3a..c5e76604087 100644
--- a/code/controllers/subsystem/tgui.dm
+++ b/code/controllers/subsystem/tgui.dm
@@ -24,8 +24,8 @@ SUBSYSTEM_DEF(tgui)
/datum/controller/subsystem/tgui/Shutdown()
close_all_uis()
-/datum/controller/subsystem/tgui/stat_entry()
- ..("P:[processing_uis.len]")
+/datum/controller/subsystem/tgui/get_stat_details()
+ return "P:[length(processing_uis)]"
/datum/controller/subsystem/tgui/get_metrics()
. = ..()
diff --git a/code/controllers/subsystem/throwing.dm b/code/controllers/subsystem/throwing.dm
index be2d62e09e9..d991167b3e2 100644
--- a/code/controllers/subsystem/throwing.dm
+++ b/code/controllers/subsystem/throwing.dm
@@ -12,8 +12,8 @@ SUBSYSTEM_DEF(throwing)
var/list/currentrun
var/list/processing = list()
-/datum/controller/subsystem/throwing/stat_entry()
- ..("P:[processing.len]")
+/datum/controller/subsystem/throwing/get_stat_details()
+ return "P:[length(processing)]"
/datum/controller/subsystem/throwing/get_metrics()
. = ..()
diff --git a/code/controllers/subsystem/tickets/tickets.dm b/code/controllers/subsystem/tickets/tickets.dm
index 43cc3a71092..7587e5f9af3 100644
--- a/code/controllers/subsystem/tickets/tickets.dm
+++ b/code/controllers/subsystem/tickets/tickets.dm
@@ -62,8 +62,8 @@ SUBSYSTEM_DEF(tickets)
report += "[num], "
message_staff("Tickets [report] have been open for over [TICKET_TIMEOUT / 600] minutes. Changing status to stale.")
-/datum/controller/subsystem/tickets/stat_entry()
- ..("Tickets: [LAZYLEN(allTickets)]")
+/datum/controller/subsystem/tickets/get_stat_details()
+ return "Tickets: [LAZYLEN(allTickets)]"
/datum/controller/subsystem/tickets/proc/checkStaleness()
var/stales = list()
diff --git a/code/controllers/subsystem/timer.dm b/code/controllers/subsystem/timer.dm
index 9860e906779..fa0c93cd29d 100644
--- a/code/controllers/subsystem/timer.dm
+++ b/code/controllers/subsystem/timer.dm
@@ -58,8 +58,8 @@ SUBSYSTEM_DEF(timer)
head_offset = world.time
bucket_resolution = world.tick_lag
-/datum/controller/subsystem/timer/stat_entry(msg)
- ..("B:[bucket_count] P:[length(second_queue)] H:[length(hashes)] C:[length(clienttime_timers)] S:[length(timer_id_dict)] RST:[bucket_reset_count]")
+/datum/controller/subsystem/timer/get_stat_details()
+ return "B:[bucket_count] P:[length(second_queue)] H:[length(hashes)] C:[length(clienttime_timers)] S:[length(timer_id_dict)] RST:[bucket_reset_count]"
/datum/controller/subsystem/timer/proc/dump_timer_buckets(full = TRUE)
var/list/to_log = list("Timer bucket reset. world.time: [world.time], head_offset: [head_offset], practical_offset: [practical_offset]")
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index 70959d97e12..924fb8d6fc5 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -167,6 +167,7 @@ GLOBAL_LIST_INIT(admin_verbs_debug, list(
/client/proc/uid_log,
/client/proc/visualise_active_turfs,
/client/proc/reestablish_db_connection,
+ /client/proc/ss_breakdown,
#ifdef REFERENCE_TRACKING
/datum/proc/find_refs,
/datum/proc/qdel_then_find_references,
@@ -282,6 +283,7 @@ GLOBAL_LIST_INIT(admin_verbs_maintainer, list(
verbs += /client/proc/cmd_display_del_log_simple
verbs += /client/proc/toggledebuglogs
verbs += /client/proc/debug_variables /*allows us to -see- the variables of any instance in the game. +VAREDIT needed to modify*/
+ verbs += /client/proc/ss_breakdown
spawn(1) // This setting exposes the profiler for people with R_VIEWRUNTIMES. They must still have it set in cfg/admin.txt
control_freak = 0
diff --git a/code/modules/client/client_defines.dm b/code/modules/client/client_defines.dm
index 2d0ffc409e1..c038386c303 100644
--- a/code/modules/client/client_defines.dm
+++ b/code/modules/client/client_defines.dm
@@ -65,6 +65,9 @@
//datum that controls the displaying and hiding of tooltips
var/datum/tooltip/tooltips
+ // Overlay for showing debug info
+ var/obj/screen/debugtextholder/debug_text_overlay
+
/// Persistent storage for the flavour text of examined atoms.
var/list/description_holders = list()
diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm
index 1703fc3b018..71383b098f5 100644
--- a/code/modules/client/client_procs.dm
+++ b/code/modules/client/client_procs.dm
@@ -415,6 +415,7 @@
/client/Destroy()
announce_leave() // Do not put this below
+ SSdebugview.stop_processing(src)
if(holder)
holder.owner = null
GLOB.admins -= src
diff --git a/code/modules/keybindings/bindings_admin.dm b/code/modules/keybindings/bindings_admin.dm
index 695a5c6baef..90ad3b3be67 100644
--- a/code/modules/keybindings/bindings_admin.dm
+++ b/code/modules/keybindings/bindings_admin.dm
@@ -1,5 +1,14 @@
/datum/admins/key_down(_key, client/user)
switch(_key)
+ if("F3")
+ if(user.keys_held["Shift"])
+ if(!check_rights(R_DEBUG|R_VIEWRUNTIMES))
+ return
+ if(user in SSdebugview.processing)
+ SSdebugview.stop_processing(user)
+ else
+ SSdebugview.start_processing(user)
+ return
if("F5")
user.get_admin_say()
return
diff --git a/code/modules/keybindings/bindings_client.dm b/code/modules/keybindings/bindings_client.dm
index a224e630df3..f59f12bdee7 100644
--- a/code/modules/keybindings/bindings_client.dm
+++ b/code/modules/keybindings/bindings_client.dm
@@ -58,11 +58,13 @@
adminhelp()
return
if("F2") // Screenshot. Hold shift to choose a name and location to save in
+ // AA 2022-06-23 - What the heck is the above comment here
ooc()
return
- if("F3")
- mob.say_wrapper()
- return
+ if("F3") // Who the hell uses F3 to say
+ if(!keys_held["Shift"]) // Shift+F3 shows admin debug menu
+ mob.say_wrapper()
+ return
if("F4")
mob.me_wrapper()
return
diff --git a/paradise.dme b/paradise.dme
index 3c95d85b24b..cd94244ab1c 100644
--- a/paradise.dme
+++ b/paradise.dme
@@ -233,6 +233,7 @@
#include "code\controllers\subsystem\chat_pings.dm"
#include "code\controllers\subsystem\cleanup.dm"
#include "code\controllers\subsystem\dbcore.dm"
+#include "code\controllers\subsystem\debugview.dm"
#include "code\controllers\subsystem\discord.dm"
#include "code\controllers\subsystem\events.dm"
#include "code\controllers\subsystem\fires.dm"