mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-13 19:22:20 +00:00
* Moves spawners and decals to a different init/delete scheme Rather then fully creating and then immediately deleting these things, we instead do the bare minimum. This is faster, if in theory more fragile. We should be safe since any errors should be caught in compile since this is very close to a "static" action. It does mean these atoms cannot use signals, etc. * Potentially saves init time, mostly cleans up a silly pattern We use sleeps and INVOKE_ASYNC to ensure that handing back turfs doesn't block a space reservation, but this by nature consumes up to the threshold and a bit more of whatever working block we were in. This is silly. Should just be a subsystem, so I made it one, with support for awaiting its finish if you want to * Optimizes garbage/proc/Queue slightly Queue takes about 1.6 seconds to process 26k items right now. The MASSIVE majority of this time is spent on using \ref This is because \ref returns a string, and that string requires being inserted into the global cache of strings we store What I'm doing is caching the result of ANY \ref on the datum it's applied to. This ensures previous uses will never decay from the string tree. This saves about 0.2 seconds of init
220 lines
5.8 KiB
Plaintext
220 lines
5.8 KiB
Plaintext
// JATUM. System for making the serializing and deserializing of PoD types easier
|
|
|
|
/**
|
|
* Gets the flat list that can be passed in a `new /type(argslist(retval))` expression to recreate the datum. Must only return a list containing values that can be JATUM serialized
|
|
*/
|
|
/datum/proc/jatum_new_arglist()
|
|
return null
|
|
|
|
/// The JATUM version used for serializing and deserializing
|
|
#define JATUM_VERSION 1
|
|
|
|
/**
|
|
* Attempt to serialize a given value to the JATUM format.
|
|
*
|
|
* * value - The var to serialize.
|
|
*/
|
|
/world/proc/jatum_serialize(value)
|
|
var/list/json_structure
|
|
try
|
|
json_structure = _jatum_serialize_value(value, list())
|
|
catch(var/exception/e)
|
|
CRASH(e)
|
|
|
|
return json_encode(list(
|
|
"jatum\\version" = JATUM_VERSION,
|
|
"content" = json_structure
|
|
))
|
|
|
|
/world/proc/_jatum_serialize_value(value, list/seen_references)
|
|
if(isnull(value))
|
|
return null
|
|
|
|
if(isnum(value) || istext(value))
|
|
return list(
|
|
"type" = "jatum\\raw",
|
|
"value" = value
|
|
)
|
|
|
|
if(ispath(value))
|
|
return list(
|
|
"type" = "jatum\\path",
|
|
"path" = value
|
|
)
|
|
|
|
var/ref = text_ref(value)
|
|
var/existing_ref = seen_references[ref]
|
|
if(existing_ref)
|
|
return list(
|
|
"type" = "jatum\\ref",
|
|
"jatum\\id" = existing_ref)
|
|
|
|
// Simple incrementing ID system
|
|
var/ref_id = seen_references.len + 1
|
|
seen_references[ref] = ref_id
|
|
|
|
if(istype(value, /matrix)) // matricies work with json_encode so use a custom arglist
|
|
return list(
|
|
"jatum\\id" = ref_id,
|
|
"type" = "/matrix",
|
|
"jatum\\new_arglist" = _jatum_serialize_value(json_decode(json_encode(value))), seen_references)
|
|
|
|
if(istype(value, /savefile)) // Just store the path, rely on BYOND for the rest
|
|
var/savefile/save = value
|
|
return list(
|
|
"jatum\\id" = ref_id,
|
|
"type" = "/savefile",
|
|
"jatum\\new_arglist" = _jatum_serialize_value(list(save.name), seen_references)
|
|
)
|
|
|
|
if(istype(value, /regex)) // store construct params
|
|
var/regex/rx = value
|
|
return list(
|
|
"jatum\\id" = ref_id,
|
|
"type" = "/regex",
|
|
"name" = rx.name,
|
|
"flags" = rx.flags
|
|
)
|
|
|
|
if(islist(value))
|
|
// Serialize all lists as dicts, list("a") and list("a" = null) can't be differentiated in DM
|
|
var/list_contents = list()
|
|
for(var/key in value)
|
|
var/l_value
|
|
try
|
|
l_value = value[key]
|
|
catch
|
|
// Expected, indicates a flat list
|
|
|
|
if(!isnull(l_value))
|
|
list_contents += list(list(
|
|
"key" = _jatum_serialize_value(key, seen_references),
|
|
"value" = _jatum_serialize_value(l_value, seen_references)
|
|
))
|
|
else
|
|
list_contents += list(list(
|
|
"value" = _jatum_serialize_value(key, seen_references)
|
|
))
|
|
return list(
|
|
"jatum\\id" = ref_id,
|
|
"type" = "/list",
|
|
"contents" = list_contents)
|
|
|
|
// JATUM is really only meant for PoD types
|
|
if(!isdatum(value)\
|
|
|| istype(value, /image)\
|
|
|| istype(value, /icon)\
|
|
|| istype(value, /sound)\
|
|
|| istype(value, /atom)\
|
|
|| istype(value, /mutable_appearance)\
|
|
|| istype(value, /client)\
|
|
|| istype(value, /database))
|
|
CRASH("Incompatible type for JATUM: [value]([ref])")
|
|
|
|
// Confirmed /datum type
|
|
var/datum/D = value
|
|
var/json_structure = list(
|
|
"jatum\\id" = ref_id,
|
|
"type" = "[D.type]"
|
|
)
|
|
var/new_arglist = D.jatum_new_arglist()
|
|
if(new_arglist)
|
|
if(!islist(new_arglist))
|
|
CRASH("Non-list return from jatum_new_arglist from [D.type]!")
|
|
json_structure["jatum\\new_arglist"] = _jatum_serialize_value(new_arglist, seen_references)
|
|
|
|
for(var/var_name in D.vars)
|
|
if(var_name == "vars" || var_name == "parent_type" || var_name == "type")
|
|
continue
|
|
|
|
var/d_value = D.vars[var_name]
|
|
json_structure[var_name] = _jatum_serialize_value(d_value, seen_references)
|
|
|
|
return json_structure
|
|
|
|
/**
|
|
* Attempt to create a value from a JATUM JSON.
|
|
*
|
|
* * json - The JSON to deserialize.
|
|
*/
|
|
/world/proc/jatum_deserialize(json)
|
|
if(!istext(json))
|
|
CRASH("Non-text passed!")
|
|
|
|
var/list/structure = json_decode(json)
|
|
if(!structure)
|
|
CRASH("Invalid JSON!")
|
|
|
|
var/jatum_version = structure["jatum\\version"]
|
|
if(isnull(jatum_version))
|
|
CRASH("Not JATUM JSON!")
|
|
|
|
if(jatum_version != JATUM_VERSION)
|
|
CRASH("Incompatible JATUM_VERSION")
|
|
|
|
try
|
|
return _jatum_deserialize_value(structure["content"], list())
|
|
catch(var/exception/e)
|
|
CRASH(e)
|
|
|
|
/world/proc/_jatum_deserialize_value(list/structure, list/active_references)
|
|
if(!structure)
|
|
return null
|
|
|
|
var/ref_id = structure["jatum\\id"]
|
|
var/entry_type = structure["type"]
|
|
switch(entry_type)
|
|
if("jatum\\raw")
|
|
return structure["value"]
|
|
if("jatum\\path")
|
|
var/string_path = structure["path"]
|
|
var/path = text2path(string_path)
|
|
if(!path)
|
|
CRASH("Invalid path: [string_path]")
|
|
return path
|
|
if("jatum\\ref")
|
|
var/result = active_references[ref_id]
|
|
if(!result)
|
|
CRASH("Missing reference ID [ref_id]!")
|
|
return result
|
|
if("/regex")
|
|
var/name = structure["name"]
|
|
var/flags = structure["flags"]
|
|
if(flags)
|
|
. = new /regex(name, flags)
|
|
else
|
|
. = new /regex(name)
|
|
if("/list")
|
|
var/list_contents = structure["contents"]
|
|
. = list()
|
|
for(var/entry in list_contents)
|
|
var/key = entry["key"]
|
|
var/l_value = entry["value"]
|
|
if(key)
|
|
.[_jatum_deserialize_value(key, active_references)] = _jatum_deserialize_value(l_value, active_references)
|
|
else
|
|
. += _jatum_deserialize_value(l_value, active_references)
|
|
|
|
else
|
|
// everything else is a /datum and instantiates via reflection
|
|
var/list/jatum_arglist = structure["jatum\\new_arglist"]
|
|
var/full_type = text2path(entry_type)
|
|
if(!full_type)
|
|
CRASH("Invalid type: [entry_type]")
|
|
if(jatum_arglist)
|
|
var/list/new_arglist = _jatum_deserialize_value(jatum_arglist, active_references)
|
|
. = new full_type(arglist(new_arglist))
|
|
else
|
|
. = new full_type
|
|
|
|
var/datum/D = .
|
|
for(var/var_name in structure)
|
|
if(var_name == "type"\
|
|
|| var_name == "jatum\\id"\
|
|
|| var_name == "jatum\\new_arglist")
|
|
continue
|
|
var/value = structure[var_name]
|
|
D.vars[var_name] = _jatum_deserialize_value(value, active_references)
|
|
|
|
active_references["[ref_id]"] = .
|