mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-21 23:24:20 +00:00
makes say_verb() not execute immediately and instead put itself in the queue of the subsystem meant to process it: SSspeech_controller so that it executes at the start of the next tick during the MC's run instead of outside of it.
i considered making this part of #61422 (d005d76f0b) but this is good regardless of how that one pans out and i already overstuffed that one.
tldr the REAL cause of get_hearers_in_view() overtime is an effect of how byond schedules verbs within the tick.
when the server is overloaded there isnt much time between when SendMaps finishes and when the next tick was supposed to start, but verbs still need to be executed. So verbs will eat into the time the next tick should have started and the MC cant compensate for it at all since it uses byonds internal tick scheduler instead of our external tick scheduler.
55 lines
2.2 KiB
Plaintext
55 lines
2.2 KiB
Plaintext
SUBSYSTEM_DEF(speech_controller)
|
|
name = "Speech Controller"
|
|
wait = 1
|
|
flags = SS_TICKER
|
|
priority = FIRE_PRIORITY_SPEECH_CONTROLLER//has to be high priority, second in priority ONLY to SSinput
|
|
init_order = INIT_ORDER_SPEECH_CONTROLLER
|
|
runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY
|
|
|
|
///used so that an admin can force all speech verbs to execute immediately instead of queueing
|
|
var/FOR_ADMINS_IF_BROKE_immediately_execute_all_speech = FALSE
|
|
|
|
///list of the form: list(client mob, message that mob is queued to say, other say arguments (if any)).
|
|
///this is our process queue, processed every tick.
|
|
var/list/queued_says_to_execute = list()
|
|
|
|
///queues mob_to_queue into our process list so they say(message) near the start of the next tick
|
|
/datum/controller/subsystem/speech_controller/proc/queue_say_for_mob(mob/mob_to_queue, message, message_type)
|
|
|
|
if(!TICK_CHECK || FOR_ADMINS_IF_BROKE_immediately_execute_all_speech)
|
|
process_single_say(mob_to_queue, message, message_type)
|
|
return TRUE
|
|
|
|
queued_says_to_execute += list(list(mob_to_queue, message, message_type))
|
|
|
|
return TRUE
|
|
|
|
/datum/controller/subsystem/speech_controller/fire(resumed)
|
|
|
|
/// cache for sanic speed (lists are references anyways)
|
|
var/list/says_to_process = queued_says_to_execute.Copy()
|
|
queued_says_to_execute.Cut()//we should be going through the entire list every single iteration
|
|
|
|
for(var/list/say_to_process as anything in says_to_process)
|
|
|
|
var/mob/mob_to_speak = say_to_process[MOB_INDEX]//index 1 is the mob, 2 is the message, 3 is the message category
|
|
var/message = say_to_process[MESSAGE_INDEX]
|
|
var/message_category = say_to_process[CATEGORY_INDEX]
|
|
|
|
process_single_say(mob_to_speak, message, message_category)
|
|
|
|
///used in fire() to process a single mobs message through the relevant proc.
|
|
///only exists so that sleeps in the message pipeline dont cause the whole queue to wait
|
|
/datum/controller/subsystem/speech_controller/proc/process_single_say(mob/mob_to_speak, message, message_category)
|
|
set waitfor = FALSE
|
|
|
|
switch(message_category)
|
|
if(SPEECH_CONTROLLER_QUEUE_SAY_VERB)
|
|
mob_to_speak.say(message)
|
|
|
|
if(SPEECH_CONTROLLER_QUEUE_WHISPER_VERB)
|
|
mob_to_speak.whisper(message)
|
|
|
|
if(SPEECH_CONTROLLER_QUEUE_EMOTE_VERB)
|
|
mob_to_speak.emote("me",1,message,TRUE)
|