forked from Skyrat-SS13/Skyrat-tg
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSS13_base.lua
155 lines (137 loc) · 3.99 KB
/
SS13_base.lua
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
local timer = require("timer")
local state = require("state")
local SS13 = {}
__SS13_signal_handlers = __SS13_signal_handlers or {}
SS13.SSlua = dm.global_vars.SSlua
SS13.global_proc = "some_magic_bullshit"
SS13.state = state.state
function SS13.get_runner_ckey()
return SS13.state.ckey_last_runner
end
function SS13.get_runner_client()
return dm.global_vars.GLOB.directory[SS13.get_runner_ckey()]
end
SS13.type = dm.global_procs._text2path
function SS13.istype(thing, type)
return dm.global_procs._istype(thing, SS13.type(type)) == 1
end
SS13.new = dm.new
function SS13.qdel(datum)
if SS13.is_valid(datum) then
dm.global_procs.qdel(datum)
return true
end
return false
end
function SS13.is_valid(datum)
return dm.is_valid_ref(datum) and not datum.gc_destroyed
end
function SS13.await(thing_to_call, proc_to_call, ...)
if not SS13.istype(thing_to_call, "/datum") then
thing_to_call = SS13.global_proc
end
if thing_to_call == SS13.global_proc then
proc_to_call = "/proc/" .. proc_to_call
end
local promise = SS13.new("/datum/promise", thing_to_call, proc_to_call, ...)
while promise.status == 0 do
sleep()
end
return promise.return_value, promise.runtime_message
end
local function signal_handler(data, ...)
local output = 0
for func, _ in data.functions do
local result = func(...)
if type(result) == "number" then
output = bit32.bor(output, math.floor(result))
end
end
return output
end
local function create_qdeleting_callback(datum)
local callback = SS13.new("/datum/callback", SS13.state, "call_function_return_first")
callback:RegisterSignal(datum, "parent_qdeleting", "Invoke")
local path = {
"__SS13_signal_handlers",
dm.global_procs.WEAKREF(datum),
"parent_qdeleting",
"handler",
}
callback.arguments = { path }
local handler_data = { callback = callback, functions = {} }
handler_data.handler = function(source, ...)
local result = signal_handler(handler_data, source, ...)
for signal, signal_data in __SS13_signal_handlers[source] do
signal_data.callback:UnregisterSignal(source, signal)
end
__SS13_signal_handlers[source] = nil
return result
end
__SS13_signal_handlers[datum]["parent_qdeleting"] = handler_data
end
function SS13.register_signal(datum, signal, func)
if not type(func) == "function" then
return
end
if not SS13.istype(datum, "/datum") then
return
end
if not SS13.is_valid(datum) then
error("Tried to register a signal on a deleted datum", 2)
end
if not __SS13_signal_handlers[datum] then
__SS13_signal_handlers[datum] = {}
-- Turfs don't remove their signals on deletion.
if not SS13.istype(datum, "/turf") then
create_qdeleting_callback(datum)
end
end
local handler_data = __SS13_signal_handlers[datum][signal]
if not handler_data then
handler_data = { callback = nil, functions = {} }
local callback = SS13.new("/datum/callback", SS13.state, "call_function_return_first")
callback:RegisterSignal(datum, signal, "Invoke")
local path = {
"__SS13_signal_handlers",
dm.global_procs.WEAKREF(datum),
signal,
"handler",
}
callback.arguments = { path }
handler_data.callback = callback
handler_data.handler = function(...)
return signal_handler(handler_data, ...)
end
__SS13_signal_handlers[datum][signal] = handler_data
end
handler_data.functions[func] = true
return true
end
function SS13.unregister_signal(datum, signal, func)
if not (func == nil or type(func) == "function") then
return
end
if not __SS13_signal_handlers[datum] then
return
end
local handler_data = __SS13_signal_handlers[datum][signal]
if not handler_data then
return
end
if func == nil then
if signal == "parent_qdeleting" then
handler_data.functions = {}
else
handler_data.callback:UnregisterSignal(datum, signal)
__SS13_signal_handlers[datum][signal] = nil
end
else
handler_data.functions[func] = nil
if not (#handler_data.functions or (signal == "parent_qdeleting")) then
handler_data.callback:UnregisterSignal(datum, signal)
__SS13_signal_handlers[datum][signal] = nil
end
end
end
return SS13