diff --git a/code/__DEFINES/MC.dm b/code/__DEFINES/MC.dm index 0b9a85d9194..e2452ff032b 100644 --- a/code/__DEFINES/MC.dm +++ b/code/__DEFINES/MC.dm @@ -80,6 +80,17 @@ }\ /datum/controller/subsystem/timer/##X +<<<<<<< HEAD +======= +#define MOVEMENT_SUBSYSTEM_DEF(X) GLOBAL_REAL(SS##X, /datum/controller/subsystem/movement/##X);\ +/datum/controller/subsystem/movement/##X/New(){\ + NEW_SS_GLOBAL(SS##X);\ + PreInit();\ + ss_id="movement_[#X]";\ +}\ +/datum/controller/subsystem/movement/##X + +>>>>>>> bdeb199b49... Revert "Brings our MC up to date with TG (#7285)" (#7597) #define PROCESSING_SUBSYSTEM_DEF(X) GLOBAL_REAL(SS##X, /datum/controller/subsystem/processing/##X);\ /datum/controller/subsystem/processing/##X/New(){\ NEW_SS_GLOBAL(SS##X);\ diff --git a/code/controllers/failsafe.dm b/code/controllers/failsafe.dm index db856847673..8079a666519 100644 --- a/code/controllers/failsafe.dm +++ b/code/controllers/failsafe.dm @@ -92,6 +92,61 @@ GLOBAL_REAL(Failsafe, /datum/controller/failsafe) defcon = 5 sleep(initial(processing_interval)) +<<<<<<< HEAD +======= +//Emergency loop used when Master got deleted or the main loop exited while Defcon == 0 +//Loop is driven externally so runtimes only cancel the current recovery attempt +/datum/controller/failsafe/proc/emergency_loop() + //The code in this proc should be kept as simple as possible, anything complicated like to_chat might rely on master existing and runtime + //The goal should always be to get a new Master up and running before anything else + . = -1 + switch (defcon) //The lower defcon goes the harder we try to fix the MC + if (2 to 3) //Try to normally recreate the MC two times + . = Recreate_MC() + if (1) //Delete the old MC first so we don't transfer any info, in case that caused any issues + del(Master) + . = Recreate_MC() + + if (. == 1) //We were able to create a new master + to_chat_immediate(world, "Master Controller failure detected. Attempting recovery.\nThings may freeze up for a minute or two (or break entirely).") + master_iteration = 0 + SSticker.Recover() //Recover the ticket system so the Masters runlevel gets set + Master.Initialize(10, FALSE, TRUE) //Need to manually start the MC, normally world.new would do this + to_chat(GLOB.admins, "Failsafe recovered MC while in emergency state [defcon_pretty()]") + else + log_game("FailSafe: Failsafe in emergency state and was unable to recreate MC while in defcon state [defcon_pretty()].") + message_admins("Failsafe in emergency state and master down, trying to recreate MC while in defcon level [defcon_pretty()] failed.") + +///Recreate all SSs which will still cause data survive due to Recover(), the new Master will then find and take them from global.vars +/proc/recover_all_SS_and_recreate_master() + del(Master) + var/list/subsytem_types = subtypesof(/datum/controller/subsystem) + sortTim(subsytem_types, /proc/cmp_subsystem_init) + for(var/I in subsytem_types) + new I + . = Recreate_MC() + if (. == 1) //We were able to create a new master + SSticker.Recover() //Recover the ticket system so the Masters runlevel gets set + Master.Initialize(10, FALSE, TRUE) //Need to manually start the MC, normally world.new would do this + to_chat(GLOB.admins, "MC successfully recreated after recovering all subsystems!") + else + message_admins("Failed to create new MC!") + +///Delete all existing SS to basically start over +/proc/delete_all_SS_and_recreate_master() + del(Master) + for(var/global_var in global.vars) + if (istype(global.vars[global_var], /datum/controller/subsystem)) + del(global.vars[global_var]) + . = Recreate_MC() + if (. == 1) //We were able to create a new master + SSticker.Recover() //Recover the ticket system so the Masters runlevel gets set + Master.Initialize(10, FALSE, TRUE) //Need to manually start the MC, normally world.new would do this + to_chat(GLOB.admins, "MC successfully recreated after deleting and recreating all subsystems!") + else + message_admins("Failed to create new MC!") + +>>>>>>> bdeb199b49... Revert "Brings our MC up to date with TG (#7285)" (#7597) /datum/controller/failsafe/proc/defcon_pretty() return defcon diff --git a/code/controllers/globals.dm b/code/controllers/globals.dm index fea1fd209ef..cd051e24c47 100644 --- a/code/controllers/globals.dm +++ b/code/controllers/globals.dm @@ -20,8 +20,14 @@ GLOBAL_REAL(GLOB, /datum/controller/global_vars) Initialize() +<<<<<<< HEAD /datum/controller/global_vars/Destroy() //fuck off kevinz +======= +/datum/controller/global_vars/Destroy(force) + // This is done to prevent an exploit where admins can get around protected vars + SHOULD_CALL_PARENT(0) +>>>>>>> bdeb199b49... Revert "Brings our MC up to date with TG (#7285)" (#7597) return QDEL_HINT_IWILLGC /datum/controller/global_vars/stat_entry() diff --git a/code/controllers/master.dm b/code/controllers/master.dm index f20856bc01c..2f297fba55d 100644 --- a/code/controllers/master.dm +++ b/code/controllers/master.dm @@ -84,11 +84,30 @@ GLOBAL_REAL(Master, /datum/controller/master) = new Recover() qdel(Master) else +<<<<<<< HEAD var/list/subsytem_types = subtypesof(/datum/controller/subsystem) sortTim(subsytem_types, /proc/cmp_subsystem_init) for(var/I in subsytem_types) _subsystems += new I Master = src +======= + //Code used for first master on game boot or if existing master got deleted + Master = src + var/list/subsystem_types = subtypesof(/datum/controller/subsystem) + sortTim(subsystem_types, /proc/cmp_subsystem_init) + //Find any abandoned subsystem from the previous master (if there was any) + var/list/existing_subsystems = list() + for(var/global_var in global.vars) + if (istype(global.vars[global_var], /datum/controller/subsystem)) + existing_subsystems += global.vars[global_var] + //Either init a new SS or if an existing one was found use that + for(var/I in subsystem_types) + var/ss_idx = existing_subsystems.Find(I) + if (ss_idx) + _subsystems += existing_subsystems[ss_idx] + else + _subsystems += new I +>>>>>>> bdeb199b49... Revert "Brings our MC up to date with TG (#7285)" (#7597) if(!GLOB) new /datum/controller/global_vars @@ -192,7 +211,11 @@ GLOBAL_REAL(Master, /datum/controller/master) = new // Initialize subsystems. current_ticklimit = CONFIG_GET(number/tick_limit_mc_init) for (var/datum/controller/subsystem/SS in subsystems) +<<<<<<< HEAD if (SS.flags & SS_NO_INIT) +======= + if (SS.flags & SS_NO_INIT || SS.initialized) //Don't init SSs with the correspondig flag or if they already are initialzized +>>>>>>> bdeb199b49... Revert "Brings our MC up to date with TG (#7285)" (#7597) continue SS.Initialize(REALTIMEOFDAY) CHECK_TICK diff --git a/code/controllers/subsystem.dm b/code/controllers/subsystem.dm index 7f57cba7945..f47243f5517 100644 --- a/code/controllers/subsystem.dm +++ b/code/controllers/subsystem.dm @@ -222,8 +222,13 @@ //this is so the subsystem doesn't rapid fire to make up missed ticks causing more lag if (var_value) next_fire = world.time + wait +<<<<<<< HEAD if ("queued_priority") //editing this breaks things. return 0 +======= + if (NAMEOF(src, queued_priority)) //editing this breaks things. + return FALSE +>>>>>>> bdeb199b49... Revert "Brings our MC up to date with TG (#7285)" (#7597) . = ..() diff --git a/code/game/objects/structures/traps.dm b/code/game/objects/structures/traps.dm index 18b795196bf..9ddd29f2e3d 100644 --- a/code/game/objects/structures/traps.dm +++ b/code/game/objects/structures/traps.dm @@ -49,7 +49,11 @@ // Makes the trap visible, and starts the cooldown until it's // able to be triggered again. visible_message(flare_message) +<<<<<<< HEAD if(sparks) +======= + if(sparks && Master.current_runlevel) +>>>>>>> bdeb199b49... Revert "Brings our MC up to date with TG (#7285)" (#7597) spark_system.start() alpha = 200 last_trigger = world.time diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm index 1400469d311..d1c16ca227f 100644 --- a/code/modules/power/lighting.dm +++ b/code/modules/power/lighting.dm @@ -422,7 +422,11 @@ update() /obj/machinery/light/proc/broken_sparks(start_only=FALSE) +<<<<<<< HEAD if(!QDELETED(src) && status == LIGHT_BROKEN && has_power()) +======= + if(!QDELETED(src) && status == LIGHT_BROKEN && has_power() && Master.current_runlevel) +>>>>>>> bdeb199b49... Revert "Brings our MC up to date with TG (#7285)" (#7597) if(!start_only) do_sparks(3, TRUE, src) var/delay = rand(BROKEN_SPARKS_MIN, BROKEN_SPARKS_MAX) @@ -754,7 +758,11 @@ if(status == LIGHT_EMPTY || status == LIGHT_BROKEN) return +<<<<<<< HEAD if(!skip_sound_and_sparks) +======= + if(!skip_sound_and_sparks && Master.current_runlevel) //not completly sure disabling this during initialize is needed but then again there are broken lights after initialize +>>>>>>> bdeb199b49... Revert "Brings our MC up to date with TG (#7285)" (#7597) if(status == LIGHT_OK || status == LIGHT_BURNED) playsound(src.loc, 'sound/effects/glasshit.ogg', 75, 1) if(on) diff --git a/code/modules/tgchat/to_chat.dm b/code/modules/tgchat/to_chat.dm index 0bc97d09c66..550285eb8d7 100644 --- a/code/modules/tgchat/to_chat.dm +++ b/code/modules/tgchat/to_chat.dm @@ -60,7 +60,11 @@ // FIXME: These flags are now pointless and have no effect handle_whitespace = TRUE, trailing_newline = TRUE) +<<<<<<< HEAD if(Master.current_runlevel == RUNLEVEL_INIT || !SSchat?.initialized) +======= + if(isnull(Master) || Master.current_runlevel == RUNLEVEL_INIT || !SSchat?.initialized) +>>>>>>> bdeb199b49... Revert "Brings our MC up to date with TG (#7285)" (#7597) to_chat_immediate(target, html, type, text) return if(!target || (!html && !text))