Files
2020-02-16 19:40:21 -08:00

89 lines
3.3 KiB
Plaintext

/*
Wire note: I copied and adapted this from MSO's (urgh) published code here: http://www.byond.com/forum/?post=2191707
USAGE:
var/datum/callback/C = new(object|null, /proc/type/path|"procstring", arg1, arg2, ... argn)
var/timerid = addtimer(C, time, timertype)
OR
var/timerid = addtimer(CALLBACK(object|null, /proc/type/path|procstring, 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.
PROC TYPEPATH SHORTCUTS (these operate on paths, not types, so to these shortcuts, datum is NOT a parent of atom, etc...)
proc defined on current(src) object OR overridden at src or any of it's parents:
.procname
Example:
CALLBACK(src, .some_proc_here)
proc defined on parent(of src) object (when the above doesn't apply):
.proc/procname
Example:
CALLBACK(src, .proc/some_proc_here)
global proc while in another global proc:
.procname
Example:
CALLBACK(GLOBAL_PROC, .some_proc_here)
Other wise you will have to do the full typepath of the proc (/type/of/thing/proc/procname)
*/
/datum/callback
var/datum/object = GLOBAL_PROC
var/delegate
var/list/arguments
New(thingToCall, procToCall, ...)
if (thingToCall)
src.object = thingToCall
src.delegate = procToCall
if (length(args) > 2)
src.arguments = args.Copy(3)
proc/Invoke(...)
if (!src.object)
CRASH("Cannot call null. [src.delegate]")
var/list/callingArguments = src.arguments
if (length(args))
if (length(src.arguments))
callingArguments = callingArguments + args //not += so that it creates a new list so the arguments list stays clean
else
callingArguments = args
if (src.object == GLOBAL_PROC)
return call(src.delegate)(arglist(callingArguments))
return call(src.object, src.delegate)(arglist(callingArguments))
proc/InvokeAsync(...)
set waitfor = 0
if (!src.object)
CRASH("Cannot call null. [src.delegate]")
var/list/callingArguments = src.arguments
if (length(args))
if (length(src.arguments))
callingArguments = callingArguments + args //not += so that it creates a new list so the arguments list stays clean
else
callingArguments = args
if (src.object == GLOBAL_PROC)
return call(src.delegate)(arglist(callingArguments))
return call(src.object, src.delegate)(arglist(callingArguments))