<commit_before>//simplified MC that is designed to fail when procs 'break'. When it fails it's just replaced with a new one.
//It ensures master_controller.process() is never doubled up by killing the MC (hence terminating any of its sleeping procs)

//Update: all core-systems are now placed inside subsystem datums. This makes them highly configurable and easy to work with.

var/global/datum/controller/game_controller/master_controller = new()

/datum/controller/game_controller
	var/processing_interval = 1	//The minimum length of time between MC ticks (in deciseconds). The highest this can be without affecting schedules, is the GCD of all subsystem var/wait. Set to 0 to disable all processing.
	var/iteration = 0
	var/cost = 0
	var/SSCostPerSecond = 0
	var/last_thing_processed

	var/list/subsystems = list()

/datum/controller/game_controller/New()
	//There can be only one master_controller. Out with the old and in with the new.
	if(master_controller != src)
		if(istype(master_controller))
			Recover()
			qdel(master_controller)
		else
			init_subtypes(/datum/subsystem, subsystems)

		master_controller = src
	calculateGCD()

/datum/controller/game_controller/Destroy()
	..()
	return QDEL_HINT_HARDDEL_NOW


/*
calculate the longest number of ticks the MC can wait between each cycle without causing subsystems to not fire on schedule
*/
/datum/controller/game_controller/proc/calculateGCD()
	var/GCD
	//shortest fire rate is the lower of two ticks or 1ds
	var/minimumInterval = min(world.tick_lag*2,1)
	for(var/datum/subsystem/SS in subsystems)
		if(SS.wait)
			GCD = Gcd(round(SS.wait*10), GCD)
	GCD = round(GCD)
	if(GCD < minimumInterval*10)
		GCD = minimumInterval*10
	processing_interval = GCD/10

/datum/controller/game_controller/proc/setup(zlevel)
	if (zlevel && zlevel > 0 && zlevel <= world.maxz)
		for(var/datum/subsystem/S in subsystems)
			S.Initialize(world.timeofday, zlevel)
			sleep(-1)
		return
	world << "<span class='boldannounce'>Initializing Subsystems...</span>"


	//sort subsystems by priority, so they initialize in the correct order
	sortTim(subsystems, /proc/cmp_subsystem_priority)

	createRandomZlevel()	//gate system
	setup_map_transitions()
	for(var/i=0, i<max_secret_rooms, i++)
		make_mining_asteroid_secret()

	//Eventually all this other setup stuff should be contained in subsystems and done in subsystem.Initialize()
	for(var/datum/subsystem/S in subsystems)
		S.Initialize(world.timeofday, zlevel)
		sleep(-1)

	crewmonitor.generateMiniMaps()
	populate_asset_cache()

	world << "<span class='boldannounce'>Initializations complete</span>"

	world.sleep_offline = 1
	world.fps = config.fps

	sleep(-1)

	process()

//used for smoothing out the cost values so they don't fluctuate wildly
#define MC_AVERAGE(average, current) (0.8*(average) + 0.2*(current))

/datum/controller/game_controller/process()
	if(!Failsafe)	new /datum/controller/failsafe()
	spawn(0)
		var/timer = world.time
		for(var/datum/subsystem/SS in subsystems)
			timer += processing_interval
			SS.next_fire = timer

		var/start_time

		while(1)	//far more efficient than recursively calling ourself
			if(processing_interval > 0)
				++iteration
				var/startingtick = world.time
				start_time = world.timeofday
				var/SubSystemRan = 0
				for(var/datum/subsystem/SS in subsystems)
					if(SS.can_fire > 0)
						if(SS.next_fire <= world.time && SS.last_fire+(wait*0.5) <= world.time)
							SubSystemRan = 1
							timer = world.timeofday
							last_thing_processed = SS.type
							SS.last_fire = world.time
							SS.fire()
							SS.cost = MC_AVERAGE(SS.cost, world.timeofday - timer)
							if (SS.dynamic_wait)
								var/oldwait = SS.wait
								var/GlobalCostDelta = (SSCostPerSecond-(SS.cost/(SS.wait/10)))-1
								var/NewWait = MC_AVERAGE(oldwait,(SS.cost-SS.dwait_buffer+GlobalCostDelta)*SS.dwait_delta)
								NewWait = NewWait*(world.cpu/100+1)
								SS.wait = Clamp(NewWait,SS.dwait_lower,SS.dwait_upper)
								if (oldwait != SS.wait)
									calculateGCD()
							SS.next_fire += SS.wait
							++SS.times_fired
							//we caused byond to miss a tick, stop processing for a bit
							if (startingtick < world.time || start_time+1 < world.timeofday)
								break
							sleep(-1)<commit_msg>Fixes a typo in the MC breaking compiling<commit_after>//simplified MC that is designed to fail when procs 'break'. When it fails it's just replaced with a new one.
