diff --git a/code/_compile_options.dm b/code/_compile_options.dm index 372e39d7602..f409af92aaa 100644 --- a/code/_compile_options.dm +++ b/code/_compile_options.dm @@ -11,11 +11,11 @@ /***** All toggles for the GC ref finder *****/ -#define REFERENCE_TRACKING // Uncomment to enable ref finding +// #define REFERENCE_TRACKING // Uncomment to enable ref finding -//#define GC_FAILURE_HARD_LOOKUP //makes paths that fail to GC call find_references before del'ing. implies FIND_REF_NO_CHECK_TICK +// #define GC_FAILURE_HARD_LOOKUP //makes paths that fail to GC call find_references before del'ing. -//#define FIND_REF_NO_CHECK_TICK //Sets world.loop_checks to false and prevents find references from sleeping +// #define FIND_REF_NO_CHECK_TICK //Sets world.loop_checks to false and prevents find references from sleeping /***** End toggles for the GC ref finder *****/ diff --git a/code/controllers/subsystem/garbage.dm b/code/controllers/subsystem/garbage.dm index 6206d645ff0..5ea328cbd01 100644 --- a/code/controllers/subsystem/garbage.dm +++ b/code/controllers/subsystem/garbage.dm @@ -28,8 +28,7 @@ SUBSYSTEM_DEF(garbage) #ifdef REFERENCE_TRACKING var/list/reference_find_on_fail = list() - //We default to true so the game can just "continue working" if there's no one to read the data - var/ref_search_stop = TRUE + var/ref_search_stop = FALSE #endif @@ -342,8 +341,7 @@ SUBSYSTEM_DEF(garbage) #ifdef REFERENCE_TRACKING -/client/proc/find_refs() - set src in world +/datum/proc/find_refs() set category = "Debug" set name = "Find References" @@ -403,8 +401,7 @@ SUBSYSTEM_DEF(garbage) SSgarbage.can_fire = 1 SSgarbage.next_fire = world.time + world.tick_lag -/client/proc/qdel_then_find_references() - set src in world +/datum/proc/qdel_then_find_references() set category = "Debug" set name = "qdel() then Find References" if(!check_rights(R_DEBUG)) @@ -414,8 +411,7 @@ SUBSYSTEM_DEF(garbage) if(!running_find_references) find_references(TRUE) -/client/proc/qdel_then_if_fail_find_references() - set src in world +/datum/proc/qdel_then_if_fail_find_references() set category = "Debug" set name = "qdel() then Find References if GC failure" if(!check_rights(R_DEBUG)) @@ -423,59 +419,68 @@ SUBSYSTEM_DEF(garbage) qdel_and_find_ref_if_fail(src, TRUE) -/datum/proc/DoSearchVar(X, Xname, recursive_limit = 64, search_time = world.time) - if(usr && usr.client && !usr.client.running_find_references || SSgarbage.ref_search_stop) +/datum/proc/DoSearchVar(potential_container, container_name, recursive_limit = 64, search_time = world.time) + if((usr?.client && !usr.client.running_find_references) || SSgarbage.ref_search_stop) return if(!recursive_limit) - log_gc("Recursion limit hit for [Xname].") + log_gc("Recursion limit reached. [container_name]") return - if(istype(X, /datum)) - var/datum/D = X - if(D.last_find_references == search_time) + //Check each time you go down a layer. This makes it a bit slow, but it won't effect the rest of the game at all + #ifndef FIND_REF_NO_CHECK_TICK + CHECK_TICK + #endif + + if(istype(potential_container, /datum)) + var/datum/datum_container = potential_container + if(datum_container.last_find_references == search_time) return - D.last_find_references = search_time - var/list/L = D.vars + datum_container.last_find_references = search_time + var/list/vars_list = datum_container.vars - for(var/varname in L) - if(varname == "vars"|| varname == "vis_locs") //Fun fact, vis_locs don't count for references + for(var/varname in vars_list) + #ifndef FIND_REF_NO_CHECK_TICK + CHECK_TICK + #endif + if (varname == "vars" || varname == "vis_locs") //Fun fact, vis_locs don't count for references continue - var/variable = L[varname] + var/variable = vars_list[varname] if(variable == src) - log_gc("Found [src.type] \ref[src] in [D.type]'s [varname] var. [Xname]") + log_gc("Found [type] \ref[src] in [datum_container.type]'s \ref[datum_container] [varname] var. [container_name]") continue - else if(islist(variable)) - DoSearchVar(variable, "[Xname] \ref[D] -> [varname] (list)", recursive_limit - 1, search_time) + if(islist(variable)) + DoSearchVar(variable, "[container_name] \ref[datum_container] -> [varname] (list)", recursive_limit - 1, search_time) - else if(islist(X)) - var/normal = IS_NORMAL_LIST(X) - var/list/potential_cache = X - for(var/I in X) - if(I == src) - log_gc("Found [src.type] \ref[src] in list [Xname].") + else if(islist(potential_container)) + var/normal = IS_NORMAL_LIST(potential_container) + var/list/potential_cache = potential_container + for(var/element_in_list in potential_cache) + #ifndef FIND_REF_NO_CHECK_TICK + CHECK_TICK + #endif + //Check normal entrys + if(element_in_list == src) + log_gc("Found [type] \ref[src] in list [container_name].") continue var/assoc_val = null - if(!isnum(I) && normal) - assoc_val = potential_cache[I] - + if(!isnum(element_in_list) && normal) + assoc_val = potential_cache[element_in_list] //Check assoc entrys if(assoc_val == src) - log_gc("Found [src.type] \ref[src] in list [Xname]\[[I]\]") + log_gc("Found [type] \ref[src] in list [container_name]\[[element_in_list]\]") continue - //We need to run both of these checks, since our object could be hiding in either of them //Check normal sublists - if(islist(I)) - DoSearchVar(I, "[Xname] -> [I] (list)", recursive_limit - 1, search_time) - + if(islist(element_in_list)) + DoSearchVar(element_in_list, "[container_name] -> [element_in_list] (list)", recursive_limit - 1, search_time) //Check assoc sublists if(islist(assoc_val)) - DoSearchVar(X[I], "[Xname]\[[I]\] -> [X[I]] (list)", recursive_limit - 1, search_time) + DoSearchVar(potential_container[element_in_list], "[container_name]\[[element_in_list]\] -> [assoc_val] (list)", recursive_limit - 1, search_time) #ifndef FIND_REF_NO_CHECK_TICK CHECK_TICK diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index df42540c0b8..808e960ae5f 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -169,9 +169,9 @@ GLOBAL_LIST_INIT(admin_verbs_debug, list( /client/proc/visualise_active_turfs, /client/proc/reestablish_db_connection, #ifdef REFERENCE_TRACKING - /client/proc/find_refs, - /client/proc/qdel_then_find_references, - /client/proc/qdel_then_if_fail_find_references, + /datum/proc/find_refs, + /datum/proc/qdel_then_find_references, + /datum/proc/qdel_then_if_fail_find_references, #endif )) GLOBAL_LIST_INIT(admin_verbs_possess, list( diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index ff0875c763c..40a7d25aebf 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -19,6 +19,11 @@ GLOB.mob_list += src return INITIALIZE_HINT_NORMAL +/mob/new_player/Destroy() + GLOB.player_list -= src + return ..() + + /mob/new_player/verb/new_player_panel() set src = usr