mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-10 01:34:01 +00:00
* Cleans up the fallout from plane cube (#70235) * Cleans up the fallout from plane cube Alright. Makes cleaning bubbles respect planes Adds support for updating overlays on move, fixing an issue with pointing at items Adds better error messages for failing to provide args for mutable_appearance() Fixes a bug where string overlays were not respecting insertion order * Adds documentation for offset spokesman and offset_const * Better stack trace * Removes some redundant uses of cached MAs At this scale, attempting to cache MAs like this has 0 impact on anything And just makes things more messy then they need to be * ensures fullscreen objects START offset, so things are always proper * ensures chatmessages always have the right offset * fixes compile * whoops, the above lighting plane should actually be ABOVE the lighting plane * fixes compile, also cleans up the fire overlay a tad * Adds a unit test for plane masters that are shrunk by multiz being double shrunk This is slightly hacky because of how I'm handing the plane master group, but it's not THAT bad, and gives me some real good coverage * Properly targets the seethrough plane at the game world plate. This fixes unit tests, and also just makes more sense * whoops * oh * adds datum support for allocate(), cleans up a harddel from testing * Makes camera chunks index at 1, and also makes them support non powers of two sizes, since that was unneeded * fixes runtime in allocate * Cleans up the fallout from plane cube * liquid tweaks * oop Co-authored-by: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com> Co-authored-by: tastyfish <crazychris32@gmail.com>
244 lines
7.1 KiB
Plaintext
244 lines
7.1 KiB
Plaintext
#define BAD_INIT_QDEL_BEFORE 1
|
|
#define BAD_INIT_DIDNT_INIT 2
|
|
#define BAD_INIT_SLEPT 4
|
|
#define BAD_INIT_NO_HINT 8
|
|
|
|
SUBSYSTEM_DEF(atoms)
|
|
name = "Atoms"
|
|
init_order = INIT_ORDER_ATOMS
|
|
flags = SS_NO_FIRE
|
|
|
|
var/old_initialized
|
|
/// A count of how many initalize changes we've made. We want to prevent old_initialize being overriden by some other value, breaking init code
|
|
var/initialized_changed = 0
|
|
|
|
var/list/late_loaders = list()
|
|
|
|
var/list/BadInitializeCalls = list()
|
|
|
|
///initAtom() adds the atom its creating to this list iff InitializeAtoms() has been given a list to populate as an argument
|
|
var/list/created_atoms
|
|
|
|
/// Atoms that will be deleted once the subsystem is initialized
|
|
var/list/queued_deletions = list()
|
|
|
|
#ifdef PROFILE_MAPLOAD_INIT_ATOM
|
|
var/list/mapload_init_times = list()
|
|
#endif
|
|
|
|
initialized = INITIALIZATION_INSSATOMS
|
|
|
|
/datum/controller/subsystem/atoms/Initialize()
|
|
setupGenetics() //to set the mutations' sequence
|
|
|
|
initialized = INITIALIZATION_INNEW_MAPLOAD
|
|
InitializeAtoms()
|
|
initialized = INITIALIZATION_INNEW_REGULAR
|
|
|
|
return SS_INIT_SUCCESS
|
|
|
|
#ifdef PROFILE_MAPLOAD_INIT_ATOM
|
|
#define PROFILE_INIT_ATOM_BEGIN(...) var/__profile_stat_time = TICK_USAGE
|
|
#define PROFILE_INIT_ATOM_END(atom) mapload_init_times[##atom.type] += TICK_USAGE_TO_MS(__profile_stat_time)
|
|
#else
|
|
#define PROFILE_INIT_ATOM_BEGIN(...)
|
|
#define PROFILE_INIT_ATOM_END(...)
|
|
#endif
|
|
|
|
/datum/controller/subsystem/atoms/proc/InitializeAtoms(list/atoms, list/atoms_to_return)
|
|
if(initialized == INITIALIZATION_INSSATOMS)
|
|
return
|
|
|
|
set_tracked_initalized(INITIALIZATION_INNEW_MAPLOAD)
|
|
|
|
// This may look a bit odd, but if the actual atom creation runtimes for some reason, we absolutely need to set initialized BACK
|
|
CreateAtoms(atoms, atoms_to_return)
|
|
clear_tracked_initalize()
|
|
|
|
if(late_loaders.len)
|
|
for(var/I in 1 to late_loaders.len)
|
|
var/atom/A = late_loaders[I]
|
|
//I hate that we need this
|
|
if(QDELETED(A))
|
|
continue
|
|
A.LateInitialize()
|
|
testing("Late initialized [late_loaders.len] atoms")
|
|
late_loaders.Cut()
|
|
|
|
if (created_atoms)
|
|
atoms_to_return += created_atoms
|
|
created_atoms = null
|
|
|
|
for (var/queued_deletion in queued_deletions)
|
|
qdel(queued_deletion)
|
|
|
|
testing("[queued_deletions.len] atoms were queued for deletion.")
|
|
queued_deletions.Cut()
|
|
|
|
#ifdef PROFILE_MAPLOAD_INIT_ATOM
|
|
rustg_file_write(json_encode(mapload_init_times), "[GLOB.log_directory]/init_times.json")
|
|
#endif
|
|
|
|
/// Actually creates the list of atoms. Exists soley so a runtime in the creation logic doesn't cause initalized to totally break
|
|
/datum/controller/subsystem/atoms/proc/CreateAtoms(list/atoms, list/atoms_to_return = null)
|
|
if (atoms_to_return)
|
|
LAZYINITLIST(created_atoms)
|
|
|
|
#ifdef TESTING
|
|
var/count
|
|
#endif
|
|
|
|
var/list/mapload_arg = list(TRUE)
|
|
|
|
if(atoms)
|
|
#ifdef TESTING
|
|
count = atoms.len
|
|
#endif
|
|
|
|
for(var/I in 1 to atoms.len)
|
|
var/atom/A = atoms[I]
|
|
if(!(A.flags_1 & INITIALIZED_1))
|
|
CHECK_TICK
|
|
PROFILE_INIT_ATOM_BEGIN()
|
|
InitAtom(A, TRUE, mapload_arg)
|
|
PROFILE_INIT_ATOM_END(A)
|
|
else
|
|
#ifdef TESTING
|
|
count = 0
|
|
#endif
|
|
|
|
for(var/atom/A as anything in world)
|
|
if(!(A.flags_1 & INITIALIZED_1))
|
|
PROFILE_INIT_ATOM_BEGIN()
|
|
InitAtom(A, FALSE, mapload_arg)
|
|
PROFILE_INIT_ATOM_END(A)
|
|
#ifdef TESTING
|
|
++count
|
|
#endif
|
|
CHECK_TICK
|
|
|
|
testing("Initialized [count] atoms")
|
|
|
|
/// Init this specific atom
|
|
/datum/controller/subsystem/atoms/proc/InitAtom(atom/A, from_template = FALSE, list/arguments)
|
|
var/the_type = A.type
|
|
if(QDELING(A))
|
|
BadInitializeCalls[the_type] |= BAD_INIT_QDEL_BEFORE
|
|
return TRUE
|
|
|
|
// This is handled and battle tested by dreamchecker. Limit to UNIT_TESTS just in case that ever fails.
|
|
#ifdef UNIT_TESTS
|
|
var/start_tick = world.time
|
|
#endif
|
|
|
|
var/result = A.Initialize(arglist(arguments))
|
|
|
|
#ifdef UNIT_TESTS
|
|
if(start_tick != world.time)
|
|
BadInitializeCalls[the_type] |= BAD_INIT_SLEPT
|
|
#endif
|
|
|
|
var/qdeleted = FALSE
|
|
|
|
switch(result)
|
|
if (INITIALIZE_HINT_NORMAL)
|
|
// pass
|
|
if(INITIALIZE_HINT_LATELOAD)
|
|
if(arguments[1]) //mapload
|
|
late_loaders += A
|
|
else
|
|
A.LateInitialize()
|
|
if(INITIALIZE_HINT_QDEL)
|
|
qdel(A)
|
|
qdeleted = TRUE
|
|
else
|
|
BadInitializeCalls[the_type] |= BAD_INIT_NO_HINT
|
|
|
|
if(!A) //possible harddel
|
|
qdeleted = TRUE
|
|
else if(!(A.flags_1 & INITIALIZED_1))
|
|
BadInitializeCalls[the_type] |= BAD_INIT_DIDNT_INIT
|
|
else
|
|
SEND_SIGNAL(A,COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZE)
|
|
if(created_atoms && from_template && ispath(the_type, /atom/movable))//we only want to populate the list with movables
|
|
created_atoms += A.get_all_contents()
|
|
|
|
return qdeleted || QDELING(A)
|
|
|
|
/datum/controller/subsystem/atoms/proc/map_loader_begin()
|
|
set_tracked_initalized(INITIALIZATION_INSSATOMS)
|
|
|
|
/datum/controller/subsystem/atoms/proc/map_loader_stop()
|
|
clear_tracked_initalize()
|
|
|
|
/// Use this to set initialized to prevent error states where old_initialized is overriden. It keeps happening and it's cheesing me off
|
|
/datum/controller/subsystem/atoms/proc/set_tracked_initalized(value)
|
|
if(!initialized_changed)
|
|
old_initialized = initialized
|
|
initialized = value
|
|
else
|
|
stack_trace("We started maploading while we were already maploading. You doing something odd?")
|
|
initialized_changed += 1
|
|
|
|
/datum/controller/subsystem/atoms/proc/clear_tracked_initalize()
|
|
initialized_changed -= 1
|
|
if(!initialized_changed)
|
|
initialized = old_initialized
|
|
|
|
/datum/controller/subsystem/atoms/Recover()
|
|
initialized = SSatoms.initialized
|
|
if(initialized == INITIALIZATION_INNEW_MAPLOAD)
|
|
InitializeAtoms()
|
|
old_initialized = SSatoms.old_initialized
|
|
BadInitializeCalls = SSatoms.BadInitializeCalls
|
|
|
|
/datum/controller/subsystem/atoms/proc/setupGenetics()
|
|
var/list/mutations = subtypesof(/datum/mutation/human)
|
|
shuffle_inplace(mutations)
|
|
for(var/A in subtypesof(/datum/generecipe))
|
|
var/datum/generecipe/GR = A
|
|
GLOB.mutation_recipes[initial(GR.required)] = initial(GR.result)
|
|
for(var/i in 1 to LAZYLEN(mutations))
|
|
var/path = mutations[i] //byond gets pissy when we do it in one line
|
|
var/datum/mutation/human/B = new path ()
|
|
B.alias = "Mutation [i]"
|
|
GLOB.all_mutations[B.type] = B
|
|
GLOB.full_sequences[B.type] = generate_gene_sequence(B.blocks)
|
|
GLOB.alias_mutations[B.alias] = B.type
|
|
if(B.locked)
|
|
continue
|
|
if(B.quality == POSITIVE)
|
|
GLOB.good_mutations |= B
|
|
else if(B.quality == NEGATIVE)
|
|
GLOB.bad_mutations |= B
|
|
else if(B.quality == MINOR_NEGATIVE)
|
|
GLOB.not_good_mutations |= B
|
|
CHECK_TICK
|
|
|
|
/datum/controller/subsystem/atoms/proc/InitLog()
|
|
. = ""
|
|
for(var/path in BadInitializeCalls)
|
|
. += "Path : [path] \n"
|
|
var/fails = BadInitializeCalls[path]
|
|
if(fails & BAD_INIT_DIDNT_INIT)
|
|
. += "- Didn't call atom/Initialize(mapload)\n"
|
|
if(fails & BAD_INIT_NO_HINT)
|
|
. += "- Didn't return an Initialize hint\n"
|
|
if(fails & BAD_INIT_QDEL_BEFORE)
|
|
. += "- Qdel'd in New()\n"
|
|
if(fails & BAD_INIT_SLEPT)
|
|
. += "- Slept during Initialize()\n"
|
|
|
|
/// Prepares an atom to be deleted once the atoms SS is initialized.
|
|
/datum/controller/subsystem/atoms/proc/prepare_deletion(atom/target)
|
|
if (initialized == INITIALIZATION_INNEW_REGULAR)
|
|
// Atoms SS has already completed, just kill it now.
|
|
qdel(target)
|
|
else
|
|
queued_deletions += WEAKREF(target)
|
|
|
|
/datum/controller/subsystem/atoms/Shutdown()
|
|
var/initlog = InitLog()
|
|
if(initlog)
|
|
text2file(initlog, "[GLOB.log_directory]/initialize.log")
|