mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-10 01:34:01 +00:00
## About The Pull Request I added new helpers to the default SS13 lua library: `SS13.ispath`, `SS13.typecacheof`, `SS13.is_type_in_typecache`, `SS13.get_turf`, and `SS13.get_area`, which pretty much behave like their actual DM counterparts (albeit `SS13.typecacheof` lets you just input string typepaths, instead of needing to manually `SS13.type` each one) In addition, I discovered an issue with `SS13.register_signal`: `not type(func) == "function"` is the same as `(not type(func)) == "function"` - so the proper check is `type(func) ~= "function"`. ## Why It's Good For The Game ## Changelog 🆑 admin: Added some new Lua functions: SS13.ispath, SS13.typecacheof, SS13.is_type_in_typecache, SS13.get_turf, and SS13.get_area fix: Fixed a broken check in the SS13.register_signal Lua function. /🆑
206 lines
5.1 KiB
Lua
206 lines
5.1 KiB
Lua
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
|
|
|
|
function SS13.ispath(thing, path)
|
|
return dm.global_procs._ispath(thing, path) == 1
|
|
end
|
|
|
|
function SS13.type(typepath)
|
|
if type(typepath) == "string" then
|
|
return dm.global_procs._text2path(typepath)
|
|
elseif SS13.ispath(typepath) then
|
|
return typepath
|
|
else
|
|
return nil
|
|
end
|
|
end
|
|
|
|
function SS13.istype(thing, type)
|
|
return dm.global_procs._istype(thing, SS13.type(type)) == 1
|
|
end
|
|
|
|
function SS13.typecacheof(string_types)
|
|
local types = {}
|
|
for _, path in string_types do
|
|
if path ~= nil then
|
|
table.insert(types, SS13.type(path))
|
|
end
|
|
end
|
|
return dm.global_procs.typecacheof(types)
|
|
end
|
|
|
|
function SS13.is_type_in_typecache(thing, typecache)
|
|
return dm.global_procs._is_type_in_typecache(thing, typecache) == 1
|
|
end
|
|
|
|
function SS13.get_turf(thing)
|
|
return dm.global_procs._get_step(thing, 0)
|
|
end
|
|
|
|
function SS13.get_area(thing)
|
|
if SS13.istype(thing, "/area") then
|
|
return thing
|
|
else
|
|
local turf = SS13.get_turf(thing)
|
|
-- don't bother with SS13.is_valid, turfs don't get destroyed
|
|
if dm.is_valid_ref(turf) then
|
|
return turf.loc
|
|
end
|
|
end
|
|
return nil
|
|
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.check_tick(high_priority)
|
|
local tick_limit = if high_priority then 95 else dm.global_vars.Master.current_ticklimit
|
|
if dm.world.tick_usage > tick_limit then
|
|
sleep()
|
|
end
|
|
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 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
|