Files
Paradise/code/datums/callback.dm
Vi3trice caee0ec975 [TM] Verb Queue - Port of TG SSverb subsystem (#19863)
* Some verbs queue up now

* Damn you 515

* Screw you Topic

* Update client_procs.dm

* Fixes for unit testing

* Update MC.dm

* verb

* Update callback.dm

* Tweaks

* Linters might not have liked that,

* More tweaks, and fix

* Update verb_manager.dm
2023-01-29 15:05:38 +01:00

108 lines
3.4 KiB
Plaintext

/*
USAGE:
var/datum/callback/C = new(object|null, PROC_REF(procname)|GLOBAL_PROC_REF(procname)|TYPE_PROC_REF(type, procname), arg1, arg2, ... argn)
var/timerid = addtimer(C, time, timertype)
OR
var/timerid = addtimer(CALLBACK(object|null, PROC_REF(procname)|GLOBAL_PROC_REF(procname)|TYPE_PROC_REF(type, procname), arg1, arg2, ... argn), time, timertype)
Note: proc strings can only be given for datum proc calls, global procs must be proc paths
Also proc strings are strongly advised against because they don't compile error if the proc stops existing
See the note on proc typepath shortcuts
INVOKING THE CALLBACK:
var/result = C.Invoke(args, to, add) //additional args are added after the ones given when the callback was created
OR
var/result = C.InvokeAsync(args, to, add) //Sleeps will not block, returns . on the first sleep (then continues on in the "background" after the sleep/block ends), otherwise operates normally.
OR
INVOKE_ASYNC(<CALLBACK args>) to immediately create and call InvokeAsync
PROC TYPEPATH SHORTCUTS (these operate on paths, not types, so to these shortcuts, datum is NOT a parent of atom, etc...)
global proc:
GLOBAL_PROC_REF(procname)
Example:
CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(some_proc_here))
proc defined on current(src) object:
PROC_REF(procname)
Example:
CALLBACK(src, PROC_REF(some_proc_here))
proc defined on some other type:
TYPE_PROC_REF(some_type, procname)
Example:
CALLBACK(other_atom, TYPE_PROC_REF(other_atom_type, procname)
*/
/datum/callback
var/datum/object = GLOBAL_PROC
var/delegate
var/list/arguments
var/usr_uid
/datum/callback/New(thingtocall, proctocall, ...)
if(thingtocall)
object = thingtocall
delegate = proctocall
if(length(args) > 2)
arguments = args.Copy(3)
if(usr)
usr_uid = usr.UID()
/proc/ImmediateInvokeAsync(thingtocall, proctocall, ...)
set waitfor = FALSE
if(!thingtocall)
return
var/list/calling_arguments = length(args) > 2 ? args.Copy(3) : null
if(thingtocall == GLOBAL_PROC)
call(proctocall)(arglist(calling_arguments))
else
call(thingtocall, proctocall)(arglist(calling_arguments))
/datum/callback/proc/Invoke(...)
if(!usr && usr_uid)
var/mob/M = locateUID(usr_uid)
if(M)
if(length(args))
return world.invoke_callback_with_usr(arglist(list(M, src) + args))
return world.invoke_callback_with_usr(M, src)
if(!object)
return
var/list/calling_arguments = arguments
if(length(args))
if(length(arguments))
calling_arguments = calling_arguments + args //not += so that it creates a new list so the arguments list stays clean
else
calling_arguments = args
if(object == GLOBAL_PROC)
return call(delegate)(arglist(calling_arguments))
return call(object, delegate)(arglist(calling_arguments))
//copy and pasted because fuck proc overhead
/datum/callback/proc/InvokeAsync(...)
set waitfor = FALSE
if(!usr && usr_uid)
var/mob/M = locateUID(usr_uid)
if(M)
if(length(args))
return world.invoke_callback_with_usr(arglist(list(M, src) + args))
return world.invoke_callback_with_usr(M, src)
if(!object)
return
var/list/calling_arguments = arguments
if(length(args))
if(length(arguments))
calling_arguments = calling_arguments + args //not += so that it creates a new list so the arguments list stays clean
else
calling_arguments = args
if(object == GLOBAL_PROC)
return call(delegate)(arglist(calling_arguments))
return call(object, delegate)(arglist(calling_arguments))