Files
Bubberstation/code/controllers/subsystem/input.dm
SkyratBot 75c5d3d10d [MIRROR] fixes _queue_verb() runtiming from /client/Click() thousands of times [MDB IGNORE] (#17034)
* fixes _queue_verb() runtiming from /client/Click() thousands of times (#70647)

* fixes _queue_verb() runtiming from /client/Click() and adds info

* Update code/controllers/subsystem/verb_manager.dm

Co-authored-by: Mothblocks <35135081+Mothblocks@ users.noreply.github.com>

Co-authored-by: Mothblocks <35135081+Mothblocks@ users.noreply.github.com>

* fixes _queue_verb() runtiming from /client/Click() thousands of times

Co-authored-by: Kylerace <kylerlumpkin1@gmail.com>
Co-authored-by: Mothblocks <35135081+Mothblocks@ users.noreply.github.com>
2022-10-20 12:29:05 +01:00

101 lines
3.9 KiB
Plaintext

VERB_MANAGER_SUBSYSTEM_DEF(input)
name = "Input"
init_order = INIT_ORDER_INPUT
init_stage = INITSTAGE_EARLY
flags = SS_TICKER
priority = FIRE_PRIORITY_INPUT
runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY
use_default_stats = FALSE
var/list/macro_set
///running average of how many clicks inputted by a player the server processes every second. used for the subsystem stat entry
var/clicks_per_second = 0
///count of how many clicks onto atoms have elapsed before being cleared by fire(). used to average with clicks_per_second.
var/current_clicks = 0
///acts like clicks_per_second but only counts the clicks actually processed by SSinput itself while clicks_per_second counts all clicks
var/delayed_clicks_per_second = 0
///running average of how many movement iterations from player input the server processes every second. used for the subsystem stat entry
var/movements_per_second = 0
///running average of the amount of real time clicks take to truly execute after the command is originally sent to the server.
///if a click isnt delayed at all then it counts as 0 deciseconds.
var/average_click_delay = 0
/datum/controller/subsystem/verb_manager/input/Initialize()
setup_default_macro_sets()
initialized = TRUE
refresh_client_macro_sets()
return SS_INIT_SUCCESS
// This is for when macro sets are eventualy datumized
/datum/controller/subsystem/verb_manager/input/proc/setup_default_macro_sets()
macro_set = list(
"Any" = "\"KeyDown \[\[*\]\]\"",
"Any+UP" = "\"KeyUp \[\[*\]\]\"",
"Back" = "\".winset \\\"input.text=\\\"\\\"\\\"\"",
"Tab" = "\".winset \\\"input.focus=true?map.focus=true:input.focus=true\\\"\"",
"Escape" = "Reset-Held-Keys",
)
// Badmins just wanna have fun ♪
/datum/controller/subsystem/verb_manager/input/proc/refresh_client_macro_sets()
var/list/clients = GLOB.clients
for(var/i in 1 to clients.len)
var/client/user = clients[i]
user.set_macros()
/datum/controller/subsystem/verb_manager/input/can_queue_verb(datum/callback/verb_callback/incoming_callback, control)
//make sure the incoming verb is actually something we specifically want to handle
if(control != "mapwindow.map")
return FALSE
if(average_click_delay >= MAXIMUM_CLICK_LATENCY || !..())
current_clicks++
average_click_delay = MC_AVG_FAST_UP_SLOW_DOWN(average_click_delay, 0)
return FALSE
return TRUE
///stupid workaround for byond not recognizing the /atom/Click typepath for the queued click callbacks
/atom/proc/_Click(location, control, params)
if(usr)
Click(location, control, params)
/datum/controller/subsystem/verb_manager/input/fire()
..()
var/moves_this_run = 0
for(var/mob/user in GLOB.keyloop_list)
moves_this_run += user.focus?.keyLoop(user.client)//only increments if a player moves due to their own input
movements_per_second = MC_AVG_SECONDS(movements_per_second, moves_this_run, wait TICKS)
/datum/controller/subsystem/verb_manager/input/run_verb_queue()
var/deferred_clicks_this_run = 0 //acts like current_clicks but doesnt count clicks that dont get processed by SSinput
for(var/datum/callback/verb_callback/queued_click as anything in verb_queue)
if(!istype(queued_click))
stack_trace("non /datum/callback/verb_callback instance inside SSinput's verb_queue!")
continue
average_click_delay = MC_AVG_FAST_UP_SLOW_DOWN(average_click_delay, TICKS2DS((DS2TICKS(world.time) - queued_click.creation_time)) SECONDS)
queued_click.InvokeAsync()
current_clicks++
deferred_clicks_this_run++
verb_queue.Cut() //is ran all the way through every run, no exceptions
clicks_per_second = MC_AVG_SECONDS(clicks_per_second, current_clicks, wait SECONDS)
delayed_clicks_per_second = MC_AVG_SECONDS(delayed_clicks_per_second, deferred_clicks_this_run, wait SECONDS)
current_clicks = 0
/datum/controller/subsystem/verb_manager/input/stat_entry(msg)
. = ..()
. += "M/S:[round(movements_per_second,0.01)] | C/S:[round(clicks_per_second,0.01)] ([round(delayed_clicks_per_second,0.01)] | CD: [round(average_click_delay,0.01)])"