Files
VMSolidus 201592f6bd Mob Destroy Refactoring (#22573)
Refactoring the entire destroy proc path from Mob Human all the way down
to Atom while trying to find the causes for the damn mob human hard
deletes. This PR comprehensively reorganizes every single stray
snowflake var used by /atom/ all the way to /mob/living/carbon/human,
and makes sure that every var that COULD store a reference, is now
cleared during the entirety of the Mob Destroy() parent hierarchy.

This may very well be the end of the lag war. 

In total, I've hunted down and cleared 39 hanging references between
/atom and /mob/living/carbon/human

---------

Signed-off-by: VMSolidus <evilexecutive@gmail.com>
2026-06-03 15:15:56 +00:00

218 lines
6.7 KiB
Plaintext

/*
Custom click handling
All of this shit should be made redundant by signals and burned to the ground at some point, in the meantime I have updated it
*/
/// Populates `click_handlers` with the default handler if not already defined.
#define SETUP_CLICK_HANDLERS \
if(!click_handlers) { \
click_handlers = new(); \
click_handlers += new/datum/click_handler/default(src) \
}
// In the mob code, because otherwise it's a redefinition
// /mob/Destroy()
// QDEL_LIST(click_handlers)
// return ..()
/// Removes this click handler on `/mob/Logout()`.
var/global/const/CLICK_HANDLER_REMOVE_ON_MOB_LOGOUT = FLAG(0)
/// Removes and prevents creation of the click handler if it is not the active handler for the mob.
var/global/const/CLICK_HANDLER_REMOVE_IF_NOT_TOP = FLAG(1)
/datum/click_handler
/// The mob this click handler is attached to.
var/mob/user
/**
* Bitfield (Any of `CLICK_HANDLER_*`). Relevant flags to control the logic flow of this click handler.
*
* See `code\_onclick\click_handling.dm` for valid options.
*/
var/flags = EMPTY_BITFIELD
/datum/click_handler/New(mob/user)
..()
src.user = user
if (flags & CLICK_HANDLER_REMOVE_ON_MOB_LOGOUT)
RegisterSignal(user, COMSIG_MOB_LOGOUT, PROC_REF(OnMobLogout))
/datum/click_handler/Destroy()
if (flags & CLICK_HANDLER_REMOVE_ON_MOB_LOGOUT)
UnregisterSignal(user, COMSIG_MOB_LOGOUT)
user = null
. = ..()
/**
* Called when the click handler becomes the active entry in the mob's click handlers list. Called by
* `PushClickHandler()` and `RemoveClickHandler()`.
*
* Has no return value.
*/
/datum/click_handler/proc/Enter()
return
/**
* Called when the click handler was active in the mob's click handler list and has been replaced by another handler or
* otherwise removed. Called by `PushClickHandler()` and `RemoveClickHandler()`.
*
* Has no return value.
*/
/datum/click_handler/proc/Exit()
return
/**
* Event proc for `logged_out_event`. Called when the mob logs out and this click handler has the
* `CLICK_HANDLER_REMOVE_ON_MOB_LOGOUT` flag set.
*
* By default, this removes the click handler from the assigned mob.
*
* Has no return value.
*/
/datum/click_handler/proc/OnMobLogout()
user.RemoveClickHandler(src)
/**
* Called on click by `/atom/Click()` when this is the mob's currently active click handler.
*
* **Parameters**:
* - `A` - The atom clicked on.
* - `params` (list of strings) - List of click parameters. See BYOND's `CLick()` documentation.
*
* Has no return value.
*/
/datum/click_handler/proc/OnClick(atom/A, params)
return
/**
* Called on doubleclick by `/atom/DblClick()` when this is the mob's currently active click handler.
*
* **Parameters**:
* - `A` - The atom double clicked on.
* - `params` (list of strings) - List of click parameters. See BYOND's `CLick()` documentation.
*
* Has no return value.
*/
/datum/click_handler/proc/OnDblClick(atom/A, params)
return
/**
* Called on MouseDown by `/client/MouseDown()` when this is the mob's currently active click handler.
*
* **Parameters**:
* - `object` - The atom mouse is underneath.
* - `location` - the turf, stat panel, grid cell, etc. containing the object where it was clicked
* - `params` (list of strings) - List of click parameters. See BYOND's `CLick()` documentation.
*
* Has no return value.
*/
// /datum/click_handler/proc/OnMouseDown(object, location, params) //NOT IMPLEMENTED
// return
/**
* Called on MouseUp by `/client/MouseUp()` when this is the mob's currently active click handler.
*
* **Parameters**:
* - `object` - The atom underneath mouse.
* - `location` - the turf, stat panel, grid cell, etc. containing the object where it was clicked
* - `params` (list of strings) - List of click parameters. See BYOND's `CLick()` documentation.
*
* Has no return value.
*/
// /datum/click_handler/proc/OnMouseUp(object, location, params) //NOT IMPLEMENTED
// return
/datum/click_handler/default/OnClick(atom/A, params)
user.ClickOn(A, params)
/datum/click_handler/default/OnDblClick(atom/A, params)
user.DblClickOn(A, params)
/**
* Returns the mob's currently active click handler.
*
* **Parameters**:
* - `popped_handler`. Not used, should probably be removed?
*/
/mob/proc/GetClickHandler(datum/click_handler/popped_handler)
SETUP_CLICK_HANDLERS
return click_handlers[1]
/**
* Removes the given click handler from `click_handlers`.
*
* This will not remove the protected default handler.
*
* **Parameters**:
* - `click_handler` (Path or instance of `/datum/click_handler`) - The handler to remove. If a path, finds the first
* matching instance of that type.
*
* Returns boolean. Whether or not the click handler was found and removed.
*/
/mob/proc/RemoveClickHandler(datum/click_handler/click_handler)
if(!click_handlers)
return FALSE
if(ispath(click_handler)) // If we were given a path instead of an instance, find the first matching instance by type
// No removing of the default click handler
if(click_handler == /datum/click_handler/default)
return FALSE
click_handler = get_instance_of_strict_type(click_handlers, click_handler)
if(!click_handler)
return FALSE
. = (click_handler in click_handlers)
if(!.)
return
var/was_top = click_handlers[1] == click_handler
if(was_top)
click_handler.Exit()
click_handlers.Remove(click_handler)
qdel(click_handler)
if(!was_top)
return
click_handler = click_handlers[1]
if(click_handler)
click_handler.Enter()
/**
* Pushes the given click handler to the top of the `click_handlers` list, making it the active handler.
*
* **Parameters**:
* - `new_click_handler_type` (Type path - Type of `/datum/click_handler`). The click handler to make active.
*
* Returns boolean. If `TRUE`, the click handler was successfully pushed to the top. Returns `FALSE` if the handler was
* already active.
*/
/mob/proc/PushClickHandler(datum/click_handler/new_click_handler_type)
// No manipulation of the default click handler
if(new_click_handler_type == /datum/click_handler/default)
return FALSE
if ((initial(new_click_handler_type.flags) & CLICK_HANDLER_REMOVE_ON_MOB_LOGOUT) && !client)
return FALSE
SETUP_CLICK_HANDLERS
var/datum/click_handler/click_handler = click_handlers[1]
if(click_handler.type == new_click_handler_type)
return FALSE // If the top click handler is already the same as the desired one, bow out
click_handler.Exit()
if (click_handler.flags & CLICK_HANDLER_REMOVE_IF_NOT_TOP)
click_handlers.Remove(click_handler)
qdel(click_handler)
click_handler = get_instance_of_strict_type(click_handlers, click_handler)
if(click_handler)
click_handlers.Remove(click_handler)
else
click_handler = new new_click_handler_type(src)
click_handlers.Insert(1, click_handler) // Insert new handlers first
click_handler.Enter()
return TRUE
#undef SETUP_CLICK_HANDLERS