From fbf85402e3d487c4a89301d2a3f55f9ddad2bcb9 Mon Sep 17 00:00:00 2001 From: Charlie Nolan Date: Sat, 25 Jan 2025 16:53:52 -0800 Subject: [PATCH] Refactor /proc/get_mobs_in_view for speed (#28102) --- code/__HELPERS/game.dm | 43 +++++++++++++++++------------------------- 1 file changed, 17 insertions(+), 26 deletions(-) diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index 2031313ff54..0fd276eafaa 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -145,32 +145,23 @@ turfs += T return turfs - -//GLOBAL_VAR_INIT(debug_mob, 0) - -// Will recursively loop through an atom's contents and check for mobs, then it will loop through every atom in that atom's contents. -// It will keep doing this until it checks every content possible. This will fix any problems with mobs, that are inside objects, -// being unable to hear people due to being in a box within a bag. - -/proc/recursive_mob_check(atom/O, list/L = list(), recursion_limit = 3, client_check = TRUE, sight_check = TRUE) - if(!recursion_limit) - return L - for(var/atom/A in O.contents) - if(ismob(A)) - var/mob/M = A - if(client_check && !M.client) - L |= recursive_mob_check(A, L, recursion_limit - 1, client_check, sight_check) +/// Recursively loops through the contents of this atom looking for mobs, optionally requiring them to have a client. +/proc/collect_nested_mobs(atom/parent, list/mobs, recursion_limit = 3, client_check = TRUE) + var/list/next_layer = list(parent) + for(var/depth in 1 to recursion_limit) + var/list/layer = next_layer + next_layer = list() + for(var/thing in layer) + if(!ismob(thing)) continue - if(sight_check && !isInSight(A, O)) - continue - L |= M - for(var/mob/dead/observer/ghost in M.observers) - L |= ghost - //log_world("[recursion_limit] = [M] - [get_turf(M)] - ([M.x], [M.y], [M.z])") - - if(isobj(A) || ismob(A)) - L |= recursive_mob_check(A, L, recursion_limit - 1, client_check, sight_check) - return L + var/mob/this_mob = thing + if(!client_check || this_mob.client) + mobs += this_mob + for(var/mob/dead/observer/ghost in this_mob.observers) + if(!client_check || ghost.client) + mobs += ghost + if(!length(next_layer)) + return // The old system would loop through lists for a total of 5000 per function call, in an empty server. // This new system will loop at around 1000 in an empty server. @@ -195,7 +186,7 @@ hear += M if(isobj(A) || ismob(A)) - hear |= recursive_mob_check(A, hear, 3, TRUE, FALSE) + collect_nested_mobs(A, hear, 3, !include_clientless) return hear