Fix several hard-dels, add harddel ref tracking (#16174)

This commit is contained in:
Wildkins
2023-04-10 16:42:20 -04:00
committed by GitHub
parent e9a9bb3323
commit 3f4786ab23
30 changed files with 418 additions and 905 deletions
+1
View File
@@ -89,6 +89,7 @@
#include "code\__defines\tips.dm"
#include "code\__defines\traits.dm"
#include "code\__defines\turfs.dm"
#include "code\__defines\typeids.dm"
#include "code\__defines\vueui.dm"
#include "code\__defines\webhook.dm"
#include "code\__defines\ZAS.dm"
+19 -1
View File
@@ -10,4 +10,22 @@
#ifndef PRELOAD_RSC //set to:
#define PRELOAD_RSC 2 // 0 to allow using external resources or on-demand behaviour;
#endif // 1 to use the default behaviour;
// 2 for preloading absolutely everything;
// 2 for preloading absolutely everything;
//#define TESTING // Creates debug feedback messages and enables many optional testing procs/checks
#ifdef TESTING
///Used to find the sources of harddels, quite laggy, don't be surpised if it freezes your client for a good while
//#define REFERENCE_TRACKING
#ifdef REFERENCE_TRACKING
//Run a lookup on things hard deleting by default.
#define GC_FAILURE_HARD_LOOKUP
#ifdef GC_FAILURE_HARD_LOOKUP
///Don't stop when searching, go till you're totally done
#define FIND_REF_NO_CHECK_TICK
#endif //ifdef GC_FAILURE_HARD_LOOKUP
#endif //ifdef REFERENCE_TRACKING
#endif //ifdef TESTING
+2 -1
View File
@@ -4,6 +4,7 @@
#define list_find(L, needle, LIMITS...) L.Find(needle, LIMITS)
#define hex2num(hex) text2num(hex, 16)
#define num2hex(num, pad) num2text(num, pad, 16)
#define text_ref(datum) (isdatum(datum) ? (datum:cached_ref ||= "\ref[datum]") : ("\ref[datum]"))
#define span(class, text) ("<span class='[class]'>" + text + "</span>")
#define SPAN_NOTICE(X) ("<span class='notice'>" + X + "</span>")
@@ -155,4 +156,4 @@
#define LIST_PRE_INC(L) (++(L).len)
/// Decrease the size of L by 1 from the end. Is the old last entry index.
#define LIST_DEC(L) ((L).len--)
#define LIST_DEC(L) ((L).len--)
+21 -8
View File
@@ -1,13 +1,25 @@
//defines that give qdel hints. these can be given as a return in destory() or by calling
//! Defines that give qdel hints.
//!
//! These can be given as a return in [/atom/proc/Destroy] or by calling [/proc/qdel].
/// `qdel` should queue the object for deletion.
#define QDEL_HINT_QUEUE 0
/// `qdel` should let the object live after calling [/datum/proc/Destroy].
#define QDEL_HINT_LETMELIVE 1
/// Functionally the same as above. `qdel` should assume the object will gc on its own, and not check it.
#define QDEL_HINT_IWILLGC 2
/// `qdel` should assume this object won't GC, and queue a hard delete using a hardref.
#define QDEL_HINT_HARDDEL 3
/// `qdel` should assume this object won't GC, and hard delete it immediately.
#define QDEL_HINT_HARDDEL_NOW 4
#define QDEL_HINT_QUEUE 0 //qdel should queue the object for deletion.
#define QDEL_HINT_LETMELIVE 1 //qdel should let the object live after calling destory.
#define QDEL_HINT_IWILLGC 2 //functionally the same as the above. qdel should assume the object will gc on its own, and not check it.
#define QDEL_HINT_HARDDEL 3 //qdel should assume this object won't gc, and queue a hard delete using a hard reference.
#define QDEL_HINT_HARDDEL_NOW 4 //qdel should assume this object won't gc, and hard del it post haste.
#define QDEL_HINT_FINDREFERENCE 5 //functionally identical to QDEL_HINT_QUEUE if TESTING is not enabled in _compiler_options.dm.
//if TESTING is enabled, qdel will call this object's find_references() verb.
/*
* If REFERENCE_TRACKING and [GC_FAILURE_HARD_LOOKUP] are not enabled, these are functionally identical to [QDEL_HINT_QUEUE].
* If they are enabled, qdel will call this object's find_references() verb.
*/
#define QDEL_HINT_FINDREFERENCE 5
/// Same behavior as [QDEL_HINT_FINDREFERENCE], but only if GC fails and a hard delete is forced.
#define QDEL_HINT_IFFAIL_FINDREFERENCE 6
//defines for the gcDestroyed var
#define GC_QUEUED_FOR_QUEUING -1
@@ -21,3 +33,4 @@
#define QDEL_IN(item, time) addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(qdel), item), time, TIMER_STOPPABLE)
#define QDEL_NULL(item) qdel(item); item = null
#define QDEL_NULL_LIST(x) if(x) { for(var/y in x) { qdel(y) }}; if(x) {x.Cut(); x = null } // Second x check to handle items that LAZYREMOVE on qdel.
#define QDEL_NULL_ASSOC(x) if(x) { for(var/y in x) { qdel(x[y])}}; if(x) {x.Cut(); x = null } // As above, but qdels the value rather than the key
+8
View File
@@ -0,0 +1,8 @@
//Byond type ids
#define TYPEID_NULL "0"
#define TYPEID_NORMAL_LIST "f"
//helper macros
#define GET_TYPEID(ref) ( ( (length(ref) <= 10) ? "TYPEID_NULL" : copytext(ref, 4, -7) ) )
// Only allowed raw ref, since this is for lists explicitly and they will get no use from it
// Also it tends to be used in a hot context so let's be nice yes?
#define IS_NORMAL_LIST(L) (GET_TYPEID("\ref[L]") == TYPEID_NORMAL_LIST)
+1 -1
View File
@@ -4,7 +4,7 @@
* Pretty much pokes the MC to make sure it's still alive.
**/
#define FAILSAFE_MSG(msg) admin_notice("<big><em><span class='warning'>FAILSAFE: </span><font color='black'>[msg]</font></em></big>", R_DEBUG|R_ADMIN|R_DEV)
#define FAILSAFE_MSG(msg) admin_notice("<big><em><span class='warning'>FAILSAFE: </span><font color='#ff8800'>[msg]</font></em></big>", R_DEBUG|R_ADMIN|R_DEV)
var/datum/controller/failsafe/Failsafe
+123 -822
View File
@@ -1,4 +1,4 @@
#ifdef TESTING
#ifdef REFERENCE_TRACKING
/datum/var/running_find_references
/datum/var/last_find_references = 0
@@ -11,62 +11,6 @@
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].")
usr.client.running_find_references = null
running_find_references = null
//restart the garbage collector
SSgarbage.can_fire = 1
SSgarbage.next_fire = world.time + world.tick_lag
return
if(!skip_alert)
if(alert("Running this will lock everything up for about 5 minutes. Would you like to begin the search?", "Find References", "Yes", "No") == "No")
running_find_references = null
return
//this keeps the garbage collector from failing to collect objects being searched for in here
SSgarbage.can_fire = 0
if(usr && usr.client)
usr.client.running_find_references = type
testing("Beginning search for references to a [type].")
last_find_references = world.time
find_references_in_globals()
for(var/datum/thing in world)
DoSearchVar(thing, "WorldRef: [thing]")
testing("Completed search for references to a [type].")
if(usr && usr.client)
usr.client.running_find_references = null
running_find_references = null
//restart the garbage collector
SSgarbage.can_fire = 1
SSgarbage.next_fire = world.time + world.tick_lag
/client/verb/purge_all_destroyed_objects()
set category = "Debug"
if(SSgarbage)
while(SSgarbage.queue.len)
var/datum/o = locate(SSgarbage.queue[1])
if(istype(o) && o.gcDestroyed)
del(o)
SSgarbage.totaldels++
SSgarbage.queue.Cut(1, 2)
/datum/verb/qdel_then_find_references(datum/thing in world)
set category = "Debug"
set name = "qdel() then Find References"
set background = 1
qdel(thing)
if(!thing.running_find_references)
thing.find_references(TRUE)
/client/verb/show_qdeleted()
set category = "Debug"
set name = "Show qdel() Log"
@@ -80,779 +24,136 @@
tmplist[elem] = 0
tmplist[elem]++
sortTim(tmplist, GLOBAL_PROC_REF(cmp_numeric_dsc), TRUE)
for(var/path in tmplist)
dat += "[path] - [tmplist[path]] times<BR>"
usr << browse(dat, "window=qdeletedlog")
#define SearchVar(X) DoSearchVar(X, "Global: " + #X)
/datum/proc/DoSearchVar(X, Xname)
if(usr && usr.client && !usr.client.running_find_references) return
if(istype(X, /datum))
var/datum/D = X
if(D.last_find_references == last_find_references)
/datum/proc/find_references(skip_alert)
running_find_references = type
if(usr?.client)
if(usr.client.running_find_references)
testing("CANCELLED search for references to a [usr.client.running_find_references].")
usr.client.running_find_references = null
running_find_references = null
SSgarbage.enable()
return
D.last_find_references = last_find_references
for(var/V in D.vars)
for(var/varname in D.vars)
var/variable = D.vars[varname]
if(variable == src)
testing("Found [src.type] \ref[src] in [D.type]'s [varname] var. [Xname]")
else if(islist(variable))
if(src in variable)
testing("Found [src.type] \ref[src] in [D.type]'s [varname] list var. Global: [Xname]")
#ifdef GC_FAILURE_HARD_LOOKUP
for(var/I in variable)
DoSearchVar(I, TRUE)
else
DoSearchVar(variable, "[Xname]: [varname]")
#endif
else if(islist(X))
if(src in X)
testing("Found [src.type] \ref[src] in list [Xname].")
#ifdef GC_FAILURE_HARD_LOOKUP
for(var/I in X)
DoSearchVar(I, Xname + ": list")
#else
if(!skip_alert && alert(usr, "Running this will lock everything up for 5+ minutes. Would you like to begin the search?", "Find References", "Yes", "No") != "Yes")
running_find_references = null
return
SSgarbage.disable() // Keeps the GC from failing to collect objects being searched for here
if(usr?.client)
usr.client.running_find_references = type
//Time to search the whole game for our ref
testing("Beginning search for references to a [type].")
var/starting_time = world.time
//Yes we do actually need to do this. The searcher refuses to read weird lists
//And global.vars is a really weird list
var/global_vars = list()
for(var/key in global.vars)
global_vars[key] = global.vars[key]
search_var(global_vars, "Native Global", search_time = starting_time)
testing("Finished searching native globals")
for(var/datum/thing in world) // atoms (don't believe its lies)
search_var(thing, "World -> [thing.type]", search_time = starting_time)
testing("Finished searching atoms")
for(var/datum/thing) // datums
search_var(thing, "Datums -> [thing.type]", search_time = starting_time)
testing("Finished searching datums")
//Warning, attempting to search clients like this will cause crashes if done on live. Watch yourself
for(var/client/thing) // clients
search_var(thing, "Clients -> [thing.type]", search_time = starting_time)
testing("Finished searching clients")
testing("Completed all searches for references to a [type].")
if(usr?.client)
usr.client.running_find_references = null
running_find_references = null
SSgarbage.enable() //restart the garbage collector
/datum/proc/search_var(potential_container, container_name, recursive_limit = 64, search_time = world.time)
if(usr?.client && !usr.client.running_find_references)
return
if(!recursive_limit)
testing("Recursion limit reached. [container_name]")
return
//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
#endif
if(isdatum(potential_container))
var/datum/datum_container = potential_container
if(datum_container.last_find_references == search_time)
return
/datum/proc/find_references_in_globals()
SearchVar(all_areas)
SearchVar(processing_power_items)
SearchVar(med_hud_users)
SearchVar(sec_hud_users)
SearchVar(hud_icon_reference)
SearchVar(janitorial_supplies)
SearchVar(world_phylactery)
SearchVar(listening_objects)
SearchVar(global_mutations)
SearchVar(universe)
SearchVar(global_map)
SearchVar(hit_appends)
SearchVar(map_levels)
SearchVar(diary)
SearchVar(diary_runtime)
SearchVar(diary_date_string)
SearchVar(href_logfile)
SearchVar(station_name)
SearchVar(station_short)
SearchVar(dock_name)
SearchVar(boss_name)
SearchVar(boss_short)
SearchVar(company_name)
SearchVar(company_short)
SearchVar(game_version)
SearchVar(changelog_hash)
SearchVar(game_year)
SearchVar(round_progressing)
SearchVar(master_mode)
SearchVar(secret_force_mode)
SearchVar(bombers)
SearchVar(admin_log)
SearchVar(lastsignalers)
SearchVar(lawchanges)
SearchVar(reg_dna)
SearchVar(newplayer_start)
SearchVar(latejoin)
SearchVar(latejoin_gateway)
SearchVar(latejoin_cryo)
SearchVar(latejoin_cyborg)
SearchVar(latejoin_merchant)
SearchVar(latejoin_living_quarters_lift)
SearchVar(kickoffsloc)
SearchVar(tdome1)
SearchVar(tdome2)
SearchVar(tdomeobserve)
SearchVar(tdomeadmin)
SearchVar(ninjastart)
SearchVar(cardinal)
SearchVar(cornerdirs)
SearchVar(alldirs)
SearchVar(reverse_dir)
SearchVar(config)
SearchVar(combatlog)
SearchVar(IClog)
SearchVar(OOClog)
SearchVar(adminlog)
SearchVar(Debug2)
SearchVar(debugobj)
SearchVar(mods)
SearchVar(gravity_is_on)
SearchVar(awaydestinations)
SearchVar(fileaccess_timer)
SearchVar(custom_event_msg)
SearchVar(dbcon)
SearchVar(alphabet_uppercase)
SearchVar(robot_module_types)
SearchVar(scarySounds)
SearchVar(max_explosion_range)
SearchVar(global_announcer)
SearchVar(station_departments)
SearchVar(TICKS_IN_DAY)
SearchVar(TICKS_IN_HOUR)
SearchVar(TICKS_IN_SECOND)
SearchVar(exo_beacons)
SearchVar(ai_names)
SearchVar(wizard_first)
SearchVar(wizard_second)
SearchVar(ninja_titles)
SearchVar(ninja_names)
SearchVar(commando_names)
SearchVar(first_names_male)
SearchVar(first_names_female)
SearchVar(last_names)
SearchVar(clown_names)
SearchVar(verbs)
SearchVar(adjectives)
SearchVar(init)
SearchVar(world_api_rate_limit)
SearchVar(tachycardics)
SearchVar(bradycardics)
SearchVar(heartstopper)
SearchVar(cheartstopper)
SearchVar(BLINDBLOCK)
SearchVar(DEAFBLOCK)
SearchVar(HULKBLOCK)
SearchVar(TELEBLOCK)
SearchVar(FIREBLOCK)
SearchVar(XRAYBLOCK)
SearchVar(CLUMSYBLOCK)
SearchVar(FAKEBLOCK)
SearchVar(COUGHBLOCK)
SearchVar(GLASSESBLOCK)
SearchVar(EPILEPSYBLOCK)
SearchVar(TWITCHBLOCK)
SearchVar(NERVOUSBLOCK)
SearchVar(MONKEYBLOCK)
SearchVar(BLOCKADD)
SearchVar(DIFFMUT)
SearchVar(HEADACHEBLOCK)
SearchVar(NOBREATHBLOCK)
SearchVar(REMOTEVIEWBLOCK)
SearchVar(REGENERATEBLOCK)
SearchVar(INCREASERUNBLOCK)
SearchVar(REMOTETALKBLOCK)
SearchVar(MORPHBLOCK)
SearchVar(BLENDBLOCK)
SearchVar(HALLUCINATIONBLOCK)
SearchVar(NOPRINTSBLOCK)
SearchVar(SHOCKIMMUNITYBLOCK)
SearchVar(SMALLSIZEBLOCK)
SearchVar(restricted_camera_networks)
SearchVar(PUB_FREQ)
SearchVar(SEC_FREQ)
SearchVar(ENG_FREQ)
SearchVar(MED_FREQ)
SearchVar(SCI_FREQ)
SearchVar(SRV_FREQ)
SearchVar(SUP_FREQ)
SearchVar(radiochannels)
SearchVar(CENT_FREQS)
SearchVar(CENT_FREQS_ASSOC)
SearchVar(ANTAG_FREQS)
SearchVar(ANTAG_FREQS_ASSOC)
SearchVar(DEPT_FREQS)
SearchVar(DEPT_FREQS_ASSOC)
SearchVar(url_find_lazy)
SearchVar(markup_bold)
SearchVar(markup_italics)
SearchVar(markup_strike)
SearchVar(markup_underline)
SearchVar(markup_regex)
SearchVar(markup_tags)
SearchVar(csrfz_check)
SearchVar(gzn_check)
SearchVar(clients)
SearchVar(admins)
SearchVar(directory)
SearchVar(player_list)
SearchVar(mob_list)
SearchVar(human_mob_list)
SearchVar(silicon_mob_list)
SearchVar(living_mob_list)
SearchVar(dead_mob_list)
SearchVar(topic_commands)
SearchVar(topic_commands_names)
SearchVar(landmarks_list)
SearchVar(surgery_steps)
SearchVar(side_effects)
SearchVar(mechas_list)
SearchVar(joblist)
SearchVar(brig_closets)
SearchVar(teleportlocs)
SearchVar(ghostteleportlocs)
SearchVar(centcom_areas)
SearchVar(the_station_areas)
SearchVar(station_turfs)
SearchVar(implants)
SearchVar(turfs)
SearchVar(all_species)
SearchVar(all_languages)
SearchVar(language_keys)
SearchVar(whitelisted_species)
SearchVar(playable_species)
SearchVar(poster_designs)
SearchVar(world_uplinks)
SearchVar(hair_styles_list)
SearchVar(hair_styles_male_list)
SearchVar(hair_styles_female_list)
SearchVar(facial_hair_styles_list)
SearchVar(facial_hair_styles_male_list)
SearchVar(facial_hair_styles_female_list)
SearchVar(skin_styles_female_list)
SearchVar(body_marking_styles_list)
SearchVar(backbaglist)
SearchVar(pdalist)
SearchVar(headsetlist)
SearchVar(exclude_jobs)
SearchVar(visual_nets)
SearchVar(cameranet)
SearchVar(escape_list)
SearchVar(endgame_exits)
SearchVar(endgame_safespawns)
SearchVar(syndicate_access)
SearchVar(cloaking_devices)
SearchVar(church_name)
SearchVar(command_name)
SearchVar(religion_name)
SearchVar(syndicate_name)
SearchVar(syndicate_code_phrase)
SearchVar(syndicate_code_response)
SearchVar(roundstart_hour)
SearchVar(round_start_time)
SearchVar(real_round_start_time)
SearchVar(common_tools)
SearchVar(wall_items)
SearchVar(sortInstance)
SearchVar(cmp_field)
SearchVar(tk_maxrange)
SearchVar(global_hud)
SearchVar(global_huds)
SearchVar(robot_inventory)
SearchVar(pipe_colors)
SearchVar(gamemode_cache)
SearchVar(panic_targets)
SearchVar(panic_targets_data_loss)
SearchVar(Failsafe)
SearchVar(Master)
SearchVar(CURRENT_TICKLIMIT)
SearchVar(SSalarm)
SearchVar(SSchemistry)
SearchVar(SScargo)
SearchVar(SSeconomy)
SearchVar(SSeffects)
SearchVar(evacuation_controller)
SearchVar(SSevents)
SearchVar(SSexplosives)
SearchVar(SSgarbage)
SearchVar(SSlistener)
SearchVar(SSicon_smooth)
SearchVar(SSipintel)
SearchVar(SSlighting)
SearchVar(SSnightlight)
SearchVar(SSorbit)
SearchVar(SSoverlays)
SearchVar(SSradio)
SearchVar(SSrecords)
SearchVar(sun)
SearchVar(SScargo)
SearchVar(SSticker)
SearchVar(SStimer)
SearchVar(SSvote)
SearchVar(SSatoms)
SearchVar(SSxenoarch)
SearchVar(SScalamity)
SearchVar(SSdisease)
SearchVar(SSmodifiers)
SearchVar(SSnanoui)
SearchVar(SSprocessing)
SearchVar(SSshuttle)
SearchVar(SSskybox)
SearchVar(SSmapping)
SearchVar(base_law_type)
SearchVar(discord_bot)
SearchVar(diseases)
SearchVar(modules)
SearchVar(archive_diseases)
SearchVar(advance_cures)
SearchVar(list_symptoms)
SearchVar(dictionary_symptoms)
SearchVar(SYMPTOM_ACTIVATION_PROB)
SearchVar(revdata)
SearchVar(camera_repository)
SearchVar(crew_repository)
SearchVar(uplink)
SearchVar(AIRLOCK_WIRE_IDSCAN)
SearchVar(AIRLOCK_WIRE_MAIN_POWER1)
SearchVar(AIRLOCK_WIRE_MAIN_POWER2)
SearchVar(AIRLOCK_WIRE_DOOR_BOLTS)
SearchVar(AIRLOCK_WIRE_BACKUP_POWER1)
SearchVar(AIRLOCK_WIRE_BACKUP_POWER2)
SearchVar(AIRLOCK_WIRE_OPEN_DOOR)
SearchVar(AIRLOCK_WIRE_AI_CONTROL)
SearchVar(AIRLOCK_WIRE_ELECTRIFY)
SearchVar(AIRLOCK_WIRE_SAFETY)
SearchVar(AIRLOCK_WIRE_SPEED)
SearchVar(AIRLOCK_WIRE_LIGHT)
SearchVar(AALARM_WIRE_IDSCAN)
SearchVar(AALARM_WIRE_POWER)
SearchVar(AALARM_WIRE_SYPHON)
SearchVar(AALARM_WIRE_AI_CONTROL)
SearchVar(AALARM_WIRE_AALARM)
SearchVar(AUTOLATHE_HACK_WIRE)
SearchVar(AUTOLATHE_SHOCK_WIRE)
SearchVar(AUTOLATHE_DISABLE_WIRE)
SearchVar(CAMERA_WIRE_FOCUS)
SearchVar(CAMERA_WIRE_POWER)
SearchVar(CAMERA_WIRE_LIGHT)
SearchVar(CAMERA_WIRE_ALARM)
SearchVar(CAMERA_WIRE_NOTHING1)
SearchVar(CAMERA_WIRE_NOTHING2)
SearchVar(WIRE_EXPLODE)
SearchVar(WIRE_POWER1)
SearchVar(WIRE_POWER2)
SearchVar(WIRE_AVOIDANCE)
SearchVar(WIRE_LOADCHECK)
SearchVar(WIRE_MOTOR1)
SearchVar(WIRE_MOTOR2)
SearchVar(WIRE_REMOTE_RX)
SearchVar(WIRE_REMOTE_TX)
SearchVar(WIRE_BEACON_RX)
SearchVar(NUCLEARBOMB_WIRE_LIGHT)
SearchVar(NUCLEARBOMB_WIRE_TIMING)
SearchVar(NUCLEARBOMB_WIRE_SAFETY)
SearchVar(PARTICLE_TOGGLE_WIRE)
SearchVar(PARTICLE_STRENGTH_WIRE)
SearchVar(PARTICLE_INTERFACE_WIRE)
SearchVar(PARTICLE_LIMIT_POWER_WIRE)
SearchVar(WIRE_SIGNAL)
SearchVar(WIRE_RECEIVE)
SearchVar(WIRE_TRANSMIT)
SearchVar(BORG_WIRE_LAWCHECK)
SearchVar(BORG_WIRE_MAIN_POWER)
SearchVar(BORG_WIRE_LOCKED_DOWN)
SearchVar(BORG_WIRE_AI_CONTROL)
SearchVar(BORG_WIRE_CAMERA)
SearchVar(SMARTFRIDGE_WIRE_ELECTRIFY)
SearchVar(SMARTFRIDGE_WIRE_THROW)
SearchVar(SMARTFRIDGE_WIRE_IDSCAN)
SearchVar(SMES_WIRE_RCON)
SearchVar(SMES_WIRE_INPUT)
SearchVar(SMES_WIRE_OUTPUT)
SearchVar(SMES_WIRE_GROUNDING)
SearchVar(SMES_WIRE_FAILSAFES)
SearchVar(SUIT_STORAGE_WIRE_ELECTRIFY)
SearchVar(SUIT_STORAGE_WIRE_SAFETY)
SearchVar(SUIT_STORAGE_WIRE_LOCKED)
SearchVar(VENDING_WIRE_THROW)
SearchVar(VENDING_WIRE_CONTRABAND)
SearchVar(VENDING_WIRE_ELECTRIFY)
SearchVar(VENDING_WIRE_IDSCAN)
SearchVar(same_wires)
SearchVar(wireColours)
SearchVar(accessible_z_levels)
SearchVar(base_turf_by_z)
SearchVar(newscaster_standard_feeds)
SearchVar(announced_news_types)
SearchVar(send_emergency_team)
SearchVar(can_call_ert)
SearchVar(shatter_sound)
SearchVar(explosion_sound)
SearchVar(spark_sound)
SearchVar(rustle_sound)
SearchVar(punch_sound)
SearchVar(clown_sound)
SearchVar(swing_hit_sound)
SearchVar(hiss_sound)
SearchVar(page_sound)
SearchVar(fracture_sound)
SearchVar(blank)
SearchVar(catwalk)
SearchVar(wood)
SearchVar(tiles)
SearchVar(plating)
SearchVar(carpet)
SearchVar(asteroid)
SearchVar(grass)
SearchVar(water)
SearchVar(lava)
SearchVar(snow)
SearchVar(sand)
SearchVar(FALLOFF_SOUNDS)
SearchVar(all_antag_types)
SearchVar(all_antag_spawnpoints)
SearchVar(antag_names_to_ids)
SearchVar(bantype_to_antag_age)
SearchVar(borers)
SearchVar(xenomorphs)
SearchVar(actor)
SearchVar(commandos)
SearchVar(deathsquad)
SearchVar(ert)
SearchVar(mercs)
SearchVar(ninjas)
SearchVar(raiders)
SearchVar(wizards)
SearchVar(cult)
SearchVar(highlanders)
SearchVar(loyalists)
SearchVar(renegades)
SearchVar(revs)
SearchVar(malf)
SearchVar(thralls)
SearchVar(traitors)
SearchVar(vamp)
SearchVar(forced_ambiance_list)
SearchVar(dna_activity_bounds)
SearchVar(assigned_blocks)
SearchVar(dna_genes)
SearchVar(eventchance)
SearchVar(hadevent)
SearchVar(antag_add_failed)
SearchVar(additional_antag_types)
SearchVar(all_objectives)
SearchVar(process_objectives)
SearchVar(possible_changeling_IDs)
SearchVar(hivemind_bank)
SearchVar(powers)
SearchVar(powerinstances)
SearchVar(narsie_behaviour)
SearchVar(narsie_cometh)
SearchVar(narsie_list)
SearchVar(cultwords)
SearchVar(runedec)
SearchVar(engwords)
SearchVar(rnwords)
SearchVar(sacrificed)
SearchVar(universe_has_ended)
SearchVar(Holiday)
SearchVar(nuke_disks)
SearchVar(vampirepower_types)
SearchVar(vampirepowers)
SearchVar(ghost_all_access)
SearchVar(ENGSEC)
SearchVar(CAPTAIN)
SearchVar(HOS)
SearchVar(WARDEN)
SearchVar(DETECTIVE)
SearchVar(OFFICER)
SearchVar(CHIEF)
SearchVar(ENGINEER)
SearchVar(ATMOSTECH)
SearchVar(AI)
SearchVar(CYBORG)
SearchVar(INTERN_SEC)
SearchVar(INTERN_ENG)
SearchVar(FORENSICS)
SearchVar(MEDSCI)
SearchVar(RD)
SearchVar(SCIENTIST)
SearchVar(CHEMIST)
SearchVar(CMO)
SearchVar(DOCTOR)
SearchVar(GENETICIST)
SearchVar(VIROLOGIST)
SearchVar(PSYCHIATRIST)
SearchVar(ROBOTICIST)
SearchVar(XENOBIOLOGIST)
SearchVar(PARAMEDIC)
SearchVar(INTERN_MED)
SearchVar(INTERN_SCI)
SearchVar(CIVILIAN)
SearchVar(HOP)
SearchVar(BARTENDER)
SearchVar(BOTANIST)
SearchVar(CHEF)
SearchVar(JANITOR)
SearchVar(LIBRARIAN)
SearchVar(QUARTERMASTER)
SearchVar(CARGOTECH)
SearchVar(MINER)
SearchVar(LAWYER)
SearchVar(CHAPLAIN)
SearchVar(CLOWN)
SearchVar(MIME)
SearchVar(MERCHANT)
SearchVar(ASSISTANT)
SearchVar(CONSULAR)
SearchVar(command_positions)
SearchVar(engineering_positions)
SearchVar(medical_positions)
SearchVar(science_positions)
SearchVar(cargo_positions)
SearchVar(civilian_positions)
SearchVar(security_positions)
SearchVar(nonhuman_positions)
SearchVar(whitelist)
SearchVar(captain_announcement)
SearchVar(doppler_arrays)
SearchVar(floor_light_cache)
SearchVar(HOLOPAD_MODE)
SearchVar(navbeacons)
SearchVar(SSnews)
SearchVar(allCasters)
SearchVar(bomb_set)
SearchVar(req_console_assistance)
SearchVar(req_console_supplies)
SearchVar(req_console_information)
SearchVar(allConsoles)
SearchVar(ai_status_emotions)
SearchVar(station_networks)
SearchVar(engineering_networks)
SearchVar(priority_air_alarms)
SearchVar(minor_air_alarms)
SearchVar(air_alarm_topic)
SearchVar(specops_shuttle_moving_to_station)
SearchVar(specops_shuttle_moving_to_centcom)
SearchVar(specops_shuttle_at_station)
SearchVar(specops_shuttle_can_send)
SearchVar(specops_shuttle_time)
SearchVar(specops_shuttle_timeleft)
SearchVar(syndicate_elite_shuttle_moving_to_station)
SearchVar(syndicate_elite_shuttle_moving_to_mothership)
SearchVar(syndicate_elite_shuttle_at_station)
SearchVar(syndicate_elite_shuttle_can_send)
SearchVar(syndicate_elite_shuttle_time)
SearchVar(syndicate_elite_shuttle_timeleft)
SearchVar(recentmessages)
SearchVar(message_delay)
SearchVar(word_to_uristrune_table)
SearchVar(slot_flags_enumeration)
SearchVar(BUMP_TELEPORTERS)
SearchVar(active_radio_jammers)
SearchVar(default_uplink_selection)
SearchVar(chatrooms)
SearchVar(PDAs)
SearchVar(teleportbeacons)
SearchVar(default_internal_channels)
SearchVar(default_medbay_channels)
SearchVar(rod_recipes)
SearchVar(NO_EMAG_ACT)
SearchVar(last_chew)
SearchVar(tape_roll_applications)
SearchVar(malftransformermade)
SearchVar(MIN_ACTIVE_TIME)
SearchVar(MAX_ACTIVE_TIME)
SearchVar(enterloopsanity)
SearchVar(flooring_types)
SearchVar(random_junk)
SearchVar(js_byjax)
SearchVar(js_dropdowns)
SearchVar(BSACooldown)
SearchVar(floorIsLava)
SearchVar(admin_ranks)
SearchVar(admin_secrets)
SearchVar(admin_verbs_default)
SearchVar(admin_verbs_admin)
SearchVar(admin_verbs_ban)
SearchVar(admin_verbs_sounds)
SearchVar(admin_verbs_fun)
SearchVar(admin_verbs_spawn)
SearchVar(admin_verbs_server)
SearchVar(admin_verbs_debug)
SearchVar(admin_verbs_paranoid_debug)
SearchVar(admin_verbs_possess)
SearchVar(admin_verbs_permissions)
SearchVar(admin_verbs_rejuv)
SearchVar(admin_verbs_hideable)
SearchVar(admin_verbs_mod)
SearchVar(admin_verbs_dev)
SearchVar(admin_verbs_cciaa)
SearchVar(jobban_keylist)
SearchVar(admin_datums)
SearchVar(CMinutes)
SearchVar(Banlist)
SearchVar(adminhelp_ignored_words)
SearchVar(checked_for_inactives)
SearchVar(inactive_keys)
SearchVar(camera_range_display_status)
SearchVar(intercom_range_display_status)
SearchVar(debug_verbs)
SearchVar(prevent_airgroup_regroup)
SearchVar(say_disabled)
SearchVar(movement_disabled)
SearchVar(movement_disabled_exception)
SearchVar(forbidden_varedit_object_types)
SearchVar(VVlocked)
SearchVar(VVicon_edit_lock)
SearchVar(VVckey_edit)
SearchVar(VVdynamic_lock)
SearchVar(sounds_cache)
SearchVar(commandos_possible)
SearchVar(random_stock_common)
SearchVar(random_stock_uncommon)
SearchVar(random_stock_rare)
SearchVar(random_stock_large)
SearchVar(asset_datums)
SearchVar(preferences_datums)
SearchVar(seen_citizenships)
SearchVar(seen_systems)
SearchVar(seen_factions)
SearchVar(seen_religions)
SearchVar(citizenship_choices)
SearchVar(home_system_choices)
SearchVar(faction_choices)
SearchVar(religion_choices)
SearchVar(spawntypes)
SearchVar(uplink_locations)
SearchVar(valid_bloodtypes)
SearchVar(gear_tweak_free_color_choice)
SearchVar(loadout_categories)
SearchVar(gear_datums)
SearchVar(breach_brute_descriptors)
SearchVar(breach_burn_descriptors)
SearchVar(FINGERPRINT_COMPLETE)
SearchVar(weighted_randomevent_locations)
SearchVar(weighted_mundaneevent_locations)
SearchVar(severity_to_string)
SearchVar(event_last_fired)
SearchVar(dreams)
SearchVar(non_fakeattack_weapons)
SearchVar(current_map.holodeck_programs)
SearchVar(fruit_icon_cache)
SearchVar(plant_seed_sprites)
SearchVar(wax_recipes)
SearchVar(worths)
SearchVar(admin_verbs_lighting)
SearchVar(liquid_delay)
SearchVar(puddles)
SearchVar(use_preloader)
SearchVar(_preloader)
SearchVar(swapmaps_iconcache)
SearchVar(SWAPMAPS_SAV)
SearchVar(SWAPMAPS_TEXT)
SearchVar(swapmaps_mode)
SearchVar(swapmaps_compiled_maxx)
SearchVar(swapmaps_compiled_maxy)
SearchVar(swapmaps_compiled_maxz)
SearchVar(swapmaps_initialized)
SearchVar(swapmaps_loaded)
SearchVar(swapmaps_byname)
SearchVar(minevendor_list)
SearchVar(total_extraction_beacons)
SearchVar(ore_data)
SearchVar(dview_mob)
SearchVar(holder_mob_icon_cache)
SearchVar(slot_equipment_priority)
SearchVar(base_miss_chance)
SearchVar(organ_rel_size)
SearchVar(intents)
SearchVar(department_radio_keys)
SearchVar(channel_to_radio_key)
SearchVar(cleanbot_types)
SearchVar(diona_banned_languages)
SearchVar(alcohol_clumsy)
SearchVar(sparring_attack_cache)
SearchVar(MAXIMUM_MEME_POINTS)
SearchVar(host_brain)
SearchVar(controlling)
SearchVar(ai_list)
SearchVar(ai_verbs_default)
SearchVar(default_ai_icon)
SearchVar(ai_icons)
SearchVar(empty_playable_ai_cores)
SearchVar(pai_emotions)
SearchVar(robot_custom_icons)
SearchVar(robot_modules)
SearchVar(protected_objects)
SearchVar(SKILL_NONE)
SearchVar(SKILL_BASIC)
SearchVar(SKILL_ADEPT)
SearchVar(SKILL_EXPERT)
SearchVar(SKILLS)
SearchVar(SKILL_ENGINEER)
SearchVar(SKILL_ORGAN_ROBOTICIST)
SearchVar(SKILL_SECURITY_OFFICER)
SearchVar(SKILL_CHEMIST)
SearchVar(SKILL_PRE)
SearchVar(file_uid)
SearchVar(comm_message_listeners)
SearchVar(global_message_listener)
SearchVar(last_message_id)
SearchVar(nttransfer_uid)
SearchVar(warrant_uid)
SearchVar(ntnet_card_uid)
SearchVar(ntnet_global)
SearchVar(ntnrc_uid)
SearchVar(all_robolimbs)
SearchVar(chargen_robolimbs)
SearchVar(fabricator_robolimbs)
SearchVar(basic_robolimb)
SearchVar(moving_levels)
SearchVar(cached_space)
SearchVar(map_sectors)
SearchVar(ship_engines)
SearchVar(allfaxes)
SearchVar(arrived_faxes)
SearchVar(sent_faxes)
SearchVar(alldepartments)
SearchVar(admin_departments)
SearchVar(photo_count)
SearchVar(possible_cable_coil_colours)
SearchVar(blacklisted_tesla_types)
SearchVar(random_maps)
SearchVar(map_count)
SearchVar(supply_drop)
SearchVar(maze_cell_count)
SearchVar(lunchables_lunches_)
SearchVar(lunchables_snacks_)
SearchVar(lunchables_drinks_)
SearchVar(lunchables_drink_reagents_)
SearchVar(lunchables_alcohol_reagents_)
SearchVar(message_servers)
SearchVar(blackbox)
SearchVar(responsive_carriers)
SearchVar(finds_as_strings)
SearchVar(ascii_A)
SearchVar(ascii_Z)
SearchVar(ascii_a)
SearchVar(ascii_z)
SearchVar(ascii_DOLLAR)
SearchVar(ascii_ZERO)
SearchVar(ascii_NINE)
SearchVar(ascii_UNDERSCORE)
SearchVar(OOP_OR)
SearchVar(OOP_AND)
SearchVar(OOP_BIT)
SearchVar(OOP_EQUAL)
SearchVar(OOP_COMPARE)
SearchVar(OOP_ADD)
SearchVar(OOP_MULTIPLY)
SearchVar(OOP_POW)
SearchVar(OOP_UNARY)
SearchVar(OOP_GROUP)
SearchVar(KW_FAIL)
SearchVar(KW_PASS)
SearchVar(KW_ERR)
SearchVar(KW_WARN)
SearchVar(maint_all_access)
SearchVar(spells)
SearchVar(artefact_feedback)
SearchVar(GPS_list)
SearchVar(gps_by_type)
SearchVar(ventcrawl_machinery)
SearchVar(can_enter_vent_with)
SearchVar(ALL_ANTIGENS)
SearchVar(all_unit_tests_passed)
SearchVar(unit_tests_failures)
SearchVar(total_unit_tests)
SearchVar(ascii_esc)
SearchVar(ascii_red)
SearchVar(ascii_green)
SearchVar(ascii_reset)
SearchVar(assigned)
SearchVar(created)
SearchVar(merged)
SearchVar(invalid_zone)
SearchVar(air_blocked)
SearchVar(zone_blocked)
SearchVar(blocked)
SearchVar(mark)
SearchVar(contamination_overlay)
SearchVar(vsc)
SearchVar(cable_list)
datum_container.last_find_references = search_time
var/list/vars_list = datum_container.vars
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 = vars_list[varname]
if(variable == src)
testing("Found [type] [text_ref(src)] in [datum_container.type]'s [text_ref(datum_container)] [varname] var. [container_name]")
continue
if(islist(variable))
search_var(variable, "[container_name] [text_ref(datum_container)] -> [varname] (list)", recursive_limit - 1, search_time)
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 entries
if(element_in_list == src)
testing("Found [type] [text_ref(src)] in list [container_name]\[[element_in_list]\]")
continue
var/assoc_val = null
if(!isnum(element_in_list) && normal)
assoc_val = potential_cache[element_in_list]
// Check assoc entries
if(assoc_val == src)
testing("Found [type] [text_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(element_in_list))
search_var(element_in_list, "[container_name] -> [element_in_list] (list)", recursive_limit - 1, search_time)
// Check assoc sublists
if(islist(assoc_val))
search_var(potential_container[element_in_list], "[container_name]\[[element_in_list]\] -> [assoc_val] (list)", recursive_limit - 1, search_time)
/proc/qdel_and_find_ref_if_fail(datum/thing_to_qdel, force = FALSE)
thing_to_qdel.qdel_and_find_ref_if_fail(force)
/datum/proc/qdel_and_find_ref_if_fail(force = FALSE)
SSgarbage.reference_find_on_fail[text_ref(src)] = TRUE
qdel(src, force)
#endif
+32 -5
View File
@@ -31,9 +31,13 @@ var/datum/controller/subsystem/garbage_collector/SSgarbage
// of the immortality qdel hints
var/list/noforcerespect = list()
#ifdef TESTING
#ifdef TESTING
var/list/qdel_list = list() // list of all types that have been qdel()eted
#endif
#endif
#ifdef REFERENCE_TRACKING
var/list/reference_find_on_fail = list()
#endif
/datum/controller/subsystem/garbage_collector/New()
NEW_SS_GLOBAL(SSgarbage)
@@ -86,9 +90,16 @@ var/datum/controller/subsystem/garbage_collector/SSgarbage
var/starttime = world.time
var/starttimeofday = world.timeofday
var/idex = 1
#ifdef REFERENCE_TRACKING
var/ref_searching = FALSE
#endif
while((queue.len - (idex - 1)) && starttime == world.time && starttimeofday == world.timeofday)
if (MC_TICK_CHECK)
break
#ifdef REFERENCE_TRACKING
if (ref_searching)
break
#endif
var/refID = queue[idex]
if (!refID)
idex++
@@ -101,8 +112,16 @@ var/datum/controller/subsystem/garbage_collector/SSgarbage
var/datum/A
A = locate(refID)
if (A && A.gcDestroyed == GCd_at_time) // So if something else coincidently gets the same ref, it's not deleted by mistake
#ifdef REFERENCE_TRACKING
if(reference_find_on_fail[text_ref(D)])
INVOKE_ASYNC(D, TYPE_PROC_REF(/datum, find_references))
ref_searching = TRUE
#ifdef GC_FAILURE_HARD_LOOKUP
A.find_references()
else
INVOKE_ASYNC(D, TYPE_PROC_REF(/datum, find_references))
ref_searching = TRUE
#endif
reference_find_on_fail -= text_ref(D)
#endif
// Something's still referring to the qdel'd object. Kill it.
@@ -117,6 +136,9 @@ var/datum/controller/subsystem/garbage_collector/SSgarbage
else
++gcedlasttick
++totalgcs
#ifdef REFERENCE_TRACKING
reference_find_on_fail -= text_ref(D)
#endif
if (idex > 1)
queue.Cut(1, idex)
@@ -222,11 +244,16 @@ var/datum/controller/subsystem/garbage_collector/SSgarbage
SSgarbage.HardQueue(D)
if (QDEL_HINT_HARDDEL_NOW) //qdel should assume this object won't gc, and hard del it post haste.
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.
if (QDEL_HINT_FINDREFERENCE)//qdel will, if REFERENCE_TRACKING is enabled, display all references to this object, then queue the object for deletion.
SSgarbage.QueueForQueuing(D)
#ifdef TESTING
#ifdef REFERENCE_TRACKING
D.find_references()
#endif
if (QDEL_HINT_IFFAIL_FINDREFERENCE) // qdel will, if REFERENCE_TRACKING is enabled and the object fails to collect, display all references to this object
SSgarbage.QueueForQueuing(D)
#ifdef REFERENCE_TRACKING
SSgarbage.reference_find_on_fail[text_ref(D)] = TRUE
#endif
else
if(!SSgarbage.noqdelhint["[D.type]"])
SSgarbage.noqdelhint["[D.type]"] = "[D.type]"
@@ -43,13 +43,13 @@ var/datum/controller/subsystem/atoms/SSatoms
if(atoms)
created_atoms = list()
count = atoms.len
for(var/I in atoms)
if(InitAtom(I, mapload_arg))
atoms -= I
for(var/I in 1 to atoms.len)
var/atom/A = atoms[I]
InitAtom(A, mapload_arg)
CHECK_TICK
else
count = 0
for(var/atom/A in world)
for(var/atom/A as anything in world)
if(!A.initialized)
InitAtom(A, mapload_arg)
++count
@@ -61,8 +61,10 @@ var/datum/controller/subsystem/atoms/SSatoms
initialized = INITIALIZATION_INNEW_REGULAR
if(late_loaders.len)
for(var/I in late_loaders)
var/atom/A = I
for(var/I in 1 to late_loaders.len)
var/atom/A = late_loaders[I]
if(QDELETED(A))
continue
A.LateInitialize()
admin_notice(SPAN_DANGER("Late-initialized [late_loaders.len] atoms."), R_DEBUG)
log_ss("atoms", "Late initialized [late_loaders.len] atoms")
@@ -81,6 +83,7 @@ var/datum/controller/subsystem/atoms/SSatoms
if(atoms)
. = created_atoms + atoms
created_atoms = null
// Note this doesn't actually do anything because we didn't finish porting TG init :^)
/datum/controller/subsystem/atoms/proc/InitAtom(atom/A, list/arguments)
var/the_type = A.type
+2
View File
@@ -145,6 +145,8 @@ if(Datum.isprocessing) {\
/datum/controller/subsystem/machinery/proc/setup_atmos_machinery(list/machines)
var/list/atmos_machines = list()
for (var/obj/machinery/atmospherics/machine in machines)
if(QDELETED(machine))
continue
atmos_machines += machine
admin_notice(SPAN_DANGER("Initializing atmos machinery."), R_DEBUG)
log_ss("machinery", "Initializing atmos machinery.")
-6
View File
@@ -129,12 +129,6 @@ var/datum/controller/subsystem/radio/SSradio
if(frequency)
frequency.remove_listener(device)
if(frequency.devices.len == 0)
qdel(frequency)
frequencies -= f_text
return 1
/datum/controller/subsystem/radio/proc/remove_object_all(obj/device)
for(var/freq in frequencies)
SSradio.remove_object(device, text2num(freq))
+53 -10
View File
@@ -447,7 +447,7 @@
SEND_SIGNAL(intersecting_cell, SPATIAL_GRID_CELL_EXITED(RECURSIVE_CONTENTS_HEARING_SENSITIVE), old_target)
if(old_target.important_recursive_contents[RECURSIVE_CONTENTS_AI_TARGETS])
GRID_CELL_REMOVE(intersecting_cell.hearing_contents, old_target.important_recursive_contents[RECURSIVE_CONTENTS_AI_TARGETS])
GRID_CELL_REMOVE(intersecting_cell.tgt_contents, old_target.important_recursive_contents[RECURSIVE_CONTENTS_AI_TARGETS])
SEND_SIGNAL(intersecting_cell, SPATIAL_GRID_CELL_EXITED(RECURSIVE_CONTENTS_AI_TARGETS), old_target)
@@ -465,6 +465,7 @@
GRID_CELL_REMOVE(input_cell.client_contents, to_remove)
GRID_CELL_REMOVE(input_cell.hearing_contents, to_remove)
GRID_CELL_REMOVE(input_cell.tgt_contents, to_remove)
///if shit goes south, this will find hanging references for qdeleting movables inside the spatial grid
/datum/controller/subsystem/spatial_grid/proc/find_hanging_cell_refs_for_movable(atom/movable/to_remove, remove_from_cells = TRUE)
@@ -484,7 +485,7 @@
for(var/list/z_level_grid as anything in grids_by_z_level)
for(var/list/cell_row as anything in z_level_grid)
for(var/datum/spatial_grid_cell/cell as anything in cell_row)
if(to_remove in (cell.hearing_contents | cell.client_contents))
if(to_remove in (cell.hearing_contents | cell.client_contents | cell.tgt_contents))
containing_cells += cell
if(remove_from_cells)
force_remove_from_cell(to_remove, cell)
@@ -509,17 +510,21 @@
/atom/proc/find_grid_statistics_for_z_level(insert_clients = 0)
var/raw_clients = 0
var/raw_hearables = 0
var/raw_targets = 0
var/cells_with_clients = 0
var/cells_with_hearables = 0
var/cells_with_targets = 0
var/list/client_list = list()
var/list/hearable_list = list()
var/list/target_list = list()
var/total_cells = (world.maxx / SPATIAL_GRID_CELLSIZE) ** 2
var/average_clients_per_cell = 0
var/average_hearables_per_cell = 0
var/average_targets_per_cell = 0
var/hearable_min_x = (world.maxx / SPATIAL_GRID_CELLSIZE)
var/hearable_max_x = 1
@@ -533,6 +538,12 @@
var/client_min_y = (world.maxy / SPATIAL_GRID_CELLSIZE)
var/client_max_y = 1
var/target_min_x = (world.maxx / SPATIAL_GRID_CELLSIZE)
var/target_max_x = 1
var/target_min_y = (world.maxy / SPATIAL_GRID_CELLSIZE)
var/target_max_y = 1
var/list/inserted_clients = list()
if(insert_clients)
@@ -546,7 +557,7 @@
for(var/client_to_insert in 0 to insert_clients)
var/turf/random_turf = pick(turfs)
var/mob/fake_client = new()
fake_client.important_recursive_contents = list(SPATIAL_GRID_CONTENTS_TYPE_HEARING = list(fake_client), SPATIAL_GRID_CONTENTS_TYPE_CLIENTS = list(fake_client))
fake_client.important_recursive_contents = list(SPATIAL_GRID_CONTENTS_TYPE_HEARING = list(fake_client), SPATIAL_GRID_CONTENTS_TYPE_CLIENTS = list(fake_client), SPATIAL_GRID_CONTENTS_TYPE_TARGETS = list(fake_client))
fake_client.forceMove(random_turf)
inserted_clients += fake_client
@@ -555,9 +566,11 @@
for(var/datum/spatial_grid_cell/cell as anything in all_z_level_cells)
var/client_length = length(cell.client_contents)
var/hearable_length = length(cell.hearing_contents)
var/target_length = length(cell.tgt_contents)
raw_clients += client_length
raw_hearables += hearable_length
raw_targets += target_length
if(client_length)
cells_with_clients++
@@ -593,11 +606,30 @@
if(cell.cell_y > hearable_max_y)
hearable_max_y = cell.cell_y
if(target_length)
cells_with_targets++
target_list += cell.tgt_contents
if(cell.cell_x < target_min_x)
target_min_x = cell.cell_x
if(cell.cell_x > target_max_x)
target_max_x = cell.cell_x
if(cell.cell_y < target_min_y)
target_min_y = cell.cell_y
if(cell.cell_y > target_max_y)
target_max_y = cell.cell_y
var/total_client_distance = 0
var/total_hearable_distance = 0
var/total_target_distance = 0
var/average_client_distance = 0
var/average_hearable_distance = 0
var/average_target_distance = 0
for(var/hearable in hearable_list)//n^2 btw
for(var/other_hearable in hearable_list)
@@ -611,24 +643,35 @@
continue
total_client_distance += get_dist(client, other_client)
for(var/target in target_list)
for(var/other_target in target_list)
if(target == other_target)
continue
total_target_distance += get_dist(target, other_target)
if(length(hearable_list))
average_hearable_distance = total_hearable_distance / length(hearable_list)
if(length(client_list))
average_client_distance = total_client_distance / length(client_list)
if(length(target_list))
average_target_distance = total_target_distance / length(target_list)
average_clients_per_cell = raw_clients / total_cells
average_hearables_per_cell = raw_hearables / total_cells
average_targets_per_cell = raw_targets / total_cells
for(var/mob/inserted_client as anything in inserted_clients)
qdel(inserted_client)
message_admins("on z level [z] there are [raw_clients] clients ([insert_clients] of whom are fakes inserted to random station turfs) \
and [raw_hearables] hearables. all of whom are inside the bounding box given by \
clients: ([client_min_x], [client_min_y]) x ([client_max_x], [client_max_y]) \
and hearables: ([hearable_min_x], [hearable_min_y]) x ([hearable_max_x], [hearable_max_y]) \
on average there are [average_clients_per_cell] clients per cell and [average_hearables_per_cell] hearables per cell. \
[cells_with_clients] cells have clients and [cells_with_hearables] have hearables, \
the average client distance is: [average_client_distance] and the average hearable_distance is [average_hearable_distance].")
message_admins("on z level [z] there are [raw_clients] clients ([insert_clients] of whom are fakes inserted to random station turfs), \
[raw_hearables] hearables, and [raw_targets] targets. all of whom are inside the bounding box given by \
clients: ([client_min_x], [client_min_y]) x ([client_max_x], [client_max_y]), \
hearables: ([hearable_min_x], [hearable_min_y]) x ([hearable_max_x], [hearable_max_y]), \
and targets: ([target_min_x], [target_min_y]) x ([target_max_x], [target_max_y]). \
on average there are [average_clients_per_cell] clients per cell, [average_hearables_per_cell] hearables per cell, and \
[average_targets_per_cell] targets per cell. [cells_with_clients] cells have clients, [cells_with_hearables] have hearables, \
and [cells_with_targets] have targets. the average client distance is: [average_client_distance], the average hearable_distance \
is [average_hearable_distance], and the average target distance is [average_target_distance].")
#undef GRID_CELL_ADD
#undef GRID_CELL_REMOVE
+4
View File
@@ -17,6 +17,10 @@
/// Is this datum capable of sending signals?
/// Set to true when a signal has been registered
var/signal_enabled = FALSE
/// A cached version of our \ref
/// The brunt of \ref costs are in creating entries in the string tree (a tree of immutable strings)
/// This avoids doing that more then once per datum by ensuring ref strings always have a reference to them after they're first pulled
var/cached_ref
// Default implementation of clean-up code.
// This should be overridden to remove all references pointing to the object being destroyed.
+9 -1
View File
@@ -14,6 +14,14 @@ var/singleton/observ/moved/moved_event = new()
child = parent
parent = child.loc
/singleton/observ/moved/proc/register_all_movement(var/event_source, var/listener)
moved_event.register(event_source, listener, /atom/movable/proc/recursive_move)
dir_set_event.register(event_source, listener, /atom/proc/recursive_dir_set)
/singleton/observ/moved/proc/unregister_all_movement(var/event_source, var/listener)
moved_event.unregister(event_source, listener, /atom/movable/proc/recursive_move)
dir_set_event.unregister(event_source, listener, /atom/proc/recursive_dir_set)
/********************
* Movement Handling *
********************/
@@ -24,7 +32,7 @@ var/singleton/observ/moved/moved_event = new()
forceMove(T)
/atom/movable/proc/recursive_move(var/atom/movable/am, var/old_loc, var/new_loc)
moved_event.raise_event(list(src, old_loc, new_loc))
moved_event.raise_event(src, old_loc, new_loc)
/atom/Entered(var/atom/movable/am, atom/old_loc)
..()
+2 -2
View File
@@ -114,7 +114,7 @@ var/singleton/sound_player/sound_player = new()
listeners = list()
listener_status = list()
destroyed_event.register(source, src, TYPE_PROC_REF(/datum/, qdel))
destroyed_event.register(source, src, TYPE_PROC_REF(/datum, qdel_self))
PrivLocateListeners()
START_PROCESSING(SSprocessing, src)
@@ -260,4 +260,4 @@ var/singleton/sound_player/sound_player = new()
return TRUE
/datum/sound_token/static_environment/PrivGetEnvironment()
return sound.environment
return sound.environment
+6 -3
View File
@@ -42,11 +42,14 @@
..()*/
/atom/movable/Destroy()
if (important_recursive_contents && (important_recursive_contents[RECURSIVE_CONTENTS_CLIENT_MOBS] || important_recursive_contents[RECURSIVE_CONTENTS_HEARING_SENSITIVE]))
if (HAS_SPATIAL_GRID_CONTENTS(src))
SSspatial_grid.force_remove_from_cell(src)
LAZYCLEARLIST(contained_mobs)
LAZYCLEARLIST(important_recursive_contents)
moved_event.unregister_all_movement(loc, src)
. = ..()
for(var/atom/movable/AM in contents)
@@ -436,7 +439,7 @@
var/turf/our_turf = get_turf(src)
if(our_turf && SSspatial_grid.init_state == SS_INITSTATE_DONE)
SSspatial_grid.exit_cell(src, our_turf)
SSspatial_grid.exit_cell(src, our_turf, RECURSIVE_CONTENTS_HEARING_SENSITIVE)
else if(our_turf && SSspatial_grid.init_state != SS_INITSTATE_DONE)
SSspatial_grid.remove_from_pre_init_queue(src, RECURSIVE_CONTENTS_HEARING_SENSITIVE)
@@ -502,7 +505,7 @@
/atom/movable/proc/clear_from_target_grid()
var/turf/our_turf = get_turf(src)
if(our_turf && SSspatial_grid.init_state == SS_INITSTATE_DONE)
SSspatial_grid.exit_cell(src, our_turf)
SSspatial_grid.exit_cell(src, our_turf, RECURSIVE_CONTENTS_AI_TARGETS)
else if(our_turf && SSspatial_grid.init_state != SS_INITSTATE_DONE)
SSspatial_grid.remove_from_pre_init_queue(src, RECURSIVE_CONTENTS_AI_TARGETS)
@@ -13,8 +13,9 @@
var/maximum_pressure = 90 * ONE_ATMOSPHERE
/obj/machinery/portable_atmospherics/Destroy()
qdel(air_contents)
qdel(holding)
disconnect()
QDEL_NULL(air_contents)
QDEL_NULL(holding)
return ..()
/obj/machinery/portable_atmospherics/Initialize()
@@ -43,11 +44,6 @@
update_icon()
SSvueui.check_uis_for_change(src)
/obj/machinery/portable_atmospherics/Destroy()
qdel(air_contents)
return ..()
/obj/machinery/portable_atmospherics/proc/StandardAirMix()
return list(
GAS_OXYGEN = O2STANDARD * MolesForPressure(),
+1
View File
@@ -150,6 +150,7 @@ Class Procs:
/obj/machinery/Destroy()
STOP_PROCESSING_MACHINE(src, MACHINERY_PROCESS_ALL)
SSmachinery.machinery -= src
if(component_parts)
for(var/atom/A in component_parts)
if(A.loc == src) // If the components are inside the machine, delete them.
@@ -234,7 +234,8 @@ var/obj/machinery/blackbox_recorder/blackbox
if(blackbox)
if(istype(blackbox,/obj/machinery/blackbox_recorder))
qdel(src)
blackbox = src
else
blackbox = src
/obj/machinery/blackbox_recorder/Destroy()
feedback_set_details("blackbox_destroyed","true")
@@ -32,7 +32,6 @@
set_listening(TRUE)
recalculateChannels(TRUE)
possibly_deactivate_in_loc()
moved_event.register(src, src, PROC_REF(possibly_deactivate_in_loc))
/obj/item/device/radio/headset/proc/possibly_deactivate_in_loc()
if(ismob(loc))
@@ -45,6 +44,10 @@
QDEL_NULL(keyslot2)
return ..()
/obj/item/device/radio/headset/Moved(atom/old_loc, forced)
. = ..()
possibly_deactivate_in_loc()
/obj/item/device/radio/headset/set_listening(new_listening, actual_setting = TRUE)
. = ..()
if(listening && on)
@@ -266,7 +266,7 @@
else if(reference==node3)
qdel(network_node3)
node2 = null
node3 = null
update_underlays()
@@ -21,6 +21,7 @@
thing.parent = null
members = null
edges = null
return ..()
+71 -18
View File
@@ -5,23 +5,10 @@
remove_system(hardpoint, force = 1)
hardpoints.Cut()
if(arms)
frame.arms = arms
arms.forceMove(frame)
arms = null
if(legs)
frame.legs = legs
legs.forceMove(frame)
pass_flags &= PASSRAILING //if previously was hoverthrusters, need to update pass flag
legs = null
if(body)
frame.body = body
body.forceMove(frame)
body = null
if(head)
frame.head = head
head.forceMove(frame)
head = null
remove_arms(frame)
remove_legs(frame)
remove_body(frame)
remove_head(frame)
frame.is_wired = FRAME_WIRED_ADJUSTED
frame.is_reinforced = FRAME_REINFORCED_WELDED
@@ -31,6 +18,72 @@
qdel(src)
/mob/living/heavy_vehicle/proc/remove_body_part(obj/item/mech_component/part, atom/dest)
if(!part)
return
if(!dest)
dest = get_turf(src)
if(part == arms)
remove_arms(dest)
else if(part == legs)
remove_legs(dest)
else if(part == body)
remove_body(dest)
else if(part == head)
remove_head(dest)
/mob/living/heavy_vehicle/proc/remove_arms(atom/dest)
if(!arms)
return
var/obj/structure/heavy_vehicle_frame/frame = dest
if(istype(frame))
frame.arms = arms
arms.forceMove(dest)
arms = null
/mob/living/heavy_vehicle/proc/remove_legs(atom/dest)
if(!legs)
return
pass_flags &= PASSRAILING //if previously was hoverthrusters, need to update pass flag
var/obj/structure/heavy_vehicle_frame/frame = dest
if(istype(frame))
frame.legs = legs
legs.forceMove(dest)
legs = null
/mob/living/heavy_vehicle/proc/remove_body(atom/dest)
if(!body)
return
var/obj/structure/heavy_vehicle_frame/frame = dest
if(istype(frame))
frame.body = body
body.forceMove(dest)
body = null
/mob/living/heavy_vehicle/proc/remove_head(atom/dest)
if(!head)
return
var/obj/structure/heavy_vehicle_frame/frame = dest
if(istype(frame))
frame.head = head
head.forceMove(dest)
head = null
/mob/living/heavy_vehicle/proc/forget_module(var/module_to_forget)
//Realistically a module disappearing without being uninstalled is wrong and a bug or adminbus
var/target = null
@@ -150,4 +203,4 @@
to_chat(user, "<span class='notice'>You remove \the [system] in \the [src]'s [system_hardpoint].</span>")
playsound(user.loc, 'sound/items/screwdriver.ogg', 100, 1)
return 1
return system
+3 -3
View File
@@ -13,14 +13,14 @@
if(exosuit)
name = "wreckage of \the [exosuit.name]"
if(!gibbed)
for(var/obj/item/thing in list(exosuit.arms, exosuit.legs, exosuit.head, exosuit.body))
if(thing && prob(40))
thing.forceMove(src)
for(var/hardpoint in exosuit.hardpoints)
if(exosuit.hardpoints[hardpoint] && prob(40))
var/obj/item/thing = exosuit.hardpoints[hardpoint]
if(exosuit.remove_system(hardpoint))
thing.forceMove(src)
for(var/obj/item/mech_component/comp in list(exosuit.arms, exosuit.legs, exosuit.head, exosuit.body))
if(comp && prob(40))
exosuit.remove_body_part(comp, src)
/obj/structure/mech_wreckage/powerloader/Initialize(mapload)
var/mob/living/heavy_vehicle/premade/ripley/new_mech = new(loc)
+14 -2
View File
@@ -97,6 +97,12 @@
selected_system = null
for(var/hardpoint in hardpoints)
var/obj/item/S = remove_system(hardpoint, force = 1)
qdel(S)
hardpoints = null
for(var/thing in pilots)
var/mob/pilot = thing
if(pilot.client)
@@ -112,14 +118,20 @@
hardpoint_hud_elements = null
hardpoints = null
QDEL_NULL(access_card)
QDEL_NULL(arms)
QDEL_NULL(legs)
QDEL_NULL(head)
QDEL_NULL(body)
QDEL_NULL(hud_health)
QDEL_NULL(hud_open)
QDEL_NULL(hud_power)
QDEL_NULL(hud_power_control)
QDEL_NULL(camera)
QDEL_NULL(radio)
. = ..()
/mob/living/heavy_vehicle/IsAdvancedToolUser()
+6 -6
View File
@@ -913,6 +913,12 @@ default behaviour is:
QDEL_NULL(reagents)
clear_from_target_grid()
if(auras)
for(var/a in auras)
remove_aura(a)
QDEL_NULL(ability_master)
return ..()
/mob/living/proc/nervous_system_failure()
@@ -993,12 +999,6 @@ default behaviour is:
return FALSE
. = TRUE
/mob/living/Destroy()
if(auras)
for(var/a in auras)
remove_aura(a)
return ..()
/mob/living/proc/needs_wheelchair()
return FALSE
@@ -51,6 +51,7 @@
friends = null
target_mob = null
targets = null
QDEL_NULL_ASSOC(target_type_validator_map)
return ..()
/mob/living/simple_animal/hostile/can_name(var/mob/living/M)
+1
View File
@@ -4,6 +4,7 @@
living_mob_list -= src
unset_machine()
QDEL_NULL(hud_used)
lose_hearing_sensitivity()
if(client)
for(var/obj/screen/movable/spell_master/spell_master in spell_masters)
qdel(spell_master)
@@ -18,6 +18,12 @@
var/datum/weakref/sensor_ref
var/list/last_scan
/obj/machinery/computer/ship/sensors/Destroy()
QDEL_NULL(sound_token)
sensors = null
identification = null
return ..()
/obj/machinery/computer/ship/sensors/proc/get_sensors()
return sensors
+12
View File
@@ -0,0 +1,12 @@
author: JohnWildkins
delete-after: True
changes:
- bugfix: "Fixed several hard-deletion issues that were causing a severe performance impact."
- bugfix: "Fixed mobs not being removed from AI targeting spatial grid cells when they moved to a new cell."
- bugfix: "Fixed valves not properly disconnecting, leading to a hanging hardref."
- backend: "Added several procs to allow removing body parts from mechs, and fixed mech wreckage deleting contained parts."
- backend: "Adjusted SSatoms init loops to be slightly more performant."
- backend: "Changed failsafe messages to a more visible color."
- backend: "Ported an updated version of reference tracking from tgstation; included optional debug flags to track down hardref issues."