Verbs subsystem (#20333)

What it says on the can; now we can better compensate for processing
spikes by queueing and accounting for verb times (assuming we actually
use this framework to invoke the bulk of them). I have added its use to
some of them, more can be ported as time goes on, eventually everything
but the most trivial ones should go through this.

No player facing changes. Hopefully.

Praise be the omnissiah.
This commit is contained in:
Fluffy
2025-01-13 12:17:37 +00:00
committed by GitHub
parent 0890f9a1e1
commit be92376296
16 changed files with 444 additions and 29 deletions
+11 -1
View File
@@ -25,7 +25,8 @@ var/list/localhost_addresses = list(
If you have any questions about this stuff feel free to ask. ~Carn
*/
/client/Topic(href, href_list, hsrc)
//the undocumented 4th argument is for ?[0x\ref] style topic links. hsrc is set to the reference and anything after the ] gets put into hsrc_command
/client/Topic(href, href_list, hsrc, hsrc_command)
if(!usr || usr != mob) //stops us calling Topic for somebody else's client. Also helps prevent usr=null
return
@@ -257,8 +258,17 @@ var/list/localhost_addresses = list(
if(QDELETED(real_src))
return
//fun fact: Topic() acts like a verb and is executed at the end of the tick like other verbs. So we have to queue it if the server is
//overloaded
if(hsrc && hsrc != holder && DEFAULT_TRY_QUEUE_VERB(VERB_CALLBACK(src, PROC_REF(_Topic), hsrc, href, href_list)))
return
..() //redirect to hsrc.Topic()
///dumb workaround because byond doesnt seem to recognize the Topic() typepath for /datum/proc/Topic() from the client Topic,
///so we cant queue it without this
/client/proc/_Topic(datum/hsrc, href, list/href_list)
return hsrc.Topic(href, href_list)
/proc/client_by_ckey(ckey)
return GLOB.directory[ckey]
+1 -1
View File
@@ -67,7 +67,7 @@
/mob/abstract/eye/pointed()
set popup_menu = 0
set src = usr.contents
return 0
return FALSE
/mob/abstract/eye/examine(mob/user, distance, is_adjacent, infix, suffix, show_extended)
SHOULD_CALL_PARENT(FALSE)
@@ -430,11 +430,12 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
W.add_hiddenprint(src)
W.visible_message(SPAN_WARNING("Invisible fingers crudely paint something in blood on [T]..."))
/mob/abstract/ghost/observer/pointed(atom/A as mob|obj|turf in view())
if(!..())
return 0
src.visible_message("<span class='deadsay'><b>[src]</b> points to [A]</span>")
return 1
/mob/abstract/ghost/observer/pointed(atom/pointing_at)
. = ..()
if(!.)
return
src.visible_message("<span class='deadsay'><b>[src]</b> points to [pointing_at]</span>")
/mob/abstract/ghost/observer/proc/manifest(mob/user)
is_manifest = 0
+7 -4
View File
@@ -8,9 +8,7 @@
return
//mob verbs are faster than object verbs. See above.
var/mob/living/next_point_time = 0
/mob/living/pointed(atom/A as mob|obj|turf in view())
/mob/living/_pointed(atom/pointing_at)
if(src.stat || src.restrained())
return FALSE
if(src.status_flags & FAKEDEATH)
@@ -19,7 +17,7 @@ var/mob/living/next_point_time = 0
. = ..()
if(.)
visible_message("<b>\The [src]</b> points to \the [A].")
visible_message("<b>\The [src]</b> points to \the [pointing_at].")
/mob/living/drop_from_inventory(var/obj/item/W, var/atom/target)
. = ..(W, target)
@@ -673,6 +671,11 @@ default behaviour is:
set name = "Resist"
set category = "IC"
DEFAULT_QUEUE_OR_CALL_VERB(VERB_CALLBACK(src, PROC_REF(execute_resist)))
///proc extender of [/mob/living/verb/resist] meant to make the process queable if the server is overloaded when the verb is called
/mob/living/proc/execute_resist()
if(!incapacitated(INCAPACITATION_KNOCKOUT) && canClick())
resist_grab()
if(!weakened)
+24 -12
View File
@@ -382,7 +382,8 @@
set name = "Examine"
set category = "IC"
examinate(usr, A)
//examinate(usr, A)
DEFAULT_QUEUE_OR_CALL_VERB(VERB_CALLBACK(src, GLOBAL_PROC_REF(examinate), src, A))
/mob/proc/can_examine()
if(client?.eye == src)
@@ -407,25 +408,32 @@
set name = "Point To"
set category = "Object"
if(!isturf(src.loc) || !(A in range(world.view, get_turf(src))))
return FALSE
if(next_point_time >= world.time)
return FALSE
DEFAULT_QUEUE_OR_CALL_VERB(VERB_CALLBACK(src, PROC_REF(_pointed), A))
next_point_time = world.time + 25
face_atom(A)
if(isturf(A))
/// possibly delayed verb that finishes the pointing process starting in [/mob/verb/pointed()].
/// either called immediately or in the tick after pointed() was called, as per the [DEFAULT_QUEUE_OR_CALL_VERB()] macro
/mob/proc/_pointed(atom/pointing_at)
if(!isturf(src.loc) || !(pointing_at in range(world.view, get_turf(src))))
return FALSE
if(TIMER_COOLDOWN_RUNNING(src, "point_verb_emote_cooldown"))
return FALSE
else
TIMER_COOLDOWN_START(src, "point_verb_emote_cooldown", 2.5 SECONDS)
face_atom(pointing_at)
if(isturf(pointing_at))
if(pointing_effect)
end_pointing_effect()
pointing_effect = new /obj/effect/decal/point(A)
pointing_effect = new /obj/effect/decal/point(pointing_at)
pointing_effect.set_invisibility(invisibility)
addtimer(CALLBACK(src, PROC_REF(end_pointing_effect), pointing_effect), 2 SECONDS)
else if(!invisibility)
var/atom/movable/M = A
var/atom/movable/M = pointing_at
M.add_filter("pointglow", 1, list(type = "drop_shadow", x = 0, y = -1, offset = 1, size = 1, color = "#F00"))
addtimer(CALLBACK(M, TYPE_PROC_REF(/atom/movable, remove_filter), "pointglow"), 2 SECONDS)
A.handle_pointed_at(src)
SEND_SIGNAL(src, COMSIG_MOB_POINT, A)
pointing_at.handle_pointed_at(src)
SEND_SIGNAL(src, COMSIG_MOB_POINT, pointing_at)
return TRUE
/mob/proc/end_pointing_effect()
@@ -436,6 +444,10 @@
set category = "Object"
set src = usr
DEFAULT_QUEUE_OR_CALL_VERB(VERB_CALLBACK(src, PROC_REF(execute_mode)))
///proc version to finish /mob/verb/mode() execution. used in case the proc needs to be queued for the tick after its first called
/mob/proc/execute_mode()
if(hand)
var/obj/item/W = l_hand
if (W)
+7 -3
View File
@@ -1,6 +1,7 @@
/mob/proc/say(var/message, var/datum/language/speaking = null, var/verb="says", var/alt_name="", var/ghost_hearing = GHOSTS_ALL_HEAR, var/whisper = FALSE)
return
///what clients use to speak. when you type a message into the chat bar in say mode, this is the first thing that goes off serverside.
/mob/verb/say_verb(message as text)
set name = "Say"
set category = "IC"
@@ -14,7 +15,10 @@
if (src.client.handle_spam_prevention(message, MUTE_IC))
return
usr.say(message)
//queue this message because verbs are scheduled to process after SendMaps in the tick and speech is pretty expensive when it happens.
//by queuing this for next tick the mc can compensate for its cost instead of having speech delay the start of the next tick
if(message)
QUEUE_OR_CALL_VERB_FOR(VERB_CALLBACK(src, PROC_REF(say), message), SSspeech_controller)
/mob/verb/me_verb(message as text)
set name = "Me"
@@ -30,9 +34,9 @@
return
if(use_me)
usr.client_emote("me",usr.emote_type,message)
QUEUE_OR_CALL_VERB_FOR(VERB_CALLBACK(src, PROC_REF(client_emote), "me", usr.emote_type, message), SSspeech_controller)
else
usr.emote(message)
QUEUE_OR_CALL_VERB_FOR(VERB_CALLBACK(src, PROC_REF(emote), message), SSspeech_controller)
/mob/proc/say_dead(var/message)
if(say_disabled) //This is here to try to identify lag problems
+1 -2
View File
@@ -329,8 +329,7 @@
window = window,
src_object = src_object)
process_status()
on_act_message(act_type, payload, state)
//DEFAULT_QUEUE_OR_CALL_VERB(VERB_CALLBACK(src, PROC_REF(on_act_message), act_type, payload, state))
DEFAULT_QUEUE_OR_CALL_VERB(VERB_CALLBACK(src, PROC_REF(on_act_message), act_type, payload, state))
return FALSE
switch(type)
if("ready")