Files
Bubberstation/code/controllers/subsystem/input.dm
Kylerace 293e85f94b fixes & increases SSinput click delay threshold & moves it and average_click_delay to deciseconds (#71520)
## About The Pull Request
theres an issue with SSinput calculating the average_click_delay that
made it skip queuing clicks much faster than it should have. now it
should work. also moves everything to deciseconds for consistency
(except for the statpanel display, which changes it to per second). also
i increased the click delay threshold to 1 tick in deciseconds because
really we should only be refusing to queue if SSinput is being skipped
for whatever reason or each tick is receiving massive non input overtime
## Why It's Good For The Game
feex queuing clicks to lower overtime when the server is overloaded
## Changelog
🆑
fix: queuing clicks should work correctly now
/🆑
2022-12-06 00:59:11 -08: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)))
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 / (1 SECONDS),0.01)])"