From 169c42a262316184e5602386cf435d934f6533ce Mon Sep 17 00:00:00 2001 From: SkyratBot <59378654+SkyratBot@users.noreply.github.com> Date: Tue, 17 Aug 2021 21:29:11 +0200 Subject: [PATCH] [MIRROR] Refactors connect_loc_behalf into a component (#7613) * Refactors connect_loc_behalf into a component (#60678) See title. Also refactors caltrops into a component because they use connect_loc_behalf which requires them to hold the state. This also fixes COMPONENT_DUPE_SELECTIVE from just outright not working. connect_loc_behalf doesn't make sense as an element because it tries to hold states. There is also no way to maintain current behaviour and not have the states that it needs. Due to the fact that it tries to hold states, it means the code itself is a lot more buggy because it's a lot harder to successfully manage these states without runtimes or bugs. On metastation, there is only 2519 connect_loc_behalf components at roundstart. MrStonedOne has told me that datums take up this much space: image If we do the (oversimplified) math, there are only ever 5 variables that'll likely be changed on most connect_loc_behalf components at runtime: connections, tracked, signal_atom, parent, signal_procs This means that on metastation at roundstart, we take up this amount: (24 + 16 * 5) * 2519 = 261.97600 kilobytes This is not really significant and the benefits of moving this to a component greatly outweighs the memory cost. (Basically the memory cost is outweighed by the maint cost of tracking down issues with the thing. It's too buggy to be viable longterm basically) * Update glass.dm Co-authored-by: Watermelon914 <37270891+Watermelon914@users.noreply.github.com> Co-authored-by: Gandalf --- code/datums/ai/monkey/monkey_controller.dm | 8 +- code/datums/components/_component.dm | 24 ++--- code/datums/components/butchering.dm | 3 +- .../{elements => components}/caltrop.dm | 27 +++--- code/datums/components/connect_loc_behalf.dm | 81 +++++++++++++++++ code/datums/components/food/edible.dm | 3 +- code/datums/components/infective.dm | 3 +- code/datums/components/pellet_cloud.dm | 3 +- code/datums/components/rot.dm | 6 +- code/datums/components/singularity.dm | 4 +- code/datums/components/slippery.dm | 32 ++++--- .../{elements => components}/squashable.dm | 4 +- code/datums/components/squeak.dm | 5 +- code/datums/components/swarming.dm | 3 +- code/datums/elements/connect_loc.dm | 91 ------------------- .../objects/effects/decals/cleanable/misc.dm | 2 +- code/game/objects/items/dice.dm | 2 +- .../game/objects/items/stacks/sheets/glass.dm | 2 +- code/modules/assembly/mousetrap.dm | 4 +- code/modules/hydroponics/grown/towercap.dm | 2 +- code/modules/mining/lavaland/ash_flora.dm | 2 +- .../living/simple_animal/hostile/cockroach.dm | 2 +- code/modules/power/lighting.dm | 2 +- .../modules/materials_glass/glass.dm | 2 +- tgstation.dme | 5 +- 25 files changed, 164 insertions(+), 158 deletions(-) rename code/datums/{elements => components}/caltrop.dm (78%) create mode 100644 code/datums/components/connect_loc_behalf.dm rename code/datums/{elements => components}/squashable.dm (94%) diff --git a/code/datums/ai/monkey/monkey_controller.dm b/code/datums/ai/monkey/monkey_controller.dm index 921a7b93d28..b2c3be20cda 100644 --- a/code/datums/ai/monkey/monkey_controller.dm +++ b/code/datums/ai/monkey/monkey_controller.dm @@ -54,25 +54,25 @@ have ways of interacting with a specific mob and control it. RegisterSignal(new_pawn, COMSIG_MOB_MOVESPEED_UPDATED, .proc/update_movespeed) RegisterSignal(new_pawn, COMSIG_FOOD_EATEN, .proc/on_eat) - AddElement(/datum/element/connect_loc_behalf, new_pawn, loc_connections) + AddComponent(/datum/component/connect_loc_behalf, new_pawn, loc_connections) movement_delay = living_pawn.cached_multiplicative_slowdown return ..() //Run parent at end /datum/ai_controller/monkey/UnpossessPawn(destroy) UnregisterSignal(pawn, list(COMSIG_PARENT_ATTACKBY, COMSIG_ATOM_ATTACK_HAND, COMSIG_ATOM_ATTACK_PAW, COMSIG_ATOM_BULLET_ACT, COMSIG_ATOM_HITBY, COMSIG_LIVING_START_PULL,\ COMSIG_LIVING_TRY_SYRINGE, COMSIG_ATOM_HULK_ATTACK, COMSIG_CARBON_CUFF_ATTEMPTED, COMSIG_MOB_MOVESPEED_UPDATED, COMSIG_ATOM_ATTACK_ANIMAL, COMSIG_MOB_ATTACK_ALIEN)) - RemoveElement(/datum/element/connect_loc_behalf, pawn, loc_connections) + qdel(GetComponent(/datum/component/connect_loc_behalf)) return ..() //Run parent at end // Stops sentient monkeys from being knocked over like weak dunces. /datum/ai_controller/monkey/on_sentience_gained() . = ..() - RemoveElement(/datum/element/connect_loc_behalf, pawn, loc_connections) + qdel(GetComponent(/datum/component/connect_loc_behalf)) /datum/ai_controller/monkey/on_sentience_lost() . = ..() - AddElement(/datum/element/connect_loc_behalf, pawn, loc_connections) + AddComponent(/datum/component/connect_loc_behalf, pawn, loc_connections) /datum/ai_controller/monkey/able_to_run() . = ..() diff --git a/code/datums/components/_component.dm b/code/datums/components/_component.dm index 785b78c4ee9..a0dab5ac16c 100644 --- a/code/datums/components/_component.dm +++ b/code/datums/components/_component.dm @@ -417,7 +417,7 @@ raw_args[1] = src - if(dm != COMPONENT_DUPE_ALLOWED) + if(dm != COMPONENT_DUPE_ALLOWED && dm != COMPONENT_DUPE_SELECTIVE) if(!dt) old_comp = GetExactComponent(nt) else @@ -443,19 +443,19 @@ old_comp.InheritComponent(arglist(arguments)) else old_comp.InheritComponent(new_comp, TRUE) - if(COMPONENT_DUPE_SELECTIVE) - var/list/arguments = raw_args.Copy() - arguments[1] = new_comp - var/make_new_component = TRUE - for(var/datum/component/existing_component as anything in GetComponents(new_type)) - if(existing_component.CheckDupeComponent(arglist(arguments))) - make_new_component = FALSE - QDEL_NULL(new_comp) - break - if(!new_comp && make_new_component) - new_comp = new nt(raw_args) else if(!new_comp) new_comp = new nt(raw_args) // There's a valid dupe mode but there's no old component, act like normal + else if(dm == COMPONENT_DUPE_SELECTIVE) + var/list/arguments = raw_args.Copy() + arguments[1] = new_comp + var/make_new_component = TRUE + for(var/datum/component/existing_component as anything in GetComponents(new_type)) + if(existing_component.CheckDupeComponent(arglist(arguments))) + make_new_component = FALSE + QDEL_NULL(new_comp) + break + if(!new_comp && make_new_component) + new_comp = new nt(raw_args) else if(!new_comp) new_comp = new nt(raw_args) // Dupes are allowed, act like normal diff --git a/code/datums/components/butchering.dm b/code/datums/components/butchering.dm index 147a99ea274..1ac3d15eddf 100644 --- a/code/datums/components/butchering.dm +++ b/code/datums/components/butchering.dm @@ -137,6 +137,7 @@ ///Special snowflake component only used for the recycler. /datum/component/butchering/recycler + /datum/component/butchering/recycler/Initialize(_speed, _effectiveness, _bonus_modifier, _butcher_sound, disabled, _can_be_blunt) if(!istype(parent, /obj/machinery/recycler)) //EWWW return COMPONENT_INCOMPATIBLE @@ -147,7 +148,7 @@ var/static/list/loc_connections = list( COMSIG_ATOM_ENTERED = .proc/on_entered, ) - AddElement(/datum/element/connect_loc_behalf, parent, loc_connections) + AddComponent(/datum/component/connect_loc_behalf, parent, loc_connections) /datum/component/butchering/recycler/proc/on_entered(datum/source, atom/movable/arrived, atom/old_loc, list/atom/old_locs) SIGNAL_HANDLER diff --git a/code/datums/elements/caltrop.dm b/code/datums/components/caltrop.dm similarity index 78% rename from code/datums/elements/caltrop.dm rename to code/datums/components/caltrop.dm index 4b6078f8979..3d4dcb8146c 100644 --- a/code/datums/elements/caltrop.dm +++ b/code/datums/components/caltrop.dm @@ -3,10 +3,7 @@ * * Used for broken glass, cactuses and four sided dice. */ -/datum/element/caltrop - element_flags = ELEMENT_BESPOKE | ELEMENT_DETACH - id_arg_index = 2 - +/datum/component/caltrop ///Minimum damage done when crossed var/min_damage @@ -27,10 +24,11 @@ COMSIG_ATOM_ENTERED = .proc/on_entered, ) -/datum/element/caltrop/Attach(datum/target, min_damage = 0, max_damage = 0, probability = 100, flags = NONE, soundfile = null) + +/datum/component/caltrop/Initialize(min_damage = 0, max_damage = 0, probability = 100, flags = NONE, soundfile = null) . = ..() - if(!isatom(target)) - return ELEMENT_INCOMPATIBLE + if(!isatom(parent)) + return COMPONENT_INCOMPATIBLE src.min_damage = min_damage src.max_damage = max(min_damage, max_damage) @@ -38,12 +36,12 @@ src.flags = flags src.soundfile = soundfile - if(ismovable(target)) - AddElement(/datum/element/connect_loc_behalf, target, crossed_connections) + if(ismovable(parent)) + AddComponent(/datum/component/connect_loc_behalf, parent, crossed_connections) else - RegisterSignal(get_turf(target), COMSIG_ATOM_ENTERED, .proc/on_entered) + RegisterSignal(get_turf(parent), COMSIG_ATOM_ENTERED, .proc/on_entered) -/datum/element/caltrop/proc/on_entered(datum/source, atom/movable/arrived, atom/old_loc, list/atom/old_locs) +/datum/component/caltrop/proc/on_entered(datum/source, atom/movable/arrived, atom/old_loc, list/atom/old_locs) SIGNAL_HANDLER if(!prob(probability)) @@ -106,7 +104,6 @@ return playsound(H, soundfile, 15, TRUE, -3) -/datum/element/caltrop/Detach(datum/target) - . = ..() - if(ismovable(target)) - RemoveElement(/datum/element/connect_loc_behalf, target, crossed_connections) +/datum/component/caltrop/UnregisterFromParent() + if(ismovable(parent)) + qdel(GetComponent(/datum/component/connect_loc_behalf)) diff --git a/code/datums/components/connect_loc_behalf.dm b/code/datums/components/connect_loc_behalf.dm new file mode 100644 index 00000000000..7ab338fe33d --- /dev/null +++ b/code/datums/components/connect_loc_behalf.dm @@ -0,0 +1,81 @@ +/// This component behaves similar to connect_loc, hooking into a signal on a tracked object's turf +/// It has the ability to react to that signal on behalf of a seperate listener however +/// This has great use, primarially for components, but it carries with it some overhead +/// So we do it seperately as it needs to hold state which is very likely to lead to bugs if it remains as an element. +/datum/component/connect_loc_behalf + dupe_mode = COMPONENT_DUPE_UNIQUE + + /// An assoc list of signal -> procpath to register to the loc this object is on. + var/list/connections + + var/atom/movable/tracked + + var/atom/tracked_loc + +/datum/component/connect_loc_behalf/Initialize(atom/movable/tracked, list/connections) + . = ..() + if (!istype(tracked)) + return COMPONENT_INCOMPATIBLE + src.connections = connections + src.tracked = tracked + +/datum/component/connect_loc_behalf/CheckDupeComponent(datum/component/component, atom/movable/tracked, list/connections) + if(src.tracked != tracked) + return FALSE + + // Not equivalent. Checks if they are not the same list via shallow comparison. + if(!compare_list(src.connections, connections)) + return FALSE + + return TRUE + + +/datum/component/connect_loc_behalf/RegisterWithParent() + RegisterSignal(tracked, COMSIG_MOVABLE_MOVED, .proc/on_moved) + RegisterSignal(tracked, COMSIG_PARENT_QDELETING, .proc/handle_tracked_qdel) + update_signals() + +/datum/component/connect_loc_behalf/UnregisterFromParent() + unregister_signals() + UnregisterSignal(tracked, list( + COMSIG_MOVABLE_MOVED, + COMSIG_PARENT_QDELETING, + )) + + tracked = null + +/datum/component/connect_loc_behalf/proc/handle_tracked_qdel() + SIGNAL_HANDLER + qdel(src) + +/datum/component/connect_loc_behalf/proc/update_signals() + unregister_signals() + //You may ask yourself, isn't this just silencing an error? + //The answer is yes, but there's no good cheap way to fix it + //What happens is the tracked object or hell the listener gets say, deleted, which makes targets[old_loc] return a null + //The null results in a bad index, because of course it does + //It's not a solvable problem though, since both actions, the destroy and the move, are sourced from the same signal send + //And sending a signal should be agnostic of the order of listeners + //So we need to either pick the order agnositic, or destroy safe + //And I picked destroy safe. Let's hope this is the right path! + if(isnull(tracked.loc)) + return + + tracked_loc = tracked.loc + + for (var/signal in connections) + parent.RegisterSignal(tracked_loc, signal, connections[signal]) + +/datum/component/connect_loc_behalf/proc/unregister_signals() + if(isnull(tracked_loc)) + return + + for (var/signal in connections) + parent.UnregisterSignal(tracked_loc, signal) + + tracked_loc = null + +/datum/component/connect_loc_behalf/proc/on_moved(sigtype, atom/movable/tracked, atom/old_loc) + SIGNAL_HANDLER + update_signals() + diff --git a/code/datums/components/food/edible.dm b/code/datums/components/food/edible.dm index 5d3368aeccc..b9208a6557c 100644 --- a/code/datums/components/food/edible.dm +++ b/code/datums/components/food/edible.dm @@ -45,6 +45,7 @@ Behavior that's still missing from this component that original food items had t ///The type of atom this creates when the object is microwaved. var/atom/microwaved_type + /datum/component/edible/Initialize( list/initial_reagents, food_flags = NONE, @@ -73,7 +74,7 @@ Behavior that's still missing from this component that original food items had t var/static/list/loc_connections = list( COMSIG_ATOM_ENTERED = .proc/on_entered, ) - AddElement(/datum/element/connect_loc_behalf, parent, loc_connections) + AddComponent(/datum/component/connect_loc_behalf, parent, loc_connections) if(isitem(parent)) RegisterSignal(parent, COMSIG_ITEM_ATTACK, .proc/UseFromHand) diff --git a/code/datums/components/infective.dm b/code/datums/components/infective.dm index eab7b3c974a..3656f9eb388 100644 --- a/code/datums/components/infective.dm +++ b/code/datums/components/infective.dm @@ -3,6 +3,7 @@ var/expire_time var/required_clean_types = CLEAN_TYPE_DISEASE + /datum/component/infective/Initialize(list/datum/disease/_diseases, expire_in) if(islist(_diseases)) diseases = _diseases @@ -18,7 +19,7 @@ var/static/list/disease_connections = list( COMSIG_ATOM_ENTERED = .proc/try_infect_crossed, ) - AddElement(/datum/element/connect_loc_behalf, parent, disease_connections) + AddComponent(/datum/component/connect_loc_behalf, parent, disease_connections) RegisterSignal(parent, COMSIG_COMPONENT_CLEAN_ACT, .proc/clean) RegisterSignal(parent, COMSIG_MOVABLE_BUCKLE, .proc/try_infect_buckle) diff --git a/code/datums/components/pellet_cloud.dm b/code/datums/components/pellet_cloud.dm index fea55d23107..15bd6a62111 100644 --- a/code/datums/components/pellet_cloud.dm +++ b/code/datums/components/pellet_cloud.dm @@ -53,6 +53,7 @@ /// for if we're an ammo casing being fired var/mob/living/shooter + /datum/component/pellet_cloud/Initialize(projectile_type=/obj/item/shrapnel, magnitude=5) if(!isammocasing(parent) && !isgrenade(parent) && !islandmine(parent) && !issupplypod(parent) && !ishorrorling(parent)) //SKYRAT EDIT CHANGE: if(!isammocasing(parent) && !isgrenade(parent) && !islandmine(parent) && !issupplypod(parent)) return COMPONENT_INCOMPATIBLE @@ -339,7 +340,7 @@ var/static/list/loc_connections = list( COMSIG_ATOM_EXITED =.proc/grenade_uncrossed, ) - AddElement(/datum/element/connect_loc_behalf, parent, loc_connections) + AddComponent(/datum/component/connect_loc_behalf, parent, loc_connections) /// Someone dropped the grenade, so set them to the shooter in case they're on top of it when it goes off /datum/component/pellet_cloud/proc/grenade_dropped(obj/item/nade, mob/living/slick_willy) diff --git a/code/datums/components/rot.dm b/code/datums/components/rot.dm index a5545a0caff..c8a2d04e83e 100644 --- a/code/datums/components/rot.dm +++ b/code/datums/components/rot.dm @@ -21,6 +21,8 @@ COMSIG_ATOM_ENTERED = .proc/on_entered, ) + + /datum/component/rot/Initialize(delay, scaling, severity) if(!isatom(parent)) return COMPONENT_INCOMPATIBLE @@ -37,7 +39,7 @@ RegisterSignal(parent, list(COMSIG_ATOM_HULK_ATTACK, COMSIG_ATOM_ATTACK_ANIMAL, COMSIG_ATOM_ATTACK_HAND), .proc/rot_react_touch) RegisterSignal(parent, COMSIG_PARENT_ATTACKBY, .proc/rot_hit_react) if(ismovable(parent)) - AddElement(/datum/element/connect_loc_behalf, parent, loc_connections) + AddComponent(/datum/component/connect_loc_behalf, parent, loc_connections) RegisterSignal(parent, COMSIG_MOVABLE_BUMP, .proc/rot_react) if(isliving(parent)) RegisterSignal(parent, COMSIG_LIVING_REVIVE, .proc/react_to_revive) //mobs stop this when they come to life @@ -60,7 +62,7 @@ /datum/component/rot/UnregisterFromParent() . = ..() if(ismovable(parent)) - RemoveElement(/datum/element/connect_loc_behalf, parent, loc_connections) + qdel(GetComponent(/datum/component/connect_loc_behalf)) ///One of two procs that modifies blockers, this one handles removing a blocker and potentially restarting the rot /datum/component/rot/proc/start_up(blocker_type) diff --git a/code/datums/components/singularity.dm b/code/datums/components/singularity.dm index b5899b426b6..96fc734b7d8 100644 --- a/code/datums/components/singularity.dm +++ b/code/datums/components/singularity.dm @@ -40,6 +40,8 @@ /// If specified, the singularity will slowly move to this target var/atom/target + + /datum/component/singularity/Initialize( bsa_targetable = TRUE, consume_range = 0, @@ -85,7 +87,7 @@ var/static/list/loc_connections = list( COMSIG_ATOM_ENTERED = .proc/on_entered, ) - AddElement(/datum/element/connect_loc_behalf, parent, loc_connections) + AddComponent(/datum/component/connect_loc_behalf, parent, loc_connections) RegisterSignal(parent, COMSIG_ATOM_BULLET_ACT, .proc/consume_bullets) diff --git a/code/datums/components/slippery.dm b/code/datums/components/slippery.dm index 5c2ca25fe35..d594dff9483 100644 --- a/code/datums/components/slippery.dm +++ b/code/datums/components/slippery.dm @@ -25,6 +25,9 @@ COMSIG_ATOM_ENTERED = .proc/Slip_on_wearer, ) + /// The connect_loc_behalf component for the holder_connections list. + var/datum/weakref/holder_connect_loc_behalf + /datum/component/slippery/Initialize(knockdown, lube_flags = NONE, datum/callback/callback, paralyze, force_drop = FALSE, slot_whitelist) src.knockdown_time = max(knockdown, 0) src.paralyze_time = max(paralyze, 0) @@ -33,15 +36,19 @@ src.callback = callback if(slot_whitelist) src.slot_whitelist = slot_whitelist - if(ismovable(parent)) - AddElement(/datum/element/connect_loc_behalf, parent, default_connections) - if(isitem(parent)) - RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, .proc/on_equip) - RegisterSignal(parent, COMSIG_ITEM_DROPPED, .proc/on_drop) + add_connect_loc_behalf_to_parent() + if(ismovable(parent)) + if(isitem(parent)) + RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, .proc/on_equip) + RegisterSignal(parent, COMSIG_ITEM_DROPPED, .proc/on_drop) else RegisterSignal(parent, COMSIG_ATOM_ENTERED, .proc/Slip) +/datum/component/slippery/proc/add_connect_loc_behalf_to_parent() + if(ismovable(parent)) + AddComponent(/datum/component/connect_loc_behalf, parent, default_connections) + /datum/component/slippery/InheritComponent(datum/component/slippery/component, i_am_original, knockdown, lube_flags = NONE, datum/callback/callback, paralyze, force_drop = FALSE, slot_whitelist) if(component) knockdown = component.knockdown_time @@ -86,7 +93,8 @@ if((!LAZYLEN(slot_whitelist) || (slot in slot_whitelist)) && isliving(equipper)) holder = equipper - AddElement(/datum/element/connect_loc_behalf, holder, holder_connections) + qdel(GetComponent(/datum/component/connect_loc_behalf)) + AddComponent(/datum/component/connect_loc_behalf, holder, holder_connections) RegisterSignal(holder, COMSIG_PARENT_PREQDELETED, .proc/holder_deleted) /* @@ -113,9 +121,11 @@ SIGNAL_HANDLER UnregisterSignal(user, COMSIG_PARENT_PREQDELETED) - if(holder) - RemoveElement(/datum/element/connect_loc_behalf, holder, holder_connections) - holder = null + + qdel(GetComponent(/datum/component/connect_loc_behalf)) + add_connect_loc_behalf_to_parent() + + holder = null /* * The slip proc, but for equipped items. @@ -132,9 +142,7 @@ /datum/component/slippery/UnregisterFromParent() . = ..() - if(holder) - RemoveElement(/datum/element/connect_loc_behalf, holder, holder_connections) - RemoveElement(/datum/element/connect_loc_behalf, parent, default_connections) + qdel(GetComponent(/datum/component/connect_loc_behalf)) /// Used for making the clown PDA only slip if the clown is wearing his shoes and the elusive banana-skin belt /datum/component/slippery/clowning diff --git a/code/datums/elements/squashable.dm b/code/datums/components/squashable.dm similarity index 94% rename from code/datums/elements/squashable.dm rename to code/datums/components/squashable.dm index 92d0b5e6aa4..ce0e91533e2 100644 --- a/code/datums/elements/squashable.dm +++ b/code/datums/components/squashable.dm @@ -27,7 +27,7 @@ if(!src.on_squash_callback && squash_callback) on_squash_callback = CALLBACK(parent, squash_callback) - AddElement(/datum/element/connect_loc_behalf, parent, loc_connections) + AddComponent(/datum/component/connect_loc_behalf, parent, loc_connections) ///Handles the squashing of the mob /datum/component/squashable/proc/on_entered(turf/source_turf, atom/movable/crossing_movable) @@ -72,4 +72,4 @@ /datum/component/squashable/UnregisterFromParent() . = ..() - RemoveElement(/datum/element/connect_loc_behalf, parent, loc_connections) + qdel(GetComponent(/datum/component/connect_loc_behalf)) diff --git a/code/datums/components/squeak.dm b/code/datums/components/squeak.dm index ce7478d6990..b07e2bd6ff4 100644 --- a/code/datums/components/squeak.dm +++ b/code/datums/components/squeak.dm @@ -26,6 +26,7 @@ COMSIG_ATOM_ENTERED = .proc/play_squeak_crossed, ) + /datum/component/squeak/Initialize(custom_sounds, volume_override, chance_override, step_delay_override, use_delay_override, extrarange, falloff_exponent, fallof_distance) if(!isatom(parent)) return COMPONENT_INCOMPATIBLE @@ -33,7 +34,7 @@ if(ismovable(parent)) RegisterSignal(parent, list(COMSIG_MOVABLE_BUMP, COMSIG_MOVABLE_IMPACT, COMSIG_PROJECTILE_BEFORE_FIRE), .proc/play_squeak) - AddElement(/datum/element/connect_loc_behalf, parent, item_connections) + AddComponent(/datum/component/connect_loc_behalf, parent, item_connections) RegisterSignal(parent, COMSIG_MOVABLE_DISPOSING, .proc/disposing_react) if(isitem(parent)) RegisterSignal(parent, list(COMSIG_ITEM_ATTACK, COMSIG_ITEM_ATTACK_OBJ, COMSIG_ITEM_HIT_REACT), .proc/play_squeak) @@ -67,7 +68,7 @@ /datum/component/squeak/UnregisterFromParent() . = ..() - RemoveElement(/datum/element/connect_loc_behalf, parent, item_connections) + qdel(GetComponent(/datum/component/connect_loc_behalf)) /datum/component/squeak/proc/play_squeak() SIGNAL_HANDLER diff --git a/code/datums/components/swarming.dm b/code/datums/components/swarming.dm index 5aa18bd96cf..56493cd9e6a 100644 --- a/code/datums/components/swarming.dm +++ b/code/datums/components/swarming.dm @@ -8,13 +8,14 @@ COMSIG_ATOM_ENTERED = .proc/join_swarm ) + /datum/component/swarming/Initialize(max_x = 24, max_y = 24) if(!ismovable(parent)) return COMPONENT_INCOMPATIBLE offset_x = rand(-max_x, max_x) offset_y = rand(-max_y, max_y) - AddElement(/datum/element/connect_loc_behalf, parent, swarming_loc_connections) + AddComponent(/datum/component/connect_loc_behalf, parent, swarming_loc_connections) /datum/component/swarming/Destroy() for(var/other in swarm_members) diff --git a/code/datums/elements/connect_loc.dm b/code/datums/elements/connect_loc.dm index 4de95339c6e..1687ce35f56 100644 --- a/code/datums/elements/connect_loc.dm +++ b/code/datums/elements/connect_loc.dm @@ -42,94 +42,3 @@ SIGNAL_HANDLER unregister_signals(listener, old_loc) update_signals(listener) - -/// This element behaves the same as connect_loc, hooking into a signal on a tracked object's turf -/// It has the ability to react to that signal on behalf of a seperate listener however -/// This has great use, primarially for components, but it carries with it some overhead -/// So we do it seperately rather then intigrating the behavior with the main element -/datum/element/connect_loc_behalf - element_flags = ELEMENT_BESPOKE | ELEMENT_DETACH | ELEMENT_COMPLEX_DETACH - id_arg_index = 3 - - /// An assoc list of signal -> procpath to register to the loc this object is on. - var/list/connections - - /// An assoc list of locs that are being occupied and a list of targets that occupy them. - var/list/targets = list() - -/datum/element/connect_loc_behalf/Attach(datum/listener, atom/movable/tracked, list/connections) - . = ..() - if (!istype(tracked)) - return ELEMENT_INCOMPATIBLE - - src.connections = connections - - RegisterSignal(tracked, COMSIG_MOVABLE_MOVED, .proc/on_moved, override = TRUE) - update_signals(listener, tracked) - -/datum/element/connect_loc_behalf/Detach(datum/listener, atom/movable/tracked, list/connections) - . = ..() - - if(!tracked) - unregister_all(listener) - else if(targets[tracked.loc]) // Detach can happen multiple times due to qdel - unregister_signals(listener, tracked, tracked.loc) - UnregisterSignal(tracked, COMSIG_MOVABLE_MOVED) - -/datum/element/connect_loc_behalf/proc/update_signals(datum/listener, atom/movable/tracked) - var/existing = length(targets[tracked.loc]) - if(!existing) - targets[tracked.loc] = list() - targets[tracked.loc][tracked] = listener - - if(isnull(tracked.loc)) - return - - for (var/signal in connections) - listener.RegisterSignal(tracked.loc, signal, connections[signal], override=TRUE) - //override=TRUE because more than one connect_loc element instance tracked object can be on the same loc - -/datum/element/connect_loc_behalf/proc/unregister_all(datum/listener) - for(var/atom/location as anything in targets) - var/list/loc_targets = targets[location] - for(var/atom/movable/tracked as anything in loc_targets) - if(tracked == listener) - unregister_signals(loc_targets[tracked], tracked, location) - else if(loc_targets[tracked] == listener) - unregister_signals(listener, tracked, location) - else - continue - UnregisterSignal(tracked, COMSIG_MOVABLE_MOVED) - -/datum/element/connect_loc_behalf/proc/unregister_signals(datum/listener, atom/movable/tracked, atom/old_loc) - if (length(targets[old_loc]) <= 1) - targets -= old_loc - else - targets[old_loc] -= tracked - - // Yes this is after the above because we use null as a key when objects are in nullspace - if(isnull(old_loc)) - return - - for (var/signal in connections) - listener.UnregisterSignal(old_loc, signal) - -/datum/element/connect_loc_behalf/proc/on_moved(atom/movable/tracked, atom/old_loc) - SIGNAL_HANDLER - var/list/objects_in_old_loc = targets[old_loc] - //You may ask yourself, isn't this just silencing an error? - //The answer is yes, but there's no good cheap way to fix it - //What happens is the tracked object or hell the listener gets say, deleted, which makes targets[old_loc] return a null - //The null results in a bad index, because of course it does - //It's not a solvable problem though, since both actions, the destroy and the move, are sourced from the same signal send - //And sending a signal should be agnostic of the order of listeners - //So we need to either pick the order agnositic, or destroy safe - //And I picked destroy safe. Let's hope this is the right path! - if(!objects_in_old_loc) - return - var/datum/listener = objects_in_old_loc[tracked] - if(!listener) //See above - return - unregister_signals(listener, tracked, old_loc) - update_signals(listener, tracked) - diff --git a/code/game/objects/effects/decals/cleanable/misc.dm b/code/game/objects/effects/decals/cleanable/misc.dm index e79706459ac..e37c9b9f7f3 100644 --- a/code/game/objects/effects/decals/cleanable/misc.dm +++ b/code/game/objects/effects/decals/cleanable/misc.dm @@ -273,4 +273,4 @@ reagents.add_reagent(/datum/reagent/ants, rand(2, 5)) pixel_x = rand(-5, 5) pixel_y = rand(-5, 5) - AddElement(/datum/element/caltrop, min_damage = 0.2, max_damage = 1, flags = (CALTROP_NOCRAWL | CALTROP_NOSTUN | CALTROP_BYPASS_SHOES), soundfile = 'sound/weapons/bite.ogg') + AddComponent(/datum/component/caltrop, min_damage = 0.2, max_damage = 1, flags = (CALTROP_NOCRAWL | CALTROP_NOSTUN | CALTROP_BYPASS_SHOES), soundfile = 'sound/weapons/bite.ogg') diff --git a/code/game/objects/items/dice.dm b/code/game/objects/items/dice.dm index 869a3dd7865..d037731e6db 100644 --- a/code/game/objects/items/dice.dm +++ b/code/game/objects/items/dice.dm @@ -89,7 +89,7 @@ /obj/item/dice/d4/Initialize(mapload) . = ..() // 1d4 damage - AddElement(/datum/element/caltrop, min_damage = 1, max_damage = 4) + AddComponent(/datum/component/caltrop, min_damage = 1, max_damage = 4) /obj/item/dice/d6 name = "d6" diff --git a/code/game/objects/items/stacks/sheets/glass.dm b/code/game/objects/items/stacks/sheets/glass.dm index 6bd03eab16e..bb495c1bf9d 100644 --- a/code/game/objects/items/stacks/sheets/glass.dm +++ b/code/game/objects/items/stacks/sheets/glass.dm @@ -275,7 +275,7 @@ GLOBAL_LIST_INIT(plastitaniumglass_recipes, list( /obj/item/shard/Initialize() . = ..() - AddElement(/datum/element/caltrop, min_damage = force) + AddComponent(/datum/component/caltrop, min_damage = force) AddComponent(/datum/component/butchering, 150, 65) icon_state = pick("large", "medium", "small") switch(icon_state) diff --git a/code/modules/assembly/mousetrap.dm b/code/modules/assembly/mousetrap.dm index 648e1d1d0fd..19c48ed32a5 100644 --- a/code/modules/assembly/mousetrap.dm +++ b/code/modules/assembly/mousetrap.dm @@ -47,11 +47,11 @@ /obj/item/assembly/mousetrap/on_attach() . = ..() - AddElement(/datum/element/connect_loc_behalf, holder, holder_connections) + AddComponent(/datum/component/connect_loc_behalf, holder, holder_connections) /obj/item/assembly/mousetrap/on_detach() . = ..() - RemoveElement(/datum/element/connect_loc_behalf, holder, holder_connections) + qdel(GetComponent(/datum/component/connect_loc_behalf)) /obj/item/assembly/mousetrap/proc/triggered(mob/target, type = "feet") if(!armed) diff --git a/code/modules/hydroponics/grown/towercap.dm b/code/modules/hydroponics/grown/towercap.dm index 81dab89e8da..c06affd2ff6 100644 --- a/code/modules/hydroponics/grown/towercap.dm +++ b/code/modules/hydroponics/grown/towercap.dm @@ -112,7 +112,7 @@ /obj/structure/punji_sticks/Initialize(mapload) . = ..() - AddElement(/datum/element/caltrop, min_damage = 20, max_damage = 30, flags = CALTROP_BYPASS_SHOES) + AddComponent(/datum/component/caltrop, min_damage = 20, max_damage = 30, flags = CALTROP_BYPASS_SHOES) /obj/structure/punji_sticks/spikes name = "wooden spikes" diff --git a/code/modules/mining/lavaland/ash_flora.dm b/code/modules/mining/lavaland/ash_flora.dm index e406600ffe1..3264c0458bf 100644 --- a/code/modules/mining/lavaland/ash_flora.dm +++ b/code/modules/mining/lavaland/ash_flora.dm @@ -144,7 +144,7 @@ /obj/structure/flora/ash/cacti/Initialize(mapload) . = ..() - AddElement(/datum/element/caltrop, min_damage = 3, max_damage = 6, probability = 70) + AddComponent(/datum/component/caltrop, min_damage = 3, max_damage = 6, probability = 70) /obj/structure/flora/ash/seraka icon_state = "seraka_mushroom" diff --git a/code/modules/mob/living/simple_animal/hostile/cockroach.dm b/code/modules/mob/living/simple_animal/hostile/cockroach.dm index f44f9843068..accc44ab76c 100644 --- a/code/modules/mob/living/simple_animal/hostile/cockroach.dm +++ b/code/modules/mob/living/simple_animal/hostile/cockroach.dm @@ -109,7 +109,7 @@ /mob/living/simple_animal/hostile/cockroach/hauberoach/Initialize() . = ..() - AddElement(/datum/element/caltrop, min_damage = 10, max_damage = 15, flags = (CALTROP_BYPASS_SHOES | CALTROP_SILENT)) + AddComponent(/datum/component/caltrop, min_damage = 10, max_damage = 15, flags = (CALTROP_BYPASS_SHOES | CALTROP_SILENT)) /mob/living/simple_animal/hostile/cockroach/hauberoach/make_squashable() AddComponent(/datum/component/squashable, squash_chance = 100, squash_damage = 1, squash_callback = /mob/living/simple_animal/hostile/cockroach/hauberoach/.proc/on_squish) diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm index 7f33abc0429..d15b51c4aa3 100644 --- a/code/modules/power/lighting.dm +++ b/code/modules/power/lighting.dm @@ -959,7 +959,7 @@ /obj/item/light/Initialize() . = ..() create_reagents(LIGHT_REAGENT_CAPACITY, INJECTABLE | DRAINABLE) - AddElement(/datum/element/caltrop, min_damage = force) + AddComponent(/datum/component/caltrop, min_damage = force) update() var/static/list/loc_connections = list( COMSIG_ATOM_ENTERED = .proc/on_entered, diff --git a/modular_skyrat/modules/materials_glass/glass.dm b/modular_skyrat/modules/materials_glass/glass.dm index cb6cc62f801..1ce79b4ad51 100644 --- a/modular_skyrat/modules/materials_glass/glass.dm +++ b/modular_skyrat/modules/materials_glass/glass.dm @@ -258,7 +258,7 @@ GLOBAL_LIST_INIT(glass_recipes, list ( \ /obj/item/shard/Initialize() . = ..() - AddElement(/datum/element/caltrop, min_damage = force) + AddComponent(/datum/component/caltrop, min_damage = force) AddComponent(/datum/component/butchering, 150, 65) icon_state = pick("large", "medium", "small") switch(icon_state) diff --git a/tgstation.dme b/tgstation.dme index e59bcf91e81..fbd22d7f02b 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -548,8 +548,10 @@ #include "code\datums\components\beetlejuice.dm" #include "code\datums\components\bloodysoles.dm" #include "code\datums\components\butchering.dm" +#include "code\datums\components\caltrop.dm" #include "code\datums\components\chasm.dm" #include "code\datums\components\codeword_hearing.dm" +#include "code\datums\components\connect_loc_behalf.dm" #include "code\datums\components\construction.dm" #include "code\datums\components\cracked.dm" #include "code\datums\components\creamed.dm" @@ -617,6 +619,7 @@ #include "code\datums\components\spill.dm" #include "code\datums\components\spinny.dm" #include "code\datums\components\spirit_holding.dm" +#include "code\datums\components\squashable.dm" #include "code\datums\components\squeak.dm" #include "code\datums\components\stationloving.dm" #include "code\datums\components\stationstuck.dm" @@ -740,7 +743,6 @@ #include "code\datums\elements\beauty.dm" #include "code\datums\elements\bed_tucking.dm" #include "code\datums\elements\bsa_blocker.dm" -#include "code\datums\elements\caltrop.dm" #include "code\datums\elements\chewable.dm" #include "code\datums\elements\cleaning.dm" #include "code\datums\elements\climbable.dm" @@ -785,7 +787,6 @@ #include "code\datums\elements\skittish.dm" #include "code\datums\elements\snail_crawl.dm" #include "code\datums\elements\spooky.dm" -#include "code\datums\elements\squashable.dm" #include "code\datums\elements\squish.dm" #include "code\datums\elements\strippable.dm" #include "code\datums\elements\surgery_initiator.dm"