mirror of
https://github.com/vgstation-coders/vgstation13.git
synced 2025-12-10 02:16:05 +00:00
Added lazy events (#27091)
* Added lazy events * remember to compile before changing your code * Converted on_z_transition and on_post_z_transition to lazy events * add todo * fix oops * fix another oops * and anotha one * Moved unit tests to the proper place
This commit is contained in:
@@ -500,7 +500,7 @@ var/list/variables_not_to_be_copied = list(
|
||||
"type","loc","locs","vars","parent","parent_type","verbs","ckey","key",
|
||||
"group","on_login","on_ban","on_unban","on_pipenet_tick","on_item_added",
|
||||
"on_item_removed","on_moved","on_destroyed","on_density_change",
|
||||
"on_z_transition","on_use","on_emote","on_life","on_resist","post_z_transition",
|
||||
"on_use","on_emote","on_life","on_resist",
|
||||
"on_spellcast","on_uattack","on_ruattack","on_logout","on_damaged",
|
||||
"on_irradiate","on_death","on_clickon","on_attackhand","on_attackby",
|
||||
"on_explode","on_projectile","in_chamber","power_supply","contents",
|
||||
|
||||
@@ -51,3 +51,92 @@
|
||||
args["event"] = src
|
||||
if(call(objRef,procName)(args, holder)) //An intercept value so whatever code section knows we mean business
|
||||
. = 1
|
||||
|
||||
#define EVENT_HANDLER_OBJREF_INDEX 1
|
||||
#define EVENT_HANDLER_PROCNAME_INDEX 2
|
||||
|
||||
/proc/CallAsync(datum/source, proctype, list/arguments)
|
||||
set waitfor = FALSE
|
||||
return call(source, proctype)(arglist(arguments))
|
||||
|
||||
// Declare children of this type path to use as identifiers for the events.
|
||||
/lazy_event
|
||||
|
||||
// TODO: Document here the arguments that need to be passed to the procs invoked by each event
|
||||
/lazy_event/on_z_transition
|
||||
/lazy_event/on_post_z_transition
|
||||
|
||||
/datum
|
||||
/// Associative list of type path -> list(),
|
||||
/// where the type path is a descendant of /event_type.
|
||||
/// The inner list is itself an associative list of string -> list(),
|
||||
/// where string is the \ref of an object + the proc to be called.
|
||||
/// The list associated with the string above contains the hard-ref
|
||||
/// to an object and the proc to be called.
|
||||
var/list/list/registered_events
|
||||
|
||||
/**
|
||||
* Calls all registered event handlers with the specified parameters, if any.
|
||||
* Arguments:
|
||||
* * lazy_event/event_type Required. The typepath of the event to invoke.
|
||||
* * list/arguments Optional. List of parameters to be passed to the event handlers.
|
||||
*/
|
||||
/datum/proc/lazy_invoke_event(lazy_event/event_type, list/arguments)
|
||||
SHOULD_NOT_OVERRIDE(TRUE)
|
||||
if(!length(registered_events))
|
||||
// No event at all is registered for this datum.
|
||||
return
|
||||
var/list/event_handlers = registered_events[event_type]
|
||||
if(!length(event_handlers))
|
||||
// This datum does not have any handler registered for this event_type.
|
||||
return
|
||||
. = NONE
|
||||
for(var/key in event_handlers)
|
||||
var/list/handler = event_handlers[key]
|
||||
var/objRef = handler[EVENT_HANDLER_OBJREF_INDEX]
|
||||
var/procName = handler[EVENT_HANDLER_PROCNAME_INDEX]
|
||||
. |= CallAsync(objRef, procName, arguments)
|
||||
|
||||
/**
|
||||
* Registers a proc to be called on an object whenever the specified event_type
|
||||
* is invoked on this datum.
|
||||
* Arguments:
|
||||
* * lazy_event/event_type Required. The typepath of the event to register.
|
||||
* * datum/target Required. The object that the proc will be called on.
|
||||
* * procname Required. The proc to be called.
|
||||
*/
|
||||
/datum/proc/lazy_register_event(lazy_event/event_type, datum/target, procname)
|
||||
SHOULD_NOT_OVERRIDE(TRUE)
|
||||
if(!registered_events)
|
||||
registered_events = list()
|
||||
if(!registered_events[event_type])
|
||||
registered_events[event_type] = list()
|
||||
var/key = "[ref(target)]:[procname]"
|
||||
registered_events[event_type][key] = list(
|
||||
EVENT_HANDLER_OBJREF_INDEX = target,
|
||||
EVENT_HANDLER_PROCNAME_INDEX = procname
|
||||
)
|
||||
|
||||
/**
|
||||
* Unregisters a proc so that it is no longer called when the specified
|
||||
* event is invoked.
|
||||
* Arguments:
|
||||
* * lazy_event/event_type Required. The typepath of the event to unregister.
|
||||
* * datum/target Required. The object that's been previously registered.
|
||||
* * procname Required. The proc of the object.
|
||||
*/
|
||||
/datum/proc/lazy_unregister_event(lazy_event/event_type, datum/target, procname)
|
||||
SHOULD_NOT_OVERRIDE(TRUE)
|
||||
if(!registered_events)
|
||||
return
|
||||
if(!registered_events[event_type])
|
||||
return
|
||||
var/key = "[ref(target)]:[procname]"
|
||||
registered_events[event_type] -= key
|
||||
if(!registered_events[event_type].len)
|
||||
registered_events -= event_type
|
||||
if(!registered_events.len)
|
||||
registered_events = null
|
||||
|
||||
#undef EVENT_HANDLER_OBJREF_INDEX
|
||||
#undef EVENT_HANDLER_PROCNAME_INDEX
|
||||
|
||||
@@ -50,10 +50,11 @@
|
||||
second.equip_to_slot(cuffs, slot_handcuffed)
|
||||
first.equip_to_slot(cuffs, slot_handcuffed)
|
||||
|
||||
first.z_transition_bringalong_key = first.on_z_transition.Add(first, "z_transition_bringalong")
|
||||
second.z_transition_bringalong_key = second.on_z_transition.Add(second, "z_transition_bringalong")
|
||||
first.post_z_transition_bringalong_key = first.post_z_transition.Add(first, "post_z_transition_bringalong")
|
||||
second.post_z_transition_bringalong_key = second.post_z_transition.Add(second, "post_z_transition_bringalong")
|
||||
first.lazy_register_event(/lazy_event/on_z_transition, first, /mob/living/carbon/proc/z_transition_bringalong)
|
||||
second.lazy_register_event(/lazy_event/on_z_transition, second, /mob/living/carbon/proc/z_transition_bringalong)
|
||||
|
||||
first.lazy_register_event(/lazy_event/on_post_z_transition, first, /mob/living/carbon/proc/post_z_transition_bringalong)
|
||||
second.lazy_register_event(/lazy_event/on_post_z_transition, second, /mob/living/carbon/proc/post_z_transition_bringalong)
|
||||
|
||||
second.mutual_handcuffed_to_event_key = second.on_moved.Add(first, "on_mutual_cuffed_move")
|
||||
first.mutual_handcuffed_to_event_key = first.on_moved.Add(second, "on_mutual_cuffed_move")
|
||||
@@ -77,11 +78,11 @@
|
||||
C.on_moved.Remove(C.mutual_handcuffed_to_event_key)
|
||||
handcuffed_to.on_moved.Remove(handcuffed_to.mutual_handcuffed_to_event_key)
|
||||
|
||||
C.on_z_transition.Remove(C.z_transition_bringalong_key)
|
||||
handcuffed_to.on_z_transition.Remove(handcuffed_to.z_transition_bringalong_key)
|
||||
C.lazy_unregister_event(/lazy_event/on_z_transition, C, /mob/living/carbon/proc/z_transition_bringalong)
|
||||
handcuffed_to.lazy_unregister_event(/lazy_event/on_z_transition, handcuffed_to, /mob/living/carbon/proc/z_transition_bringalong)
|
||||
|
||||
C.post_z_transition.Remove(C.post_z_transition_bringalong_key)
|
||||
handcuffed_to.post_z_transition.Remove(handcuffed_to.post_z_transition_bringalong_key)
|
||||
C.lazy_unregister_event(/lazy_event/on_post_z_transition, C, /mob/living/carbon/proc/post_z_transition_bringalong)
|
||||
handcuffed_to.lazy_unregister_event(/lazy_event/on_post_z_transition, handcuffed_to, /mob/living/carbon/proc/post_z_transition_bringalong)
|
||||
|
||||
//reset the mob's vars
|
||||
handcuffed_to.mutual_handcuffed_to = null
|
||||
@@ -113,10 +114,8 @@
|
||||
/mob/living/carbon/proc/z_transition_bringalong(var/mob/user, var/from_z, var/to_z)
|
||||
if (mutual_handcuffed_to)
|
||||
// Remove the ability to bring his buddy, since his buddy already brought him here
|
||||
mutual_handcuffed_to.on_z_transition.Remove(mutual_handcuffed_to.z_transition_bringalong_key)
|
||||
mutual_handcuffed_to.z_transition_bringalong_key = null
|
||||
mutual_handcuffed_to.post_z_transition.Remove(mutual_handcuffed_to.post_z_transition_bringalong_key)
|
||||
mutual_handcuffed_to.post_z_transition_bringalong_key = null
|
||||
mutual_handcuffed_to.lazy_unregister_event(/lazy_event/on_z_transition, mutual_handcuffed_to, /mob/living/carbon/proc/z_transition_bringalong)
|
||||
mutual_handcuffed_to.lazy_unregister_event(/lazy_event/on_post_z_transition, mutual_handcuffed_to, /mob/living/carbon/proc/post_z_transition_bringalong)
|
||||
mutual_handcuffed_to.on_moved.Remove(mutual_handcuffed_to.mutual_handcuffed_to_event_key)
|
||||
mutual_handcuffed_to_event_key = null
|
||||
|
||||
@@ -124,6 +123,6 @@
|
||||
if (mutual_handcuffed_to)
|
||||
// Re-adds the events on the fly once the transition is done.
|
||||
mutual_handcuffed_to.forceMove(get_turf(src))
|
||||
mutual_handcuffed_to.z_transition_bringalong_key = mutual_handcuffed_to.on_z_transition.Add(mutual_handcuffed_to, "z_transition_bringalong")
|
||||
mutual_handcuffed_to.post_z_transition_bringalong_key = mutual_handcuffed_to.post_z_transition.Add(mutual_handcuffed_to, "post_z_transition_bringalong")
|
||||
mutual_handcuffed_to.lazy_register_event(/lazy_event/on_z_transition, mutual_handcuffed_to, /mob/living/carbon/proc/z_transition_bringalong)
|
||||
mutual_handcuffed_to.lazy_register_event(/lazy_event/on_post_z_transition, mutual_handcuffed_to, /mob/living/carbon/proc/post_z_transition_bringalong)
|
||||
mutual_handcuffed_to_event_key = mutual_handcuffed_to.on_moved.Add(src, "on_mutual_cuffed_move")
|
||||
|
||||
@@ -137,9 +137,9 @@
|
||||
P.reflected = TRUE//you can now get hit by the projectile you just fired. Careful with portals!
|
||||
|
||||
if(curturf.z != destturf.z)
|
||||
INVOKE_EVENT(teleatom.on_z_transition, list("user" = teleatom, "from_z" = curturf.z, "to_z" = destturf.z))
|
||||
teleatom.lazy_invoke_event(/lazy_event/on_z_transition, list("user" = teleatom, "from_z" = curturf.z, "to_z" = destturf.z))
|
||||
for(var/atom/movable/AA in recursive_type_check(teleatom))
|
||||
INVOKE_EVENT(AA.on_z_transition, list("user" = AA, "from_z" = curturf.z, "to_z" = destturf.z))
|
||||
AA.lazy_invoke_event(/lazy_event/on_z_transition, list("user" = AA, "from_z" = curturf.z, "to_z" = destturf.z))
|
||||
|
||||
if(force_teleport)
|
||||
teleatom.forceMove(destturf,TRUE)
|
||||
|
||||
@@ -333,7 +333,7 @@
|
||||
destination_port = null
|
||||
return 0
|
||||
for(var/atom/movable/AA in linked_area)
|
||||
INVOKE_EVENT(AA.on_z_transition, list("user" = AA, "to_z" = D.z, "from_z" = linked_port.z))
|
||||
AA.lazy_invoke_event(/lazy_event/on_z_transition, list("user" = AA, "to_z" = D.z, "from_z" = linked_port.z))
|
||||
|
||||
if(transit_port && get_transit_delay())
|
||||
if(broadcast)
|
||||
|
||||
@@ -45,10 +45,6 @@
|
||||
var/throwpass = 0
|
||||
var/level = 2
|
||||
|
||||
// Change of z-level.
|
||||
var/event/on_z_transition
|
||||
var/event/post_z_transition
|
||||
|
||||
// When this object moves. (args: loc)
|
||||
var/event/on_moved
|
||||
// When the object is qdel'd
|
||||
@@ -75,8 +71,6 @@
|
||||
|
||||
on_destroyed = new("owner"=src)
|
||||
on_moved = new("owner"=src)
|
||||
on_z_transition = new("owner"=src)
|
||||
post_z_transition = new("owner"=src)
|
||||
|
||||
/atom/movable/Destroy()
|
||||
var/turf/T = loc
|
||||
@@ -87,14 +81,6 @@
|
||||
qdel(materials)
|
||||
materials = null
|
||||
|
||||
if(on_z_transition)
|
||||
on_z_transition.holder = null
|
||||
qdel(on_z_transition)
|
||||
on_z_transition = null
|
||||
if(post_z_transition)
|
||||
post_z_transition.holder = null
|
||||
qdel(post_z_transition)
|
||||
post_z_transition = null
|
||||
if(on_moved)
|
||||
on_moved.holder = null
|
||||
on_moved = null
|
||||
@@ -456,7 +442,7 @@
|
||||
INVOKE_EVENT(on_moved,list("loc"=loc))
|
||||
var/turf/T = get_turf(destination)
|
||||
if(old_loc && T && old_loc.z != T.z)
|
||||
INVOKE_EVENT(on_z_transition, list("user" = src, "from_z" = old_loc.z, "to_z" = T.z))
|
||||
lazy_invoke_event(/lazy_event/on_z_transition, list("user" = src, "from_z" = old_loc.z, "to_z" = T.z))
|
||||
return 1
|
||||
|
||||
/atom/movable/proc/update_client_hook(atom/destination)
|
||||
|
||||
@@ -200,7 +200,6 @@
|
||||
var/charges = 0
|
||||
var/soulbound
|
||||
var/mindbound
|
||||
var/z_bound
|
||||
var/mob/bound_soul
|
||||
var/datum/mind/bound_mind
|
||||
|
||||
@@ -225,8 +224,7 @@
|
||||
/obj/item/phylactery/Destroy()
|
||||
if(bound_soul.on_death)
|
||||
bound_soul.on_death.Remove(soulbound)
|
||||
bound_soul.on_z_transition.Remove(z_bound)
|
||||
z_bound = null
|
||||
bound_soul.lazy_unregister_event(/lazy_event/on_z_transition, src, .proc/z_block)
|
||||
soulbound = null
|
||||
if(bound_soul)
|
||||
to_chat(bound_soul, "<span class = 'warning'><b>You feel your form begin to unwind!</b></span>")
|
||||
@@ -291,18 +289,17 @@
|
||||
update_icon()
|
||||
|
||||
/obj/item/phylactery/proc/unbind()
|
||||
if(bound_soul)
|
||||
bound_soul.lazy_unregister_event(/lazy_event/on_z_transition, src, .proc/z_block)
|
||||
if(bound_soul.on_death)
|
||||
bound_soul.on_death.Remove(soulbound)
|
||||
if(bound_soul.on_z_transition)
|
||||
bound_soul.on_z_transition.Remove(z_bound)
|
||||
z_bound = null
|
||||
soulbound = null
|
||||
bound_soul = null
|
||||
update_icon()
|
||||
|
||||
/obj/item/phylactery/proc/bind(var/mob/to_bind)
|
||||
soulbound = to_bind.on_death.Add(src, "revive_soul")
|
||||
z_bound = to_bind.on_z_transition.Add(src, "z_block")
|
||||
to_bind.lazy_register_event(/lazy_event/on_z_transition, src, .proc/z_block)
|
||||
bound_soul = to_bind
|
||||
|
||||
/obj/item/phylactery/proc/unbind_mind()
|
||||
|
||||
@@ -90,14 +90,14 @@
|
||||
if(!success)
|
||||
tempL.Remove(attempt)
|
||||
else
|
||||
INVOKE_EVENT(user.on_z_transition, list("user" = user, "to_z" = user.z, "from_z" = prev_z))
|
||||
user.lazy_invoke_event(/lazy_event/on_z_transition, list("user" = user, "to_z" = user.z, "from_z" = prev_z))
|
||||
break
|
||||
|
||||
if(!success)
|
||||
user.forceMove(pick(L))
|
||||
INVOKE_EVENT(user.on_z_transition, list("user" = user, "to_z" = user.z, "from_z" = prev_z))
|
||||
user.lazy_invoke_event(/lazy_event/on_z_transition, list("user" = user, "to_z" = user.z, "from_z" = prev_z))
|
||||
|
||||
smoke.start()
|
||||
src.uses -= 1
|
||||
|
||||
log_game("[key_name(user)] teleported to [thearea.name] using a scroll.")
|
||||
log_game("[key_name(user)] teleported to [thearea.name] using a scroll.")
|
||||
|
||||
@@ -239,9 +239,9 @@
|
||||
if(!move_to_z)
|
||||
return
|
||||
|
||||
INVOKE_EVENT(A.on_z_transition, list("user" = A, "from_z" = A.z, "to_z" = move_to_z))
|
||||
A.lazy_invoke_event(/lazy_event/on_z_transition, list("user" = A, "from_z" = A.z, "to_z" = move_to_z))
|
||||
for(var/atom/movable/AA in contents_brought)
|
||||
INVOKE_EVENT(AA.on_z_transition, list("user" = AA, "from_z" = AA.z, "to_z" = move_to_z))
|
||||
AA.lazy_invoke_event(/lazy_event/on_z_transition, list("user" = AA, "from_z" = AA.z, "to_z" = move_to_z))
|
||||
A.z = move_to_z
|
||||
|
||||
if(src.x <= TRANSITIONEDGE)
|
||||
@@ -271,9 +271,9 @@
|
||||
var/obj/item/projectile/P = A
|
||||
P.reset()//fixing linear projectile movement
|
||||
|
||||
INVOKE_EVENT(A.post_z_transition, list("user" = A, "from_z" = A.z, "to_z" = move_to_z))
|
||||
A.lazy_invoke_event(/lazy_event/on_post_z_transition, list("user" = A, "from_z" = A.z, "to_z" = move_to_z))
|
||||
for(var/atom/movable/AA in contents_brought)
|
||||
INVOKE_EVENT(AA.post_z_transition, list("user" = AA, "from_z" = AA.z, "to_z" = move_to_z))
|
||||
AA.lazy_invoke_event(/lazy_event/on_post_z_transition, list("user" = AA, "from_z" = AA.z, "to_z" = move_to_z))
|
||||
|
||||
if(A && A.opacity)
|
||||
has_opaque_atom = TRUE // Make sure to do this before reconsider_lights(), incase we're on instant updates. Guaranteed to be on in this case.
|
||||
|
||||
@@ -10,8 +10,6 @@
|
||||
|
||||
var/mob/living/carbon/mutual_handcuffed_to = null
|
||||
var/mutual_handcuffed_to_event_key = null
|
||||
var/z_transition_bringalong_key = null
|
||||
var/post_z_transition_bringalong_key = null
|
||||
var/obj/item/handcuffed = null //Whether or not the mob is handcuffed.
|
||||
var/obj/item/weapon/handcuffs/mutual_handcuffs = null // whether or not cuffed to somebody else
|
||||
var/mutual_handcuff_forcemove_time = 0 //last teleport time when user moves ontop of another
|
||||
@@ -37,4 +35,4 @@
|
||||
. = ..()
|
||||
|
||||
/mob/living/carbon/proc/hasmouth()
|
||||
return hasmouth
|
||||
return hasmouth
|
||||
|
||||
@@ -7,4 +7,5 @@
|
||||
#include "slipping.dm"
|
||||
#include "names.dm"
|
||||
#include "turretid.dm"
|
||||
#include "lazy_events.dm"
|
||||
#endif
|
||||
|
||||
38
code/modules/unit_tests/lazy_events.dm
Normal file
38
code/modules/unit_tests/lazy_events.dm
Normal file
@@ -0,0 +1,38 @@
|
||||
/lazy_event/demo_event
|
||||
/datum/unit_test
|
||||
var/did_something = FALSE
|
||||
/datum/unit_test/lazy_event_does_stuff/start()
|
||||
var/datum/demo_datum = new
|
||||
demo_datum.lazy_register_event(/lazy_event/demo_event, src, .proc/do_something)
|
||||
demo_datum.lazy_invoke_event(/lazy_event/demo_event)
|
||||
if(!did_something)
|
||||
fail("lazy event did nothing")
|
||||
/datum/unit_test/lazy_event_does_stuff/proc/do_something()
|
||||
did_something = TRUE
|
||||
|
||||
/datum/unit_test/lazy_event_cleanup/start()
|
||||
var/datum/demo_datum = new
|
||||
if(!isnull(demo_datum.registered_events))
|
||||
fail("registered_events is not null by default")
|
||||
demo_datum.lazy_register_event(/lazy_event/demo_event, src, .proc/do_nothing)
|
||||
assert_eq(demo_datum.registered_events.len, 1)
|
||||
assert_eq(demo_datum.registered_events[/lazy_event/demo_event].len, 1)
|
||||
demo_datum.lazy_unregister_event(/lazy_event/demo_event, src, .proc/do_nothing)
|
||||
if(!isnull(demo_datum.registered_events))
|
||||
fail("registered_events is not null after removing the last handler")
|
||||
/datum/unit_test/lazy_event_cleanup/proc/do_nothing()
|
||||
|
||||
/datum/unit_test/lazy_event_arguments/start()
|
||||
var/datum/demo_datum = new
|
||||
demo_datum.lazy_register_event(/lazy_event/demo_event, src, .proc/do_stuff_with_args)
|
||||
demo_datum.lazy_invoke_event(/lazy_event/demo_event, list("abc", 123))
|
||||
demo_datum.lazy_unregister_event(/lazy_event/demo_event, src, .proc/do_stuff_with_args)
|
||||
|
||||
demo_datum.lazy_register_event(/lazy_event/demo_event, src, .proc/do_something_with_named_args)
|
||||
demo_datum.lazy_invoke_event(/lazy_event/demo_event, list("second_parameter"=1))
|
||||
/datum/unit_test/lazy_event_arguments/proc/do_stuff_with_args(string, number)
|
||||
assert_eq(string, "abc")
|
||||
assert_eq(number, 123)
|
||||
/datum/unit_test/lazy_event_arguments/proc/do_something_with_named_args(first_parameter, second_parameter)
|
||||
assert_eq(first_parameter, null)
|
||||
assert_eq(second_parameter, 1)
|
||||
Reference in New Issue
Block a user