[MIRROR] (Partially) Fixes Out Of Memory crashes (#10092)

Co-authored-by: Cameron Lennox <killer65311@gmail.com>
Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com>
This commit is contained in:
CHOMPStation2StaffMirrorBot
2025-02-07 08:36:42 -07:00
committed by GitHub
parent 133f37de97
commit ec71611656
31 changed files with 124 additions and 67 deletions

View File

@@ -248,7 +248,7 @@ Proc for attack log creation, because really why not
. = FALSE
break
if(target_zone && user.zone_sel.selecting != target_zone)
if(target_zone && user.zone_sel?.selecting != target_zone)
. = FALSE
break

View File

@@ -33,6 +33,8 @@
#define qdel_null(x) if(x) { qdel(x) ; x = null }
#define qdel_swap(x,y) if(x) { qdel(x) }; x = y;
#define sequential_id(key) uniqueness_repository.Generate(/datum/uniqueness_generator/id_sequential, key)
#define random_id(key,min_id,max_id) uniqueness_repository.Generate(/datum/uniqueness_generator/id_random, key, min_id, max_id)

View File

@@ -282,6 +282,8 @@ SUBSYSTEM_DEF(transcore)
// Called from body_record to add itself to the transcore.
/datum/transcore_db/proc/add_body(var/datum/transhuman/body_record/BR)
ASSERT(BR)
if(body_scans[BR.mydna.name])
qdel(body_scans[BR.mydna.name])
body_scans[BR.mydna.name] = BR
body_scans = sortAssoc(body_scans)
log_debug("Added [BR.mydna.name] to transcore body DB.")

View File

@@ -40,7 +40,7 @@
/datum/dna2/record/proc/copy()
var/datum/dna2/record/newrecord = new /datum/dna2/record
newrecord.dna = dna.Clone()
qdel_swap(newrecord.dna, dna.Clone())
newrecord.types = types
newrecord.name = name
newrecord.mind = mind

View File

@@ -45,8 +45,8 @@
if(M)
if (M.dna)
O.dna = M.dna.Clone()
M.dna = null
qdel_swap(O.dna, M.dna.Clone())
QDEL_NULL(M.dna)
if (M.suiciding)
O.suiciding = M.suiciding
@@ -116,8 +116,8 @@
if (M)
if (M.dna)
O.dna = M.dna.Clone()
M.dna = null
qdel_swap(O.dna, M.dna.Clone())
QDEL_NULL(M.dna)
if (M.suiciding)
O.suiciding = M.suiciding

View File

@@ -10,9 +10,13 @@
/datum/absorbed_dna/New(var/newName, var/newDNA, var/newSpecies, var/newLanguages, var/newIdentifying_Gender, var/list/newFlavour, var/list/newGenMods)
..()
name = newName
dna = newDNA
qdel_swap(dna, newDNA)
speciesName = newSpecies
languages = newLanguages
identifying_gender = newIdentifying_Gender
flavour_texts = newFlavour ? newFlavour.Copy() : null
genMods = newGenMods ? newGenMods.Copy() : null
genMods = newGenMods ? newGenMods.Copy() : null
/datum/absorbed_dna/Destroy()
. = ..()
qdel(dna)

View File

@@ -58,7 +58,7 @@
changeling.chem_charges--
C.remove_changeling_powers()
C.visible_message(span_warning("[C] transforms!"))
C.dna = chosen_dna.Clone()
qdel_swap(C.dna, chosen_dna.Clone())
var/list/implants = list()
for (var/obj/item/implant/I in C) //Still preserving implants
@@ -85,8 +85,8 @@
O.gender = FEMALE
else
O.gender = MALE
O.dna = C.dna.Clone()
C.dna = null
qdel_swap(O.dna, C.dna.Clone())
QDEL_NULL(C.dna)
O.real_name = chosen_dna.real_name
for(var/obj/T in C)

View File

@@ -37,7 +37,7 @@
var/newSpecies = chosen_dna.speciesName
H.set_species(newSpecies,1)
src.dna = chosen_dna.dna.Clone()
qdel_swap(src.dna, chosen_dna.dna.Clone())
src.dna.b_type = "AB+" //This is needed to avoid blood rejection bugs. The fact that the blood type might not match up w/ records could be a *FEATURE* too.
if(ishuman(src))
var/mob/living/carbon/human/H = src

View File

@@ -36,7 +36,7 @@
return 0
add_attack_logs(src,T,"Transformation sting (changeling)")
T.visible_message(span_warning("[T] transforms!"))
T.dna = chosen_dna.Clone()
qdel_swap(T.dna, chosen_dna.Clone())
T.real_name = chosen_dna.real_name
T.UpdateAppearance()
domutcheck(T, null)

View File

@@ -130,9 +130,9 @@
if(!R.dna)
H.dna = new /datum/dna()
H.dna.real_name = H.real_name
qdel_swap(H.dna, new /datum/dna())
else
H.dna = R.dna
qdel_swap(H.dna, R.dna)
H.UpdateAppearance()
H.sync_organ_dna()
if(heal_level < 60)

View File

@@ -34,6 +34,9 @@
/obj/machinery/computer/cloning/Destroy()
releasecloner()
for(var/datum/dna2/record/R in records)
qdel(R.dna)
qdel(R)
return ..()
/obj/machinery/computer/cloning/process()
@@ -210,6 +213,7 @@
return
if(check_access(C))
records.Remove(active_record)
qdel(active_record.dna)
qdel(active_record)
set_temp("Record deleted.", "success")
menu = MENU_RECORDS
@@ -344,6 +348,7 @@
set_temp("Initiating cloning cycle...", "success")
playsound(src, 'sound/machines/medbayscanner1.ogg', 100, 1)
records.Remove(C)
qdel(C.dna)
qdel(C)
menu = MENU_MAIN
else
@@ -423,7 +428,7 @@
subject.dna.check_integrity()
var/datum/dna2/record/R = new /datum/dna2/record()
R.dna = subject.dna
qdel_swap(R.dna, subject.dna)
R.ckey = subject.ckey
R.id = copytext(md5(subject.real_name), 2, 6)
R.name = R.dna.real_name

View File

@@ -81,8 +81,6 @@
if(!D.has_AI())
continue
D.ai_holder.lose_target()
watchowner.emote("deathgasp")
watchowner.alpha = 15
makeacorpse(watchowner)
return
@@ -97,7 +95,8 @@
if(H.isSynthetic())
return
corpse = new /mob/living/carbon/human(H.loc)
corpse.setDNA(H.dna.Clone())
qdel_swap(corpse.dna,H.dna.Clone())
corpse.emote("deathgasp")
corpse.death(1) //Kills the new mob
var/obj/item/clothing/temp = null
if(H.get_equipped_item(slot_w_uniform))

View File

@@ -315,6 +315,8 @@ var/list/preferences_datums = list()
else if(href_list["close"])
// User closed preferences window, cleanup anything we need to.
clear_character_previews()
if(GLOB.mannequins[client_ckey])
qdel_null(GLOB.mannequins[client_ckey])
return 1
else
return 0

View File

@@ -124,7 +124,7 @@
brainmob = new(src)
brainmob.name = H.real_name
brainmob.real_name = H.real_name
brainmob.dna = H.dna
qdel_swap(brainmob.dna, H.dna.Clone())
brainmob.container = src
// Copy modifiers.
@@ -227,7 +227,7 @@
..()
/obj/item/mmi/digital/transfer_identity(var/mob/living/carbon/H)
brainmob.dna = H.dna
qdel_swap(brainmob.dna, H.dna.Clone())
brainmob.timeofhostdeath = H.timeofdeath
brainmob.set_stat(CONSCIOUS)
if(H.mind)

View File

@@ -24,6 +24,7 @@
if(stat != DEAD) //If not dead.
death(1) //Brains can die again. AND THEY SHOULD AHA HA HA HA HA HA
ghostize() //Ghostize checks for key so nothing else is necessary.
qdel(dna)
return ..()
/mob/living/carbon/brain/say_understands(var/other)//Goddamn is this hackish, but this say code is so odd

View File

@@ -173,7 +173,7 @@
check_dna()
dna.ready_dna(src)
for(var/obj/item/organ/O in organs)
O.dna = dna // Update all of those because apparently they're separate, and icons won't update properly
qdel_swap(O.dna, dna.Clone()) // Update all of those because apparently they're separate, and icons won't update properly
/mob/living/carbon/human/proc/generate_valid_species(var/check_whitelist = 1, var/list/whitelist = list(), var/list/blacklist = list())
var/list/valid_species = new()

View File

@@ -1310,18 +1310,16 @@
var/datum/mob_descriptor/descriptor = species.descriptors[desctype]
descriptors[desctype] = descriptor.default_value
spawn(0)
if(regen_icons) regenerate_icons()
make_blood()
if(vessel.total_volume < species.blood_volume)
vessel.maximum_volume = species.blood_volume
vessel.add_reagent(REAGENT_ID_BLOOD, species.blood_volume - vessel.total_volume)
else if(vessel.total_volume > species.blood_volume)
vessel.remove_reagent(REAGENT_ID_BLOOD,vessel.total_volume - species.blood_volume) //This one should stay remove_reagent to work even lack of a O_heart
vessel.maximum_volume = species.blood_volume
fixblood()
species.update_attack_types() //VOREStation Edit - Required for any trait that updates unarmed_types in setup.
species.update_vore_belly_def_variant()
make_blood()
if(vessel.total_volume < species.blood_volume)
vessel.maximum_volume = species.blood_volume
vessel.add_reagent(REAGENT_ID_BLOOD, species.blood_volume - vessel.total_volume)
else if(vessel.total_volume > species.blood_volume)
vessel.remove_reagent(REAGENT_ID_BLOOD,vessel.total_volume - species.blood_volume) //This one should stay remove_reagent to work even lack of a O_heart
vessel.maximum_volume = species.blood_volume
fixblood()
species.update_attack_types() //Required for any trait that updates unarmed_types in setup.
species.update_vore_belly_def_variant()
// Rebuild the HUD. If they aren't logged in then login() should reinstantiate it for them.
update_hud()

View File

@@ -12,10 +12,10 @@
client.screen = list()
if(mind && mind.current == src)
spellremove(src)
if(!istype(src,/mob/observer)) //CHOMPEdit
ghostize() //CHOMPEdit
//ChompEDIT start - fix hard qdels
QDEL_NULL(soulgem) //CHOMPAdd
if(!istype(src,/mob/observer))
ghostize()
QDEL_NULL(soulgem) // CHOMPAdd Soulcatcher
QDEL_NULL(dna)
QDEL_NULL(plane_holder)
QDEL_NULL(hud_used)
for(var/key in alerts) //clear out alerts
@@ -23,6 +23,12 @@
if(pulling)
stop_pulling() //TG does this on atom/movable but our stop_pulling proc is here so whatever
vore_selected = null
if(vore_organs)
QDEL_NULL_LIST(vore_organs)
if(vorePanel)
QDEL_NULL(vorePanel)
previewing_belly = null // from code/modules/vore/eating/mob_ch.dm
vore_selected = null // from code/modules/vore/eating/mob_vr
focus = null
@@ -37,6 +43,7 @@
update_client_z(null)
//return QDEL_HINT_HARDDEL_NOW
/mob/proc/remove_screen_obj_references()
hands = null
pullin = null

View File

@@ -41,7 +41,7 @@
M.real_name = src.real_name
if(src.dna)
M.dna = src.dna.Clone()
qdel_swap(M.dna, src.dna.Clone())
if(mind)
mind.transfer_to(M)

View File

@@ -240,7 +240,7 @@
//If they have these values, apply them
if(ishuman(M))
var/mob/living/carbon/human/H = M
brainmob.dna = H.dna
qdel_swap(brainmob.dna, H.dna.Clone())
brainmob.ooc_notes = H.ooc_notes
brainmob.ooc_notes_likes = H.ooc_notes_likes
brainmob.ooc_notes_dislikes = H.ooc_notes_dislikes

View File

@@ -90,6 +90,8 @@ GLOBAL_LIST_BOILERPLATE(all_brain_organs, /obj/item/organ/internal/brain)
brainmob.client.screen.len = null //clear the hud
/obj/item/organ/internal/brain/Destroy()
if(brainmob && brainmob.dna)
qdel(brainmob.dna)
QDEL_NULL(brainmob)
. = ..()
@@ -101,7 +103,7 @@ GLOBAL_LIST_BOILERPLATE(all_brain_organs, /obj/item/organ/internal/brain)
brainmob.real_name = H.real_name
if(istype(H))
brainmob.dna = H.dna.Clone()
qdel_swap(brainmob.dna, H.dna.Clone())
brainmob.timeofhostdeath = H.timeofdeath
brainmob.ooc_notes = H.ooc_notes //VOREStation Edit
brainmob.ooc_notes_likes = H.ooc_notes_likes
@@ -213,7 +215,7 @@ GLOBAL_LIST_BOILERPLATE(all_brain_organs, /obj/item/organ/internal/brain)
/obj/item/organ/internal/brain/slime/proc/reviveBody()
var/datum/dna2/record/R = new /datum/dna2/record()
R.dna = brainmob.dna
qdel_swap(R.dna, brainmob.dna.Clone())
R.ckey = brainmob.ckey
R.id = copytext(md5(brainmob.real_name), 2, 6)
R.name = R.dna.real_name
@@ -253,7 +255,7 @@ GLOBAL_LIST_BOILERPLATE(all_brain_organs, /obj/item/organ/internal/brain)
H.dna = new /datum/dna()
H.dna.real_name = H.real_name
else
H.dna = R.dna
qdel_swap(H.dna, R.dna.Clone())
H.UpdateAppearance()
H.sync_organ_dna()
@@ -287,6 +289,8 @@ GLOBAL_LIST_BOILERPLATE(all_brain_organs, /obj/item/organ/internal/brain)
for(var/datum/language/L in R.languages)
H.add_language(L.name)
H.flavor_texts = R.flavor.Copy()
qdel(R.dna)
qdel(R)
qdel(src)
return 1

View File

@@ -54,7 +54,7 @@ var/list/organ_cache = list()
if(transplant_data) transplant_data.Cut()
if(autopsy_data) autopsy_data.Cut()
if(trace_chemicals) trace_chemicals.Cut()
dna = null
QDEL_NULL(dna)
species = null
return ..()
@@ -93,8 +93,8 @@ var/list/organ_cache = list()
var/mob/living/carbon/C = holder
species = GLOB.all_species[SPECIES_HUMAN]
if(holder.dna)
dna = C.dna.Clone()
species = C.species //VOREStation Edit - For custom species
qdel_swap(dna, C.dna.Clone())
species = C.species
else
log_debug("[src] at [loc] spawned without a proper DNA.")
var/mob/living/carbon/human/H = C
@@ -131,7 +131,7 @@ var/list/organ_cache = list()
/obj/item/organ/proc/set_dna(var/datum/dna/new_dna)
if(new_dna)
dna = new_dna.Clone()
qdel_swap(dna, new_dna.Clone())
if(blood_DNA)
blood_DNA.Cut()
blood_DNA[dna.unique_enzymes] = dna.b_type

View File

@@ -95,6 +95,9 @@
parent.children -= src
parent = null
if(wounds)
QDEL_LIST(wounds)
if(children)
for(var/obj/item/organ/external/C in children)
children -= C

View File

@@ -12,19 +12,21 @@
var/controller_lock = 0 //whether or not the gun is locked by the primar controller, 0 or 1, at 1 it is locked and does not allow
var/exploding = 0
/obj/item/dnalockingchip/Destroy(force, ...)
. = ..()
/obj/item/gun/proc/get_dna(mob/user)
var/mob/living/M = user
if(!attached_lock.controller_lock)
if(!attached_lock.stored_dna && !(M.dna in attached_lock.stored_dna))
if(attached_lock.stored_dna && (M.dna.unique_enzymes in attached_lock.stored_dna))
to_chat(M, span_warning("\The [src] buzzes and displays a symbol showing the gun already contains your DNA."))
return 0
else
attached_lock.stored_dna += M.dna
attached_lock.stored_dna += M.dna.unique_enzymes
to_chat(M, span_notice("\The [src] pings and a needle flicks out from the grip, taking a DNA sample from you."))
if(!attached_lock.controller_dna)
attached_lock.controller_dna = M.dna
attached_lock.controller_dna = M.dna.unique_enzymes
to_chat(M, span_notice("\The [src] processes the dna sample and pings, acknowledging you as the primary controller."))
return 1
else
@@ -44,10 +46,9 @@
to_chat(M, span_warning("\The [src] buzzes and displays an invalid user symbol."))
return 0
else
attached_lock.stored_dna -= user.dna
attached_lock.stored_dna -= user.dna.unique_enzymes
to_chat(M, span_notice("\The [src] beeps and clears the DNA it has stored."))
if(M.dna == attached_lock.controller_dna)
attached_lock.controller_dna = null
if(M.dna.unique_enzymes == attached_lock.controller_dna)
to_chat(M, span_notice("\The [src] beeps and removes you as the primary controller."))
if(attached_lock.controller_lock)
attached_lock.controller_lock = 0
@@ -64,7 +65,7 @@
/obj/item/gun/proc/toggledna(mob/user)
var/mob/living/M = user
if(authorized_user(M) && user.dna == attached_lock.controller_dna)
if(authorized_user(M) && user.dna.unique_enzymes == attached_lock.controller_dna)
if(!attached_lock.controller_lock)
attached_lock.controller_lock = 1
to_chat(M, span_notice("\The [src] beeps and displays a locked symbol, informing you it will no longer allow DNA samples."))
@@ -83,6 +84,6 @@
/obj/item/gun/proc/authorized_user(mob/user)
if(!attached_lock.stored_dna || !attached_lock.stored_dna.len)
return 1
if(!(user.dna in attached_lock.stored_dna))
if(!(user.dna.unique_enzymes in attached_lock.stored_dna))
return 0
return 1

View File

@@ -27,11 +27,9 @@
else
O.species = GLOB.all_species["Human"]
O.robotize(prosfab.manufacturer)
O.dna = new/datum/dna() //Uuughhhh... why do I have to do this?
qdel_swap(O.dna, new/datum/dna()) //Uuughhhh... why do I have to do this?
O.dna.ResetUI()
O.dna.ResetSE()
spawn(10) //Limbs love to flop around. Who am I to deny them?
O.dir = 2
return O
return ..()
@@ -68,7 +66,7 @@
manf = all_robolimbs["Unbranded"]
O.robotize(manf.company)
O.dna = new/datum/dna()
qdel_swap(O.dna, new/datum/dna())
O.dna.ResetUI()
O.dna.ResetSE()

View File

@@ -402,7 +402,7 @@
I.digitize()
// Apply DNA
H.dna = R.dna.Clone()
qdel_swap(H.dna, R.dna.Clone())
H.UpdateAppearance() // Update all appearance stuff from the DNA record
// H.sync_dna_traits(FALSE) // Traitgenes edit - Sync traits to genetics if needed // Currently not implemented
H.sync_organ_dna() // Do this because sprites depend on DNA-gender of organs (chest etc)

View File

@@ -113,7 +113,8 @@
init_from_mob(copyfrom, add_to_db, ckeylock)
/datum/transhuman/body_record/Destroy()
mydna = null
qdel_null(mydna.dna)
qdel_null(mydna)
client_ref = null
mind_ref = null
limb_data.Cut()
@@ -153,7 +154,7 @@
//The DNA2 stuff
mydna = new ()
mydna.dna = M.dna.Clone()
qdel_swap(mydna.dna, M.dna.Clone())
mydna.ckey = M.ckey
mydna.id = copytext(md5(M.real_name), 2, 6)
mydna.name = M.dna.real_name
@@ -224,7 +225,7 @@
ASSERT(!QDELETED(orig))
ASSERT(istype(orig))
src.mydna = new ()
src.mydna.dna = orig.mydna.dna.Clone()
qdel_swap(src.mydna.dna, orig.mydna.dna.Clone())
src.mydna.ckey = orig.mydna.ckey
src.mydna.id = orig.mydna.id
src.mydna.name = orig.mydna.name

View File

@@ -98,7 +98,7 @@
H.real_name = R.dna.real_name
//Apply DNA
H.dna = R.dna.Clone()
qdel_swap(H.dna, R.dna.Clone())
H.original_player = current_project.ckey
//Apply genetic modifiers
@@ -354,7 +354,7 @@
H.real_name = R.dna.real_name
//Apply DNA
H.dna = R.dna.Clone()
qdel_swap(H.dna, R.dna.Clone())
H.original_player = current_project.ckey
//Apply damage

View File

@@ -15,5 +15,3 @@
var/no_latejoin_prey_warning_persists = FALSE //Do we save it?
var/belly_rub_target = null
var/soulcatcher_pref_flags = 0 //Default disabled
var/obj/soulgem/soulgem

View File

@@ -68,3 +68,5 @@
var/vore_icons = 0 // Bitfield for which fields we have vore icons for.
var/vore_eyes = FALSE // For mobs with fullness specific eye overlays.
var/obj/soulgem/soulgem // CHOMPEnable Soulcatcher. Needs to be up-ported sometime.

View File

@@ -0,0 +1,30 @@
///NOTE: LEAVE THIS FILE UNTICKED AND THE SEGMENTS OF CODE COMMENTED OUT UNLESS YOU NEED TO DO SOMETHING SPECIFIC / TRACK SOMETHING SPECIFIC.
/*
/// Testing if DNA & Species datums get destoryed or not. Use this as a basis to test for memory leaks.
/// This happens if DNA is copied from somewhere but not qdel_swap()'d. WARNING: Not every time it's copied should be qdel_swap()'d.
/// But if you are doing anything DNA copy related, turn this on and make sure it's not infintely storing a datum somewhere.
GLOBAL_VAR(total_dna_counters)
GLOBAL_VAR(total_species_counters)
/datum/dna/New()
. = ..()
GLOB.total_dna_counters += 1
/datum/dna/Destroy()
. = ..()
GLOB.total_dna_counters -= 1
/datum/species/New()
. = ..()
GLOB.total_species_counters += 1
/datum/species/Destroy()
. = ..()
GLOB.total_species_counters -= 1
/proc/delete_all_monkeys()
for(var/mob/living/carbon/human/monkey/monkeys in world)
qdel(monkeys)
*/