//It ensures master_controller.process() is never doubled up by killing the MC (hence terminating any of its sleeping procs)

//Update: all core-systems are now placed inside subsystem datums. This makes them highly configurable and easy to work with.

var/global/datum/controller/game_controller/master_controller = new()

/datum/controller/game_controller
	var/processing_interval = 1	//The minimum length of time between MC ticks (in deciseconds). The highest this can be without affecting schedules, is the GCD of all subsystem var/wait. Set to 0 to disable all processing.
	var/iteration = 0
	var/cost = 0
	var/SSCostPerSecond = 0
	var/last_thing_processed

	var/list/subsystems = list()

/datum/controller/game_controller/New()
	//There can be only one master_controller. Out with the old and in with the new.
	if(master_controller != src)
		if(istype(master_controller))
			Recover()
			qdel(master_controller)
		else
			init_subtypes(/datum/subsystem, subsystems)

		master_controller = src
	calculateGCD()

/datum/controller/game_controller/Destroy()
	..()
	return QDEL_HINT_HARDDEL_NOW


/*
calculate the longest number of ticks the MC can wait between each cycle without causing subsystems to not fire on schedule
*/
/datum/controller/game_controller/proc/calculateGCD()
	var/GCD
	//shortest fire rate is the lower of two ticks or 1ds
	var/minimumInterval = min(world.tick_lag*2,1)
	for(var/datum/subsystem/SS in subsystems)
		if(SS.wait)
			GCD = Gcd(round(SS.wait*10), GCD)
	GCD = round(GCD)
	if(GCD < minimumInterval*10)
		GCD = minimumInterval*10
	processing_interval = GCD/10

/datum/controller/game_controller/proc/setup(zlevel)
	if (zlevel && zlevel > 0 && zlevel <= world.maxz)
		for(var/datum/subsystem/S in subsystems)
			S.Initialize(world.timeofday, zlevel)
			sleep(-1)
		return
	world << "<span class='boldannounce'>Initializing Subsystems...</span>"


	//sort subsystems by priority, so they initialize in the correct order
	sortTim(subsystems, /proc/cmp_subsystem_priority)

	createRandomZlevel()	//gate system
	setup_map_transitions()
	for(var/i=0, i<max_secret_rooms, i++)
		make_mining_asteroid_secret()

	//Eventually all this other setup stuff should be contained in subsystems and done in subsystem.Initialize()
	for(var/datum/subsystem/S in subsystems)
		S.Initialize(world.timeofday, zlevel)
		sleep(-1)

	crewmonitor.generateMiniMaps()
	populate_asset_cache()

	world << "<span class='boldannounce'>Initializations complete</span>"

	world.sleep_offline = 1
	world.fps = config.fps

	sleep(-1)

	process()

//used for smoothing out the cost values so they don't fluctuate wildly
#define MC_AVERAGE(average, current) (0.8*(average) + 0.2*(current))

/datum/controller/game_controller/process()
	if(!Failsafe)	new /datum/controller/failsafe()
	spawn(0)
		var/timer = world.time
		for(var/datum/subsystem/SS in subsystems)
			timer += processing_interval
			SS.next_fire = timer

		var/start_time

		while(1)	//far more efficient than recursively calling ourself
			if(processing_interval > 0)
				++iteration
				var/startingtick = world.time
				start_time = world.timeofday
				var/SubSystemRan = 0
				for(var/datum/subsystem/SS in subsystems)
					if(SS.can_fire > 0)
						if(SS.next_fire <= world.time && SS.last_fire+(SS.wait*0.5) <= world.time)
							SubSystemRan = 1
							timer = world.timeofday
							last_thing_processed = SS.type
							SS.last_fire = world.time
							SS.fire()
							SS.cost = MC_AVERAGE(SS.cost, world.timeofday - timer)
							if (SS.dynamic_wait)
								var/oldwait = SS.wait
								var/GlobalCostDelta = (SSCostPerSecond-(SS.cost/(SS.wait/10)))-1
								var/NewWait = MC_AVERAGE(oldwait,(SS.cost-SS.dwait_buffer+GlobalCostDelta)*SS.dwait_delta)
								NewWait = NewWait*(world.cpu/100+1)
								SS.wait = Clamp(NewWait,SS.dwait_lower,SS.dwait_upper)
								if (oldwait != SS.wait)
									calculateGCD()
							SS.next_fire += SS.wait
							++SS.times_fired
							//we caused byond to miss a tick, stop processing for a bit
							if (startingtick < world.time || start_time+1 < world.timeofday)
								break
							sleep(-1)
{'fraction_non_alphanumeric': 0.10461430081014442, 'fraction_numerical': 0.0100974521545145, 'mean_word_length': 3.777341559169938, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2348881', 'n_tokens_mistral': 3303, 'n_tokens_neox': 2782, 'n_words': 736}