diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm index 0b27e01326..c0b9a20d3b 100644 --- a/code/__DEFINES/subsystems.dm +++ b/code/__DEFINES/subsystems.dm @@ -20,6 +20,24 @@ #define FLIGHTSUIT_PROCESSING_NONE 0 #define FLIGHTSUIT_PROCESSING_FULL 1 +#define INITIALIZATION_INSSATOMS 0 //New should not call Initialize +#define INITIALIZATION_INNEW_MAPLOAD 1 //New should call Initialize(TRUE) +#define INITIALIZATION_INNEW_REGULAR 2 //New should call Initialize(FALSE) + +#define INITIALIZE_HINT_NORMAL 0 //Nothing happens +#define INITIALIZE_HINT_LATELOAD 1 //Call LateInitialize +#define INITIALIZE_HINT_QDEL 2 //Call qdel on the atom + +//type and all subtypes should always call Initialize in New() +#define INITIALIZE_IMMEDIATE(X) ##X/New(loc, ...){\ + ..();\ + if(!initialized) {\ + args[1] = TRUE;\ + SSatoms.InitAtom(src, args);\ + }\ +} + + // Subsystem init_order, from highest priority to lowest priority // The numbers just define the ordering, they are meaningless otherwise. diff --git a/code/controllers/subsystem/atoms.dm b/code/controllers/subsystem/atoms.dm index 487946696d..711da25889 100644 --- a/code/controllers/subsystem/atoms.dm +++ b/code/controllers/subsystem/atoms.dm @@ -2,32 +2,35 @@ #define BAD_INIT_DIDNT_INIT 2 #define BAD_INIT_SLEPT 4 #define BAD_INIT_NO_HINT 8 - -SUBSYSTEM_DEF(atoms) - name = "Atoms" + +SUBSYSTEM_DEF(atoms) + name = "Atoms" init_order = INIT_ORDER_ATOMS - flags = SS_NO_FIRE - - var/initialized = INITIALIZATION_INSSATOMS - var/old_initialized - - var/list/late_loaders - -/datum/controller/subsystem/atoms/Initialize(timeofday) - GLOB.fire_overlay.appearance_flags = RESET_COLOR - setupGenetics() //to set the mutations' place in structural enzymes, so monkey.initialize() knows where to put the monkey mutation. - initialized = INITIALIZATION_INNEW_MAPLOAD - InitializeAtoms() - return ..() - + flags = SS_NO_FIRE + + var/initialized = INITIALIZATION_INSSATOMS + var/old_initialized + + var/list/late_loaders + var/list/created_atoms + + var/list/BadInitializeCalls = list() + +/datum/controller/subsystem/atoms/Initialize(timeofday) + GLOB.fire_overlay.appearance_flags = RESET_COLOR + setupGenetics() //to set the mutations' place in structural enzymes, so monkey.initialize() knows where to put the monkey mutation. + initialized = INITIALIZATION_INNEW_MAPLOAD + InitializeAtoms() + return ..() + /datum/controller/subsystem/atoms/proc/InitializeAtoms(list/atoms) - if(initialized == INITIALIZATION_INSSATOMS) - return - + if(initialized == INITIALIZATION_INSSATOMS) + return + initialized = INITIALIZATION_INNEW_MAPLOAD LAZYINITLIST(late_loaders) - + var/count var/list/mapload_arg = list(TRUE) if(atoms) @@ -57,10 +60,10 @@ SUBSYSTEM_DEF(atoms) A.LateInitialize() testing("Late initialized [late_loaders.len] atoms") late_loaders.Cut() - + if(atoms) . = created_atoms + atoms - created_atoms = null + created_atoms = null /datum/controller/subsystem/atoms/proc/InitAtom(atom/A, list/arguments) var/the_type = A.type @@ -74,7 +77,7 @@ SUBSYSTEM_DEF(atoms) if(start_tick != world.time) BadInitializeCalls[the_type] |= BAD_INIT_SLEPT - + var/qdeleted = FALSE if(result != INITIALIZE_HINT_NORMAL) @@ -89,43 +92,67 @@ SUBSYSTEM_DEF(atoms) 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 || QDELETED(A) - -/datum/controller/subsystem/atoms/proc/map_loader_begin() - old_initialized = initialized - initialized = INITIALIZATION_INSSATOMS - -/datum/controller/subsystem/atoms/proc/map_loader_stop() - initialized = old_initialized - -/datum/controller/subsystem/atoms/Recover() - initialized = SSatoms.initialized - if(initialized == INITIALIZATION_INNEW_MAPLOAD) - InitializeAtoms() - old_initialized = SSatoms.old_initialized + +/datum/controller/subsystem/atoms/proc/map_loader_begin() + old_initialized = initialized + initialized = INITIALIZATION_INSSATOMS + +/datum/controller/subsystem/atoms/proc/map_loader_stop() + 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/avnums = new /list(DNA_STRUC_ENZYMES_BLOCKS) - for(var/i=1, i<=DNA_STRUC_ENZYMES_BLOCKS, i++) - avnums[i] = i - CHECK_TICK - - for(var/A in subtypesof(/datum/mutation/human)) - var/datum/mutation/human/B = new A() - if(B.dna_block == NON_SCANNABLE) - continue - B.dna_block = pick_n_take(avnums) - 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/setupGenetics() + var/list/avnums = new /list(DNA_STRUC_ENZYMES_BLOCKS) + for(var/i=1, i<=DNA_STRUC_ENZYMES_BLOCKS, i++) + avnums[i] = i + CHECK_TICK + + for(var/A in subtypesof(/datum/mutation/human)) + var/datum/mutation/human/B = new A() + if(B.dna_block == NON_SCANNABLE) + continue + B.dna_block = pick_n_take(avnums) + 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()\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) + log_world(initlog) + +#undef BAD_INIT_QDEL_BEFORE +#undef BAD_INIT_DIDNT_INIT +#undef BAD_INIT_SLEPT +#undef BAD_INIT_NO_HINT diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 22045b99ff..19e2c372b3 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -166,8 +166,10 @@ GLOBAL_LIST_INIT(admin_verbs_debug, AVerbsDebug()) //citadel code /client/proc/give_humans_genitals, /client/proc/test_mammal_overlays, - /client/proc/pump_random_event + /client/proc/pump_random_event, + /client/proc/cmd_display_init_log ) + GLOBAL_PROTECT(admin_verbs_possess) GLOBAL_LIST_INIT(admin_verbs_possess, list(/proc/possess,/proc/release)) GLOBAL_PROTECT(admin_verbs_permissions) diff --git a/code/modules/holodeck/computer.dm b/code/modules/holodeck/computer.dm index 18be292e97..7947ef4413 100644 --- a/code/modules/holodeck/computer.dm +++ b/code/modules/holodeck/computer.dm @@ -45,52 +45,52 @@ var/list/effects = list() var/last_change = 0 - + /obj/machinery/computer/holodeck/Initialize(mapload) - . = mapload //late-initialize, area_copy need turfs to have air - if(!mapload) - ..() + ..() + return INITIALIZE_HINT_LATELOAD - if(ispath(holodeck_type,/area)) - var/list/possible = get_areas(holodeck_type,subtypes = FALSE) - linked = pop(possible) - if(ispath(offline_program,/area)) - var/list/possible = get_areas(offline_program,subtypes = FALSE) - offline_program = pop(possible) - // the following is necessary for power reasons - if(!linked || !offline_program) - log_world("No matching holodeck area found") - qdel(src) - return - var/area/AS = get_area(src) - if(istype(AS,/area/holodeck)) - log_world("### MAPPING ERROR") - log_world("Holodeck computer cannot be in a holodeck.") - log_world("This would cause circular power dependency.") - qdel(src) // todo handle constructed computers - return //l-lewd... - else - linked.linked = src // todo detect multiple/constructed computers +/obj/machinery/computer/holodeck/LateInitialize() + if(ispath(holodeck_type,/area)) + var/list/possible = get_areas(holodeck_type,subtypes = FALSE) + linked = pop(possible) + if(ispath(offline_program,/area)) + var/list/possible = get_areas(offline_program,subtypes = FALSE) + offline_program = pop(possible) + // the following is necessary for power reasons + if(!linked || !offline_program) + log_world("No matching holodeck area found") + qdel(src) + return + var/area/AS = get_area(src) + if(istype(AS,/area/holodeck)) + log_world("### MAPPING ERROR") + log_world("Holodeck computer cannot be in a holodeck.") + log_world("This would cause circular power dependency.") + qdel(src) // todo handle constructed computers + return //l-lewd... + else + linked.linked = src // todo detect multiple/constructed computers - program_cache = list() - emag_programs = list() - for(var/typekey in subtypesof(program_type)) - var/area/holodeck/A = locate(typekey) - if(!A || A == offline_program) - continue - if(A.contents.len == 0) - continue // not loaded - if(A.restricted) - emag_programs += A - else - program_cache += A - if(typekey == init_program) - load_program(A,force=1) - if(random_program && program_cache.len && init_program == null) - load_program(pick(program_cache),force=1) - else if(!program) - load_program(offline_program) + program_cache = list() + emag_programs = list() + for(var/typekey in subtypesof(program_type)) + var/area/holodeck/A = locate(typekey) + if(!A || A == offline_program) + continue + if(A.contents.len == 0) + continue // not loaded + if(A.restricted) + emag_programs += A + else + program_cache += A + if(typekey == init_program) + load_program(A,force=1) + if(random_program && program_cache.len && init_program == null) + load_program(pick(program_cache),force=1) + else if(!program) + load_program(offline_program) /obj/machinery/computer/holodeck/power_change() ..() diff --git a/code/modules/mob/dead/new_player/new_player.dm b/code/modules/mob/dead/new_player/new_player.dm index 72f83bf546..e6adb53ff6 100644 --- a/code/modules/mob/dead/new_player/new_player.dm +++ b/code/modules/mob/dead/new_player/new_player.dm @@ -30,6 +30,7 @@ loc = pick(GLOB.newplayer_start) else loc = locate(1,1,1) + return INITIALIZE_HINT_NORMAL /mob/dead/new_player/proc/new_player_panel() @@ -48,11 +49,11 @@ output += "

