Updated SSAtoms to TG's version (#18032)

* emperor protects

* sdfas

* sadf

* sdf
This commit is contained in:
Fluffy
2023-12-25 21:38:08 +01:00
committed by GitHub
parent 472d379ad7
commit a02be9f1fd
42 changed files with 495 additions and 281 deletions
+6 -1
View File
@@ -17,9 +17,11 @@
#include "code\names.dm"
#include "code\stylesheet.dm"
#include "code\__datastructures\stack.dm"
#include "code\__defines\_atoms.dm"
#include "code\__defines\_click.dm"
#include "code\__defines\_common.dm"
#include "code\__defines\_compile_helpers.dm"
#include "code\__defines\_flags.dm"
#include "code\__defines\_layers.dm"
#include "code\__defines\_macros.dm"
#include "code\__defines\_protect.dm"
@@ -128,7 +130,9 @@
#include "code\__defines\dcs\flags.dm"
#include "code\__defines\dcs\helpers.dm"
#include "code\__defines\dcs\signals.dm"
#include "code\__defines\dcs\signals_atom\signals_atom_x_act.dm"
#include "code\__defines\dcs\signals\signals_global.dm"
#include "code\__defines\dcs\signals\signals_atom\signals_atom_main.dm"
#include "code\__defines\dcs\signals\signals_atom\signals_atom_x_act.dm"
#include "code\_global_vars\edible.dm"
#include "code\_helpers\_global_objects.dm"
#include "code\_helpers\_string_lists.dm"
@@ -549,6 +553,7 @@
#include "code\game\area\ai_monitored.dm"
#include "code\game\area\area_power.dm"
#include "code\game\area\areas.dm"
#include "code\game\atom\atoms_initializing_EXPENSIVE.dm"
#include "code\game\dna\dna2.dm"
#include "code\game\dna\dna2_domutcheck.dm"
#include "code\game\dna\dna2_helpers.dm"
+12
View File
@@ -0,0 +1,12 @@
#define BAD_INIT_QDEL_BEFORE 1
#define BAD_INIT_DIDNT_INIT 2
#define BAD_INIT_SLEPT 4
#define BAD_INIT_NO_HINT 8
#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
+2
View File
@@ -0,0 +1,2 @@
///Whether /atom/Initialize() has already run for the object
#define INITIALIZED_1 (1<<5)
@@ -0,0 +1,9 @@
// Main atom signals. Format:
// When the signal is called: (signal arguments)
// All signals send the source datum of the signal as the first argument
// /atom signals
//from SSatoms InitAtom - Only if the atom was not deleted or failed initialization
#define COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZE "atom_init_success"
//from SSatoms InitAtom - Only if the atom was not deleted or failed initialization and has a loc
#define COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZED_ON "atom_init_success_on"
@@ -0,0 +1,10 @@
// Global signals. Format:
// When the signal is called: (signal arguments)
// All signals send the source datum of the signal as the first argument
// global signals
// These are signals which can be listened to by any component on any parent
// start global signals with "!", this used to be necessary but now it's just a formatting choice
/// called post /obj/item initialize (obj/item/created_item)
#define COMSIG_GLOB_ATOM_AFTER_POST_INIT "!atom_after_post_init"
+20 -8
View File
@@ -47,12 +47,15 @@
///TRUE if the INITIAL SSatoms initialization has finished, aka the atoms are initialized and mapload has finished
#define SSATOMS_IS_PROBABLY_DONE (SSatoms.initialized == INITIALIZATION_INNEW_REGULAR)
//type and all subtypes should always call Initialize in New()
///type and all subtypes should always immediately call Initialize in New()
#define INITIALIZE_IMMEDIATE(X) ##X/New(loc, ...){\
..();\
if(!initialized) {\
if(!(flags_1 & INITIALIZED_1)) {\
var/previous_initialized_value = SSatoms.initialized;\
SSatoms.initialized = INITIALIZATION_INNEW_MAPLOAD;\
args[1] = TRUE;\
SSatoms.InitAtom(src, args);\
SSatoms.InitAtom(src, FALSE, args);\
SSatoms.initialized = previous_initialized_value;\
}\
}
@@ -65,11 +68,20 @@
///New should call Initialize(FALSE)
#define INITIALIZATION_INNEW_REGULAR 1
// Initialize() hints for SSatoms.
#define INITIALIZE_HINT_NORMAL 0 //Nothing happens
#define INITIALIZE_HINT_LATELOAD 1 //Call LateInitialize
#define INITIALIZE_HINT_QDEL 2 //Call qdel on the atom
#define INITIALIZE_HINT_LATEQDEL 3 //Call qdel on the atom instead of LateInitialize
///Nothing happens.
#define INITIALIZE_HINT_NORMAL 0
/**
* call LateInitialize at the end of all atom Initalization
*
* The item will be added to the late_loaders list, this is iterated over after
* initalization of subsystems is complete and calls LateInitalize on the atom
* see [this file for the LateIntialize proc](atom.html#proc/LateInitialize)
*/
#define INITIALIZE_HINT_LATELOAD 1
///Call qdel on the atom after intialization
#define INITIALIZE_HINT_QDEL 2
// -- SSoverlays --
+10
View File
@@ -1,3 +1,13 @@
///Returns the src and all recursive contents as a list.
/atom/proc/get_all_contents(ignore_flag_1)
. = list(src)
var/i = 0
while(i < length(.))
var/atom/checked_atom = .[++i]
if(checked_atom.flags_1 & ignore_flag_1)
continue
. += checked_atom.contents
///similar function to range(), but with no limitations on the distance; will search spiralling outwards from the center
///NOT Z-Level aware
/proc/spiral_range(dist = 0, center = usr, orange = FALSE)
+19 -4
View File
@@ -30,10 +30,25 @@
world.log << "## WARNING: [msg][log_end]"
log_world("WARNING: [msg]")
//print a testing-mode debug message to world.log
/proc/testing(msg)
world.log << "## TESTING: [msg][log_end]"
log_world("TESTING: [msg]")
//print a testing-mode debug message to world.log and world
#ifdef TESTING
#define testing(msg) log_world("## TESTING: [msg]"); to_chat(world, "## TESTING: [msg]")
//When we port GLOB ...
//GLOBAL_LIST_INIT(testing_global_profiler, list("_PROFILE_NAME" = "Global"))
// we don't really check if a word or name is used twice, be aware of that
#define testing_profile_start(NAME, LIST) LIST[NAME] = world.timeofday
#define testing_profile_current(NAME, LIST) round((world.timeofday - LIST[NAME])/10,0.1)
#define testing_profile_output(NAME, LIST) testing("[LIST["_PROFILE_NAME"]] profile of [NAME] is [testing_profile_current(NAME,LIST)]s")
#define testing_profile_output_all(LIST) { for(var/_NAME in LIST) { testing_profile_current(,_NAME,LIST); }; };
#else
#define testing(msg)
#define testing_profile_start(NAME, LIST)
#define testing_profile_current(NAME, LIST)
#define testing_profile_output(NAME, LIST)
#define testing_profile_output_all(LIST)
#endif
/proc/game_log(category, text)
WRITE_LOG(diary, "[game_id] [category]: [text][log_end]")
-3
View File
@@ -9,8 +9,5 @@
. = params2list(params)
#ifdef TESTING
testing("X: [.["icon-x"]], Y: [.["icon-y"]]")
#endif
return list("icon-x" = Clamp(text2num(.["icon-x"]), 0, lim_x),
"icon-y" = Clamp(text2num(.["icon-y"]), 0, lim_y))
+5 -1
View File
@@ -31,7 +31,11 @@
/mob/abstract/oranges_ear/Initialize(mapload)
SHOULD_CALL_PARENT(FALSE)
initialized = TRUE
if(flags_1 & INITIALIZED_1)
stack_trace("Warning: [src]([type]) initialized multiple times!")
flags_1 |= INITIALIZED_1
return INITIALIZE_HINT_NORMAL
/mob/abstract/oranges_ear/Destroy(force)
+3
View File
@@ -12,6 +12,9 @@
/// Which stage does this subsystem init at. Earlier stages can fire while later stages init.
var/init_stage = INITSTAGE_MAIN
/// This var is set to TRUE after the subsystem has been initialized.
var/initialized = FALSE
/// Levels of the game that the SS can fire. See __defines/subsystem_priority.dm
var/runlevels = RUNLEVELS_DEFAULT
+1 -1
View File
@@ -23,7 +23,7 @@ SUBSYSTEM_DEF(events)
var/datum/event_meta/new_event = new
var/initialized = FALSE
initialized = FALSE
/datum/controller/subsystem/events/Initialize()
allEvents = subtypesof(/datum/event)
+1 -1
View File
@@ -55,7 +55,7 @@ SUBSYSTEM_DEF(icon_smooth)
if(QDELETED(smoothing_atom) || !(smoothing_atom.smoothing_flags & SMOOTH_QUEUED))
continue
if(smoothing_atom.initialized && !(smoothing_atom.icon_update_queued))
if((smoothing_atom.flags_1 & INITIALIZED_1) && !(smoothing_atom.icon_update_queued))
smooth_icon(smoothing_atom)
else
deferred += smoothing_atom
+1 -1
View File
@@ -33,7 +33,7 @@ SUBSYSTEM_DEF(icon_update)
var/list/argv = icon_update_queue_cache[A]
icon_update_queue_cache.len--
if(A.initialized)
if(A.flags_1 & INITIALIZED_1)
A.icon_update_queued = FALSE
//Do not target qdeleted atoms
@@ -1,10 +1,4 @@
#define SUBSYSTEM_INIT_SOURCE "subsystem init"
#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 = SS_INIT_ATOMS
@@ -15,159 +9,106 @@ SUBSYSTEM_DEF(atoms)
var/list/initialized_state = list()
var/base_initialized
var/initialized = INITIALIZATION_INSSATOMS
var/old_initialized
var/list/late_misc_firers // this is a list of things that fire when late misc init is called
var/list/late_loaders
var/list/created_atoms
var/list/late_qdel
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()
var/init_start_time
#ifdef PROFILE_MAPLOAD_INIT_ATOM
var/list/mapload_init_times = list()
#endif
initialized = INITIALIZATION_INSSATOMS
/datum/controller/subsystem/atoms/Initialize(timeofday)
init_start_time = world.time
initialized = INITIALIZATION_INNEW_MAPLOAD
InitializeAtoms()
initialized = INITIALIZATION_INNEW_REGULAR
return ..()
/datum/controller/subsystem/atoms/proc/InitializeAtoms(list/atoms)
/datum/controller/subsystem/atoms/proc/InitializeAtoms(list/atoms, list/atoms_to_return)
if(initialized == INITIALIZATION_INSSATOMS)
return
set_tracked_initalized(INITIALIZATION_INNEW_MAPLOAD, SUBSYSTEM_INIT_SOURCE)
LAZYINITLIST(late_loaders)
LAZYINITLIST(late_qdel)
var/count
var/list/mapload_arg = list(TRUE)
if(atoms)
created_atoms = list()
count = atoms.len
for(var/I in 1 to atoms.len)
var/atom/A = atoms[I]
InitAtom(A, mapload_arg)
CHECK_TICK
else
count = 0
for(var/atom/A as anything in world)
if(!A.initialized)
InitAtom(A, mapload_arg)
++count
CHECK_TICK
admin_notice(SPAN_DANGER("Initialized [count] atoms."), R_DEBUG)
log_subsystem("atoms", "Initialized [count] atoms.")
// 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(SUBSYSTEM_INIT_SOURCE)
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()
admin_notice(SPAN_DANGER("Late-initialized [late_loaders.len] atoms."), R_DEBUG)
log_subsystem("atoms", "Late initialized [late_loaders.len] atoms")
testing("Late initialized [late_loaders.len] atoms")
late_loaders.Cut()
if(late_qdel.len)
var/num_qdels = late_qdel.len
for(var/thing in late_qdel)
qdel(thing)
if (created_atoms)
atoms_to_return += created_atoms
created_atoms = null
admin_notice(SPAN_DANGER("Late-qdeleted [num_qdels] atoms."), R_DEBUG)
log_subsystem("atoms", "Late qdeleted [num_qdels] atoms.")
for (var/queued_deletion in queued_deletions)
qdel(queued_deletion)
late_qdel.Cut()
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)
. = created_atoms + atoms
created_atoms = null
// Note this doesn't actually do anything because we didn't finish porting TG init :^)
#ifdef TESTING
count = atoms.len
#endif
/datum/controller/subsystem/atoms/proc/InitAtom(atom/A, list/arguments)
var/the_type = A.type
if(QDELING(A))
BadInitializeCalls[the_type] |= BAD_INIT_QDEL_BEFORE
return TRUE
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
var/start_tick = world.time
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
var/result = A.Initialize(arglist(arguments))
if(start_tick != world.time)
BadInitializeCalls[the_type] |= BAD_INIT_SLEPT
if(result !=INITIALIZE_HINT_NORMAL)
switch(result)
if(INITIALIZE_HINT_LATELOAD)
if(arguments[1]) //mapload
late_loaders += A
else
A.LateInitialize()
if(INITIALIZE_HINT_QDEL)
qdel(A)
return TRUE
if(INITIALIZE_HINT_LATEQDEL)
if(arguments[1]) //mapload
late_qdel += A
else
qdel(A)
return TRUE
else
BadInitializeCalls[the_type] |= BAD_INIT_NO_HINT
if(!A) //possible harddel
return TRUE
else if(!A.initialized)
BadInitializeCalls[the_type] |= BAD_INIT_DIDNT_INIT
return QDELETED(A)
/datum/controller/subsystem/atoms/proc/ForceInitializeContents(atom/A)
var/list/mload_args = list(TRUE)
var/loaded = 0
set_tracked_initalized(INITIALIZATION_INNEW_MAPLOAD, SUBSYSTEM_INIT_SOURCE+"- ForceInitializeContents: [text_ref(A)]")
for (var/thing in A)
var/atom/movable/AM = thing
if (!AM.initialized)
InitAtom(AM, mload_args)
++loaded
clear_tracked_initalize(SUBSYSTEM_INIT_SOURCE+"- ForceInitializeContents: [text_ref(A)]")
LOG_DEBUG("atoms: force-loaded [loaded] out of [A.contents.len] atoms in [A].")
/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()\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"
/*datum/controller/subsystem/atoms/Shutdown()
var/initlog = InitLog()
if(initlog)
world.log << initlog*/
/datum/controller/subsystem/atoms/Recover()
initialized = SSatoms.initialized
if(initialized == INITIALIZATION_INNEW_MAPLOAD)
InitializeAtoms()
initialized_state = SSatoms.initialized_state
BadInitializeCalls = SSatoms.BadInitializeCalls
testing("Initialized [count] atoms")
/datum/controller/subsystem/atoms/proc/map_loader_begin(source)
set_tracked_initalized(INITIALIZATION_INSSATOMS, source)
@@ -201,4 +142,40 @@ SUBSYSTEM_DEF(atoms)
/datum/controller/subsystem/atoms/proc/initializing_something()
return length(initialized_state) > 1
/datum/controller/subsystem/atoms/Recover()
initialized = SSatoms.initialized
if(initialized == INITIALIZATION_INNEW_MAPLOAD)
InitializeAtoms()
initialized_state = SSatoms.initialized_state
BadInitializeCalls = SSatoms.BadInitializeCalls
/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()\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)
world.log << initlog
//text2file(initlog, "[log_directory]/initialize.log")
#undef SUBSYSTEM_INIT_SOURCE
@@ -27,9 +27,9 @@ SUBSYSTEM_DEF(misc_late)
populate_code_phrases()
// this covers mapped in drone fabs
for(var/atom/thing as anything in SSatoms.late_misc_firers)
for(var/atom/thing as anything in SSatoms.late_loaders)
thing.do_late_fire()
LAZYREMOVE(SSatoms.late_misc_firers, thing)
LAZYREMOVE(SSatoms.late_loaders, thing)
if (config.use_forumuser_api)
update_admins_from_api(TRUE)
+1 -1
View File
@@ -11,7 +11,7 @@ SUBSYSTEM_DEF(overlays)
var/idex = 1
var/list/overlay_icon_state_caches = list()
var/list/overlay_icon_cache = list()
var/initialized = FALSE
initialized = FALSE
/datum/controller/subsystem/overlays/stat_entry(msg)
msg = "Ov:[processing.len - (idex - 1)]"
@@ -0,0 +1,164 @@
/// 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))
// Check init_start_time to not worry about atoms created before the atoms SS that are cleaned up before this
if (A.gcDestroyed > init_start_time)
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_TEST
var/start_tick = world.time
#endif
var/result = A.Initialize(arglist(arguments))
#ifdef UNIT_TEST
if(start_tick != world.time)
BadInitializeCalls[the_type] |= BAD_INIT_SLEPT
#endif
var/qdeleted = FALSE
if(result != INITIALIZE_HINT_NORMAL)
switch(result)
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)
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_ATOM_AFTER_POST_INIT, A)
var/atom/location = A.loc
if(location)
/// Sends a signal that the new atom `src`, has been created at `loc`
SEND_SIGNAL(location, COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZED_ON, A, arguments[1])
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)
/**
* Called when an atom is created in byond (built in engine proc)
*
* Not a lot happens here in SS13 code, as we offload most of the work to the
* [Intialization][/atom/proc/Initialize] proc, mostly we run the preloader
* if the preloader is being used and then call [InitAtom][/datum/controller/subsystem/atoms/proc/InitAtom] of which the ultimate
* result is that the Intialize proc is called.
*
*/
/atom/New(loc, ...)
// For the DMM Suite.
if(use_preloader && (type == _preloader.target_path))//in case the instanciated atom is creating other atoms in New()
_preloader.load(src)
//. = ..() //uncomment if you are dumb enough to add a /datum/New() proc
var/do_initialize = SSatoms.initialized
if(do_initialize != INITIALIZATION_INSSATOMS)
args[1] = do_initialize == INITIALIZATION_INNEW_MAPLOAD
if(SSatoms.InitAtom(src, FALSE, args))
//we were deleted
return
/**
* The primary method that objects are setup in SS13 with
*
* we don't use New as we have better control over when this is called and we can choose
* to delay calls or hook other logic in and so forth
*
* During roundstart map parsing, atoms are queued for intialization in the base atom/New(),
* After the map has loaded, then Initalize is called on all atoms one by one. NB: this
* is also true for loading map templates as well, so they don't Initalize until all objects
* in the map file are parsed and present in the world
*
* If you're creating an object at any point after SSInit has run then this proc will be
* immediately be called from New.
*
* mapload: This parameter is true if the atom being loaded is either being intialized during
* the Atom subsystem intialization, or if the atom is being loaded from the map template.
* If the item is being created at runtime any time after the Atom subsystem is intialized then
* it's false.
*
* The mapload argument occupies the same position as loc when Initialize() is called by New().
* loc will no longer be needed after it passed New(), and thus it is being overwritten
* with mapload at the end of atom/New() before this proc (atom/Initialize()) is called.
*
* You must always call the parent of this proc, otherwise failures will occur as the item
* will not be seen as initalized (this can lead to all sorts of strange behaviour, like
* the item being completely unclickable)
*
* You must not sleep in this proc, or any subprocs
*
* Any parameters from new are passed through (excluding loc), naturally if you're loading from a map
* there are no other arguments
*
* Must return an [initialization hint][INITIALIZE_HINT_NORMAL] or a runtime will occur.
*
* Note: the following functions don't call the base for optimization and must copypasta handling:
* * [/turf/proc/Initialize]
* * [/turf/open/space/proc/Initialize]
*
* NOTE: This desc is of TG's implementation, it might not be reflective of the current one we have here
*/
/atom/proc/Initialize(mapload, ...)
SHOULD_CALL_PARENT(TRUE)
SHOULD_NOT_SLEEP(TRUE)
if(flags_1 & INITIALIZED_1)
stack_trace("Warning: [src]([type]) initialized multiple times!")
flags_1 |= INITIALIZED_1
if(LAZYLEN(reagents_to_add))
if(!reagents)
create_reagents(0)
for(var/v in reagents_to_add)
reagents.maximum_volume += max(LAZYACCESS(reagents_to_add, v) - REAGENTS_FREE_SPACE(reagents), 0)
reagents.add_reagent(v, LAZYACCESS(reagents_to_add, v), LAZYACCESS(reagent_data, v))
if (light_power && light_range)
update_light()
if (opacity && isturf(loc))
var/turf/T = loc
T.has_opaque_atom = TRUE // No need to recalculate it in this case, it's guaranteed to be on afterwards anyways.
#ifdef AO_USE_LIGHTING_OPACITY
if (!mapload)
T.regenerate_ao()
#endif
if (update_icon_on_init)
SSicon_update.add_to_queue(src)
return INITIALIZE_HINT_NORMAL
/**
* Late Intialization, for code that should run after all atoms have run Intialization
*
* To have your LateIntialize proc be called, your atoms [Initalization][/atom/proc/Initialize]
* proc must return the hint
* [INITIALIZE_HINT_LATELOAD] otherwise it will never be called.
*
* useful for doing things like finding other machines on GLOB.machines because you can guarantee
* that all atoms will actually exist in the "WORLD" at this time and that all their Intialization
* code has been run
*/
/atom/proc/LateInitialize()
set waitfor = FALSE
//You can override this in your inheritance if you *really* need to, but probably shouldn't
SHOULD_NOT_SLEEP(TRUE)
+1 -1
View File
@@ -729,7 +729,7 @@
if(SSticker.current_state == GAME_STATE_PLAYING)
do_late_fire()
return
LAZYADD(SSatoms.late_misc_firers, src)
LAZYADD(SSatoms.late_loaders, src)
/atom/proc/do_late_fire()
return
+3 -75
View File
@@ -1,81 +1,9 @@
/atom
///Whether /atom/Initialize() has already run for the object
var/initialized = FALSE
///First atom flags var
var/flags_1 = NONE
var/update_icon_on_init // Default to 'no'.
/atom/New(loc, ...)
// For the DMM Suite.
if(use_preloader && (type == _preloader.target_path))//in case the instanciated atom is creating other atoms in New()
_preloader.load(src)
//. = ..() //uncomment if you are dumb enough to add a /datum/New() proc
var/do_initialize = SSatoms.initialized
if(do_initialize > INITIALIZATION_INSSATOMS)
args[1] = do_initialize == INITIALIZATION_INNEW_MAPLOAD
if(SSatoms.InitAtom(src, args))
//we were deleted
return
var/list/created = SSatoms.created_atoms
if(created)
created += src
/atom/proc/Initialize(mapload, ...)
SHOULD_CALL_PARENT(TRUE)
SHOULD_NOT_SLEEP(TRUE)
if(initialized)
crash_with("Warning: [src]([type]) initialized multiple times!")
initialized = TRUE
if(LAZYLEN(reagents_to_add))
if(!reagents)
create_reagents(0)
for(var/v in reagents_to_add)
reagents.maximum_volume += max(LAZYACCESS(reagents_to_add, v) - REAGENTS_FREE_SPACE(reagents), 0)
reagents.add_reagent(v, LAZYACCESS(reagents_to_add, v), LAZYACCESS(reagent_data, v))
if (light_power && light_range)
update_light()
if (opacity && isturf(loc))
var/turf/T = loc
T.has_opaque_atom = TRUE // No need to recalculate it in this case, it's guaranteed to be on afterwards anyways.
#ifdef AO_USE_LIGHTING_OPACITY
if (!mapload)
T.regenerate_ao()
#endif
if (update_icon_on_init)
SSicon_update.add_to_queue(src)
return INITIALIZE_HINT_NORMAL
/**
* Late Intialization, for code that should run after all atoms have run Intialization
*
* To have your LateIntialize proc be called, your atoms [Initalization][/atom/proc/Initialize]
* proc must return the hint
* [INITIALIZE_HINT_LATELOAD] otherwise it will never be called.
*
* useful for doing things like finding other machines because you can guarantee
* that all atoms will actually exist in the "WORLD" at this time and that all their Intialization
* code has been run
*/
/atom/proc/LateInitialize()
set waitfor = FALSE
//You can override this in your inheritance if you *really* need to, but probably shouldn't
SHOULD_NOT_SLEEP(TRUE)
var/static/list/warned_types = list()
if(!warned_types[type])
WARNING("Old style LateInitialize behaviour detected in [type]!")
warned_types[type] = TRUE
Initialize(FALSE)
/atom/Destroy(force = FALSE)
if (reagents)
QDEL_NULL(reagents)
@@ -122,6 +122,11 @@
/obj/effect/decal/cleanable/foam/Initialize(mapload, amt = 1, nologs = 0)
SHOULD_CALL_PARENT(FALSE)
if(flags_1 & INITIALIZED_1)
stack_trace("Warning: [src]([type]) initialized multiple times!")
flags_1 |= INITIALIZED_1
src.amount = amt
var/has_spread = 0
@@ -133,8 +138,6 @@
has_spread = 1
break
initialized = TRUE
if(!has_spread)
Spread()
QDEL_IN(src, 2 MINUTES)
@@ -24,6 +24,10 @@
if(!current_map.use_overmap)
return ..()
if(flags_1 & INITIALIZED_1)
stack_trace("Warning: [src]([type]) initialized multiple times!")
flags_1 |= INITIALIZED_1
var/turf/T = get_turf(src)
var/obj/effect/overmap/visitable/V = map_sectors["[T.z]"]
if(istype(V) && V.comms_support)
@@ -38,7 +42,6 @@
if(use_common)
channels += list(CHANNEL_COMMON = TRUE)
initialized = TRUE
return INITIALIZE_HINT_NORMAL
/obj/item/device/encryptionkey/ship/common
@@ -452,9 +452,12 @@ pixel_x = 8;
/obj/item/device/radio/intercom/broadcasting/Initialize()
SHOULD_CALL_PARENT(FALSE)
if(flags_1 & INITIALIZED_1)
stack_trace("Warning: [src]([type]) initialized multiple times!")
flags_1 |= INITIALIZED_1
set_broadcasting(TRUE)
initialized = TRUE
return INITIALIZE_HINT_NORMAL
/obj/item/device/radio/intercom/locked
@@ -53,7 +53,10 @@
imprisoned = temporarymob
if(health == 0) //meaning if the statue didn't find a valid target
initialized = TRUE
if(flags_1 & INITIALIZED_1)
stack_trace("Warning: [src]([type]) initialized multiple times!")
flags_1 |= INITIALIZED_1
return INITIALIZE_HINT_QDEL
START_PROCESSING(SSprocessing, src)
+4 -5
View File
@@ -27,16 +27,15 @@
/turf/space/Initialize()
SHOULD_CALL_PARENT(FALSE)
if(flags_1 & INITIALIZED_1)
stack_trace("Warning: [src]([type]) initialized multiple times!")
flags_1 |= INITIALIZED_1
if(use_space_appearance)
appearance = SSskybox.space_appearance_cache[(((x + y) ^ ~(x * y) + z) % 25) + 1]
if(config.starlight && use_starlight && lighting_overlays_initialized)
update_starlight()
if (initialized)
crash_with("Warning: [src]([type]) initialized multiple times!")
initialized = TRUE
for(var/atom/movable/AM as mob|obj in src)
src.Entered(AM, AM.loc)
+3 -4
View File
@@ -59,10 +59,9 @@
/turf/Initialize(mapload, ...)
SHOULD_CALL_PARENT(FALSE)
if (initialized)
crash_with("Warning: [src]([type]) initialized multiple times!")
initialized = TRUE
if(flags_1 & INITIALIZED_1)
stack_trace("Warning: [src]([type]) initialized multiple times!")
flags_1 |= INITIALIZED_1
for(var/atom/movable/AM as mob|obj in src)
Entered(AM, src)
+5 -2
View File
@@ -50,8 +50,11 @@
/turf/unsimulated/mask/Initialize()
SHOULD_CALL_PARENT(FALSE)
initialized = TRUE
return
if(flags_1 & INITIALIZED_1)
stack_trace("Warning: [src]([type]) initialized multiple times!")
flags_1 |= INITIALIZED_1
return INITIALIZE_HINT_NORMAL
/turf/unsimulated/chasm_mask/New()
return
@@ -34,7 +34,7 @@
activate()
return INITIALIZE_HINT_LATEQDEL
return INITIALIZE_HINT_QDEL
/obj/effect/map_effect/window_spawner/proc/activate()
if(activated)
@@ -51,7 +51,7 @@ do { \
run_generator()
/obj/effect/mazegen/generator/Destroy()
LAZYREMOVE(SSatoms.late_misc_firers, src)
LAZYREMOVE(SSatoms.late_loaders, src)
return ..()
// "Push" a turf to the working "stack"
@@ -8,7 +8,7 @@
..()
parts_to_spawn = get_parts_to_spawn()
spawn_parts()
return INITIALIZE_HINT_LATEQDEL
return INITIALIZE_HINT_QDEL
/obj/effect/map_effect/mecha_part_spawner/proc/get_parts_to_spawn()
return list()
+1 -1
View File
@@ -121,7 +121,7 @@
apcs += A
if(isnull(A))
atoms -= A
if(A.initialized)
if(A.flags_1 & INITIALIZED_1)
atoms -= A
var/notsuspended
+9 -11
View File
@@ -64,14 +64,13 @@ var/list/mineral_can_smooth_with = list(
// Copypaste parent call for performance.
/turf/simulated/mineral/Initialize(mapload)
if(initialized)
crash_with("Warning: [src]([type]) initialized multiple times!")
if(flags_1 & INITIALIZED_1)
stack_trace("Warning: [src]([type]) initialized multiple times!")
flags_1 |= INITIALIZED_1
if(icon != actual_icon)
icon = actual_icon
initialized = TRUE
if(isStationLevel(z))
station_turfs += src
@@ -184,14 +183,13 @@ var/list/mineral_can_smooth_with = list(
/turf/unsimulated/mineral/asteroid/Initialize(mapload)
SHOULD_CALL_PARENT(FALSE)
if(initialized)
crash_with("Warning: [src]([type]) initialized multiple times!")
if(flags_1 & INITIALIZED_1)
stack_trace("Warning: [src]([type]) initialized multiple times!")
flags_1 |= INITIALIZED_1
if(icon != actual_icon)
icon = actual_icon
initialized = TRUE
if(isStationLevel(z))
station_turfs += src
@@ -652,9 +650,9 @@ var/list/asteroid_floor_smooth = list(
// Copypaste parent for performance.
/turf/unsimulated/floor/asteroid/Initialize(mapload)
if(initialized)
crash_with("Warning: [src]([type]) initialized multiple times!")
initialized = TRUE
if(flags_1 & INITIALIZED_1)
stack_trace("Warning: [src]([type]) initialized multiple times!")
flags_1 |= INITIALIZED_1
if(icon != base_icon) // Setting icon is an appearance change, so avoid it if we can.
icon = base_icon
@@ -227,7 +227,7 @@
SSjobs.EquipCustomDeferred(mannequin, src, leftovers, used_slots)
if (!SSATOMS_IS_PROBABLY_DONE)
SSatoms.ForceInitializeContents(mannequin)
SSatoms.CreateAtoms(list(mannequin))
mannequin.regenerate_icons()
else
mannequin.update_icon()
+4 -3
View File
@@ -27,9 +27,10 @@
/mob/living/announcer/Initialize()
// we specifically do not call parent Initialize here because this mob should not need it and its point is to be lightweight
SHOULD_CALL_PARENT(FALSE)
if(initialized)
crash_with("Warning: [src]([type]) initialized multiple times!")
initialized = TRUE
if(flags_1 & INITIALIZED_1)
stack_trace("Warning: [src]([type]) initialized multiple times!")
flags_1 |= INITIALIZED_1
for(var/K in all_languages)
add_language(K)
@@ -2,11 +2,13 @@
real_name = "Test Dummy"
status_flags = GODMODE|CANPUSH
/mob/living/carbon/human/dummy/mannequin
mob_thinks = FALSE
INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy/mannequin)
/mob/living/carbon/human/dummy/mannequin/Initialize()
. = ..()
mob_list -= src
@@ -137,9 +137,6 @@
filling.color = COLOR_PINK
add_overlay(filling)
initialized = TRUE
return INITIALIZE_HINT_NORMAL
/obj/item/docility_serum/attack(mob/living/carbon/slime/M as mob, mob/user as mob)
if(!istype(M, /mob/living/carbon/slime/))//If target is not a slime.
to_chat(user, SPAN_WARNING("The docility serum only works on slimes!"))
@@ -183,9 +180,6 @@
filling.color = COLOR_PALE_PINK
add_overlay(filling)
initialized = TRUE
return INITIALIZE_HINT_NORMAL
/obj/item/advanced_docility_serum/attack(mob/living/carbon/slime/M as mob, mob/user as mob)
if(!istype(M, /mob/living/carbon/slime/))//If target is not a slime.
to_chat(user, SPAN_WARNING("The docility serum only works on slimes!"))
@@ -226,11 +220,14 @@
/obj/item/slimesteroid/Initialize() // Better than hardsprited in stuff.
SHOULD_CALL_PARENT(FALSE)
if(flags_1 & INITIALIZED_1)
stack_trace("Warning: [src]([type]) initialized multiple times!")
flags_1 |= INITIALIZED_1
var/mutable_appearance/filling = mutable_appearance(icon, "[icon_state]-100")
filling.color = COLOR_GREEN
add_overlay(filling)
initialized = TRUE
return INITIALIZE_HINT_NORMAL
/obj/item/slimesteroid/attack(mob/living/carbon/slime/M as mob, mob/user as mob)
@@ -262,11 +259,14 @@
/obj/item/extract_enhancer/Initialize() // Better than hardsprited in stuff.
SHOULD_CALL_PARENT(FALSE)
if(flags_1 & INITIALIZED_1)
stack_trace("Warning: [src]([type]) initialized multiple times!")
flags_1 |= INITIALIZED_1
var/mutable_appearance/filling = mutable_appearance(icon, "[icon_state]-100")
filling.color = COLOR_BLUE
add_overlay(filling)
initialized = TRUE
return INITIALIZE_HINT_NORMAL
/obj/effect/golemrune
@@ -31,9 +31,6 @@
. = ..()
createCorpse()
initialized = TRUE
return INITIALIZE_HINT_NORMAL
/obj/effect/landmark/mobcorpse/proc/createCorpse() //Creates a mob and checks for gear in each slot before attempting to equip it.
var/mob/living/carbon/human/M = new /mob/living/carbon/human (src.loc)
M.real_name = src.name
+2 -2
View File
@@ -151,8 +151,8 @@
var/original_z
var/override_depth
/atom/movable/openspace/mimic/New()
initialized = TRUE
/atom/movable/openspace/mimic/Initialize(mapload, ...)
. = ..()
SSzcopy.openspace_overlays += 1
/atom/movable/openspace/mimic/Destroy()
+5 -5
View File
@@ -47,11 +47,11 @@
var/force_skintone = FALSE // If true, icon generation will skip is-robotic checks. Used for synthskin limbs.
var/list/species_restricted //used by augments and biomods to see what species can have this augment
/obj/item/organ/New(loc, ...)
..()
if (!initialized && istype(loc, /mob/living/carbon/human/dummy/mannequin))
args[1] = TRUE
SSatoms.InitAtom(src, args)
INITIALIZE_IMMEDIATE(/obj/item/organ)
/obj/item/organ/Initialize(mapload, internal)
. = ..()
/obj/item/organ/Destroy()
STOP_PROCESSING(SSprocessing, src)
+4 -1
View File
@@ -322,6 +322,10 @@ var/list/GPS_list = list()
/obj/item/device/gps/stationary/Initialize()
SHOULD_CALL_PARENT(FALSE)
if(flags_1 & INITIALIZED_1)
stack_trace("Warning: [src]([type]) initialized multiple times!")
flags_1 |= INITIALIZED_1
compass = new(src)
update_position()
@@ -352,7 +356,6 @@ var/list/GPS_list = list()
START_PROCESSING(SSprocessing, src)
initialized = TRUE
return INITIALIZE_HINT_NORMAL
/obj/item/device/gps/stationary/attack_hand() // Don't let users pick it up.
@@ -0,0 +1,52 @@
################################
# Example Changelog File
#
# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb.
#
# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.)
# When it is, any changes listed below will disappear.
#
# Valid Prefixes:
# bugfix
# wip (For works in progress)
# tweak
# soundadd
# sounddel
# rscadd (general adding of nice things)
# rscdel (general deleting of nice things)
# imageadd
# imagedel
# maptweak
# spellcheck (typo fixes)
# experiment
# balance
# admin
# backend
# security
# refactor
#################################
# Your name.
author: FluffyGhost
# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again.
delete-after: True
# Any changes you've made. See valid prefix list above.
# INDENT WITH TWO SPACES. NOT TABS. SPACES.
# SCREW THIS UP AND IT WON'T WORK.
# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries.
# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog.
changes:
- backend: "Updated SSAtoms to TG's version."
- backend: "Added signals for initialization, repathed old signal_athom_x_act.dm to its updated home."
- backend: "Moved /atom initialization related procs in atom/atoms_initializing_EXPENSIVE.dm as per TG."
- backend: "Updated INITIALIZE_IMMEDIATE to work with the new subsystem."
- backend: "Adapted various procs and other subsystems to work with the new SSAtoms."
- backend: "Reordered some procs to set the initialization flag at the start, as that is the supposed behavior."
- backend: "Transformed the testing() proc to a macro, as per TG."
- backend: "Cleaned up some initializations a bit."
- backend: "Flagged organs for immediate initialization."
- backend: "Initialized variable is now flags_1, as per TG."
- backend: "The Initialized variable is now global for every subsytem."
- backend: "Various reordering and flags/defines additions."