diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 5fd1b9455b0..f8e062a3bc8 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -443,6 +443,20 @@ if(old_turf?.z != new_turf?.z) on_changed_z_level(old_turf, new_turf) + if(HAS_SPATIAL_GRID_CONTENTS(src)) + if(old_turf && new_turf && (old_turf.z != new_turf.z \ + || GET_SPATIAL_INDEX(old_turf.x) != GET_SPATIAL_INDEX(new_turf.x) \ + || GET_SPATIAL_INDEX(old_turf.y) != GET_SPATIAL_INDEX(new_turf.y))) + + SSspatial_grid.exit_cell(src, old_turf) + SSspatial_grid.enter_cell(src, new_turf) + + else if(old_turf && !new_turf) + SSspatial_grid.exit_cell(src, old_turf) + + else if(new_turf && !old_turf) + SSspatial_grid.enter_cell(src, new_turf) + var/datum/light_source/L var/thing for(thing in light_sources) // Cycle through the light sources on this atom and tell them to update. @@ -1307,3 +1321,33 @@ for(var/atom/movable/location as anything in get_nested_locs(src) + src) LAZYREMOVEASSOC(location.important_recursive_contents, RECURSIVE_CONTENTS_AREA_SENSITIVE, src) + +/// Propogates ourselves through our nested contents, similar to other important_recursive_contents procs +/// Main difference is that client contents need to possibly duplicate recursive contents for the clients mob AND its eye +/mob/proc/enable_client_mobs_in_contents() + for(var/atom/movable/movable_loc as anything in get_nested_locs(src) + src) + LAZYINITLIST(movable_loc.important_recursive_contents) + var/list/recursive_contents = movable_loc.important_recursive_contents // blue hedgehog velocity + if(!length(recursive_contents[RECURSIVE_CONTENTS_CLIENT_MOBS])) + SSspatial_grid.add_grid_awareness(movable_loc, SPATIAL_GRID_CONTENTS_TYPE_CLIENTS) + LAZYINITLIST(recursive_contents[RECURSIVE_CONTENTS_CLIENT_MOBS]) + recursive_contents[RECURSIVE_CONTENTS_CLIENT_MOBS] |= src + + var/turf/our_turf = get_turf(src) + /// We got our awareness updated by the important recursive contents stuff, now we add our membership + SSspatial_grid.add_grid_membership(src, our_turf, SPATIAL_GRID_CONTENTS_TYPE_CLIENTS) + +/// Clears the clients channel of this mob +/mob/proc/clear_important_client_contents() + var/turf/our_turf = get_turf(src) + SSspatial_grid.remove_grid_membership(src, our_turf, SPATIAL_GRID_CONTENTS_TYPE_CLIENTS) + + for(var/atom/movable/movable_loc as anything in get_nested_locs(src) + src) + LAZYINITLIST(movable_loc.important_recursive_contents) + var/list/recursive_contents = movable_loc.important_recursive_contents // blue hedgehog velocity + LAZYINITLIST(recursive_contents[RECURSIVE_CONTENTS_CLIENT_MOBS]) + recursive_contents[RECURSIVE_CONTENTS_CLIENT_MOBS] -= src + if(!length(recursive_contents[RECURSIVE_CONTENTS_CLIENT_MOBS])) + SSspatial_grid.remove_grid_awareness(movable_loc, SPATIAL_GRID_CONTENTS_TYPE_CLIENTS) + ASSOC_UNSETEMPTY(recursive_contents, RECURSIVE_CONTENTS_CLIENT_MOBS) + UNSETEMPTY(movable_loc.important_recursive_contents) diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index c62e1fd3fd3..b84c479ae7e 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -484,6 +484,7 @@ holder.owner = null GLOB.admins -= src + mob?.become_uncliented() GLOB.directory -= ckey GLOB.clients -= src #ifdef MULTIINSTANCE diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index ca83ec350b4..40af887e57e 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -1491,6 +1491,19 @@ GLOBAL_LIST_INIT(holy_areas, typecacheof(list( if(.) set_typing_indicator(FALSE) +/// Cleanup proc that's called when a mob loses a client, either through client destroy or logout +/// Logout happens post client del, so we can't just copypaste this there. This keeps things clean and consistent +/mob/proc/become_uncliented() + if(!canon_client) + return + + if(canon_client?.movingmob) + LAZYREMOVE(canon_client.movingmob.client_mobs_in_contents, src) + canon_client.movingmob = null + + clear_important_client_contents() + canon_client = null + ///Makes a call in the context of a different usr. Use sparingly /world/proc/invoke_callback_with_usr(mob/user_mob, datum/callback/invoked_callback, ...) var/temp = usr @@ -1656,4 +1669,3 @@ GLOBAL_LIST_INIT(holy_areas, typecacheof(list( . *= 0.5 if(5 to 6) return 0 - diff --git a/code/modules/mob/mob_login_base.dm b/code/modules/mob/mob_login_base.dm index cbb4a7f043c..e70260a70bf 100644 --- a/code/modules/mob/mob_login_base.dm +++ b/code/modules/mob/mob_login_base.dm @@ -60,6 +60,9 @@ // For us, (1,1,1) is a space tile. This means roughly 200,000! calls to Move() // You do not want this + canon_client = client + enable_client_mobs_in_contents(client) + SEND_SIGNAL(src, COMSIG_MOB_LOGIN) reset_perspective(loc) diff --git a/code/modules/mob/mob_logout_base.dm b/code/modules/mob/mob_logout_base.dm index 3b178e91b80..7f8e5d4b0b9 100644 --- a/code/modules/mob/mob_logout_base.dm +++ b/code/modules/mob/mob_logout_base.dm @@ -22,5 +22,6 @@ GLOB.discord_manager.send2discord_simple(DISCORD_WEBHOOK_MENTOR, "[key_name(src)] logged out - 0 active mentors, [mentorcounter[2]] non-mentor staff, [mentorcounter[3]] inactive mentors.") ..() + become_uncliented() update_morgue() return 1 diff --git a/code/modules/mob/mob_vars.dm b/code/modules/mob/mob_vars.dm index 6ce7f0f8785..d204c7e232e 100644 --- a/code/modules/mob/mob_vars.dm +++ b/code/modules/mob/mob_vars.dm @@ -8,6 +8,11 @@ pressure_resistance = 8 throwforce = 10 var/datum/mind/mind + /// The current client inhabiting this mob. Managed by login/logout + /// This exists so we can do cleanup in logout for occasions where a client was transfere rather then destroyed + /// We need to do this because the mob on logout never actually has a reference to client + /// We also need to clear this var/do other cleanup in client/Destroy, since that happens before logout + var/client/canon_client blocks_emissive = EMISSIVE_BLOCK_GENERIC rad_insulation_beta = RAD_MOB_INSULATION rad_insulation_gamma = RAD_MOB_INSULATION