From 8fdf5960e43b97cd039ea363c5e1d1c7dc315cfe Mon Sep 17 00:00:00 2001 From: AffectedArc07 <25063394+AffectedArc07@users.noreply.github.com> Date: Tue, 25 May 2021 11:00:13 +0100 Subject: [PATCH 1/5] DNM - Ref finder improvements --- code/__HELPERS/_logging.dm | 8 ++ code/_compile_options.dm | 10 +- code/_globalvars/logging.dm | 5 + code/controllers/subsystem/garbage.dm | 136 +++++++++++++++++--------- code/datums/datum.dm | 2 +- code/game/world.dm | 5 + code/modules/admin/admin_verbs.dm | 7 +- 7 files changed, 123 insertions(+), 50 deletions(-) diff --git a/code/__HELPERS/_logging.dm b/code/__HELPERS/_logging.dm index 34e7f3fda28..f1b76b72004 100644 --- a/code/__HELPERS/_logging.dm +++ b/code/__HELPERS/_logging.dm @@ -143,6 +143,14 @@ GLOBAL_PROTECT(log_end) /proc/log_tgui(text) rustg_log_write(GLOB.tgui_log, "[text][GLOB.log_end]") +#ifdef REFERENCE_TRACKING +/proc/log_gc(text) + rustg_log_write(GLOB.gc_log, "[text][GLOB.log_end]") + for(var/client/C in GLOB.admins) + if(check_rights(R_DEBUG, 0, C.mob) && (C.prefs.toggles & PREFTOGGLE_CHAT_DEBUGLOGS)) + to_chat(C, "GC DEBUG: [text]") +#endif + /proc/log_sql(text) rustg_log_write(GLOB.sql_log, "[text][GLOB.log_end]") SEND_TEXT(world.log, text) // Redirect it to DD too diff --git a/code/_compile_options.dm b/code/_compile_options.dm index 21e3765ddde..372e39d7602 100644 --- a/code/_compile_options.dm +++ b/code/_compile_options.dm @@ -9,13 +9,15 @@ #define UNIT_TESTS #endif -#ifdef TESTING -//#define GC_FAILURE_HARD_LOOKUP //makes paths that fail to GC call find_references before del'ing. - //implies FIND_REF_NO_CHECK_TICK +/***** All toggles for the GC ref finder *****/ + +#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 FIND_REF_NO_CHECK_TICK //Sets world.loop_checks to false and prevents find references from sleeping -#endif +/***** End toggles for the GC ref finder *****/ #define IS_MODE_COMPILED(MODE) (ispath(text2path("/datum/game_mode/"+(MODE)))) diff --git a/code/_globalvars/logging.dm b/code/_globalvars/logging.dm index 1e0a82c1c28..6fbfde6168d 100644 --- a/code/_globalvars/logging.dm +++ b/code/_globalvars/logging.dm @@ -24,6 +24,11 @@ GLOBAL_PROTECT(sql_log) GLOBAL_VAR(round_id) GLOBAL_PROTECT(round_id) +#ifdef REFERENCE_TRACKING +GLOBAL_VAR(gc_log) +GLOBAL_PROTECT(gc_log) +#endif + GLOBAL_LIST_EMPTY(jobMax) GLOBAL_PROTECT(jobMax) GLOBAL_LIST_EMPTY(admin_log) diff --git a/code/controllers/subsystem/garbage.dm b/code/controllers/subsystem/garbage.dm index e50c372584a..6206d645ff0 100644 --- a/code/controllers/subsystem/garbage.dm +++ b/code/controllers/subsystem/garbage.dm @@ -26,8 +26,10 @@ SUBSYSTEM_DEF(garbage) //Queue var/list/queues - #ifdef TESTING + #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 #endif @@ -137,7 +139,7 @@ SUBSYSTEM_DEF(garbage) ++gcedlasttick ++totalgcs pass_counts[level]++ - #ifdef TESTING + #ifdef REFERENCE_TRACKING reference_find_on_fail -= refID //It's deleted we don't care anymore. #endif if(MC_TICK_CHECK) @@ -146,20 +148,27 @@ SUBSYSTEM_DEF(garbage) // Something's still referring to the qdel'd object. fail_counts[level]++ + #ifdef REFERENCE_TRACKING + var/ref_searching = FALSE + #endif switch(level) if(GC_QUEUE_CHECK) - #ifdef TESTING - if(reference_find_on_fail[refID]) - D.find_references() + #ifdef REFERENCE_TRACKING + if(reference_find_on_fail[refID] && !ref_search_stop) + INVOKE_ASYNC(D, /datum/proc/find_references) + ref_searching = TRUE #ifdef GC_FAILURE_HARD_LOOKUP - else - D.find_references() + else if (!ref_search_stop) + INVOKE_ASYNC(D, /datum/proc/find_references) + ref_searching = TRUE #endif reference_find_on_fail -= refID #endif var/type = D.type var/datum/qdel_item/I = items[type] - testing("GC: -- \ref[src] | [type] was unable to be GC'd --") + #ifdef REFERENCE_TRACKING + log_gc("GC: -- \ref[src] | [type] was unable to be GC'd --") + #endif I.failures++ if(GC_QUEUE_HARDDELETE) HardDelete(D) @@ -169,6 +178,11 @@ SUBSYSTEM_DEF(garbage) Queue(D, level + 1) + #ifdef REFERENCE_TRACKING + if(ref_searching) + return + #endif + if(MC_TICK_CHECK) return if(count) @@ -243,10 +257,14 @@ SUBSYSTEM_DEF(garbage) /datum/qdel_item/New(mytype) name = "[mytype]" -#ifdef TESTING -/proc/qdel_and_find_ref_if_fail(datum/D, force = FALSE) - SSgarbage.reference_find_on_fail["\ref[D]"] = TRUE - qdel(D, force) +#ifdef REFERENCE_TRACKING +/proc/qdel_and_find_ref_if_fail(datum/thing_to_del, force = FALSE) + thing_to_del.qdel_and_find_ref_if_fail(force) + +/datum/proc/qdel_and_find_ref_if_fail(force = FALSE) + SSgarbage.reference_find_on_fail["\ref[src]"] = TRUE + qdel(src, force) + #endif // Should be treated as a replacement for the 'del' keyword. @@ -304,38 +322,40 @@ SUBSYSTEM_DEF(garbage) SSgarbage.HardDelete(D) if(QDEL_HINT_FINDREFERENCE)//qdel will, if TESTING is enabled, display all references to this object, then queue the object for deletion. SSgarbage.Queue(D) - #ifdef TESTING + #ifdef REFERENCE_TRACKING D.find_references() #endif if(QDEL_HINT_IFFAIL_FINDREFERENCE) SSgarbage.Queue(D) - #ifdef TESTING + #ifdef REFERENCE_TRACKING SSgarbage.reference_find_on_fail["\ref[D]"] = TRUE #endif else - #ifdef TESTING + #ifdef REFERENCE_TRACKING if(!I.no_hint) - testing("WARNING: [D.type] is not returning a qdel hint. It is being placed in the queue. Further instances of this type will also be queued.") + log_gc("WARNING: [D.type] is not returning a qdel hint. It is being placed in the queue. Further instances of this type will also be queued.") #endif I.no_hint++ SSgarbage.Queue(D) else if(D.gc_destroyed == GC_CURRENTLY_BEING_QDELETED) CRASH("[D.type] destroy proc was called multiple times, likely due to a qdel loop in the Destroy logic") -#ifdef TESTING +#ifdef REFERENCE_TRACKING -/datum/verb/find_refs() +/client/proc/find_refs() + set src in world set category = "Debug" set name = "Find References" - set src in world + if(!check_rights(R_DEBUG)) + return find_references(FALSE) /datum/proc/find_references(skip_alert) running_find_references = type if(usr && usr.client) if(usr.client.running_find_references) - testing("CANCELLED search for references to a [usr.client.running_find_references].") + log_gc("CANCELLED search for references to a [usr.client.running_find_references].") usr.client.running_find_references = null running_find_references = null //restart the garbage collector @@ -354,20 +374,27 @@ SUBSYSTEM_DEF(garbage) if(usr && usr.client) usr.client.running_find_references = type - testing("Beginning search for references to a [type].") - last_find_references = world.time + log_gc("Beginning search for references to a [type].") + var/starting_time = world.time - DoSearchVar(GLOB) //globals + DoSearchVar(GLOB, "GLOB") //globals + log_gc("Finished searching globals") for(var/datum/thing in world) //atoms (don't beleive it's lies) - DoSearchVar(thing, "World -> [thing]") + DoSearchVar(thing, "World -> [thing.type]", search_time = starting_time) + + log_gc("Finished searching atoms") for(var/datum/thing) //datums - DoSearchVar(thing, "World -> [thing]") + DoSearchVar(thing, "World -> [thing.type]", search_time = starting_time) + + log_gc("Finished searching datums") for(var/client/thing) //clients - DoSearchVar(thing, "World -> [thing]") + DoSearchVar(thing, "World -> [thing.type]", search_time = starting_time) - testing("Completed search for references to a [type].") + log_gc("Finished searching clients") + + log_gc("Completed search for references to a [type].") if(usr && usr.client) usr.client.running_find_references = null running_find_references = null @@ -376,58 +403,79 @@ SUBSYSTEM_DEF(garbage) SSgarbage.can_fire = 1 SSgarbage.next_fire = world.time + world.tick_lag -/datum/verb/qdel_then_find_references() +/client/proc/qdel_then_find_references() + set src in world set category = "Debug" set name = "qdel() then Find References" - set src in world + if(!check_rights(R_DEBUG)) + return - qdel(src, TRUE) //Force. + qdel(src, TRUE) //force a qdel if(!running_find_references) find_references(TRUE) -/datum/verb/qdel_then_if_fail_find_references() +/client/proc/qdel_then_if_fail_find_references() + set src in world set category = "Debug" set name = "qdel() then Find References if GC failure" - set src in world + if(!check_rights(R_DEBUG)) + return qdel_and_find_ref_if_fail(src, TRUE) -/datum/proc/DoSearchVar(X, Xname, recursive_limit = 64) - if(usr && usr.client && !usr.client.running_find_references) +/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) return + if(!recursive_limit) + log_gc("Recursion limit hit for [Xname].") return if(istype(X, /datum)) var/datum/D = X - if(D.last_find_references == last_find_references) + if(D.last_find_references == search_time) return - D.last_find_references = last_find_references + D.last_find_references = search_time var/list/L = D.vars for(var/varname in L) - if(varname == "vars") + if(varname == "vars"|| varname == "vis_locs") //Fun fact, vis_locs don't count for references continue var/variable = L[varname] if(variable == src) - testing("Found [src.type] \ref[src] in [D.type]'s [varname] var. [Xname]") + log_gc("Found [src.type] \ref[src] in [D.type]'s [varname] var. [Xname]") + continue else if(islist(variable)) - DoSearchVar(variable, "[Xname] -> list", recursive_limit - 1) + DoSearchVar(variable, "[Xname] \ref[D] -> [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) - testing("Found [src.type] \ref[src] in list [Xname].") + log_gc("Found [src.type] \ref[src] in list [Xname].") + continue - else if(I && !isnum(I) && normal && X[I] == src) - testing("Found [src.type] \ref[src] in list [Xname]\[[I]\]") + var/assoc_val = null + if(!isnum(I) && normal) + assoc_val = potential_cache[I] - else if(islist(I)) - DoSearchVar(I, "[Xname] -> list", recursive_limit - 1) + //Check assoc entrys + if(assoc_val == src) + log_gc("Found [src.type] \ref[src] in list [Xname]\[[I]\]") + 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) + + //Check assoc sublists + if(islist(assoc_val)) + DoSearchVar(X[I], "[Xname]\[[I]\] -> [X[I]] (list)", recursive_limit - 1, search_time) #ifndef FIND_REF_NO_CHECK_TICK CHECK_TICK diff --git a/code/datums/datum.dm b/code/datums/datum.dm index 8d3ec92cf40..68acd8c8d61 100644 --- a/code/datums/datum.dm +++ b/code/datums/datum.dm @@ -10,7 +10,7 @@ var/var_edited = FALSE //Warranty void if seal is broken var/tmp/unique_datum_id = null -#ifdef TESTING +#ifdef REFERENCE_TRACKING var/running_find_references var/last_find_references = 0 #endif diff --git a/code/game/world.dm b/code/game/world.dm index c72ed4859ab..3ec63280fd2 100644 --- a/code/game/world.dm +++ b/code/game/world.dm @@ -260,6 +260,11 @@ GLOBAL_LIST_EMPTY(world_topic_handlers) start_log(GLOB.http_log) start_log(GLOB.sql_log) + #ifdef REFERENCE_TRACKING + GLOB.gc_log = "[GLOB.log_directory]/gc_debug.log" + start_log(GLOB.gc_log) + #endif + // This log follows a special format and this path should NOT be used for anything else GLOB.runtime_summary_log = "data/logs/runtime_summary.log" if(fexists(GLOB.runtime_summary_log)) diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index ef2b92e28d7..df42540c0b8 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -167,7 +167,12 @@ GLOBAL_LIST_INIT(admin_verbs_debug, list( /client/proc/toggle_medal_disable, /client/proc/uid_log, /client/proc/visualise_active_turfs, - /client/proc/reestablish_db_connection + /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, + #endif )) GLOBAL_LIST_INIT(admin_verbs_possess, list( /proc/possess, From 6ee2bd72cb0ca87196863fc52bb9b4a2f1cbdb80 Mon Sep 17 00:00:00 2001 From: AffectedArc07 <25063394+AffectedArc07@users.noreply.github.com> Date: Tue, 25 May 2021 13:12:25 +0100 Subject: [PATCH 2/5] Tweaks --- code/_compile_options.dm | 6 +- code/controllers/subsystem/garbage.dm | 79 ++++++++++++----------- code/modules/admin/admin_verbs.dm | 6 +- code/modules/mob/new_player/new_player.dm | 5 ++ 4 files changed, 53 insertions(+), 43 deletions(-) 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 From da29f4ede138d1ea1d33f0c52b026b8f299aedcb Mon Sep 17 00:00:00 2001 From: AffectedArc07 <25063394+AffectedArc07@users.noreply.github.com> Date: Tue, 25 May 2021 16:03:13 +0000 Subject: [PATCH 3/5] Apply suggestions from code review Co-authored-by: SabreML <57483089+SabreML@users.noreply.github.com> --- code/__HELPERS/_logging.dm | 2 +- code/controllers/subsystem/garbage.dm | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/__HELPERS/_logging.dm b/code/__HELPERS/_logging.dm index f1b76b72004..2761f06351f 100644 --- a/code/__HELPERS/_logging.dm +++ b/code/__HELPERS/_logging.dm @@ -147,7 +147,7 @@ GLOBAL_PROTECT(log_end) /proc/log_gc(text) rustg_log_write(GLOB.gc_log, "[text][GLOB.log_end]") for(var/client/C in GLOB.admins) - if(check_rights(R_DEBUG, 0, C.mob) && (C.prefs.toggles & PREFTOGGLE_CHAT_DEBUGLOGS)) + if(check_rights(R_DEBUG, FALSE, C.mob) && (C.prefs.toggles & PREFTOGGLE_CHAT_DEBUGLOGS)) to_chat(C, "GC DEBUG: [text]") #endif diff --git a/code/controllers/subsystem/garbage.dm b/code/controllers/subsystem/garbage.dm index 5ea328cbd01..e66b93b6eda 100644 --- a/code/controllers/subsystem/garbage.dm +++ b/code/controllers/subsystem/garbage.dm @@ -444,7 +444,7 @@ SUBSYSTEM_DEF(garbage) #ifndef FIND_REF_NO_CHECK_TICK CHECK_TICK #endif - if (varname == "vars" || varname == "vis_locs") //Fun fact, vis_locs don't count for references + if(varname == "vars" || varname == "vis_locs") //Fun fact, vis_locs don't count for references continue var/variable = vars_list[varname] From 89d6a26991a412be6dd6c282dd683e338afae11e Mon Sep 17 00:00:00 2001 From: AffectedArc07 <25063394+AffectedArc07@users.noreply.github.com> Date: Sat, 12 Jun 2021 20:14:58 +0100 Subject: [PATCH 4/5] Not required --- code/modules/mob/new_player/new_player.dm | 5 ----- 1 file changed, 5 deletions(-) diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index 40a7d25aebf..ff0875c763c 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -19,11 +19,6 @@ 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 From 8ddfe635b59adb9506da3c79ad76a2b8bd8883cd Mon Sep 17 00:00:00 2001 From: AffectedArc07 <25063394+AffectedArc07@users.noreply.github.com> Date: Sun, 13 Jun 2021 16:18:43 +0100 Subject: [PATCH 5/5] AAAAAAAAAAAAAAAAAAAAAAAAAAAAA --- code/game/jobs/job/job.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/jobs/job/job.dm b/code/game/jobs/job/job.dm index fd3e1a0442b..8f313c185dc 100644 --- a/code/game/jobs/job/job.dm +++ b/code/game/jobs/job/job.dm @@ -225,7 +225,7 @@ to_chat(H, "Failed to locate a storage object on your mob, either you spawned with no hands free and no backpack or this is a bug.") qdel(G) - qdel(gear_leftovers) + gear_leftovers.Cut() return 1