mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-10 02:09:41 +00:00
Move recursive listening to component (#7894)
Co-authored-by: Raeschen <rycoop29@gmail.com>
This commit is contained in:
119
code/datums/components/recursive_move.dm
Normal file
119
code/datums/components/recursive_move.dm
Normal 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))
|
||||
@@ -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)
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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/))
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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))
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user