diff --git a/code/controllers/subsystem/input.dm b/code/controllers/subsystem/input.dm index 78c8ad19917e..f3edbabbc6a1 100644 --- a/code/controllers/subsystem/input.dm +++ b/code/controllers/subsystem/input.dm @@ -139,7 +139,7 @@ VERB_MANAGER_SUBSYSTEM_DEF(input) 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, (REALTIMEOFDAY - queued_click.creation_time)) + 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++ diff --git a/code/controllers/subsystem/verb_manager.dm b/code/controllers/subsystem/verb_manager.dm index 2095b57dcd4a..438916b5ae85 100644 --- a/code/controllers/subsystem/verb_manager.dm +++ b/code/controllers/subsystem/verb_manager.dm @@ -56,9 +56,24 @@ 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(QDELETED(incoming_callback) \ - || QDELETED(incoming_callback.object)) - stack_trace("_queue_verb() returned false because it was given an invalid callback!") + if(QDELETED(incoming_callback)) + var/destroyed_string + if(!incoming_callback) + destroyed_string = "callback is null." + else + destroyed_string = "callback was deleted [DS2TICKS(world.time - incoming_callback.gc_destroyed)] ticks ago. callback was created [DS2TICKS(world.time) - incoming_callback.creation_time] ticks ago." + + stack_trace("_queue_verb() returned false because it was given a deleted callback! [destroyed_string]") + return FALSE + + if(!istext(incoming_callback.object) && QDELETED(incoming_callback.object)) //just in case the object is GLOBAL_PROC + var/destroyed_string + if(!incoming_callback.object) + destroyed_string = "callback.object is null." + else + destroyed_string = "callback.object was deleted [DS2TICKS(world.time - incoming_callback.object.gc_destroyed)] ticks ago. callback was created [DS2TICKS(world.time) - incoming_callback.creation_time] ticks ago." + + stack_trace("_queue_verb() returned false because it was given a callback acting on a qdeleted object! [destroyed_string]") 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 diff --git a/code/datums/verb_callbacks.dm b/code/datums/verb_callbacks.dm index 4741963ebaf8..6468974260f7 100644 --- a/code/datums/verb_callbacks.dm +++ b/code/datums/verb_callbacks.dm @@ -1,8 +1,8 @@ ///like normal callbacks but they also record their creation time for measurement purposes /datum/callback/verb_callback - ///the REALTIMEOFDAY this callback datum was created in. used for testing latency + ///the tick this callback datum was created in. used for testing latency var/creation_time = 0 /datum/callback/verb_callback/New(thingtocall, proctocall, ...) - creation_time = REALTIMEOFDAY + creation_time = DS2TICKS(world.time) . = ..() diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index 5d6ed064fea7..102f2ca9ecbb 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -909,7 +909,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( //check if the server is overloaded and if it is then queue up the click for next tick //yes having it call a wrapping proc on the subsystem is fucking stupid glad we agree unfortunately byond insists its reasonable - if(TRY_QUEUE_VERB(VERB_CALLBACK(object, /atom/proc/_Click, location, control, params), VERB_HIGH_PRIORITY_QUEUE_THRESHOLD, SSinput, control)) + if(!QDELETED(object) && TRY_QUEUE_VERB(VERB_CALLBACK(object, /atom/proc/_Click, location, control, params), VERB_HIGH_PRIORITY_QUEUE_THRESHOLD, SSinput, control)) return if (prefs.hotkeys)