/
machinery_public_vars.dm
112 lines (92 loc) · 3.59 KB
/
machinery_public_vars.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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
/singleton/public_access
var/name
var/desc
/singleton/public_access/public_variable
var/expected_type
var/can_write = FALSE
var/var_type = IC_FORMAT_BOOLEAN // Reuses IC defines for better compatibility.
var/has_updates = FALSE // Can register listeners for updates on change.
var/list/listeners = list()
/*
Must be implemented by subtypes.
*/
// Reads off the var value and returns it
/singleton/public_access/public_variable/proc/access_var(datum/owner)
// Writes to the var. Returns true if change occured, false otherwise.
// Subtypes shall call parent, and perform the actual write if the return value is true.
// If the var has_updates, you must never modify the var except through this proc.
/singleton/public_access/public_variable/proc/write_var(datum/owner, new_value)
var/old_value = access_var(owner)
if(old_value == new_value)
return FALSE
if(has_updates)
var_changed(owner, old_value, new_value)
return TRUE
// Any sanitization should be done in here.
/singleton/public_access/public_variable/proc/write_var_protected(datum/owner, new_value)
if(!can_write)
return FALSE
write_var(owner, new_value)
/*
Listener registration. You must unregister yourself if you are destroyed; the owner being destroyed will be handled automatically.
*/
/singleton/public_access/public_variable/proc/register_listener(datum/listener, datum/owner, registered_proc)
. = FALSE
if(!istype(owner, expected_type))
CRASH("[log_info_line(listener)] attempted to register for the public variable [type], but passed an invalid owner of type [owner.type].")
if(!has_updates)
return // Can try and register, but updates aren't coming
if(!listeners[owner])
listeners[owner] = list()
GLOB.destroyed_event.register(owner, src, .proc/owner_destroyed)
LAZYADD(listeners[owner][listener], registered_proc)
return TRUE
/singleton/public_access/public_variable/proc/unregister_listener(datum/listener, datum/owner, registered_proc)
if(!listeners[owner])
return
if(!listeners[owner][listener])
return
if(registered_proc) // Remove the proc and remove the listener if no more procs
listeners[owner][listener] -= registered_proc
if(!length(listeners[owner][listener]))
listeners[owner] -= listener
else // Remove the listener
listeners[owner] -= listener
if(!length(listeners[owner])) // Clean up the list if no longer listening to anything.
listeners -= owner
GLOB.destroyed_event.unregister(owner, src)
/*
Internal procs. Do not modify.
*/
/singleton/public_access/public_variable/proc/owner_destroyed(datum/owner)
GLOB.destroyed_event.unregister(owner, src)
listeners -= owner
/singleton/public_access/public_variable/proc/var_changed(owner, old_value, new_value)
var/list/to_alert = listeners[owner]
for(var/thing in to_alert)
for(var/call_proc in to_alert[thing])
call(thing, call_proc)(src, owner, old_value, new_value)
/*
Public methods machines can expose. Pretty bare-bones; just wraps a proc and gives it a name for UI purposes.
*/
/singleton/public_access/public_method
var/call_proc
var/forward_args = FALSE
/singleton/public_access/public_method/proc/perform(datum/owner, ...)
if(forward_args)
call(owner, call_proc)(arglist(args.Copy(2)))
else
call(owner, call_proc)()
/*
Machinery implementation
*/
/// List of all registered `public_variable` singletons.
/obj/machinery/var/list/public_variables
/// List of all registered `public_method` singletons.
/obj/machinery/var/list/public_methods
/obj/machinery/Initialize()
for(var/path in public_variables)
public_variables[path] = GET_SINGLETON(path)
for(var/path in public_methods)
public_methods[path] = GET_SINGLETON(path)
. = ..()