Files
Bubberstation/code/datums/components/crate_carrier.dm
SkyratBot 067188d366 [MIRROR] Micro-optimize qdel by only permitting one parameter [MDB IGNORE] (#25889)
* 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.

* Micro-optimize qdel by only permitting one parameter

---------

Co-authored-by: Mothblocks <35135081+Mothblocks@users.noreply.github.com>
2023-12-29 14:41:12 +00:00

86 lines
3.0 KiB
Plaintext

/**
* Component for simplemobs and basicmobs that allow them to carry crates.
*/
/datum/component/crate_carrier
/// The max number of crates we can carry
var/crate_limit = 3
/// Typecache of all the types we can pick up and carry
var/list/carriable_cache
/// A lazylist of all crates we are carrying
var/list/atom/movable/crates_in_hand
/datum/component/crate_carrier/Initialize(crate_limit = 3, list/carriable_types)
. = ..()
if(!isanimal_or_basicmob(parent))
return COMPONENT_INCOMPATIBLE
src.crate_limit = crate_limit
if(carriable_types)
src.carriable_cache = typecacheof(carriable_types)
else
var/static/default_cache = typecacheof(list(/obj/structure/closet/crate))
src.carriable_cache = default_cache
/datum/component/crate_carrier/Destroy(force)
LAZYCLEARLIST(crates_in_hand)
return ..()
/datum/component/crate_carrier/RegisterWithParent()
RegisterSignal(parent, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine))
RegisterSignal(parent, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(on_unarm_attack))
RegisterSignal(parent, COMSIG_LIVING_DEATH, PROC_REF(on_death))
/datum/component/crate_carrier/UnregisterFromParent()
UnregisterSignal(parent, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_LIVING_DEATH, COMSIG_ATOM_EXAMINE))
/// Signal proc for [COMSIG_ATOM_EXAMINE] to show when we're carrying crates
/datum/component/crate_carrier/proc/on_examine(mob/living/source, mob/examiner, list/examine_list)
SIGNAL_HANDLER
var/num_crates = LAZYLEN(crates_in_hand)
if(num_crates > 0)
examine_list += span_notice("[source.p_Theyre()] carrying [num_crates == 1 ? "a crate":"[num_crates] crates"].")
/// Signal proc for [COMSIG_LIVING_UNARMED_ATTACK] to allow mobs to pick up or drop crates
/datum/component/crate_carrier/proc/on_unarm_attack(mob/living/source, atom/target, proximity, modifiers)
SIGNAL_HANDLER
if(source.combat_mode)
return
if(is_type_in_typecache(target, carriable_cache))
var/atom/movable/movable_target = target
if(LAZYLEN(crates_in_hand) >= crate_limit)
source.balloon_alert(source, "too many crates!")
return COMPONENT_CANCEL_ATTACK_CHAIN
for(var/mob/living/inside_mob in movable_target.get_all_contents())
if(inside_mob.mob_size < MOB_SIZE_HUMAN)
continue
source.balloon_alert(source, "crate too heavy!")
return COMPONENT_CANCEL_ATTACK_CHAIN
LAZYADD(crates_in_hand, target)
movable_target.forceMove(source)
source.balloon_alert(source, "grabbed crate")
return COMPONENT_CANCEL_ATTACK_CHAIN
if(isopenturf(target) && LAZYLEN(crates_in_hand))
drop_all_crates(target)
source.balloon_alert(source, "dropped crate")
return COMPONENT_CANCEL_ATTACK_CHAIN
/// Signal proc for [COMSIG_LIVING_DEATH], so we drop crates on death or gib
/datum/component/crate_carrier/proc/on_death(mob/living/source, gibbed)
SIGNAL_HANDLER
drop_all_crates(source.drop_location())
/// Drops all the crates in our crate list.
/datum/component/crate_carrier/proc/drop_all_crates(atom/drop_to)
for(var/obj/structure/closet/crate/held_crate as anything in crates_in_hand)
held_crate.forceMove(drop_to)
LAZYREMOVE(crates_in_hand, held_crate)