[MIRROR] fixes verbs not actually queuing. [MDB IGNORE] (#15444)

* fixes verbs not actually queuing.  (#68990)

thanks to Vallat for pointing this out

whoops turns out most verbs havent been queued since may 11th because I made /datum/controller/subsystem/verb_manager have the SS_NO_INIT flag, without also removing a check in verb_manager/proc/can_queue_verb() that stops the verb callback from being queued if the subsystem isnt initialized yet. since subsystems with SS_NO_INIT obviously never have initialized set to TRUE, this always failed for every verb manager subsystem except for SSinput (because it doesnt have SS_NO_INIT).

also adds a debug var to force a subsystem to always queue incoming verbs if possible.

now the default verb management subsystem, and speech_controller will successfully queue verbs again. SSinput always queued verbs so that shouldnt change.

* fixes verbs not actually queuing.

Co-authored-by: Kylerace <kylerlumpkin1@gmail.com>
This commit is contained in:
SkyratBot
2022-08-07 06:51:38 +02:00
committed by GitHub
parent 75e992b517
commit 6ef42d16d7
4 changed files with 58 additions and 18 deletions

View File

@@ -65,9 +65,16 @@ VERB_MANAGER_SUBSYSTEM_DEF(input)
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)
@@ -83,16 +90,11 @@ VERB_MANAGER_SUBSYSTEM_DEF(input)
verb_queue.Cut() //is ran all the way through every run, no exceptions
for(var/mob/user in GLOB.keyloop_list)
moves_this_run += user.focus?.keyLoop(user.client)//only increments if a player changes their movement input from the last tick
clicks_per_second = MC_AVG_SECONDS(clicks_per_second, current_clicks, wait TICKS)
delayed_clicks_per_second = MC_AVG_SECONDS(delayed_clicks_per_second, deferred_clicks_this_run, wait TICKS)
movements_per_second = MC_AVG_SECONDS(movements_per_second, moves_this_run, wait TICKS)
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)])"
. += "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)])"

View File

@@ -46,6 +46,9 @@ SUBSYSTEM_DEF(verb_manager)
///for obvious reasons dont make this be TRUE on the code level this is for admins to turn on
var/message_admins_on_queue = FALSE
///always queue if possible. overides can_queue_admin_verbs but not FOR_ADMINS_IF_VERBS_FUCKED_immediately_execute_all_verbs
var/always_queue = FALSE
/**
* queue a callback for the given verb/verblike proc and any given arguments to the specified verb subsystem, so that they process in the next tick.
* intended to only work with verbs or verblike procs called directly from client input, use as part of TRY_QUEUE_VERB() and co.
@@ -53,14 +56,30 @@ SUBSYSTEM_DEF(verb_manager)
* returns TRUE if the queuing was successful, FALSE otherwise.
*/
/proc/_queue_verb(datum/callback/verb_callback/incoming_callback, tick_check, datum/controller/subsystem/verb_manager/subsystem_to_use = SSverb_manager, ...)
if(TICK_USAGE < tick_check \
|| QDELETED(incoming_callback) \
|| QDELETED(incoming_callback.object) \
|| !ismob(usr) \
|| QDELING(usr))
if(QDELETED(incoming_callback) \
|| QDELETED(incoming_callback.object))
stack_trace("_queue_verb() returned false because it was given an invalid callback!")
return FALSE
//we want unit tests to be able to directly call verbs that attempt to queue, and since unit tests should test internal behavior, we want the queue
//to happen as if it was actually from player input if its called on a mob.
#ifdef UNIT_TESTS
if(QDELETED(usr) && ismob(incoming_callback.object))
incoming_callback.user = WEAKREF(incoming_callback.object)
var/datum/callback/new_us = CALLBACK(arglist(list(GLOBAL_PROC, /proc/_queue_verb) + args.Copy()))
return world.push_usr(incoming_callback.object, new_us)
#endif
//debatable whether this is needed, this is just to try and ensure that you dont use this to queue stuff that isnt from player input.
if(QDELETED(usr))
stack_trace("_queue_verb() returned false because it wasnt called from player input!")
return FALSE
if(!istype(subsystem_to_use))
stack_trace("_queue_verb() returned false because it was given an invalid subsystem to queue for!")
return FALSE
if((TICK_USAGE < tick_check) && !subsystem_to_use.always_queue)
return FALSE
var/list/args_to_check = args.Copy()
@@ -80,9 +99,12 @@ SUBSYSTEM_DEF(verb_manager)
* in TRY_QUEUE_VERB() and co.
*/
/datum/controller/subsystem/verb_manager/proc/can_queue_verb(datum/callback/verb_callback/incoming_callback)
if(usr.client?.holder && !can_queue_admin_verbs \
if(always_queue && !FOR_ADMINS_IF_VERBS_FUCKED_immediately_execute_all_verbs)
return TRUE
if((usr.client?.holder && !can_queue_admin_verbs) \
|| (!initialized && !(flags & SS_NO_INIT)) \
|| FOR_ADMINS_IF_VERBS_FUCKED_immediately_execute_all_verbs \
|| !initialized \
|| !(runlevels & Master.current_runlevel))
return FALSE
@@ -102,6 +124,12 @@ SUBSYSTEM_DEF(verb_manager)
return TRUE
/datum/controller/subsystem/verb_manager/fire(resumed)
run_verb_queue()
/// runs through all of this subsystems queue of verb callbacks.
/// goes through the entire verb queue without yielding.
/// used so you can flush the queue outside of fire() without interfering with anything else subtype subsystems might do in fire().
/datum/controller/subsystem/verb_manager/proc/run_verb_queue()
var/executed_verbs = 0
for(var/datum/callback/verb_callback/verb_callback as anything in verb_queue)
@@ -113,7 +141,8 @@ SUBSYSTEM_DEF(verb_manager)
executed_verbs++
verb_queue.Cut()
verbs_executed_per_second = MC_AVG_SECONDS(verbs_executed_per_second, executed_verbs, wait TICKS)
verbs_executed_per_second = MC_AVG_SECONDS(verbs_executed_per_second, executed_verbs, wait SECONDS)
//note that wait SECONDS is incorrect if this is called outside of fire() but because byond is garbage i need to add a timer to rustg to find a valid solution
/datum/controller/subsystem/verb_manager/stat_entry(msg)
. = ..()