mirror of
https://github.com/PolarisSS13/Polaris.git
synced 2025-12-14 20:22:42 +00:00
jiggle SSatoms gently
This commit is contained in:
@@ -1,156 +1,119 @@
|
||||
#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
|
||||
|
||||
// override and GetArguments() exists for mod-override/downstream hook functionality.
|
||||
// Useful for total-overhaul type modifications.
|
||||
var/adjust_init_arguments = FALSE
|
||||
// Bad initialization types.
|
||||
var/const/QDEL_BEFORE_INITIALIZE = 1
|
||||
var/const/DID_NOT_SET_INITIALIZED = 2
|
||||
var/const/SLEPT_IN_INITIALIZE = 4
|
||||
var/const/DID_NOT_RETURN_HINT = 8
|
||||
|
||||
var/atom_init_stage = INITIALIZATION_INSSATOMS
|
||||
var/old_init_stage
|
||||
var/static/atom_init_stage = INITIALIZATION_INSSATOMS
|
||||
var/static/old_init_stage
|
||||
var/static/list/late_loaders = list()
|
||||
var/static/list/created_atoms = list()
|
||||
var/static/list/bad_init_calls = list()
|
||||
|
||||
var/list/late_loaders
|
||||
var/list/BadInitializeCalls = list()
|
||||
|
||||
/datum/controller/subsystem/atoms/Initialize(timeofday)
|
||||
/datum/controller/subsystem/atoms/Initialize(start_uptime)
|
||||
atom_init_stage = INITIALIZATION_INNEW_MAPLOAD
|
||||
InitializeAtoms()
|
||||
|
||||
/datum/controller/subsystem/atoms/proc/InitializeAtoms(var/list/supplied_atoms)
|
||||
|
||||
if(atom_init_stage <= INITIALIZATION_INSSATOMS_LATE)
|
||||
return
|
||||
|
||||
atom_init_stage = INITIALIZATION_INNEW_MAPLOAD
|
||||
|
||||
LAZYINITLIST(late_loaders)
|
||||
|
||||
var/list/mapload_arg = list(TRUE)
|
||||
var/count = LAZYLEN(supplied_atoms)
|
||||
if(count)
|
||||
while(supplied_atoms.len)
|
||||
var/atom/A = supplied_atoms[supplied_atoms.len]
|
||||
supplied_atoms.len--
|
||||
if(!A.initialized)
|
||||
InitAtom(A, GetArguments(A, mapload_arg))
|
||||
CHECK_TICK
|
||||
else if(!subsystem_initialized)
|
||||
// If wondering why not just store all atoms in a list and use the block above: that turns out unbearably expensive.
|
||||
// Instead, atoms without extra arguments in New created on server start are fished out of world directly.
|
||||
// We do this exactly once.
|
||||
|
||||
for(var/atom/A in world)
|
||||
if(!A.initialized)
|
||||
InitAtom(A, GetArguments(A, mapload_arg, FALSE))
|
||||
++count
|
||||
CHECK_TICK
|
||||
|
||||
report_progress("Initialized [count] atom\s")
|
||||
|
||||
atom_init_stage = INITIALIZATION_INNEW_REGULAR
|
||||
|
||||
if(late_loaders.len)
|
||||
for(var/I in late_loaders)
|
||||
var/atom/A = I
|
||||
A.LateInitialize(arglist(late_loaders[A]))
|
||||
report_progress("Late initialized [late_loaders.len] atom\s")
|
||||
late_loaders.Cut()
|
||||
|
||||
/datum/controller/subsystem/atoms/proc/InitAtom(atom/A, list/arguments)
|
||||
LAZYREMOVE(global.pre_init_created_atoms, A)
|
||||
var/the_type = A.type
|
||||
if(QDELING(A))
|
||||
BadInitializeCalls[the_type] |= BAD_INIT_QDEL_BEFORE
|
||||
return TRUE
|
||||
|
||||
var/start_tick = world.time
|
||||
|
||||
var/result = A.Initialize(arglist(arguments))
|
||||
|
||||
if(start_tick != world.time)
|
||||
BadInitializeCalls[the_type] |= BAD_INIT_SLEPT
|
||||
|
||||
var/qdeleted = FALSE
|
||||
|
||||
if(result != INITIALIZE_HINT_NORMAL)
|
||||
switch(result)
|
||||
if(INITIALIZE_HINT_LATELOAD)
|
||||
if(arguments[1]) //mapload
|
||||
late_loaders[A] = arguments
|
||||
else
|
||||
A.LateInitialize(arglist(arguments))
|
||||
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.initialized)
|
||||
BadInitializeCalls[the_type] |= BAD_INIT_DIDNT_INIT
|
||||
|
||||
return qdeleted || QDELING(A)
|
||||
|
||||
// override and GetArguments() exists for mod-override/downstream hook functionality.
|
||||
// Useful for total-overhaul type modifications.
|
||||
/atom/proc/AdjustInitializeArguments(list/arguments)
|
||||
// Lists are passed by reference so can simply modify the arguments list without returning it
|
||||
|
||||
/datum/controller/subsystem/atoms/proc/GetArguments(atom/A, list/mapload_arg, created=TRUE)
|
||||
if(!created && !adjust_init_arguments)
|
||||
return mapload_arg // Performance optimization. Nothing to do.
|
||||
var/list/arguments = mapload_arg.Copy()
|
||||
var/extra_args = LAZYACCESS(global.pre_init_created_atoms, A)
|
||||
if(created && extra_args)
|
||||
arguments += extra_args
|
||||
if(adjust_init_arguments)
|
||||
A.AdjustInitializeArguments(arguments)
|
||||
return arguments
|
||||
|
||||
/datum/controller/subsystem/atoms/stat_entry(msg)
|
||||
..("Bad Initialize Calls:[BadInitializeCalls.len]")
|
||||
|
||||
/datum/controller/subsystem/atoms/proc/map_loader_begin()
|
||||
old_init_stage = atom_init_stage
|
||||
atom_init_stage = INITIALIZATION_INSSATOMS_LATE
|
||||
|
||||
/datum/controller/subsystem/atoms/proc/map_loader_stop()
|
||||
atom_init_stage = old_init_stage
|
||||
|
||||
/datum/controller/subsystem/atoms/Recover()
|
||||
atom_init_stage = SSatoms.atom_init_stage
|
||||
if(atom_init_stage == INITIALIZATION_INNEW_MAPLOAD)
|
||||
created_atoms.Cut()
|
||||
late_loaders.Cut()
|
||||
if (atom_init_stage == INITIALIZATION_INNEW_MAPLOAD)
|
||||
InitializeAtoms()
|
||||
old_init_stage = SSatoms.old_init_stage
|
||||
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"
|
||||
|
||||
/datum/controller/subsystem/atoms/Shutdown()
|
||||
var/initlog = InitLog()
|
||||
if(initlog)
|
||||
text2file(initlog, "[log_path]-initialize.log")
|
||||
if (!initlog)
|
||||
return
|
||||
text2file(initlog, "[log_path]/initialize.log")
|
||||
|
||||
#undef BAD_INIT_QDEL_BEFORE
|
||||
#undef BAD_INIT_DIDNT_INIT
|
||||
#undef BAD_INIT_SLEPT
|
||||
#undef BAD_INIT_NO_HINT
|
||||
|
||||
/datum/controller/subsystem/atoms/proc/InitializeAtoms()
|
||||
if (atom_init_stage <= INITIALIZATION_INSSATOMS_LATE)
|
||||
return
|
||||
atom_init_stage = INITIALIZATION_INNEW_MAPLOAD
|
||||
var/list/mapload_arg = list(TRUE)
|
||||
var/count = 0
|
||||
var/atom/created
|
||||
var/list/arguments
|
||||
for (var/i = 1 to length(created_atoms))
|
||||
created = created_atoms[i]
|
||||
if (!created.initialized)
|
||||
arguments = created_atoms[created] ? mapload_arg + created_atoms[created] : mapload_arg
|
||||
InitAtom(created, arguments)
|
||||
CHECK_TICK
|
||||
created_atoms.Cut()
|
||||
if (!subsystem_initialized)
|
||||
for (var/atom/atom in world)
|
||||
if (!atom.initialized)
|
||||
InitAtom(atom, mapload_arg)
|
||||
++count
|
||||
CHECK_TICK
|
||||
report_progress("Initialized [count] atom\s")
|
||||
atom_init_stage = INITIALIZATION_INNEW_REGULAR
|
||||
if (!length(late_loaders))
|
||||
return
|
||||
for (var/atom/atom as anything in late_loaders)
|
||||
atom.LateInitialize(arglist(late_loaders[atom]))
|
||||
report_progress("Late initialized [length(late_loaders)] atom\s")
|
||||
late_loaders.Cut()
|
||||
|
||||
|
||||
/datum/controller/subsystem/atoms/proc/InitAtom(atom/atom, list/arguments)
|
||||
var/atom_type = atom?.type
|
||||
if (QDELING(atom))
|
||||
bad_init_calls[atom_type] |= QDEL_BEFORE_INITIALIZE
|
||||
return TRUE
|
||||
var/start_tick = world.time
|
||||
var/result = atom.Initialize(arglist(arguments))
|
||||
if (start_tick != world.time)
|
||||
bad_init_calls[atom_type] |= SLEPT_IN_INITIALIZE
|
||||
var/qdeleted = FALSE
|
||||
if (result != INITIALIZE_HINT_NORMAL)
|
||||
switch (result)
|
||||
if (INITIALIZE_HINT_LATELOAD)
|
||||
if (arguments[1]) //mapload
|
||||
late_loaders[atom] = arguments
|
||||
else
|
||||
atom.LateInitialize(arglist(arguments))
|
||||
if (INITIALIZE_HINT_QDEL)
|
||||
qdel(atom)
|
||||
qdeleted = TRUE
|
||||
else
|
||||
bad_init_calls[atom_type] |= DID_NOT_RETURN_HINT
|
||||
if (!atom)
|
||||
qdeleted = TRUE
|
||||
else if (!atom.initialized)
|
||||
bad_init_calls[atom_type] |= DID_NOT_SET_INITIALIZED
|
||||
return qdeleted || QDELING(atom)
|
||||
|
||||
|
||||
/datum/controller/subsystem/atoms/proc/BeginMapLoad()
|
||||
old_init_stage = atom_init_stage
|
||||
atom_init_stage = INITIALIZATION_INSSATOMS_LATE
|
||||
|
||||
|
||||
/datum/controller/subsystem/atoms/proc/FinishMapLoad()
|
||||
atom_init_stage = old_init_stage
|
||||
|
||||
|
||||
/datum/controller/subsystem/atoms/proc/InitLog()
|
||||
. = ""
|
||||
for (var/path in bad_init_calls)
|
||||
. += "Path : [path] \n"
|
||||
var/fails = bad_init_calls[path]
|
||||
if (fails & DID_NOT_SET_INITIALIZED)
|
||||
. += "- Didn't call atom/Initialize()\n"
|
||||
if (fails & DID_NOT_RETURN_HINT)
|
||||
. += "- Didn't return an Initialize hint\n"
|
||||
if (fails & QDEL_BEFORE_INITIALIZE)
|
||||
. += "- Qdel'd in New()\n"
|
||||
if (fails & SLEPT_IN_INITIALIZE)
|
||||
. += "- Slept during Initialize()\n"
|
||||
|
||||
@@ -404,13 +404,13 @@
|
||||
// As this is only done at runtime, we have to create all the vending machines in existence and force them
|
||||
// to register their products when this asset initializes.
|
||||
/datum/asset/spritesheet/vending/proc/populate_vending_products()
|
||||
SSatoms.map_loader_begin()
|
||||
SSatoms.BeginMapLoad()
|
||||
for(var/path in subtypesof(/obj/machinery/vending))
|
||||
var/obj/machinery/vending/x = new path(null)
|
||||
// force an inventory build; with map_loader_begin active, init isn't called
|
||||
// force an inventory build; with BeginMapLoad active, init isn't called
|
||||
x.build_inventory()
|
||||
qdel(x)
|
||||
SSatoms.map_loader_stop()
|
||||
SSatoms.FinishMapLoad()
|
||||
|
||||
// /datum/asset/simple/genetics
|
||||
// assets = list(
|
||||
|
||||
@@ -366,7 +366,7 @@ var/global/use_preloader = FALSE
|
||||
first_turf_index++
|
||||
|
||||
//turn off base new Initialization until the whole thing is loaded
|
||||
SSatoms.map_loader_begin()
|
||||
SSatoms.BeginMapLoad()
|
||||
//instanciate the first /turf
|
||||
var/turf/T
|
||||
if(members[first_turf_index] != /turf/template_noop)
|
||||
@@ -385,7 +385,7 @@ var/global/use_preloader = FALSE
|
||||
for(index in 1 to first_turf_index-1)
|
||||
instance_atom(members[index],members_attributes[index],crds,no_changeturf,orientation)
|
||||
//Restore initialization to the previous value
|
||||
SSatoms.map_loader_stop()
|
||||
SSatoms.FinishMapLoad()
|
||||
|
||||
////////////////
|
||||
//Helpers procs
|
||||
@@ -406,9 +406,9 @@ var/global/use_preloader = FALSE
|
||||
|
||||
//custom CHECK_TICK here because we don't want things created while we're sleeping to not initialize
|
||||
if(TICK_CHECK)
|
||||
SSatoms.map_loader_stop()
|
||||
SSatoms.FinishMapLoad()
|
||||
stoplag()
|
||||
SSatoms.map_loader_begin()
|
||||
SSatoms.BeginMapLoad()
|
||||
|
||||
// Rotate the atom now that it exists, rather than changing its orientation beforehand through the fields["dir"]
|
||||
if(orientation != 0) // 0 means no rotation
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
name = "SUBSYSTEM - ATOMS: Shall have no bad init calls"
|
||||
|
||||
/datum/unit_test/subsystem_atom_shall_have_no_bad_init_calls/start_test()
|
||||
if(SSatoms.BadInitializeCalls.len)
|
||||
if(SSatoms.bad_init_calls.len)
|
||||
log_bad(jointext(SSatoms.InitLog(), null))
|
||||
fail("[SSatoms] had bad initialization calls.")
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user