From feef0ea814bd79cb39486414c188ff9eb04b5ff1 Mon Sep 17 00:00:00 2001 From: Ryan <80364400+Sirryan2002@users.noreply.github.com> Date: Wed, 8 Mar 2023 14:42:44 -0500 Subject: [PATCH] Fixes Garbage Collection issues with Xenobiology (#20190) * xenobio gc fixes * requested changes * requested changes --- code/game/objects/items/devices/scanners.dm | 3 +- .../kitchen_machinery/monkeyrecycler.dm | 11 ++ .../kitchen_machinery/processor.dm | 1 + .../living/simple_animal/slime/slime_death.dm | 7 +- .../living/simple_animal/slime/slime_mob.dm | 50 ++------ .../simple_animal/slime/slime_powers.dm | 5 +- .../research/xenobiology/xenobio_camera.dm | 114 +++++++++++------- 7 files changed, 97 insertions(+), 94 deletions(-) diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index 932e730b085..e3a274326f0 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -548,8 +548,7 @@ REAGENT SCANNER if(!isslime(M)) to_chat(user, "This device can only scan slimes!") return - var/mob/living/simple_animal/slime/T = M - slime_scan(T, user) + slime_scan(M, user) /proc/slime_scan(mob/living/simple_animal/slime/T, mob/living/user) to_chat(user, "========================") diff --git a/code/modules/food_and_drinks/kitchen_machinery/monkeyrecycler.dm b/code/modules/food_and_drinks/kitchen_machinery/monkeyrecycler.dm index 76792806490..8510e6bce62 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/monkeyrecycler.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/monkeyrecycler.dm @@ -25,6 +25,7 @@ GLOBAL_LIST_EMPTY(monkey_recyclers) component_parts += new /obj/item/stock_parts/matter_bin(null) GLOB.monkey_recyclers += src RefreshParts() + locate_camera_console() /obj/machinery/monkey_recycler/Destroy() GLOB.monkey_recyclers -= src @@ -34,6 +35,15 @@ GLOBAL_LIST_EMPTY(monkey_recyclers) connected.Cut() return ..() +/obj/machinery/monkey_recycler/proc/locate_camera_console() + if(length(connected)) + return // we're already connected! + for(var/obj/machinery/computer/camera_advanced/xenobio/xeno_camera in GLOB.machines) + if(get_area(xeno_camera) == get_area(loc)) + xeno_camera.connected_recycler = src + connected |= xeno_camera + break + /obj/machinery/monkey_recycler/RefreshParts() var/req_grind = 5 var/cubes_made = 1 @@ -92,6 +102,7 @@ GLOBAL_LIST_EMPTY(monkey_recyclers) else user.drop_item() qdel(target) + target = null //we sleep in this proc, clear reference NOW to_chat(user, "You stuff the monkey in the machine.") playsound(loc, 'sound/machines/juicer.ogg', 50, 1) var/offset = prob(50) ? -2 : 2 diff --git a/code/modules/food_and_drinks/kitchen_machinery/processor.dm b/code/modules/food_and_drinks/kitchen_machinery/processor.dm index 54291db7963..b71bdd1bb20 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/processor.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/processor.dm @@ -51,6 +51,7 @@ var/output var/time = 40 +/// WHO NAME A PARAMETER FOR A PROC "what" holy hell /datum/food_processor_process/proc/process_food(loc, what, obj/machinery/processor/processor) if(output && loc && processor) for(var/i = 0, i < processor.rating_amount, i++) diff --git a/code/modules/mob/living/simple_animal/slime/slime_death.dm b/code/modules/mob/living/simple_animal/slime/slime_death.dm index 8dbcefac68a..8aa4e2f67f0 100644 --- a/code/modules/mob/living/simple_animal/slime/slime_death.dm +++ b/code/modules/mob/living/simple_animal/slime/slime_death.dm @@ -1,6 +1,10 @@ /mob/living/simple_animal/slime/death(gibbed) if(stat == DEAD) return + + if(buckled) + Feedstop(silent = TRUE) //releases ourselves from the mob we fed on. + if(!gibbed) if(is_adult) var/mob/living/simple_animal/slime/M = new(loc, colour) @@ -18,9 +22,6 @@ update_name() return - if(buckled) - Feedstop(silent = TRUE) //releases ourselves from the mob we fed on. - set_stat(DEAD) //Temporarily set to dead for icon updates regenerate_icons() set_stat(CONSCIOUS) diff --git a/code/modules/mob/living/simple_animal/slime/slime_mob.dm b/code/modules/mob/living/simple_animal/slime/slime_mob.dm index 96fac4bdd19..ac613a4d69c 100644 --- a/code/modules/mob/living/simple_animal/slime/slime_mob.dm +++ b/code/modules/mob/living/simple_animal/slime/slime_mob.dm @@ -351,6 +351,7 @@ discipline_slime(M) + /mob/living/simple_animal/slime/attackby(obj/item/I, mob/living/user, params) if(stat == DEAD && surgeries.len) if(user.a_intent == INTENT_HELP || user.a_intent == INTENT_DISARM) @@ -362,6 +363,7 @@ ++Friends[user] else Friends[user] = 1 + RegisterSignal(user, COMSIG_PARENT_QDELETING, PROC_REF(clear_friend)) to_chat(user, "You feed the slime the plasma. It chirps happily.") var/obj/item/stack/sheet/mineral/plasma/S = I S.use(1) @@ -381,50 +383,12 @@ force_effect = round(I.force / 2) if(prob(10 + force_effect)) discipline_slime(user) -/* if(istype(I, /obj/item/storage/bag/bio)) - var/obj/item/storage/P = I - if(!effectmod) - to_chat(user, "The slime is not currently being mutated.") - return - var/hasOutput = FALSE //Have we outputted text? - var/hasFound = FALSE //Have we found an extract to be added? - for(var/obj/item/slime_extract/S in P.contents) - if(S.effectmod == effectmod) - SEND_SIGNAL(P, COMSIG_TRY_STORAGE_TAKE, S, get_turf(src), TRUE) - qdel(S) - applied++ - hasFound = TRUE - if(applied >= SLIME_EXTRACT_CROSSING_REQUIRED) - to_chat(user, "You feed the slime as many of the extracts from the bag as you can, and it mutates!") - playsound(src, 'sound/effects/attackblob.ogg', 50, TRUE) - spawn_corecross() - hasOutput = TRUE - break - if(!hasOutput) - if(!hasFound) - to_chat(user, "There are no extracts in the bag that this slime will accept!") - else - to_chat(user, "You feed the slime some extracts from the bag.") - playsound(src, 'sound/effects/attackblob.ogg', 50, TRUE) - return */ ..() -/* -/mob/living/simple_animal/slime/proc/spawn_corecross() - var/static/list/crossbreeds = subtypesof(/obj/item/slimecross) - visible_message("[src] shudders, its mutated core consuming the rest of its body!") - playsound(src, 'sound/magic/smoke.ogg', 50, TRUE) - var/crosspath - for(var/X in crossbreeds) - var/obj/item/slimecross/S = X - if(initial(S.colour) == colour && initial(S.effect) == effectmod) - crosspath = S - break - if(crosspath) - new crosspath(loc) - else - visible_message("The mutated core shudders, and collapses into a puddle, unable to maintain its form.") - qdel(src) -*/ + +/mob/living/simple_animal/slime/proc/clear_friend(mob/living/friend) + UnregisterSignal(friend, COMSIG_PARENT_QDELETING) + Friends -= friend + /mob/living/simple_animal/slime/water_act(volume, temperature, source, method = REAGENT_TOUCH) . = ..() var/water_damage = rand(10, 15) * volume diff --git a/code/modules/mob/living/simple_animal/slime/slime_powers.dm b/code/modules/mob/living/simple_animal/slime/slime_powers.dm index a4ac4d4a242..e8686b5f09a 100644 --- a/code/modules/mob/living/simple_animal/slime/slime_powers.dm +++ b/code/modules/mob/living/simple_animal/slime/slime_powers.dm @@ -170,6 +170,9 @@ to_chat(src, "I must be conscious to do this...") return + if(istype(loc, /obj/machinery/computer/camera_advanced/xenobio)) + return //no you cannot split while you're in the matrix (this prevents GC issues and slimes disappearing) + var/list/babies = list() var/new_nutrition = round(nutrition * 0.9) var/new_powerlevel = round(powerlevel / 4) @@ -187,7 +190,7 @@ M.set_nutrition(new_nutrition) //Player slimes are more robust at spliting. Once an oversight of poor copypasta, now a feature! M.powerlevel = new_powerlevel if(i != 1) - step_away(M,src) + step_away(M, get_turf(src)) M.Friends = Friends.Copy() babies += M M.mutation_chance = clamp(mutation_chance+(rand(5,-5)),0,100) diff --git a/code/modules/research/xenobiology/xenobio_camera.dm b/code/modules/research/xenobiology/xenobio_camera.dm index bf500c3a845..531dc923780 100644 --- a/code/modules/research/xenobiology/xenobio_camera.dm +++ b/code/modules/research/xenobiology/xenobio_camera.dm @@ -3,27 +3,38 @@ visible_icon = 1 icon = 'icons/obj/abductor.dmi' icon_state = "camera_target" - var/allowed_area = null // The Xenobio Console does not trigger the AI Detector ai_detector_visible = FALSE + /// Area that the xenobio camera eye is allowed to travel + var/allowed_area = null -/mob/camera/aiEye/remote/xenobio/New(loc) +/mob/camera/aiEye/remote/xenobio/Initialize(mapload) + . = ..() var/area/A = get_area(loc) allowed_area = A.name - ..() /mob/camera/aiEye/remote/xenobio/setLoc(t) var/area/new_area = get_area(t) - if(new_area && new_area.name == allowed_area || new_area && new_area.xenobiology_compatible) - return ..() - else + if(!new_area) return + if(new_area.name != allowed_area && !new_area.xenobiology_compatible) + return + return ..() +/* + * # Slime Management Console + * + * Camera overview console for xenobiology, handles slime management and xenobio actions +*/ /obj/machinery/computer/camera_advanced/xenobio name = "slime management console" desc = "A computer used for remotely handling slimes." + icon_screen = "slime_comp" + icon_keyboard = "rd_key" networks = list("SS13") circuit = /obj/item/circuitboard/xenobiology + + var/datum/action/innate/slime_place/slime_place_action = new var/datum/action/innate/slime_pick_up/slime_up_action = new var/datum/action/innate/feed_slime/feed_slime_action = new @@ -38,19 +49,17 @@ var/obj/item/slimepotion/slime/current_potion var/obj/machinery/monkey_recycler/connected_recycler - icon_screen = "slime_comp" - icon_keyboard = "rd_key" - /obj/machinery/computer/camera_advanced/xenobio/Initialize(mapload) - ..() - return INITIALIZE_HINT_LATELOAD + . = ..() + if(!connected_recycler) + locate_recycler() -/obj/machinery/computer/camera_advanced/xenobio/LateInitialize() - ..() +/obj/machinery/computer/camera_advanced/xenobio/proc/locate_recycler() for(var/obj/machinery/monkey_recycler/recycler in GLOB.monkey_recyclers) - if(get_area(recycler.loc) == get_area(loc)) + if(get_area(recycler) == get_area(loc)) connected_recycler = recycler - connected_recycler.connected += src + connected_recycler.connected |= src + break /obj/machinery/computer/camera_advanced/xenobio/Destroy() QDEL_NULL(current_potion) @@ -73,7 +82,7 @@ /obj/machinery/computer/camera_advanced/xenobio/CreateEye() eyeobj = new /mob/camera/aiEye/remote/xenobio(get_turf(src)) eyeobj.origin = src - eyeobj.visible_icon = 1 + eyeobj.visible_icon = TRUE eyeobj.acceleration = FALSE eyeobj.icon = 'icons/obj/abductor.dmi' eyeobj.icon_state = "camera_target" @@ -124,10 +133,7 @@ RegisterSignal(user, COMSIG_XENO_MONKEY_CLICK_CTRL, PROC_REF(XenoMonkeyClickCtrl)) if(!connected_recycler) - for(var/obj/machinery/monkey_recycler/recycler in GLOB.monkey_recyclers) - if(get_area(recycler.loc) == get_area(loc)) - connected_recycler = recycler - connected_recycler.connected += src + locate_recycler() /obj/machinery/computer/camera_advanced/xenobio/remove_eye_control(mob/living/user) UnregisterSignal(user, COMSIG_XENO_SLIME_CLICK_CTRL) @@ -138,6 +144,33 @@ UnregisterSignal(user, COMSIG_XENO_MONKEY_CLICK_CTRL) ..() +/obj/machinery/computer/camera_advanced/xenobio/proc/insert_potion(obj/item/slimepotion/slime/potion) + clear_potion() + potion.forceMove(src) + current_potion = potion + RegisterSignal(current_potion, COMSIG_PARENT_QDELETING, PROC_REF(clear_potion)) + +/obj/machinery/computer/camera_advanced/xenobio/proc/clear_potion() + if(!QDELETED(current_potion)) + current_potion.forceMove(drop_location()) + UnregisterSignal(current_potion, COMSIG_PARENT_QDELETING) + current_potion = null + +/obj/machinery/computer/camera_advanced/xenobio/proc/capture_slime(mob/living/simple_animal/slime/slime) + slime.visible_message("[slime] vanishes in a flash of light!") + slime.forceMove(src) + stored_slimes += slime + RegisterSignal(slime, COMSIG_PARENT_QDELETING, PROC_REF(clear_slime)) + +/obj/machinery/computer/camera_advanced/xenobio/proc/release_slime(mob/living/simple_animal/slime/slime, release_spot) + slime.visible_message("[slime] warps in!") + clear_slime(slime) + slime.forceMove(release_spot) + +/obj/machinery/computer/camera_advanced/xenobio/proc/clear_slime(mob/living/simple_animal/slime/slime) + UnregisterSignal(slime, COMSIG_PARENT_QDELETING) + stored_slimes -= slime + /obj/machinery/computer/camera_advanced/xenobio/attack_hand(mob/user) if(!ishuman(user)) //AIs using it might be weird return @@ -151,13 +184,10 @@ qdel(O) return else if(istype(O, /obj/item/slimepotion/slime)) - var/replaced = FALSE - if(user.drop_item()) - if(!QDELETED(current_potion)) - current_potion.forceMove(drop_location()) - replaced = TRUE - current_potion = O - to_chat(user, "You load [O] in the console's potion slot[replaced ? ", replacing the one that was there before" : ""].") + if(!user.drop_item()) + return + to_chat(user, "You load [O] in the console's potion slot[current_potion ? ", replacing the one that was there before" : ""].") + insert_potion(O, user) return else if(istype(O, /obj/item/storage/bag) || istype(O, /obj/item/storage/box)) var/obj/item/storage/P = O @@ -184,6 +214,7 @@ connected_recycler.connected += src to_chat(user, "You link [src] to the recycler stored in [M]'s buffer.") +// === SLIME ACTION DATUMS ==== /datum/action/innate/slime_place name = "Place Slimes" button_icon_state = "slime_down" @@ -200,9 +231,7 @@ return else if(GLOB.cameranet.checkTurfVis(remote_eye.loc)) for(var/mob/living/simple_animal/slime/S in X.stored_slimes) - S.forceMove(remote_eye.loc) - S.visible_message("[S] warps in!") - X.stored_slimes -= S + X.release_slime(S, remote_eye.loc) else to_chat(owner, "Target is not near a camera. Cannot proceed.") @@ -219,14 +248,12 @@ if(GLOB.cameranet.checkTurfVis(remote_eye.loc)) for(var/mob/living/simple_animal/slime/S in remote_eye.loc) - if(X.stored_slimes.len >= X.max_slimes) + if(length(X.stored_slimes) >= X.max_slimes) break if(!S.ckey) if(S.buckled) S.Feedstop(silent = TRUE) - S.visible_message("[S] vanishes in a flash of light!") - S.forceMove(X) - X.stored_slimes += S + X.capture_slime(S) else to_chat(owner, "Target is not near a camera. Cannot proceed.") @@ -280,7 +307,7 @@ if(issmall(M) && M.stat) M.visible_message("[M] vanishes as [M.p_theyre()] reclaimed for recycling!") recycler.use_power(500) - X.monkeys = round(X.monkeys + recycler.cube_production/recycler.required_grind, 0.1) + X.monkeys = round(X.monkeys + recycler.cube_production / recycler.required_grind, 0.1) qdel(M) else to_chat(owner, "Target is not near a camera. Cannot proceed.") @@ -331,12 +358,12 @@ /datum/action/innate/hotkey_help/Activate() if(!target || !isliving(owner)) return + var/obj/machinery/computer/camera_advanced/xenobio/X = owner.machine to_chat(owner, "Click shortcuts:") to_chat(owner, "Shift-click a slime to pick it up, or the floor to drop all held slimes.") to_chat(owner, "Ctrl-click a slime to scan it.") to_chat(owner, "Alt-click a slime to feed it a potion.") to_chat(owner, "Ctrl-click or a dead monkey to recycle it, or the floor to place a new monkey.") - var/obj/machinery/computer/camera_advanced/xenobio/X = owner.machine to_chat(owner, "[X] now has [X.monkeys] monkeys left.") // @@ -393,7 +420,7 @@ var/mob/camera/aiEye/remote/xenobio/E = C.remote_control var/obj/machinery/computer/camera_advanced/xenobio/X = E.origin var/area/mobarea = get_area(S.loc) - if(QDELETED(X.current_potion)) + if(!X.current_potion) to_chat(C, "No potion loaded.") return if(mobarea.name == E.allowed_area || mobarea.xenobiology_compatible) @@ -409,7 +436,7 @@ var/obj/machinery/computer/camera_advanced/xenobio/X = E.origin var/area/mobarea = get_area(S.loc) if(mobarea.name == E.allowed_area || mobarea.xenobiology_compatible) - if(X.stored_slimes.len >= X.max_slimes) + if(length(X.stored_slimes) >= X.max_slimes) to_chat(C, "Slime storage is full.") return if(S.ckey) @@ -417,9 +444,8 @@ return if(S.buckled) S.Feedstop(silent = TRUE) - S.visible_message("[S] vanishes in a flash of light!") - S.forceMove(X) - X.stored_slimes += S + + X.capture_slime(S) //Place slimes /obj/machinery/computer/camera_advanced/xenobio/proc/XenoTurfClickShift(mob/living/user, turf/T) @@ -435,9 +461,7 @@ return else if(turfarea.name == E.allowed_area || turfarea.xenobiology_compatible) for(var/mob/living/simple_animal/slime/S in X.stored_slimes) - S.forceMove(T) - S.visible_message("[S] warps in!") - X.stored_slimes -= S + X.release_slime(S, T) //Place monkey /obj/machinery/computer/camera_advanced/xenobio/proc/XenoTurfClickCtrl(mob/living/user, turf/T) @@ -455,7 +479,7 @@ if(X.monkeys >= 1) var/mob/living/carbon/human/monkey/food = new /mob/living/carbon/human/monkey(T) food.LAssailant = C - X.monkeys -- + X.monkeys-- X.monkeys = round(X.monkeys, 0.1) to_chat(user, "[X] now has [X.monkeys] monkeys left.")