Files
Bubberstation/code/datums/components/magnet.dm
Mothblocks c1d68698fb Micro-optimize qdel by only permitting one parameter (#80628)
Productionizes #80615.

The core optimization is this:

```patch
-	var/hint = to_delete.Destroy(arglist(args.Copy(2))) // Let our friend know they're about to get fucked up.
+	var/hint = to_delete.Destroy(force) // Let our friend know they're about to get fucked up.
```

We avoid a heap allocation in the form of copying the args over to a new
list. A/B testing shows this results in 33% better overtime, and in a
real round shaving off a full second of self time and 0.4 seconds of
overtime--both of these would be doubled in the event this is merged as
the new proc was only being run 50% of the time.
2023-12-28 13:52:44 -08:00

71 lines
2.0 KiB
Plaintext

/// Attracts items of a certain typepath
/datum/component/magnet
/// Range at which to pull items
var/pull_range
/// List of things we attract
var/list/attracted_typecache
/// What to do when we pull something
var/datum/callback/on_pulled
/// What to do when something reaches us
var/datum/callback/on_contact
/// Are we currently working?
var/active = TRUE
/datum/component/magnet/Initialize(
pull_range = 5,
attracted_typecache = list(/obj/item/kitchen/spoon, /obj/item/kitchen/fork, /obj/item/knife),
on_pulled,
on_contact,
)
. = ..()
if (!length(attracted_typecache))
CRASH("Attempted to instantiate a [src] on [parent] which does not do anything.")
if (!isatom(parent))
return COMPONENT_INCOMPATIBLE
src.pull_range = pull_range
src.attracted_typecache = typecacheof(attracted_typecache)
src.on_pulled = on_pulled
src.on_contact = on_contact
/datum/component/magnet/RegisterWithParent()
. = ..()
START_PROCESSING(SSdcs, src)
if (!isliving(parent))
return
RegisterSignal(parent, COMSIG_MOB_STATCHANGE, PROC_REF(toggle_on_stat_change))
/datum/component/magnet/UnregisterFromParent()
. = ..()
STOP_PROCESSING(SSdcs, src)
UnregisterSignal(parent, COMSIG_MOB_STATCHANGE)
/datum/component/magnet/Destroy(force)
STOP_PROCESSING(SSdcs, src)
on_pulled = null
on_contact = null
return ..()
/// If a mob dies we stop attracting stuff
/datum/component/magnet/proc/toggle_on_stat_change(mob/living/source)
SIGNAL_HANDLER
if (source.stat == DEAD)
STOP_PROCESSING(SSdcs, src)
else
START_PROCESSING(SSdcs, src)
/datum/component/magnet/process(seconds_per_tick)
for (var/atom/movable/thing in orange(pull_range, parent))
if (!is_type_in_typecache(thing, attracted_typecache))
continue
var/range = get_dist(thing, parent)
if (range == 0)
continue
if (range == 1 && !isnull(on_contact))
on_contact.Invoke(thing)
continue
var/moved = thing.Move(get_step_towards(thing, parent))
if (moved && !isnull(on_pulled))
on_pulled.Invoke(thing)
CHECK_TICK