diff --git a/code/__DEFINES/_click.dm b/code/__DEFINES/_click.dm index 1ee40b497ded..25e69f5a988d 100644 --- a/code/__DEFINES/_click.dm +++ b/code/__DEFINES/_click.dm @@ -39,7 +39,7 @@ //Pixel coordinates in screen_loc format ("[tile_x]:[pixel_x],[tile_y]:[pixel_y]") #define SCREEN_LOC "screen-loc" -//Click catcher e.g. /atom/moveable/screen/click_catcher +//Click catcher e.g. /atom/movable/screen/click_catcher #define CLICK_CATCHER "click_catcher" #define CLICK_CATCHER_ADD_PARAM ";click_catcher=1" diff --git a/code/__DEFINES/dcs/signals/atom/signals_turf.dm b/code/__DEFINES/dcs/signals/atom/signals_turf.dm index 9528609851a8..7fcffb9e07de 100644 --- a/code/__DEFINES/dcs/signals/atom/signals_turf.dm +++ b/code/__DEFINES/dcs/signals/atom/signals_turf.dm @@ -1,14 +1,24 @@ -///from /turf/Entered +/** + * From /turf/Entered(): (turf/entered_turf) + * NOTE: This will occur for all locs including during turf/ChangeTurf() once Initialize occurs (mapload may delay it) + */ #define COMSIG_MOVABLE_TURF_ENTERED "movable_turf_entered" -/// from base of turf/ChangeTurf(): (path, list/new_baseturfs, flags, list/post_change_callbacks). -/// `post_change_callbacks` is a list that signal handlers can mutate to append `/datum/callback` objects. -/// They will be called with the new turf after the turf has changed. +/** + * From base of turf/ChangeTurf(): (path, list/new_baseturfs, flags, list/post_change_callbacks) + * `post_change_callbacks` is a list that signal handlers can mutate to append `/datum/callback` objects. + * They will be called with the new turf after the turf has changed (but the turf's Initialize may not have occured yet for mapload). + */ #define COMSIG_PRE_TURF_CHANGE "pre_turf_change" #define COMSIG_TURF_ENTER "turf_enter" #define COMPONENT_TURF_ALLOW_MOVEMENT (1<<0) #define COMPONENT_TURF_DENY_MOVEMENT (1<<1) + +/** + * From /turf/Entered(): (atom/movable/entered_movable) + * NOTE: This cannot detect a turf/ChangeTurf() because signals are not retained during a ChangeTurf. + */ #define COMSIG_TURF_ENTERED "turf_entered" /// Called when a bullet hits a turf diff --git a/code/controllers/subsystem/hijack.dm b/code/controllers/subsystem/hijack.dm index b9daf9c2e9ca..d66c5002795e 100644 --- a/code/controllers/subsystem/hijack.dm +++ b/code/controllers/subsystem/hijack.dm @@ -973,12 +973,9 @@ SUBSYSTEM_DEF(hijack) target = target.ChangeTurf(make_current_walkable_type) return target - // Make target open_space and chuck stuff down + // Make target open_space (which will chuck stuff down) var/turf/open_space/space = target.ChangeTurf(/turf/open_space) - for(var/atom/movable/thing in space) - if(istype(thing, /obj/vis_contents_holder)) - continue - space.check_fall(thing) + return space //~~~~~~~~~~~~~~~~~~~~~~~~ FTL STUFF ~~~~~~~~~~~~~~~~~~~~~~~~// diff --git a/code/datums/components/weed_food.dm b/code/datums/components/weed_food.dm index e2f0d0b46a63..da43f6ffe411 100644 --- a/code/datums/components/weed_food.dm +++ b/code/datums/components/weed_food.dm @@ -87,7 +87,8 @@ parent_buckle = null /datum/component/weed_food/RegisterWithParent() - RegisterSignal(parent_mob, list(COMSIG_MOVABLE_MOVED, COMSIG_ATOM_AFTER_SHUTTLE_MOVE), PROC_REF(on_move)) + // COMSIG_MOVABLE_TURF_ENTERED to handle movement and ChangeTurf + RegisterSignal(parent_mob, list(COMSIG_MOVABLE_TURF_ENTERED, COMSIG_ATOM_AFTER_SHUTTLE_MOVE), PROC_REF(on_move)) RegisterSignal(parent_mob, list(COMSIG_LIVING_REJUVENATED, COMSIG_HUMAN_REVIVED), PROC_REF(on_rejuv)) RegisterSignal(parent_mob, COMSIG_HUMAN_SET_UNDEFIBBABLE, PROC_REF(on_update)) RegisterSignal(parent_mob, COMSIG_LIVING_PREIGNITION, PROC_REF(on_preignition)) @@ -98,7 +99,7 @@ /datum/component/weed_food/UnregisterFromParent() if(parent_mob) UnregisterSignal(parent_mob, list( - COMSIG_MOVABLE_MOVED, + COMSIG_MOVABLE_TURF_ENTERED, COMSIG_ATOM_AFTER_SHUTTLE_MOVE, COMSIG_LIVING_REJUVENATED, COMSIG_HUMAN_REVIVED, @@ -115,7 +116,7 @@ UnregisterSignal(parent_nest, COMSIG_PARENT_QDELETING) UnregisterSignal(SSdcs, COMSIG_GLOB_GROUNDSIDE_FORSAKEN_HANDLING) -/// SIGNAL_HANDLER for COMSIG_MOVABLE_MOVED and COMSIG_ATOM_AFTER_SHUTTLE_MOVE +/// SIGNAL_HANDLER for COMSIG_MOVABLE_TURF_ENTERED and COMSIG_ATOM_AFTER_SHUTTLE_MOVE /datum/component/weed_food/proc/on_move() SIGNAL_HANDLER diff --git a/code/datums/datum.dm b/code/datums/datum.dm index a4e5b41030ec..51cf9ec48849 100644 --- a/code/datums/datum.dm +++ b/code/datums/datum.dm @@ -130,14 +130,6 @@ debug_log("'[src]' datum_components was not null after removing all components! [length(datum_components)] entries remained...") datum_components.Cut() - clear_signal_refs() - //END: ECS SHIT - - return QDEL_HINT_QUEUE - -///Only override this if you know what you're doing. You do not know what you're doing -///This is a threat -/datum/proc/clear_signal_refs() var/list/lookup = comp_lookup if(lookup) for(var/sig in lookup) @@ -152,6 +144,9 @@ for(var/target in signal_procs) UnregisterSignal(target, signal_procs[target]) + //END: ECS SHIT + + return QDEL_HINT_QUEUE /** * Callback called by a timer to end an associative-list-indexed cooldown. diff --git a/code/game/machinery/telecomms/presets.dm b/code/game/machinery/telecomms/presets.dm index 1eafc222a52a..b3b344c87787 100644 --- a/code/game/machinery/telecomms/presets.dm +++ b/code/game/machinery/telecomms/presets.dm @@ -218,9 +218,19 @@ GLOBAL_LIST_EMPTY(all_static_telecomms_towers) /// Holds the delay for when a cluster can recorrupt the comms tower after a pylon has been destroyed COOLDOWN_DECLARE(corruption_delay) -/obj/structure/machinery/telecomms/relay/preset/tower/mapcomms/Initialize() +/obj/structure/machinery/telecomms/relay/preset/tower/mapcomms/Initialize(mapload, ...) . = ..() - RegisterSignal(get_turf(src), COMSIG_WEEDNODE_GROWTH, PROC_REF(handle_xeno_acquisition)) + // COMSIG_MOVABLE_TURF_ENTERED to handle ChangeTurf + RegisterSignal(src, COMSIG_MOVABLE_TURF_ENTERED, PROC_REF(register_with_turf)) + if(!mapload) + register_with_turf() + +/// Handler for callback of COMSIG_MOVABLE_TURF_ENTERED (turf changed) +/obj/structure/machinery/telecomms/relay/preset/tower/mapcomms/proc/register_with_turf(atom/movable/source, turf/new_turf) + SIGNAL_HANDLER + var/turf/location = get_turf(src) + if(location && (!new_turf || location == new_turf)) // We only need to monitor our loc not our locs + RegisterSignal(location, COMSIG_WEEDNODE_GROWTH, PROC_REF(handle_xeno_acquisition)) /obj/structure/machinery/telecomms/relay/preset/tower/mapcomms/get_examine_text(mob/user) . = ..() diff --git a/code/game/objects/structures/multiz_stairs.dm b/code/game/objects/structures/multiz_stairs.dm index 1a041cedb363..4728182bd3ab 100644 --- a/code/game/objects/structures/multiz_stairs.dm +++ b/code/game/objects/structures/multiz_stairs.dm @@ -5,7 +5,10 @@ /obj/structure/stairs/multiz/Initialize(mapload, ...) . = ..() - RegisterSignal(loc, COMSIG_TURF_ENTERED, PROC_REF(on_turf_entered)) + // COMSIG_MOVABLE_TURF_ENTERED to handle ChangeTurf + RegisterSignal(src, COMSIG_MOVABLE_TURF_ENTERED, PROC_REF(register_with_turf)) + if(!mapload) + register_with_turf() for(var/turf/blocked_turf in range(1, src)) blockers += WEAKREF(new /obj/effect/build_blocker(blocked_turf, src)) blockers += WEAKREF(new /obj/structure/blocker/anti_cade(blocked_turf)) @@ -15,7 +18,12 @@ QDEL_LIST(blockers) return ..() -/obj/structure/stairs/multiz/proc/on_turf_entered(turf/source, atom/movable/enterer) +/// Handler for callback of COMSIG_MOVABLE_TURF_ENTERED (turf changed) +/obj/structure/stairs/multiz/proc/register_with_turf() + SIGNAL_HANDLER + RegisterSignal(loc, COMSIG_TURF_ENTERED, PROC_REF(on_stairs_moved)) + +/obj/structure/stairs/multiz/proc/on_stairs_moved(turf/source, atom/movable/enterer) SIGNAL_HANDLER if(!istype(enterer, /mob)) return @@ -143,8 +151,21 @@ LAZYADD(from_turf_to_images[from_turf], destination_turf_images[to_turf]) break // we found stairs that work, go on to the next turf if(length(from_turf_to_images[from_turf])) - RegisterSignal(from_turf, COMSIG_TURF_ENTERED, PROC_REF(handle_entered), TRUE) + RegisterSignal(from_turf, COMSIG_TURF_ENTERED, PROC_REF(handle_entered), override=TRUE) + RegisterSignal(from_turf, COMSIG_PRE_TURF_CHANGE, PROC_REF(handle_pre_turf_change), override=TRUE) + +/// Handler for COMSIG_PRE_TURF_CHANGE to set post_change_callbacks +/datum/staircase/proc/handle_pre_turf_change(turf/source, path, list/new_baseturfs, flags, list/post_change_callbacks) + SIGNAL_HANDLER + post_change_callbacks += CALLBACK(src, PROC_REF(re_register_from_turf_signals), source) + +/// Re-registers the COMSIG_TURF_ENTERED and COMSIG_PRE_TURF_CHANGE for handle_pre_turf_change +/datum/staircase/proc/re_register_from_turf_signals(turf/new_turf) + SHOULD_NOT_SLEEP(TRUE) + RegisterSignal(new_turf, COMSIG_TURF_ENTERED, PROC_REF(handle_entered)) + RegisterSignal(new_turf, COMSIG_PRE_TURF_CHANGE, PROC_REF(handle_pre_turf_change)) +/// Handles COMSIG_TURF_ENTERED for mobs that enters a from_turf to register handle_movement and handle_deleted /datum/staircase/proc/handle_entered(turf/originator, atom/what_did_it) SIGNAL_HANDLER @@ -161,7 +182,7 @@ in_range_mob += mover - +/// Handles COMSIG_MOVABLE_MOVED for mobs that were in a from_turf /datum/staircase/proc/handle_movement(mob/mover, old_loc, direction) SIGNAL_HANDLER @@ -180,6 +201,7 @@ in_range_mob -= mover UnregisterSignal(mover, list(COMSIG_MOVABLE_MOVED, COMSIG_PARENT_QDELETING)) +/// Handles COMSIG_PARENT_QDELETING for mobs that were in a from_turf /datum/staircase/proc/handle_deleted(atom/updater) SIGNAL_HANDLER diff --git a/code/game/turfs/open_space.dm b/code/game/turfs/open_space.dm index dfbffbc77c2d..db41a33420e6 100644 --- a/code/game/turfs/open_space.dm +++ b/code/game/turfs/open_space.dm @@ -16,7 +16,7 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr plane = OPEN_SPACE_PLANE_START is_weedable = NOT_WEEDABLE -/turf/open_space/Initialize() +/turf/open_space/Initialize(mapload, ...) pass_flags = GLOB.pass_flags_cache[type] if (isnull(pass_flags)) @@ -27,6 +27,21 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr initialize_pass_flags() ADD_TRAIT(src, TURF_Z_TRANSPARENT_TRAIT, TRAIT_SOURCE_INHERENT) + + #if defined(UNIT_TESTS) || defined(TESTING) + // Assert when testing that this open_space is placed somewhere valid + if(!istype(get_area(src), /area/misc/testroom)) + var/turf/below = get_turf_below() + while(istype(below, /turf/open_space)) + below = SSmapping.get_turf_below(below) + if(!below) + stack_trace("[src] at [COORD(src)] falls through the world!") + #endif + + // We don't call parent and this is important + for(var/atom/movable/thing in src) + Entered(thing) + return INITIALIZE_HINT_LATELOAD /turf/open_space/Enter(atom/movable/mover, atom/forget) @@ -70,6 +85,15 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr to_chat(user, SPAN_WARNING("It would be too dangerous to go that way.")) return + var/turf/below = get_turf_below() + while(istype(below, /turf/open_space)) + below = SSmapping.get_turf_below(below) + if(!below) + to_chat(user, SPAN_WARNING("You can't go that way.")) + return + + user.visible_message(SPAN_WARNING("[user] starts climbing down."), SPAN_WARNING("You start climbing down.")) + var/climb_down_time = 1 SECONDS if(ishuman_strict(user)) climb_down_time = 2.5 SECONDS @@ -80,8 +104,6 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr else climb_down_time = 1 SECONDS - user.visible_message(SPAN_WARNING("[user] starts climbing down."), SPAN_WARNING("You start climbing down.")) - var/list/grabbed_things = list() var/hands_full = FALSE for(var/obj/item/in_hand in list(user.l_hand, user.r_hand)) @@ -101,15 +123,10 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr user.visible_message(SPAN_WARNING("[user] climbs down."), SPAN_WARNING("You climb down.")) - var/turf/below = get_turf_below() - while(istype(below, /turf/open_space)) - below = SSmapping.get_turf_below(below) - user.forceMove(below) for(var/atom/movable/thing as anything in grabbed_things) // grabbed things aren't moved to the tile immediately to: make the animation better, preserve the grab thing.forceMove(below) below.on_climb_down(user) - return /turf/open_space/proc/check_fall(atom/movable/movable, kill_if_blocked=TRUE) if(movable.flags_atom & NO_ZFALL) @@ -121,6 +138,9 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr below = SSmapping.get_turf_below(below) height++ + if(!below) + return + movable.forceMove(below) movable.onZImpact(below, height) diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index f9ab30019ca1..6449e5160fe3 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -105,8 +105,9 @@ else initialize_pass_flags() - for(var/atom/movable/AM in src) - Entered(AM) + // Be sure to do this if you don't call parent! + for(var/atom/movable/thing in src) + Entered(thing) if(light_power && light_range) update_light() @@ -131,6 +132,7 @@ vis_flags = VIS_HIDE mouse_opacity = MOUSE_OPACITY_TRANSPARENT anchored = TRUE + flags_atom = NO_ZFALL /obj/vis_contents_holder/Initialize(mapload, vis, offset) . = ..() @@ -358,6 +360,10 @@ return TRUE //Nothing found to block so return success! /turf/Entered(atom/movable/A) + SHOULD_CALL_PARENT(TRUE) + + ..() // Shouldn't do anything but to satisfy lint + if(!istype(A)) return @@ -458,13 +464,6 @@ created_baseturf_lists[new_baseturfs[length(new_baseturfs)]] = new_baseturfs.Copy() return new_baseturfs -/// WARNING WARNING -/// Turfs DO NOT lose their signals when they get replaced, REMEMBER THIS -/// It's possible because turfs are fucked, and if you have one in a list and it's replaced with another one, the list ref points to the new turf -/// We do it because moving signals over was needlessly expensive, and bloated a very commonly used bit of code -/turf/clear_signal_refs() - return - // Creates a new turf // new_baseturfs can be either a single type or list of types, formatted the same as baseturfs. see turf.dm /turf/proc/ChangeTurf(path, list/new_baseturfs, flags) @@ -498,19 +497,8 @@ changing_turf = TRUE qdel(src) //Just get the side effects and call Destroy - // Get signal registrations post-Destroy so stuff that's unregistered on Destroy won't be readded - var/list/old_comp_lookup = comp_lookup?.Copy() - var/list/old_signal_procs = signal_procs?.Copy() var/turf/W = new path(src) - // WARNING WARNING - // Turfs DO NOT lose their signals when they get replaced, REMEMBER THIS - // It's possible because turfs are fucked, and if you have one in a list and it's replaced with another one, the list ref points to the new turf - if(old_comp_lookup) - LAZYOR(W.comp_lookup, old_comp_lookup) - if(old_signal_procs) - LAZYOR(W.signal_procs, old_signal_procs) - W.weak_reference = old_ref for(var/datum/callback/callback as anything in post_change_callbacks) diff --git a/code/game/turfs/walls/wall_types.dm b/code/game/turfs/walls/wall_types.dm index 7ec978aef332..5e14aae26f95 100644 --- a/code/game/turfs/walls/wall_types.dm +++ b/code/game/turfs/walls/wall_types.dm @@ -1286,7 +1286,10 @@ hivenumber = hive set_hive_data(src, hive) recalculate_structure() - update_tied_turf(loc) + if(!mapload) + update_tied_turf() + // COMSIG_MOVABLE_TURF_ENTERED to handle movement and ChangeTurf + RegisterSignal(src, COMSIG_MOVABLE_TURF_ENTERED, PROC_REF(update_tied_turf)) RegisterSignal(src, COMSIG_MOVABLE_XENO_START_PULLING, PROC_REF(allow_xeno_drag)) RegisterSignal(src, COMSIG_MOVABLE_PULLED, PROC_REF(continue_allowing_drag)) @@ -1397,20 +1400,17 @@ return ..() -/obj/structure/alien/movable_wall/proc/update_tied_turf(turf/T) - SIGNAL_HANDLER +/obj/structure/alien/movable_wall/proc/update_tied_turf() + SIGNAL_HANDLER // COMSIG_MOVABLE_TURF_ENTERED - if(!T) + if(!loc) return if(tied_turf) - UnregisterSignal(tied_turf, COMSIG_TURF_ENTER) - RegisterSignal(T, COMSIG_TURF_ENTER, PROC_REF(check_for_move)) - tied_turf = T + UnregisterSignal(tied_turf, list(COMSIG_TURF_ENTER)) -/obj/structure/alien/movable_wall/forceMove(atom/dest) - . = ..() - update_tied_turf(loc) + tied_turf = loc + RegisterSignal(loc, COMSIG_TURF_ENTER, PROC_REF(check_for_move)) /obj/structure/alien/movable_wall/proc/check_for_move(turf/T, atom/movable/mover) if(group.next_push > world.time) diff --git a/code/modules/cm_aliens/weeds.dm b/code/modules/cm_aliens/weeds.dm index 3d2b3021a254..67a7033b9fef 100644 --- a/code/modules/cm_aliens/weeds.dm +++ b/code/modules/cm_aliens/weeds.dm @@ -79,8 +79,9 @@ weeded_turf = turf SEND_SIGNAL(turf, COMSIG_WEEDNODE_GROWTH) // Currently for weed_food wakeup + // COMSIG_MOVABLE_TURF_ENTERED to handle ChangeTurf RegisterSignal(src, COMSIG_MOVABLE_TURF_ENTERED, PROC_REF(set_turf_weeded)) - RegisterSignal(turf, COMSIG_PRE_TURF_CHANGE, PROC_REF(pre_turf_change)) + if(hivenumber == XENO_HIVE_NORMAL) RegisterSignal(SSdcs, COMSIG_GLOB_GROUNDSIDE_FORSAKEN_HANDLING, PROC_REF(forsaken_handling)) @@ -95,10 +96,6 @@ T.weeds = src -// Before the turf changes, register a temporary callback to update `weeds` post-change. -/obj/effect/alien/weeds/proc/pre_turf_change(turf/source, path, list/new_baseturfs, flags, list/post_change_callbacks) - post_change_callbacks += CALLBACK(src, PROC_REF(set_turf_weeded), source) - /obj/effect/alien/weeds/proc/forsaken_handling() SIGNAL_HANDLER if(is_ground_level(z)) diff --git a/code/modules/tents/deployed_tents.dm b/code/modules/tents/deployed_tents.dm index 1d386bf28256..b1df28cbf3cf 100644 --- a/code/modules/tents/deployed_tents.dm +++ b/code/modules/tents/deployed_tents.dm @@ -27,8 +27,9 @@ . = ..() bound_width = x_dim * world.icon_size bound_height = y_dim * world.icon_size - for(var/turf/turf in locs) - RegisterSignal(turf, COMSIG_TURF_ENTERED, PROC_REF(movable_entering_tent), override = TRUE) + // COMSIG_MOVABLE_TURF_ENTERED to handle ChangeTurf + RegisterSignal(src, COMSIG_MOVABLE_TURF_ENTERED, PROC_REF(register_turf_signals)) + register_turf_signals() switch(SSmapping.configs[GROUND_MAP].camouflage_type) if("jungle") @@ -46,6 +47,12 @@ roof_image.appearance_flags = KEEP_APART src.overlays += roof_image +/// Handler for callback of COMSIG_MOVABLE_TURF_ENTERED (turf changed) +/obj/structure/tent/proc/register_turf_signals() + SIGNAL_HANDLER + for(var/turf/turf in locs) + RegisterSignal(turf, COMSIG_TURF_ENTERED, PROC_REF(movable_entering_tent), override = TRUE) + /obj/structure/tent/proc/movable_entering_tent(turf/hooked, atom/movable/subject) SIGNAL_HANDLER if(!ismob(subject)) @@ -53,7 +60,7 @@ var/mob/subject_mob = subject - + // COMSIG_MOVABLE_TURF_ENTERED to handle movement and ChangeTurf RegisterSignal(subject_mob, list(COMSIG_MOVABLE_TURF_ENTERED, COMSIG_GHOST_MOVED), PROC_REF(mob_moved), override = TRUE) // Must override because we can't know if mob was already inside tent without keeping an awful ref list subject_mob.RegisterSignal(src, COMSIG_PARENT_QDELETING, TYPE_PROC_REF(/mob, tent_deletion_clean_up), override = TRUE) @@ -66,10 +73,12 @@ if(ishuman(subject)) RegisterSignal(subject, COMSIG_HUMAN_COLD_PROTECTION_APPLY_MODIFIERS, PROC_REF(cold_protection), override = TRUE) +/// Handler for callback of COMSIG_HUMAN_COLD_PROTECTION_APPLY_MODIFIERS /obj/structure/tent/proc/cold_protection(mob/source, list/protection_data) SIGNAL_HANDLER protection_data["protection"] += cold_protection_factor +/// Handler for callback of COMSIG_MOVABLE_TURF_ENTERED and COMSIG_GHOST_MOVED /obj/structure/tent/proc/mob_moved(mob/subject, turf/target_turf) SIGNAL_HANDLER