From 38fe6e505247fb0edf7346680446619482f64388 Mon Sep 17 00:00:00 2001 From: SkyratBot <59378654+SkyratBot@users.noreply.github.com> Date: Tue, 14 Nov 2023 23:15:41 +0100 Subject: [PATCH] [MIRROR] Further Prevention of Disposals Qdeletion [MDB IGNORE] (#25015) * Further Prevention of Disposals Qdeletion (#79714) ## About The Pull Request Fixes the consequences of #79629 - Verdict is still out on what the root issue is This has been an issue for the last two years and everything I go bananas trying to get a consistent reproduction case to figure out the root issue. After three session of picking, I think it's just a consequence of certain thing in disposals code sleeping due to `addtimer()` and whatnot so I'm just throwing in the towel and just making it so we stop sending atoms to nullspace for no reason. `target_turf` is typically always a present arg, but regardless we are guaranteed to get a valid turf to send people to instead of the deleted mob room. We still `stack_trace()` whenever this happens, so tracking this issue doesn't change any more than the present status quo- we just don't keep torturing mobs by sending them to the shadow realm. ## Why It's Good For The Game One day we'll figure out why we keep getting `null` passed into `forceMove()` like this but today is not that day. i know turfs technically can't be deleted but it's just there as a safety since we nullcheck anyways (which is the whole point of this fix). Let's just stop screwing with players for the time being also the code looks much better ## Changelog :cl: fix: Safeties in the code have been added to prevent things in disposals going into nullspace whenever they get ejected from a pipe - you will just magically spawn at the turf that you were meant to be flung towards. /:cl: * Further Prevention of Disposals Qdeletion --------- Co-authored-by: san7890 --- code/modules/recycling/disposal/eject.dm | 38 ++++++++++++++++++----- code/modules/recycling/disposal/outlet.dm | 4 +-- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/code/modules/recycling/disposal/eject.dm b/code/modules/recycling/disposal/eject.dm index febd4f5d604..523f034703c 100644 --- a/code/modules/recycling/disposal/eject.dm +++ b/code/modules/recycling/disposal/eject.dm @@ -2,11 +2,33 @@ * General proc used to expel a holder's contents through src (for bins holder is also the src). */ /obj/proc/pipe_eject(obj/holder, direction, throw_em = TRUE, turf/target, throw_range = 5, throw_speed = 1) - var/turf/src_T = get_turf(src) - for(var/A in holder) - var/atom/movable/AM = A - AM.forceMove(src_T) - SEND_SIGNAL(AM, COMSIG_MOVABLE_PIPE_EJECTING, direction) - if(throw_em && !QDELETED(AM)) - var/turf/T = target || get_offset_target_turf(loc, rand(5)-rand(5), rand(5)-rand(5)) - AM.throw_at(T, throw_range, throw_speed) + var/turf/origin_turf = get_turf(src) + var/turf/target_turf + if(isnull(target)) // done up here as a safety + target_turf = get_offset_target_turf(loc, rand(5) - rand(5), rand(5) - rand(5)) + else + target_turf = target + + if(QDELETED(origin_turf)) + stack_trace("pipe_eject() attempted to operate on a qdeleted turf! In order to avoid sending things to nullspace, we are going to send everything directly to the target turf instead.") + origin_turf = target_turf + + var/list/contents_to_eject = holder.contents + var/list/contents_to_throw = list() + + for(var/atom/movable/thing in contents_to_eject) + thing.forceMove(origin_turf) + SEND_SIGNAL(thing, COMSIG_MOVABLE_PIPE_EJECTING, direction) + if(QDELETED(thing)) + continue + + contents_to_throw += thing + + if(!throw_em) + return + + for(var/atom/movable/throwable as anything in contents_to_throw) + if(isnull(target)) // we want the thrown things to be spread out a bit if we weren't given a target + target_turf = get_offset_target_turf(loc, rand(5) - rand(5), rand(5) - rand(5)) + + throwable.throw_at(target_turf, throw_range, throw_speed) diff --git a/code/modules/recycling/disposal/outlet.dm b/code/modules/recycling/disposal/outlet.dm index 4327567fb17..513a263160d 100644 --- a/code/modules/recycling/disposal/outlet.dm +++ b/code/modules/recycling/disposal/outlet.dm @@ -60,9 +60,9 @@ if((start_eject + 30) < world.time) start_eject = world.time playsound(src, 'sound/machines/warning-buzzer.ogg', 50, FALSE, FALSE) - addtimer(CALLBACK(src, PROC_REF(expel_holder), H, TRUE), 20) + addtimer(CALLBACK(src, PROC_REF(expel_holder), H, TRUE), 2 SECONDS) else - addtimer(CALLBACK(src, PROC_REF(expel_holder), H), 20) + addtimer(CALLBACK(src, PROC_REF(expel_holder), H), 2 SECONDS) /obj/structure/disposaloutlet/proc/expel_holder(obj/structure/disposalholder/H, playsound=FALSE) if(playsound)