Move recursive listening to component (#7894)

Co-authored-by: Raeschen <rycoop29@gmail.com>
This commit is contained in:
Cadyn
2024-03-08 04:49:31 -08:00
committed by GitHub
parent f590dbea21
commit 0fdd1ffc83
22 changed files with 162 additions and 12 deletions

View File

@@ -0,0 +1,119 @@
/**
* Recursive move listener
* Can be added willy-nilly to anything where the COMSIG_OBSERVER_MOVE signal should also trigger on a parent moving.
* Previously there was a system where COMSIG_OBSERVER_MOVE was always recursively propogated, but that was unnecessary bloat.
*/
/datum/component/recursive_move
dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS //This makes it so pretty much nothing happens when a duplicate component is created since we don't actually override InheritComponent
var/atom/movable/holder
var/list/parents = list()
var/noparents = FALSE
/datum/component/recursive_move/RegisterWithParent()
. = ..()
holder = parent
RegisterSignal(holder, COMSIG_PARENT_QDELETING, PROC_REF(on_holder_qdel))
spawn(0) // Delayed action if our holder is spawned in nullspace and then loc = target, hopefully this catches it. VV Add item does this, for example.
if(!QDELETED(src))
setup_parents()
/datum/component/recursive_move/proc/setup_parents()
if(length(parents)) // safety check just incase this was called without clearing
reset_parents()
var/atom/movable/cur_parent = holder?.loc // first loc could be null
var/recursion = 0 // safety check - max iterations
while(istype(cur_parent) && (recursion < 64))
if(cur_parent == cur_parent.loc) //safety check incase a thing is somehow inside itself, cancel
log_debug("RECURSIVE_MOVE: Parent is inside itself. ([holder]) ([holder.type])")
reset_parents()
break
if(cur_parent in parents) //safety check incase of circular contents. (A inside B, B inside C, C inside A), cancel
log_debug("RECURSIVE_MOVE: Parent is inside a circular inventory. ([holder]) ([holder.type])")
reset_parents()
break
recursion++
parents += cur_parent
RegisterSignal(cur_parent, COMSIG_ATOM_EXITED, PROC_REF(heirarchy_changed))
RegisterSignal(cur_parent, COMSIG_PARENT_QDELETING, PROC_REF(on_qdel))
cur_parent = cur_parent.loc
if(recursion >= 64) // If we escaped due to iteration limit, cancel
log_debug("RECURSIVE_MOVE: Parent hit recursion limit. ([holder]) ([holder.type])")
reset_parents()
parents.Cut()
if(length(parents))
//Only need to watch top parent for movement. Everything is covered by Exited
RegisterSignal(parents[parents.len], COMSIG_ATOM_ENTERING, PROC_REF(top_moved))
//If we have no parents of type atom/movable then we wait to see if that changes, checking every time our holder moves.
if(!length(parents) && !noparents)
noparents = TRUE
RegisterSignal(holder, COMSIG_ATOM_ENTERING, PROC_REF(setup_parents))
if(length(parents) && noparents)
noparents = FALSE
UnregisterSignal(holder, COMSIG_ATOM_ENTERING)
/datum/component/recursive_move/proc/unregister_signals()
if(noparents) // safety check
noparents = FALSE
UnregisterSignal(holder, COMSIG_ATOM_ENTERING)
if(!length(parents))
return
for(var/atom/movable/cur_parent in parents)
UnregisterSignal(cur_parent, COMSIG_PARENT_QDELETING)
UnregisterSignal(cur_parent, COMSIG_ATOM_EXITED)
UnregisterSignal(parents[parents.len], COMSIG_ATOM_ENTERING)
//Parent at top of heirarchy moved.
/datum/component/recursive_move/proc/top_moved(var/atom/movable/am, var/atom/new_loc, var/atom/old_loc)
SIGNAL_HANDLER
SEND_SIGNAL(holder, COMSIG_OBSERVER_MOVED, old_loc, new_loc)
//One of the parents other than the top parent moved.
/datum/component/recursive_move/proc/heirarchy_changed(var/atom/old_loc, var/atom/movable/am, var/atom/new_loc)
SIGNAL_HANDLER
SEND_SIGNAL(holder, COMSIG_OBSERVER_MOVED, old_loc, new_loc)
//Rebuild our list of parents
reset_parents()
setup_parents()
//Some things will move their contents on qdel so we should prepare ourselves to be moved.
//If this qdel does destroy our holder, on_holder_qdel will handle preperations for GC
/datum/component/recursive_move/proc/on_qdel()
reset_parents()
noparents = TRUE
RegisterSignal(holder, COMSIG_ATOM_ENTERING, PROC_REF(setup_parents))
/datum/component/recursive_move/proc/on_holder_qdel()
UnregisterSignal(holder, COMSIG_PARENT_QDELETING)
reset_parents()
holder = null
qdel(src)
/datum/component/recursive_move/Destroy()
. = ..()
reset_parents()
if(holder) UnregisterSignal(holder, COMSIG_PARENT_QDELETING)
holder = null
/datum/component/recursive_move/proc/reset_parents()
unregister_signals()
parents.Cut()
//the banana peel of testing stays
/obj/item/weapon/bananapeel/testing
name = "banana peel of testing"
desc = "spams world log with debugging information"
/obj/item/weapon/bananapeel/testing/proc/shmove(var/atom/source, var/atom/old_loc, var/atom/new_loc)
world.log << "the [source] moved from [old_loc]([old_loc.x],[old_loc.y],[old_loc.z]) to [new_loc]([new_loc.x],[new_loc.y],[new_loc.z])"
/obj/item/weapon/bananapeel/testing/Initialize()
. = ..()
AddComponent(/datum/component/recursive_move)
RegisterSignal(src, COMSIG_OBSERVER_MOVED, PROC_REF(shmove))

View File

@@ -1,6 +1,7 @@
/*
/atom/movable/proc/recursive_move(var/atom/movable/am, var/old_loc, var/new_loc)
SEND_SIGNAL(src,COMSIG_OBSERVER_MOVED, old_loc, new_loc)
*/
/atom/movable/proc/move_to_destination(var/atom/movable/am, var/old_loc, var/new_loc)
var/turf/T = get_turf(new_loc)
if(T && T != loc)
@@ -12,6 +13,7 @@
/datum/proc/qdel_self()
qdel(src)
/*
/proc/register_all_movement(var/event_source, var/datum/listener)
listener.RegisterSignal(event_source,COMSIG_OBSERVER_MOVED, /atom/movable/proc/recursive_move)
//GLOB.dir_set_event.register(event_source, listener, /atom/proc/recursive_dir_set)
@@ -19,3 +21,4 @@
/proc/unregister_all_movement(var/event_source, var/datum/listener)
listener.UnregisterSignal(event_source,COMSIG_OBSERVER_MOVED)
//GLOB.dir_set_event.unregister(event_source, listener, /atom/proc/recursive_dir_set)
*/

View File

@@ -28,6 +28,7 @@ GLOBAL_DATUM_INIT(moved_event, /decl/observ/moved, new)
/********************
* Movement Handling *
********************/
/*
/atom/movable/Entered(var/atom/movable/am, atom/old_loc)
. = ..()
am.RegisterSignal(src,COMSIG_OBSERVER_MOVED, /atom/movable/proc/recursive_move, override = TRUE)
@@ -35,7 +36,7 @@ GLOBAL_DATUM_INIT(moved_event, /decl/observ/moved, new)
/atom/movable/Exited(var/atom/movable/am, atom/old_loc)
. = ..()
am.UnregisterSignal(src,COMSIG_OBSERVER_MOVED)
*/
// Entered() typically lifts the moved event, but in the case of null-space we'll have to handle it.
/atom/movable/Move()
var/old_loc = loc

View File

@@ -73,14 +73,18 @@
// Do not do power stuff in New/Initialize until after ..()
/obj/machinery/Initialize()
. = ..()
RegisterSignal(src, COMSIG_OBSERVER_MOVED, PROC_REF(update_power_on_move))
AddComponent(/datum/component/recursive_move)
var/power = POWER_CONSUMPTION
REPORT_POWER_CONSUMPTION_CHANGE(0, power)
power_init_complete = TRUE
// Or in Destroy at all, but especially after the ..().
/obj/machinery/Destroy()
/*
if(ismovable(loc))
UnregisterSignal(loc, COMSIG_OBSERVER_MOVED) // Unregister just in case
*/
var/power = POWER_CONSUMPTION
REPORT_POWER_CONSUMPTION_CHANGE(power, 0)
. = ..()
@@ -90,10 +94,12 @@
/obj/machinery/Moved(atom/old_loc, direction, forced = FALSE)
. = ..()
update_power_on_move(src, old_loc, loc)
/* No
if(ismovable(old_loc)) // Unregister recursive movement.
UnregisterSignal(old_loc, COMSIG_OBSERVER_MOVED)
if(ismovable(loc)) // Register for recursive movement (if the thing we're inside moves)
RegisterSignal(loc, COMSIG_OBSERVER_MOVED, PROC_REF(update_power_on_move), override = TRUE)
*/
/obj/machinery/proc/update_power_on_move(atom/movable/mover, atom/old_loc, atom/new_loc)
var/area/old_area = get_area(old_loc)

View File

@@ -77,7 +77,8 @@
/obj/item/shield_projector/rectangle/mecha/Initialize()
. = ..()
my_mech = loc
RegisterSignal(my_mech, COMSIG_OBSERVER_MOVED, /obj/item/shield_projector/proc/update_shield_positions, override = TRUE)
RegisterSignal(my_mech, COMSIG_OBSERVER_MOVED, /obj/item/shield_projector/proc/update_shield_positions)
my_mech.AddComponent(/datum/component/recursive_move)
update_shift(my_mech)
/obj/item/shield_projector/rectangle/mecha/proc/update_shift(atom/movable/mech)

View File

@@ -743,6 +743,7 @@ modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out.
H.toggle_zoom_hud() // If the user has already limited their HUD this avoids them having a HUD when they zoom in
H.set_viewsize(viewsize)
zoom = 1
H.AddComponent(/datum/component/recursive_move)
RegisterSignal(H, COMSIG_OBSERVER_MOVED, PROC_REF(zoom), override = TRUE)
var/tilesize = 32

View File

@@ -350,6 +350,7 @@
comm.visible_message("<span class='danger'>[icon2html(src,viewers(src))] New video connection from [comm].</span>")
update_active_camera_screen()
RegisterSignal(video_source, COMSIG_OBSERVER_MOVED, PROC_REF(update_active_camera_screen))
video_source.AddComponent(/datum/component/recursive_move)
update_icon()
// Proc: end_video()

View File

@@ -46,6 +46,7 @@ var/list/GPS_list = list()
if(istype(loc, /mob))
holder = loc
RegisterSignal(holder, COMSIG_OBSERVER_MOVED, PROC_REF(update_compass), override = TRUE)
holder.AddComponent(/datum/component/recursive_move)
//GLOB.dir_set_event.register(holder, src, PROC_REF(update_compass))
if(holder && tracking)

View File

@@ -206,11 +206,13 @@
/obj/item/weapon/storage/bag/ore/equipped(mob/user)
..()
if(user.get_inventory_slot(src) == slot_wear_suit || slot_l_hand || slot_l_hand || slot_belt) //Basically every place they can go. Makes sure it doesn't unregister if moved to other slots.
user.AddComponent(/datum/component/recursive_move)
RegisterSignal(user, COMSIG_OBSERVER_MOVED, /obj/item/weapon/storage/bag/ore/proc/autoload, user, override = TRUE)
/obj/item/weapon/storage/bag/ore/dropped(mob/user)
..()
if(user.get_inventory_slot(src) == slot_wear_suit || slot_l_hand || slot_l_hand || slot_belt) //See above. This should really be a define.
user.AddComponent(/datum/component/recursive_move)
RegisterSignal(user, COMSIG_OBSERVER_MOVED, /obj/item/weapon/storage/bag/ore/proc/autoload, user, override = TRUE)
else
UnregisterSignal(user, COMSIG_OBSERVER_MOVED)

View File

@@ -43,14 +43,17 @@
var/list/all_modules = robot.module.modules
all_modules += robot.module.emag
while(TRUE)
var/add_item = tgui_input_list(usr, "Please select the module to add", "Modules", all_modules)
if(!istype(add_item, /obj/item/))
var/add_item_select = tgui_input_list(usr, "Please select the module to add", "Modules", all_modules)//ChompEDIT
if(!istype(add_item_select, /obj/item/))//ChompEDIT
break
var/obj/item/add_item = add_item_select//ChompEDIT
robot.module.emag.Remove(add_item)
robot.module.modules.Remove(add_item)
robot.module.contents.Remove(add_item)
target.module.modules.Add(add_item)
target.module.contents.Add(add_item)
spawn(0) //ChompEDIT Must be after to allow the movement to finish
SEND_SIGNAL(add_item, COMSIG_OBSERVER_MOVED)//ChompEDIT - report the movement since setting loc doesn't call Move or Moved
target.hud_used.update_robot_modules_display()
to_chat(usr, "<span class='danger'>You added \"[add_item]\" to [target].</span>")
if(istype(add_item, /obj/item/stack/))

View File

@@ -38,6 +38,7 @@
var/mob/living/carbon/human/H = holder.wearer
to_chat(H,"<span class='notice'>You activate the P.A.T. module.</span>")
H.AddComponent(/datum/component/recursive_move)
RegisterSignal(H, COMSIG_OBSERVER_MOVED, /obj/item/rig_module/pat_module/proc/boop)
/obj/item/rig_module/pat_module/deactivate()

View File

@@ -112,6 +112,7 @@
user.client.images |= holomap_datum.station_map
watching_mob = user
watching_mob.AddComponent(/datum/component/recursive_move)
RegisterSignal(watching_mob, COMSIG_OBSERVER_MOVED, /obj/machinery/station_map/proc/checkPosition)
//GLOB.dir_set_event.register(watching_mob, src, /obj/machinery/station_map/proc/checkPosition)
RegisterSignal(watching_mob, COMSIG_OBSERVER_DESTROYED, /obj/machinery/station_map/proc/stopWatching)

View File

@@ -448,6 +448,7 @@
/obj/item/integrated_circuit/output/holographic_projector/Initialize()
. = ..()
AddComponent(/datum/component/recursive_move)
RegisterSignal(src, COMSIG_OBSERVER_MOVED, PROC_REF(on_moved))
/obj/item/integrated_circuit/output/holographic_projector/Destroy()

View File

@@ -214,6 +214,7 @@
say("Down on the floor, [suspect_name]! You have [SECBOT_WAIT_TIME*2] seconds to comply.")
playsound(src, pick(preparing_arrest_sounds), 50)
// Register to be told when the target moves
target.AddComponent(/datum/component/recursive_move)
RegisterSignal(target, COMSIG_OBSERVER_MOVED, /mob/living/bot/secbot/proc/target_moved)
// Callback invoked if the registered target moves

View File

@@ -427,6 +427,7 @@
real_name = brainmob.real_name //And the OTHER name
forceMove(get_turf(parent_human))
parent_human.AddComponent(/datum/component/recursive_move)
RegisterSignal(parent_human, COMSIG_OBSERVER_MOVED, /mob/observer/eye/ar_soul/proc/human_moved)
//Time to play dressup

View File

@@ -77,6 +77,7 @@ somewhere on that shuttle. Subtypes of these can be then used to perform ship ov
L.looking_elsewhere = 1
L.handle_vision()
user.set_viewsize(world.view + extra_view)
user.AddComponent(/datum/component/recursive_move)
RegisterSignal(user, COMSIG_OBSERVER_MOVED, /obj/machinery/computer/ship/proc/unlook, override = TRUE) //This needs override or else it will spam runtimes because it is called repeatedly.
// TODO GLOB.stat_set_event.register(user, src, /obj/machinery/computer/ship/proc/unlook)
LAZYDISTINCTADD(viewers, WEAKREF(user))

View File

@@ -97,6 +97,7 @@
/obj/item/weapon/paper/sticky/Initialize()
. = ..()
AddComponent(/datum/component/recursive_move)
RegisterSignal(src, COMSIG_OBSERVER_MOVED, /obj/item/weapon/paper/sticky/proc/reset_persistence_tracking)
/obj/item/weapon/paper/sticky/proc/reset_persistence_tracking()

View File

@@ -100,14 +100,14 @@
/obj/item/shield_projector/Initialize()
START_PROCESSING(SSobj, src)
if(always_on)
create_shields()
AddComponent(/datum/component/recursive_move)
RegisterSignal(src, COMSIG_OBSERVER_MOVED, PROC_REF(moved_event))
if(istype(loc, /atom/movable)) // on initialise, if i'm inside a thing, preregister this.
var/atom/movable/am = loc
RegisterSignal(am, COMSIG_OBSERVER_MOVED, /atom/movable/proc/recursive_move, override = TRUE)
//ChompEDIT START - shields on init
if(always_on)
spawn(0)
if(!QDELETED(src))
create_shields()
//ChompEDIT END
return ..()
/obj/item/shield_projector/Destroy()

View File

@@ -65,6 +65,7 @@
owner = H
if(owner)
owner.AddComponent(/datum/component/recursive_move)
RegisterSignal(owner, COMSIG_OBSERVER_MOVED, PROC_REF(update_active_camera_screen))
check_whitelist = check_species_whitelist
whitelist = species_whitelist

View File

@@ -144,6 +144,7 @@
if(active_camera)
UnregisterSignal(active_camera, COMSIG_OBSERVER_MOVED)
active_camera = C
active_camera.AddComponent(/datum/component/recursive_move)
RegisterSignal(active_camera, COMSIG_OBSERVER_MOVED, PROC_REF(update_active_camera_screen))
playsound(tgui_host(), get_sfx("terminal_type"), 25, FALSE)
update_active_camera_screen()
@@ -171,6 +172,7 @@
if(active_camera)
UnregisterSignal(active_camera, COMSIG_OBSERVER_MOVED)
active_camera = target
active_camera.AddComponent(/datum/component/recursive_move)
RegisterSignal(active_camera, COMSIG_OBSERVER_MOVED, PROC_REF(update_active_camera_screen))
playsound(tgui_host(), get_sfx("terminal_type"), 25, FALSE)
update_active_camera_screen()

View File

@@ -55,6 +55,7 @@
user.set_machine(src)
user.reset_view(linked)
user.set_viewsize(world.view + extra_view)
user.AddComponent(/datum/component/recursive_move)
RegisterSignal(user, COMSIG_OBSERVER_MOVED, /datum/tgui_module/ship/proc/unlook)
LAZYDISTINCTADD(viewers, WEAKREF(user))

View File

@@ -403,6 +403,7 @@
#include "code\datums\components\connect_range_ch.dm"
#include "code\datums\components\material_container.dm"
#include "code\datums\components\overlay_lighting.dm"
#include "code\datums\components\recursive_move.dm"
#include "code\datums\components\resize_guard.dm"
#include "code\datums\components\crafting\crafting.dm"
#include "code\datums\components\crafting\crafting_external.dm"