mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-02-08 23:39:32 +00:00
## About The Pull Request Rewrite ticker `Reboot` proc slightly to use a timer and callback for the delay before the reboot, tracks this timer in the stat panel for players to see. Also adds a verb to cancel a pending reboot independent of the delay round end verb. ## Why It's Good For The Game It's nice to be able to see exactly how much time is left until the server restarts, and it's even nicer to see that the round end has been delayed when the "admin has delayed round end" message gets buried in a fast moving chat. ## Changelog 🆑 qol: The time until the server reboots is now visible in the status tab. admin: Added a cancel reboot verb to the server tab. /🆑
253 lines
9.4 KiB
Plaintext
253 lines
9.4 KiB
Plaintext
SUBSYSTEM_DEF(statpanels)
|
|
name = "Stat Panels"
|
|
wait = 4
|
|
init_order = INIT_ORDER_STATPANELS
|
|
init_stage = INITSTAGE_EARLY
|
|
priority = FIRE_PRIORITY_STATPANEL
|
|
runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY
|
|
flags = SS_NO_INIT
|
|
var/list/currentrun = list()
|
|
var/list/global_data
|
|
var/list/mc_data
|
|
|
|
///how many subsystem fires between most tab updates
|
|
var/default_wait = 10
|
|
///how many subsystem fires between updates of the status tab
|
|
var/status_wait = 2
|
|
///how many subsystem fires between updates of the MC tab
|
|
var/mc_wait = 5
|
|
///how many full runs this subsystem has completed. used for variable rate refreshes.
|
|
var/num_fires = 0
|
|
|
|
/datum/controller/subsystem/statpanels/fire(resumed = FALSE)
|
|
if (!resumed)
|
|
num_fires++
|
|
var/datum/map_config/cached = SSmap_vote.next_map_config
|
|
global_data = list(
|
|
"Map: [SSmapping.current_map?.map_name || "Loading..."]",
|
|
cached ? "Next Map: [cached.map_name]" : null,
|
|
"Round ID: [GLOB.round_id ? GLOB.round_id : "NULL"]",
|
|
"Server Time: [time2text(world.timeofday, "YYYY-MM-DD hh:mm:ss")]",
|
|
"Round Time: [ROUND_TIME()]",
|
|
"Station Time: [station_time_timestamp()]",
|
|
"Time Dilation: [round(SStime_track.time_dilation_current,1)]% AVG:([round(SStime_track.time_dilation_avg_fast,1)]%, [round(SStime_track.time_dilation_avg,1)]%, [round(SStime_track.time_dilation_avg_slow,1)]%)"
|
|
)
|
|
|
|
if(SSshuttle.emergency)
|
|
var/ETA = SSshuttle.emergency.getModeStr()
|
|
if(ETA)
|
|
global_data += "[ETA] [SSshuttle.emergency.getTimerStr()]"
|
|
|
|
if(SSticker.reboot_timer)
|
|
var/reboot_time = timeleft(SSticker.reboot_timer)
|
|
if(reboot_time)
|
|
global_data += "Reboot: [DisplayTimeText(reboot_time, 1)]"
|
|
// admin must have delayed round end
|
|
else if(SSticker.ready_for_reboot)
|
|
global_data += "Reboot: DELAYED"
|
|
|
|
src.currentrun = GLOB.clients.Copy()
|
|
mc_data = null
|
|
|
|
var/list/currentrun = src.currentrun
|
|
while(length(currentrun))
|
|
var/client/target = currentrun[length(currentrun)]
|
|
currentrun.len--
|
|
|
|
if(!target.stat_panel.is_ready())
|
|
continue
|
|
|
|
if(target.stat_tab == "Status" && num_fires % status_wait == 0)
|
|
set_status_tab(target)
|
|
|
|
if(!target.holder)
|
|
target.stat_panel.send_message("remove_admin_tabs")
|
|
else
|
|
target.stat_panel.send_message("update_split_admin_tabs", !!(target.prefs.toggles & SPLIT_ADMIN_TABS))
|
|
|
|
if(!("MC" in target.panel_tabs) || !("Tickets" in target.panel_tabs))
|
|
target.stat_panel.send_message("add_admin_tabs", target.holder.href_token)
|
|
|
|
if(target.stat_tab == "MC" && ((num_fires % mc_wait == 0) || target?.prefs.read_preference(/datum/preference/toggle/fast_mc_refresh)))
|
|
set_MC_tab(target)
|
|
|
|
if(target.stat_tab == "Tickets" && num_fires % default_wait == 0)
|
|
set_tickets_tab(target)
|
|
|
|
if(!length(GLOB.sdql2_queries) && ("SDQL2" in target.panel_tabs))
|
|
target.stat_panel.send_message("remove_sdql2")
|
|
|
|
else if(length(GLOB.sdql2_queries) && (target.stat_tab == "SDQL2" || !("SDQL2" in target.panel_tabs)) && num_fires % default_wait == 0)
|
|
set_SDQL2_tab(target)
|
|
|
|
if(target.mob)
|
|
var/mob/target_mob = target.mob
|
|
|
|
// Handle the action panels of the stat panel
|
|
|
|
var/update_actions = FALSE
|
|
// We're on a spell tab, update the tab so we can see cooldowns progressing and such
|
|
if(target.stat_tab in target.spell_tabs)
|
|
update_actions = TRUE
|
|
// We're not on a spell tab per se, but we have cooldown actions, and we've yet to
|
|
// set up our spell tabs at all
|
|
if(!length(target.spell_tabs) && locate(/datum/action/cooldown) in target_mob.actions)
|
|
update_actions = TRUE
|
|
|
|
if(update_actions && num_fires % default_wait == 0)
|
|
set_action_tabs(target, target_mob)
|
|
|
|
if(MC_TICK_CHECK)
|
|
return
|
|
|
|
/datum/controller/subsystem/statpanels/proc/set_status_tab(client/target)
|
|
#if MIN_COMPILER_VERSION > 515
|
|
#warn 516 is most certainly out of beta, remove this beta notice if you haven't already
|
|
#endif
|
|
var/static/list/beta_notice = list("", "You are on the BYOND 516 beta, various UIs and such may be broken!", "Please report issues, and switch back to BYOND 515 if things are causing too many issues for you.")
|
|
if(!global_data)//statbrowser hasnt fired yet and we were called from immediate_send_stat_data()
|
|
return
|
|
target.stat_panel.send_message("update_stat", list(
|
|
"global_data" = (target.byond_version < 516) ? global_data : (global_data + beta_notice),
|
|
"ping_str" = "Ping: [round(target.lastping, 1)]ms (Average: [round(target.avgping, 1)]ms)",
|
|
"other_str" = target.mob?.get_status_tab_items(),
|
|
))
|
|
|
|
/datum/controller/subsystem/statpanels/proc/set_MC_tab(client/target)
|
|
var/turf/eye_turf = get_turf(target.eye)
|
|
var/coord_entry = COORD(eye_turf)
|
|
if(!mc_data)
|
|
generate_mc_data()
|
|
target.stat_panel.send_message("update_mc", list("mc_data" = mc_data, "coord_entry" = coord_entry))
|
|
|
|
/datum/controller/subsystem/statpanels/proc/set_tickets_tab(client/target)
|
|
var/list/ahelp_tickets = GLOB.ahelp_tickets.stat_entry()
|
|
target.stat_panel.send_message("update_tickets", ahelp_tickets)
|
|
var/datum/interview_manager/m = GLOB.interviews
|
|
|
|
// get open interview count
|
|
var/dc = 0
|
|
for (var/ckey in m.open_interviews)
|
|
var/datum/interview/current_interview = m.open_interviews[ckey]
|
|
if (current_interview && !current_interview.owner)
|
|
dc++
|
|
var/stat_string = "([m.open_interviews.len - dc] online / [dc] disconnected)"
|
|
|
|
// Prepare each queued interview
|
|
var/list/queued = list()
|
|
for (var/datum/interview/queued_interview in m.interview_queue)
|
|
queued += list(list(
|
|
"ref" = REF(queued_interview),
|
|
"status" = "\[[queued_interview.pos_in_queue]\]: [queued_interview.owner_ckey][!queued_interview.owner ? " (DC)": ""] \[INT-[queued_interview.id]\]"
|
|
))
|
|
|
|
var/list/data = list(
|
|
"status" = list(
|
|
"Active:" = "[m.open_interviews.len] [stat_string]",
|
|
"Queued:" = "[m.interview_queue.len]",
|
|
"Closed:" = "[m.closed_interviews.len]"),
|
|
"interviews" = queued
|
|
)
|
|
|
|
// Push update
|
|
target.stat_panel.send_message("update_interviews", data)
|
|
|
|
/datum/controller/subsystem/statpanels/proc/set_SDQL2_tab(client/target)
|
|
var/list/sdql2A = list()
|
|
sdql2A[++sdql2A.len] = list("", "Access Global SDQL2 List", REF(GLOB.sdql2_vv_statobj))
|
|
var/list/sdql2B = list()
|
|
for(var/datum/sdql2_query/query as anything in GLOB.sdql2_queries)
|
|
sdql2B = query.generate_stat()
|
|
|
|
sdql2A += sdql2B
|
|
target.stat_panel.send_message("update_sdql2", sdql2A)
|
|
|
|
/// Set up the various action tabs.
|
|
/datum/controller/subsystem/statpanels/proc/set_action_tabs(client/target, mob/target_mob)
|
|
var/list/actions = target_mob.get_actions_for_statpanel()
|
|
target.spell_tabs.Cut()
|
|
|
|
for(var/action_data in actions)
|
|
target.spell_tabs |= action_data[1]
|
|
|
|
target.stat_panel.send_message("update_spells", list(spell_tabs = target.spell_tabs, actions = actions))
|
|
|
|
|
|
/datum/controller/subsystem/statpanels/proc/generate_mc_data()
|
|
mc_data = list(
|
|
list("CPU:", world.cpu),
|
|
list("Instances:", "[num2text(world.contents.len, 10)]"),
|
|
list("World Time:", "[world.time]"),
|
|
list("Globals:", GLOB.stat_entry(), text_ref(GLOB)),
|
|
list("[config]:", config.stat_entry(), text_ref(config)),
|
|
list("Byond:", "(FPS:[world.fps]) (TickCount:[world.time/world.tick_lag]) (TickDrift:[round(Master.tickdrift,1)]([round((Master.tickdrift/(world.time/world.tick_lag))*100,0.1)]%)) (Internal Tick Usage: [round(MAPTICK_LAST_INTERNAL_TICK_USAGE,0.1)]%)"),
|
|
list("Master Controller:", Master.stat_entry(), text_ref(Master)),
|
|
list("Failsafe Controller:", Failsafe.stat_entry(), text_ref(Failsafe)),
|
|
list("","")
|
|
)
|
|
#if defined(MC_TAB_TRACY_INFO) || defined(SPACEMAN_DMM)
|
|
var/static/tracy_dll
|
|
var/static/tracy_present
|
|
if(isnull(tracy_dll))
|
|
tracy_dll = TRACY_DLL_PATH
|
|
tracy_present = fexists(tracy_dll)
|
|
if(tracy_present)
|
|
if(GLOB.tracy_initialized)
|
|
mc_data.Insert(2, list(list("byond-tracy:", "Active (reason: [GLOB.tracy_init_reason || "N/A"])")))
|
|
else if(GLOB.tracy_init_error)
|
|
mc_data.Insert(2, list(list("byond-tracy:", "Errored ([GLOB.tracy_init_error])")))
|
|
else if(fexists(TRACY_ENABLE_PATH))
|
|
mc_data.Insert(2, list(list("byond-tracy:", "Queued for next round")))
|
|
else
|
|
mc_data.Insert(2, list(list("byond-tracy:", "Inactive")))
|
|
else
|
|
mc_data.Insert(2, list(list("byond-tracy:", "[tracy_dll] not present")))
|
|
#endif
|
|
for(var/datum/controller/subsystem/sub_system as anything in Master.subsystems)
|
|
mc_data[++mc_data.len] = list("\[[sub_system.state_letter()]][sub_system.name]", sub_system.stat_entry(), text_ref(sub_system))
|
|
mc_data[++mc_data.len] = list("Camera Net", "Cameras: [GLOB.cameranet.cameras.len] | Chunks: [GLOB.cameranet.chunks.len]", text_ref(GLOB.cameranet))
|
|
|
|
///immediately update the active statpanel tab of the target client
|
|
/datum/controller/subsystem/statpanels/proc/immediate_send_stat_data(client/target)
|
|
if(!target.stat_panel.is_ready())
|
|
return FALSE
|
|
|
|
if(target.stat_tab == "Status")
|
|
set_status_tab(target)
|
|
return TRUE
|
|
|
|
var/mob/target_mob = target.mob
|
|
|
|
// Handle actions
|
|
|
|
var/update_actions = FALSE
|
|
if(target.stat_tab in target.spell_tabs)
|
|
update_actions = TRUE
|
|
|
|
if(!length(target.spell_tabs) && locate(/datum/action/cooldown) in target_mob.actions)
|
|
update_actions = TRUE
|
|
|
|
if(update_actions)
|
|
set_action_tabs(target, target_mob)
|
|
return TRUE
|
|
|
|
if(!target.holder)
|
|
return FALSE
|
|
|
|
if(target.stat_tab == "MC")
|
|
set_MC_tab(target)
|
|
return TRUE
|
|
|
|
if(target.stat_tab == "Tickets")
|
|
set_tickets_tab(target)
|
|
return TRUE
|
|
|
|
if(!length(GLOB.sdql2_queries) && ("SDQL2" in target.panel_tabs))
|
|
target.stat_panel.send_message("remove_sdql2")
|
|
|
|
else if(length(GLOB.sdql2_queries) && target.stat_tab == "SDQL2")
|
|
set_SDQL2_tab(target)
|
|
|
|
/// Stat panel window declaration
|
|
/client/var/datum/tgui_window/stat_panel
|