From 565319095f3a0cd30b9db6b5ed78752233f5c704 Mon Sep 17 00:00:00 2001 From: Kyle Spier-Swenson Date: Sun, 24 Apr 2022 21:29:06 -0700 Subject: [PATCH] Adds MC initialization stages. Earlier stages can fire while later ones init. Fixes tgui chat reconnection banner showing during init. (#66473) * Adds MC initialization stages. Earlier stages can fire while later ones init. Removes TICK_LIMIT_MC_INIT config for barely doing anything to speed up init and being inconvenient to work with if fires and inits can happen at the same time. --- code/__DEFINES/MC.dm | 13 +- code/__DEFINES/_tick.dm | 2 - code/__DEFINES/subsystems.dm | 4 + code/__HELPERS/stoplag.dm | 2 +- .../configuration/entries/general.dm | 6 +- code/controllers/master.dm | 111 ++++++++++++------ code/controllers/subsystem.dm | 5 +- code/controllers/subsystem/dbcore.dm | 2 +- code/controllers/subsystem/garbage.dm | 1 + code/controllers/subsystem/init_profiler.dm | 1 + code/controllers/subsystem/input.dm | 1 + code/controllers/subsystem/ping.dm | 1 + code/controllers/subsystem/server_maint.dm | 1 + code/controllers/subsystem/spatial_gridmap.dm | 2 +- code/controllers/subsystem/statpanel.dm | 1 + code/controllers/subsystem/title.dm | 1 + code/controllers/subsystem/vote.dm | 2 +- .../modules/client/preferences/_preference.dm | 2 + code/modules/mob/dead/dead.dm | 2 +- code/modules/power/lighting/light.dm | 2 +- code/modules/tgchat/to_chat.dm | 2 +- config/config.txt | 4 - 22 files changed, 112 insertions(+), 56 deletions(-) diff --git a/code/__DEFINES/MC.dm b/code/__DEFINES/MC.dm index bd1312cdec5..3b39140fcde 100644 --- a/code/__DEFINES/MC.dm +++ b/code/__DEFINES/MC.dm @@ -22,8 +22,12 @@ #define START_PROCESSING(Processor, Datum) if (!(Datum.datum_flags & DF_ISPROCESSING)) {Datum.datum_flags |= DF_ISPROCESSING;Processor.processing += Datum} #define STOP_PROCESSING(Processor, Datum) Datum.datum_flags &= ~DF_ISPROCESSING;Processor.processing -= Datum;Processor.currentrun -= Datum -/// Used to trigger object removal from a processing list -#define PROCESS_KILL 26 +/// Returns true if the MC is initialized and running. +/// Optional argument init_stage controls what stage the mc must have initializted to count as initialized. Defaults to INITSTAGE_MAX if not specified. +#define MC_RUNNING(INIT_STAGE...) (Master && Master.processing > 0 && Master.current_runlevel && Master.init_stage_completed == (max(min(INITSTAGE_MAX, ##INIT_STAGE), 1))) + +#define MC_LOOP_RTN_NEWSTAGES 1 +#define MC_LOOP_RTN_GRACEFUL_EXIT 2 //! SubSystem flags (Please design any new flags so that the default is off, to make adding flags to subsystems easier) @@ -63,6 +67,11 @@ #define SS_SLEEPING 4 /// fire() slept. #define SS_PAUSING 5 /// in the middle of pausing +// Subsystem init stages +#define INITSTAGE_EARLY 1 //! Early init stuff that doesn't need to wait for mapload +#define INITSTAGE_MAIN 2 //! Main init stage +#define INITSTAGE_MAX 2 //! Highest initstage. + #define SUBSYSTEM_DEF(X) GLOBAL_REAL(SS##X, /datum/controller/subsystem/##X);\ /datum/controller/subsystem/##X/New(){\ NEW_SS_GLOBAL(SS##X);\ diff --git a/code/__DEFINES/_tick.dm b/code/__DEFINES/_tick.dm index 5c5b7d192d9..1ac004b5673 100644 --- a/code/__DEFINES/_tick.dm +++ b/code/__DEFINES/_tick.dm @@ -9,8 +9,6 @@ #define TICK_LIMIT_TO_RUN 70 /// Tick limit for MC while running #define TICK_LIMIT_MC 70 -/// Tick limit while initializing -#define TICK_LIMIT_MC_INIT_DEFAULT (100 - TICK_BYOND_RESERVE) /// for general usage of tick_usage #define TICK_USAGE world.tick_usage diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm index 13f0d4aec30..7d36bb71f37 100644 --- a/code/__DEFINES/subsystems.dm +++ b/code/__DEFINES/subsystems.dm @@ -63,6 +63,10 @@ ///Empty ID define #define TIMER_ID_NULL -1 +/// Used to trigger object removal from a processing list +#define PROCESS_KILL 26 + + //! ## Initialization subsystem ///New should not call Initialize diff --git a/code/__HELPERS/stoplag.dm b/code/__HELPERS/stoplag.dm index 25fad12c71b..a24db8f7972 100644 --- a/code/__HELPERS/stoplag.dm +++ b/code/__HELPERS/stoplag.dm @@ -5,7 +5,7 @@ ///returns the number of ticks slept /proc/stoplag(initial_delay) - if (!Master || !(Master.current_runlevel & RUNLEVELS_DEFAULT)) + if (!Master || Master.init_stage_completed < INITSTAGE_MAX) sleep(world.tick_lag) return 1 if (!initial_delay) diff --git a/code/controllers/configuration/entries/general.dm b/code/controllers/configuration/entries/general.dm index b03825c31a5..a2839e23e1b 100644 --- a/code/controllers/configuration/entries/general.dm +++ b/code/controllers/configuration/entries/general.dm @@ -221,10 +221,6 @@ /datum/config_entry/flag/allow_holidays -/datum/config_entry/number/tick_limit_mc_init //SSinitialization throttling - default = TICK_LIMIT_MC_INIT_DEFAULT - min_val = 0 //oranges warned us - integer = FALSE /datum/config_entry/flag/admin_legacy_system //Defines whether the server uses the legacy admin system with admins.txt or the SQL system protection = CONFIG_ENTRY_LOCKED @@ -546,7 +542,7 @@ /datum/config_entry/flag/resume_after_initializations/ValidateAndSet(str_val) . = ..() - if(. && Master.current_runlevel) + if(. && MC_RUNNING()) world.sleep_offline = !config_entry_value /datum/config_entry/number/rounds_until_hard_restart diff --git a/code/controllers/master.dm b/code/controllers/master.dm index bac0bb4a4a1..a3d228709d1 100644 --- a/code/controllers/master.dm +++ b/code/controllers/master.dm @@ -36,6 +36,9 @@ GLOBAL_REAL(Master, /datum/controller/master) = new /// List of subsystems to process(). var/list/subsystems + ///Most recent init stage to complete init. + var/static/init_stage_completed + // Vars for keeping track of tick drift. var/init_timeofday var/init_time @@ -209,33 +212,55 @@ GLOBAL_REAL(Master, /datum/controller/master) = new if(init_sss) init_subtypes(/datum/controller/subsystem, subsystems) + init_stage_completed = 0 + var/mc_started = FALSE + to_chat(world, span_boldannounce("Initializing subsystems...")) + var/list/stage_sorted_subsystems = new(INITSTAGE_MAX) + for (var/i in 1 to INITSTAGE_MAX) + stage_sorted_subsystems[i] = list() + // Sort subsystems by init_order, so they initialize in the correct order. sortTim(subsystems, /proc/cmp_subsystem_init) + for (var/datum/controller/subsystem/subsystem as anything in subsystems) + var/subsystem_init_stage = subsystem.init_stage + if (!isnum(subsystem_init_stage) || subsystem_init_stage < 1 || subsystem_init_stage > INITSTAGE_MAX || round(subsystem_init_stage) != subsystem_init_stage) + stack_trace("ERROR: MC: subsystem `[subsystem.type]` has invalid init_stage: `[subsystem_init_stage]`. Setting to `[INITSTAGE_MAX]`") + subsystem_init_stage = subsystem.init_stage = INITSTAGE_MAX + stage_sorted_subsystems[subsystem_init_stage] += subsystem + + // Sort subsystems by display setting for easy access. + sortTim(subsystems, /proc/cmp_subsystem_display) var/start_timeofday = REALTIMEOFDAY - // Initialize subsystems. - current_ticklimit = CONFIG_GET(number/tick_limit_mc_init) - for (var/datum/controller/subsystem/SS in subsystems) - if (SS.flags & SS_NO_INIT || SS.initialized) //Don't init SSs with the correspondig flag or if they already are initialzized - continue - current_initializing_subsystem = SS - SS.Initialize(REALTIMEOFDAY) - CHECK_TICK - current_initializing_subsystem = null - current_ticklimit = TICK_LIMIT_RUNNING + for (var/current_init_stage in 1 to INITSTAGE_MAX) + + // Initialize subsystems. + for (var/datum/controller/subsystem/subsystem in stage_sorted_subsystems[current_init_stage]) + if (subsystem.flags & SS_NO_INIT || subsystem.initialized) //Don't init SSs with the correspondig flag or if they already are initialzized + continue + current_initializing_subsystem = subsystem + subsystem.Initialize(REALTIMEOFDAY) + CHECK_TICK + current_initializing_subsystem = null + init_stage_completed = current_init_stage + if (!mc_started) + mc_started = TRUE + if (!current_runlevel) + SetRunLevel(1) + // Loop. + Master.StartProcessing(0) + var/time = (REALTIMEOFDAY - start_timeofday) / 10 + + var/msg = "Initializations complete within [time] second[time == 1 ? "" : "s"]!" to_chat(world, span_boldannounce("[msg]")) log_world(msg) - if (!current_runlevel) - SetRunLevel(1) - // Sort subsystems by display setting for easy access. - sortTim(subsystems, /proc/cmp_subsystem_display) // Set world options. world.change_fps(CONFIG_GET(number/fps)) var/initialized_tod = REALTIMEOFDAY @@ -250,8 +275,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new if(sleep_offline_after_initializations && CONFIG_GET(flag/resume_after_initializations)) world.sleep_offline = FALSE initializations_finished_with_no_players_logged_in = initialized_tod < REALTIMEOFDAY - 10 - // Loop. - Master.StartProcessing(0) + /datum/controller/master/proc/SetRunLevel(new_runlevel) var/old_runlevel = current_runlevel @@ -269,8 +293,14 @@ GLOBAL_REAL(Master, /datum/controller/master) = new if(delay) sleep(delay) testing("Master starting processing") - var/rtn = Loop() - if (rtn > 0 || processing < 0) + var/started_stage + var/rtn = -2 + do + started_stage = init_stage_completed + rtn = Loop(started_stage) + while (rtn == MC_LOOP_RTN_NEWSTAGES && processing > 0 && started_stage < init_stage_completed) + + if (rtn >= MC_LOOP_RTN_GRACEFUL_EXIT || processing < 0) return //this was suppose to happen. //loop ended, restart the mc log_game("MC crashed or runtimed, restarting") @@ -282,7 +312,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new Failsafe.defcon = 2 // Main loop. -/datum/controller/master/proc/Loop() +/datum/controller/master/proc/Loop(init_stage) . = -1 //Prep the loop (most of this is because we want MC restarts to reset as much state as we can, and because // local vars rock @@ -295,6 +325,8 @@ GLOBAL_REAL(Master, /datum/controller/master) = new var/datum/controller/subsystem/SS = thing if (SS.flags & SS_NO_FIRE) continue + if (SS.init_stage > init_stage) + continue SS.queued_time = 0 SS.queue_next = null SS.queue_prev = null @@ -344,28 +376,33 @@ GLOBAL_REAL(Master, /datum/controller/master) = new while (1) tickdrift = max(0, MC_AVERAGE_FAST(tickdrift, (((REALTIMEOFDAY - init_timeofday) - (world.time - init_time)) / world.tick_lag))) var/starting_tick_usage = TICK_USAGE + if (init_stage != init_stage_completed) + return MC_LOOP_RTN_NEWSTAGES if (processing <= 0) current_ticklimit = TICK_LIMIT_RUNNING sleep(10) continue //Anti-tick-contention heuristics: - //if there are mutiple sleeping procs running before us hogging the cpu, we have to run later. - // (because sleeps are processed in the order received, longer sleeps are more likely to run first) - if (starting_tick_usage > TICK_LIMIT_MC) //if there isn't enough time to bother doing anything this tick, sleep a bit. - sleep_delta *= 2 - current_ticklimit = TICK_LIMIT_RUNNING * 0.5 - sleep(world.tick_lag * (processing * sleep_delta)) - continue + if (init_stage == INITSTAGE_MAX) + //if there are mutiple sleeping procs running before us hogging the cpu, we have to run later. + // (because sleeps are processed in the order received, longer sleeps are more likely to run first) + if (starting_tick_usage > TICK_LIMIT_MC) //if there isn't enough time to bother doing anything this tick, sleep a bit. + sleep_delta *= 2 + current_ticklimit = TICK_LIMIT_RUNNING * 0.5 + sleep(world.tick_lag * (processing * sleep_delta)) + continue - //Byond resumed us late. assume it might have to do the same next tick - if (last_run + CEILING(world.tick_lag * (processing * sleep_delta), world.tick_lag) < world.time) - sleep_delta += 1 + //Byond resumed us late. assume it might have to do the same next tick + if (last_run + CEILING(world.tick_lag * (processing * sleep_delta), world.tick_lag) < world.time) + sleep_delta += 1 - sleep_delta = MC_AVERAGE_FAST(sleep_delta, 1) //decay sleep_delta + sleep_delta = MC_AVERAGE_FAST(sleep_delta, 1) //decay sleep_delta - if (starting_tick_usage > (TICK_LIMIT_MC*0.75)) //we ran 3/4 of the way into the tick - sleep_delta += 1 + if (starting_tick_usage > (TICK_LIMIT_MC*0.75)) //we ran 3/4 of the way into the tick + sleep_delta += 1 + else + sleep_delta = 1 //debug if (make_runtime) @@ -450,9 +487,13 @@ GLOBAL_REAL(Master, /datum/controller/master) = new CONSUME_UNTIL(overtime_target) #endif - current_ticklimit = TICK_LIMIT_RUNNING - if (processing * sleep_delta <= world.tick_lag) - current_ticklimit -= (TICK_LIMIT_RUNNING * 0.25) //reserve the tail 1/4 of the next tick for the mc if we plan on running next tick + if (init_stage != INITSTAGE_MAX) + current_ticklimit = TICK_LIMIT_RUNNING * 2 + else + current_ticklimit = TICK_LIMIT_RUNNING + if (processing * sleep_delta <= world.tick_lag) + current_ticklimit -= (TICK_LIMIT_RUNNING * 0.25) //reserve the tail 1/4 of the next tick for the mc if we plan on running next tick + sleep(world.tick_lag * (processing * sleep_delta)) diff --git a/code/controllers/subsystem.dm b/code/controllers/subsystem.dm index 71788da5de0..1f472713dcb 100644 --- a/code/controllers/subsystem.dm +++ b/code/controllers/subsystem.dm @@ -25,6 +25,9 @@ /// [Subsystem Flags][SS_NO_INIT] to control binary behavior. Flags must be set at compile time or before preinit finishes to take full effect. (You can also restart the mc to force them to process again) var/flags = NONE + /// 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 @@ -262,7 +265,7 @@ return time /datum/controller/subsystem/stat_entry(msg) - if(can_fire && !(SS_NO_FIRE & flags)) + if(can_fire && !(SS_NO_FIRE & flags) && init_stage <= Master.init_stage_completed) msg = "[round(cost,1)]ms|[round(tick_usage,1)]%([round(tick_overrun,1)]%)|[round(ticks,0.1)]\t[msg]" else msg = "OFFLINE\t[msg]" diff --git a/code/controllers/subsystem/dbcore.dm b/code/controllers/subsystem/dbcore.dm index 5902d7f02d4..516cef7bfa5 100644 --- a/code/controllers/subsystem/dbcore.dm +++ b/code/controllers/subsystem/dbcore.dm @@ -482,7 +482,7 @@ Delayed insert mode was removed in mysql 7 and only works with MyISAM type table Close() status = DB_QUERY_STARTED if(async) - if(!Master.current_runlevel || Master.processing == 0) + if(!MC_RUNNING(SSdbcore.init_stage)) SSdbcore.run_query_sync(src) else SSdbcore.queue_query(src) diff --git a/code/controllers/subsystem/garbage.dm b/code/controllers/subsystem/garbage.dm index 238103bd07c..3d365d9951d 100644 --- a/code/controllers/subsystem/garbage.dm +++ b/code/controllers/subsystem/garbage.dm @@ -28,6 +28,7 @@ SUBSYSTEM_DEF(garbage) flags = SS_POST_FIRE_TIMING|SS_BACKGROUND|SS_NO_INIT runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY init_order = INIT_ORDER_GARBAGE + init_stage = INITSTAGE_EARLY var/list/collection_timeout = list(GC_FILTER_QUEUE, GC_CHECK_QUEUE, GC_DEL_QUEUE) // deciseconds to wait before moving something up in the queue to the next level diff --git a/code/controllers/subsystem/init_profiler.dm b/code/controllers/subsystem/init_profiler.dm index 03d25ae09cd..b992652005a 100644 --- a/code/controllers/subsystem/init_profiler.dm +++ b/code/controllers/subsystem/init_profiler.dm @@ -5,6 +5,7 @@ SUBSYSTEM_DEF(init_profiler) name = "Init Profiler" init_order = INIT_ORDER_INIT_PROFILER + init_stage = INITSTAGE_MAX flags = SS_NO_FIRE /datum/controller/subsystem/init_profiler/Initialize() diff --git a/code/controllers/subsystem/input.dm b/code/controllers/subsystem/input.dm index dd389e0dfbc..246ab84768a 100644 --- a/code/controllers/subsystem/input.dm +++ b/code/controllers/subsystem/input.dm @@ -2,6 +2,7 @@ SUBSYSTEM_DEF(input) name = "Input" wait = 1 //SS_TICKER means this runs every tick init_order = INIT_ORDER_INPUT + init_stage = INITSTAGE_EARLY flags = SS_TICKER priority = FIRE_PRIORITY_INPUT runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY diff --git a/code/controllers/subsystem/ping.dm b/code/controllers/subsystem/ping.dm index 78669c987ea..8886a4b61ca 100644 --- a/code/controllers/subsystem/ping.dm +++ b/code/controllers/subsystem/ping.dm @@ -6,6 +6,7 @@ SUBSYSTEM_DEF(ping) name = "Ping" priority = FIRE_PRIORITY_PING + init_stage = INITSTAGE_EARLY wait = 4 SECONDS flags = SS_NO_INIT runlevels = RUNLEVEL_LOBBY | RUNLEVEL_SETUP | RUNLEVEL_GAME | RUNLEVEL_POSTGAME diff --git a/code/controllers/subsystem/server_maint.dm b/code/controllers/subsystem/server_maint.dm index 8eccc89db16..d5f3c1c2e8f 100644 --- a/code/controllers/subsystem/server_maint.dm +++ b/code/controllers/subsystem/server_maint.dm @@ -6,6 +6,7 @@ SUBSYSTEM_DEF(server_maint) flags = SS_POST_FIRE_TIMING priority = FIRE_PRIORITY_SERVER_MAINT init_order = INIT_ORDER_SERVER_MAINT + init_stage = INITSTAGE_EARLY runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT var/list/currentrun ///Associated list of list names to lists to clear of nulls diff --git a/code/controllers/subsystem/spatial_gridmap.dm b/code/controllers/subsystem/spatial_gridmap.dm index f1d7030f7c8..97c3bd06fa0 100644 --- a/code/controllers/subsystem/spatial_gridmap.dm +++ b/code/controllers/subsystem/spatial_gridmap.dm @@ -122,7 +122,7 @@ SUBSYSTEM_DEF(spatial_grid) for(var/datum/space_level/z_level as anything in SSmapping.z_list) propogate_spatial_grid_to_new_z(null, z_level) - CHECK_TICK_HIGH_PRIORITY + CHECK_TICK //go through the pre init queue for anything waiting to be let in the grid for(var/channel_type in waiting_to_add_by_type) diff --git a/code/controllers/subsystem/statpanel.dm b/code/controllers/subsystem/statpanel.dm index 0dcaff6435d..23d4777fb07 100644 --- a/code/controllers/subsystem/statpanel.dm +++ b/code/controllers/subsystem/statpanel.dm @@ -2,6 +2,7 @@ SUBSYSTEM_DEF(statpanels) name = "Stat Panels" wait = 4 init_order = INIT_ORDER_STATPANELS + init_stage = INITSTAGE_EARLY priority = FIRE_PRIORITY_STATPANEL runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY var/list/currentrun = list() diff --git a/code/controllers/subsystem/title.dm b/code/controllers/subsystem/title.dm index 0d356cde23b..b8ab24b5c5a 100644 --- a/code/controllers/subsystem/title.dm +++ b/code/controllers/subsystem/title.dm @@ -2,6 +2,7 @@ SUBSYSTEM_DEF(title) name = "Title Screen" flags = SS_NO_FIRE init_order = INIT_ORDER_TITLE + init_stage = INITSTAGE_EARLY var/file_path var/icon/icon diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm index db748175540..dd2d1d49245 100644 --- a/code/controllers/subsystem/vote.dm +++ b/code/controllers/subsystem/vote.dm @@ -151,7 +151,7 @@ SUBSYSTEM_DEF(vote) /datum/controller/subsystem/vote/proc/initiate_vote(vote_type, initiator_key) //Server is still intializing. - if(!Master.current_runlevel) + if(!MC_RUNNING(init_stage)) to_chat(usr, span_warning("Cannot start vote, server is not done initializing.")) return FALSE var/lower_admin = FALSE diff --git a/code/modules/client/preferences/_preference.dm b/code/modules/client/preferences/_preference.dm index 6cdd5755825..756cd9d0853 100644 --- a/code/modules/client/preferences/_preference.dm +++ b/code/modules/client/preferences/_preference.dm @@ -240,6 +240,8 @@ GLOBAL_LIST_INIT(preference_entries_by_key, init_preference_entries_by_key()) // things running pre-assets-initialization. if (!isnull(Master.current_initializing_subsystem)) extra_info = "Info was attempted to be retrieved while [Master.current_initializing_subsystem] was initializing." + else if (!MC_RUNNING()) + extra_info = "Info was attempted to be retrieved before the MC started, but not while it was actively initializing a subsystem" CRASH("Preference type `[preference_type]` is invalid! [extra_info]") diff --git a/code/modules/mob/dead/dead.dm b/code/modules/mob/dead/dead.dm index 706733868a9..04055c8ecd1 100644 --- a/code/modules/mob/dead/dead.dm +++ b/code/modules/mob/dead/dead.dm @@ -48,7 +48,7 @@ INITIALIZE_IMMEDIATE(/mob/dead) else . += "Time To Start: SOON" - . += "Players: [SSticker.totalPlayers]" + . += "Players: [LAZYLEN(GLOB.clients)]" if(client.holder) . += "Players Ready: [SSticker.totalPlayersReady]" . += "Admins Ready: [SSticker.total_admins_ready] / [length(GLOB.admins)]" diff --git a/code/modules/power/lighting/light.dm b/code/modules/power/lighting/light.dm index 86f6709067b..869debd5d76 100644 --- a/code/modules/power/lighting/light.dm +++ b/code/modules/power/lighting/light.dm @@ -195,7 +195,7 @@ update() /obj/machinery/light/proc/broken_sparks(start_only=FALSE) - if(!QDELETED(src) && status == LIGHT_BROKEN && has_power() && Master.current_runlevel) + if(!QDELETED(src) && status == LIGHT_BROKEN && has_power() && MC_RUNNING()) if(!start_only) do_sparks(3, TRUE, src) var/delay = rand(BROKEN_SPARKS_MIN, BROKEN_SPARKS_MAX) diff --git a/code/modules/tgchat/to_chat.dm b/code/modules/tgchat/to_chat.dm index c0e27a2ba37..e71e8658845 100644 --- a/code/modules/tgchat/to_chat.dm +++ b/code/modules/tgchat/to_chat.dm @@ -74,7 +74,7 @@ trailing_newline = TRUE, confidential = FALSE ) - if(isnull(Master) || Master.current_runlevel == RUNLEVEL_INIT || !SSchat?.initialized) + if(isnull(Master) || !SSchat?.initialized || !MC_RUNNING(SSchat.init_stage)) to_chat_immediate(target, html, type, text, avoid_highlighting) return diff --git a/config/config.txt b/config/config.txt index f441b285c1f..71880f55622 100644 --- a/config/config.txt +++ b/config/config.txt @@ -305,10 +305,6 @@ ALLOW_HOLIDAYS ## Uncomment to show the names of the admin sending a pm from IRC instead of showing as a stealthmin. #SHOW_IRC_NAME -## Defines the ticklimit for subsystem initialization (In percents of a byond tick). Lower makes world start smoother. Higher makes it faster. -##This is currently a testing optimized setting. A good value for production would be 98. -TICK_LIMIT_MC_INIT 500 - ##Defines the ticklag for the world. Ticklag is the amount of time between game ticks (aka byond ticks) (in 1/10ths of a second). ## This also controls the client network update rate, as well as the default client fps TICKLAG 0.5