Observe

" if(!IsGuestKey(src.key)) - if (SSdbcore.Connect()) + if (SSdbcore.Connect()) var/isadmin = 0 if(src.client && src.client.holder) isadmin = 1 - var/datum/DBQuery/query_get_new_polls = SSdbcore.NewQuery("SELECT id FROM [format_table_name("poll_question")] WHERE [(isadmin ? "" : "adminonly = false AND")] Now() BETWEEN starttime AND endtime AND id NOT IN (SELECT pollid FROM [format_table_name("poll_vote")] WHERE ckey = \"[ckey]\") AND id NOT IN (SELECT pollid FROM [format_table_name("poll_textreply")] WHERE ckey = \"[ckey]\")") + var/datum/DBQuery/query_get_new_polls = SSdbcore.NewQuery("SELECT id FROM [format_table_name("poll_question")] WHERE [(isadmin ? "" : "adminonly = false AND")] Now() BETWEEN starttime AND endtime AND id NOT IN (SELECT pollid FROM [format_table_name("poll_vote")] WHERE ckey = \"[ckey]\") AND id NOT IN (SELECT pollid FROM [format_table_name("poll_textreply")] WHERE ckey = \"[ckey]\")") if(!query_get_new_polls.Execute()) return var/newpoll = 0 @@ -302,7 +303,7 @@ if(!IsJobAvailable(rank)) alert(src, "[rank] is not available. Please try another.") return 0 - + if(SSticker.late_join_disabled) alert(src, "An administrator has disabled late join spawning.") return FALSE diff --git a/code/modules/recycling/conveyor2.dm b/code/modules/recycling/conveyor2.dm index 264b6a167d..68190f5e45 100644 --- a/code/modules/recycling/conveyor2.dm +++ b/code/modules/recycling/conveyor2.dm @@ -212,13 +212,14 @@ /obj/machinery/conveyor_switch/Initialize(mapload, newid) - if(mapload) - return TRUE //need machines list - . = ..() + ..() if(!id) id = newid update() + return INITIALIZE_HINT_LATELOAD //for machines list + +/obj/machinery/conveyor_switch/LateInitialize() conveyors = list() for(var/obj/machinery/conveyor/C in GLOB.machines) if(C.id == id) diff --git a/code/modules/shuttle/arrivals.dm b/code/modules/shuttle/arrivals.dm index b4af9d9e17..6b0279e859 100644 --- a/code/modules/shuttle/arrivals.dm +++ b/code/modules/shuttle/arrivals.dm @@ -22,20 +22,22 @@ var/perma_docked = FALSE //highlander with RESPAWN??? OH GOD!!! /obj/docking_port/mobile/arrivals/Initialize(mapload) - if(mapload) - return TRUE //late initialize to make sure the latejoin list is populated - preferred_direction = dir if(SSshuttle.arrivals) WARNING("More than one arrivals docking_port placed on map!") - qdel(src) - return + + return INITIALIZE_HINT_QDEL SSshuttle.arrivals = src - . = ..() + . = ..() + preferred_direction = dir + return INITIALIZE_HINT_LATELOAD //for latejoin list + + +/obj/docking_port/mobile/arrivals/LateInitialize() areas = list() var/list/new_latejoin = list() diff --git a/code/modules/surgery/surgery.dm b/code/modules/surgery/surgery.dm index 93acbfbb91..f9a3b5c0cf 100644 --- a/code/modules/surgery/surgery.dm +++ b/code/modules/surgery/surgery.dm @@ -54,7 +54,7 @@ return new step_type /datum/surgery/proc/complete() - feedback_add_details("surgeries_completed", type) + feedback_add_details("surgeries_completed", "[type]") qdel(src)