-
-
Notifications
You must be signed in to change notification settings - Fork 487
/
connect_loc_behalf.dm
69 lines (53 loc) · 2.44 KB
/
connect_loc_behalf.dm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
/// 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 separate listener however
/// This has great use, primarily for components, but it carries with it some overhead
/// So we do it separately 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/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
parent.UnregisterSignal(tracked_loc, connections)
tracked_loc = null
/datum/component/connect_loc_behalf/proc/on_moved(sigtype, atom/movable/tracked, atom/old_loc)
SIGNAL_HANDLER
update_signals()