mirror of
https://github.com/vgstation-coders/vgstation13.git
synced 2025-12-10 10:21:11 +00:00
Replaced the master_controller with the WIP sequential version.
Fixed a problem where TG was using this sequential master_controller but I had removed a spawn where master_controller.process() was called because I was working with the default master_controller. This problem was causing the master_controller to prevent the lighting_controller.process() ever running properly because it was hogging the current thread (thread isn't the right word there, not sure what you call it....stack?) Added debugging to both the lighting_controller and master_controller. http://filesmelt.com/dl/debugging.png Both lighting_controller and master_controller may be deleted to terminate their processes (this is done via the restart controller verb. This allows for clean restarts without 'doubling up' (where, for instance, the master_controller would be running more than one instance). lighting_controller has a prototype recovery proc which is called by the "restart controller - lighting" verb. It's basically an overly paranoid version of process() which will only transfer light_sources to the replacement controller if they don't runtime. It's not needed at the moment as the process() has yet to runtime. master_controller has the beginnings of self pruning lists. This method using list.Cut(index,index+1) is faster than doing list.Remove(thing) all over the place (the latter iterates through the list to find the thing). Added more detailed time-measurements for the master_controller. It now displays the processing costs (in real-world seconds) of each part of the master_controller's cycle. The stat panel only updates for mobs actually -looking- at the stat panel. Explosion debugging is now hidden behind a if(Debug2). To have it print that data to world.log just click the DebugGame verb debug controller and restart controller verbs are now both GameAdmin rank. Not sure how they got split up. Fixed another cause of dark splotchy space turfs. (turf/wall/ex_act was replacing the turf with space and then deleting that new space turf) git-svn-id: http://tgstation13.googlecode.com/svn/trunk@4593 316c924e-a436-60f5-8080-3fe189b3f50e
This commit is contained in:
@@ -37,9 +37,6 @@
|
||||
#define LIGHTING_LAYER 10 //Drawing layer for lighting overlays
|
||||
#define LIGHTING_ICON 'icons/effects/ss13_dark_alpha7.dmi' //Icon used for lighting shading effects
|
||||
|
||||
datum/controller/lighting/New() //moved here so its in the define. eek :S
|
||||
lighting_states = max( 0, length(icon_states(LIGHTING_ICON))-1 )
|
||||
|
||||
datum/light_source
|
||||
var/atom/owner
|
||||
var/changed = 1
|
||||
@@ -302,4 +299,4 @@ area
|
||||
#undef LIGHTING_MAX_LUMINOSITY
|
||||
#undef LIGHTING_MAX_LUMINOSITY_MOB
|
||||
#undef LIGHTING_LAYER
|
||||
#undef LIGHTING_ICON
|
||||
//#undef LIGHTING_ICON
|
||||
@@ -16,6 +16,15 @@ datum/controller/lighting
|
||||
var/list/changed_turfs = list()
|
||||
var/changed_turfs_workload_max = 0
|
||||
|
||||
datum/controller/lighting/New()
|
||||
lighting_states = max( 0, length(icon_states(LIGHTING_ICON))-1 )
|
||||
if(lighting_controller != src)
|
||||
if(istype(lighting_controller,/datum/controller/lighting))
|
||||
Recover() //if we are replacing an existing lighting_controller (due to a crash) we attempt to preserve as much as we can
|
||||
del(lighting_controller)
|
||||
lighting_controller = src
|
||||
|
||||
|
||||
//Workhorse of lighting. It cycles through each light to see which ones need their effects updating. It updates their
|
||||
//effects and then processes every turf in the queue, moving the turfs to the corresponing lighting sub-area.
|
||||
//All queue lists prune themselves, which will cause lights with no luminosity to be garbage collected (cheaper and safer
|
||||
@@ -33,9 +42,10 @@ datum/controller/lighting/proc/process()
|
||||
lights_workload_max = max(lights_workload_max,lights.len)
|
||||
for(var/i=1, i<=lights.len, i++)
|
||||
var/datum/light_source/L = lights[i]
|
||||
if(L.check())
|
||||
lights.Cut(i,i+1)
|
||||
i--
|
||||
if(L && !L.check())
|
||||
continue
|
||||
lights.Cut(i,i+1)
|
||||
i--
|
||||
|
||||
sleep(-1)
|
||||
|
||||
@@ -78,4 +88,42 @@ datum/controller/lighting/proc/Initialize(var/z_level)
|
||||
var/turf/T = locate(i,j,k)
|
||||
if(T) T.shift_to_subarea()
|
||||
|
||||
changed_turfs.Cut() // reset the changed list
|
||||
changed_turfs.Cut() // reset the changed list
|
||||
|
||||
|
||||
//Used to strip valid information from an existing controller and transfer it to a replacement
|
||||
//It works by using spawn(-1) to transfer the data, if there is a runtime the data does not get transfered but the loop
|
||||
//does not crash
|
||||
datum/controller/lighting/proc/Recover()
|
||||
if(!istype(lighting_controller.changed_turfs,/list))
|
||||
lighting_controller.changed_turfs = list()
|
||||
if(!istype(lighting_controller.lights,/list))
|
||||
lighting_controller.lights = list()
|
||||
|
||||
for(var/i=1, i<=lighting_controller.lights.len, i++)
|
||||
var/datum/light_source/L = lighting_controller.lights[i]
|
||||
if(istype(L))
|
||||
spawn(-1) //so we don't crash the loop (inefficient)
|
||||
L.check()
|
||||
lights += L //If we didn't runtime then this will get transferred over
|
||||
|
||||
for(var/i=1, i<=lighting_controller.changed_turfs.len, i++)
|
||||
var/turf/T = lighting_controller.changed_turfs[i]
|
||||
if(istype(T) && T.lighting_changed)
|
||||
spawn(-1)
|
||||
T.shift_to_subarea()
|
||||
|
||||
var/msg = "## DEBUG: [time2text(world.timeofday)] lighting_controller restarted. Reports:\n"
|
||||
for(var/varname in lighting_controller.vars)
|
||||
switch(varname)
|
||||
if("tag","bestF","type","parent_type","vars") continue
|
||||
else
|
||||
var/varval1 = lighting_controller.vars[varname]
|
||||
var/varval2 = vars[varname]
|
||||
if(istype(varval1,/list))
|
||||
varval1 = "/list([length(varval1)])"
|
||||
varval2 = "/list([length(varval2)])"
|
||||
msg += "\t [varname] = [varval1] -> [varval2]\n"
|
||||
world.log << msg
|
||||
|
||||
#undef LIGHTING_ICON
|
||||
|
||||
@@ -1,210 +1,286 @@
|
||||
//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)
|
||||
//WIP, needs lots of work still
|
||||
|
||||
var/global/datum/controller/game_controller/master_controller //Set in world.New()
|
||||
var/global/datum/failsafe/Failsafe
|
||||
|
||||
var/global/controller_iteration = 0
|
||||
|
||||
|
||||
var/global/last_tick_timeofday = world.timeofday
|
||||
var/global/last_tick_duration = 0
|
||||
|
||||
datum/controller/game_controller
|
||||
var/processing = 0
|
||||
var/breather_ticks = 2 //a somewhat crude attempt to iron over the 'bumps' caused by high-cpu use by letting the MC have a breather for this many ticks after every loop
|
||||
var/minimum_ticks = 20 //The minimum length of time between MC ticks
|
||||
|
||||
var/global/air_master_ready = 0
|
||||
var/global/sun_ready = 0
|
||||
var/global/mobs_ready = 0
|
||||
var/global/diseases_ready = 0
|
||||
var/global/machines_ready = 0
|
||||
var/global/objects_ready = 0
|
||||
var/global/networks_ready = 0
|
||||
var/global/powernets_ready = 0
|
||||
var/global/ticker_ready = 0
|
||||
var/air_cost = 0
|
||||
var/sun_cost = 0
|
||||
var/mobs_cost = 0
|
||||
var/diseases_cost = 0
|
||||
var/machines_cost = 0
|
||||
var/objects_cost = 0
|
||||
var/networks_cost = 0
|
||||
var/powernets_cost = 0
|
||||
var/ticker_cost = 0
|
||||
var/total_cost = 0
|
||||
|
||||
//Used for MC 'proc break' debugging
|
||||
var/global/obj/last_obj_processed
|
||||
var/global/datum/disease/last_disease_processed
|
||||
var/global/obj/machinery/last_machine_processed
|
||||
var/global/mob/last_mob_processed
|
||||
var/obj/machinery/last_obj_processed //Used for MC 'proc break' debugging
|
||||
var/datum/disease/last_disease_processed //Used for MC 'proc break' debugging
|
||||
var/obj/machinery/last_machine_processed //Used for MC 'proc break' debugging
|
||||
|
||||
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,/datum/controller/game_controller))
|
||||
Recover()
|
||||
del(master_controller)
|
||||
master_controller = src
|
||||
|
||||
if(!air_master)
|
||||
air_master = new /datum/controller/air_system()
|
||||
air_master.setup()
|
||||
|
||||
if(!job_master)
|
||||
job_master = new /datum/controller/occupations()
|
||||
if(job_master.SetupOccupations())
|
||||
world << "\red \b Job setup complete"
|
||||
job_master.LoadJobs("config/jobs.txt")
|
||||
|
||||
if(!syndicate_code_phrase) syndicate_code_phrase = generate_code_phrase()
|
||||
if(!syndicate_code_response) syndicate_code_response = generate_code_phrase()
|
||||
if(!ticker) ticker = new /datum/controller/gameticker()
|
||||
if(!emergency_shuttle) emergency_shuttle = new /datum/shuttle_controller/emergency_shuttle()
|
||||
|
||||
|
||||
proc/setup()
|
||||
if(master_controller && (master_controller != src))
|
||||
del(src)
|
||||
return
|
||||
//There can be only one master.
|
||||
datum/controller/game_controller/proc/setup()
|
||||
world.tick_lag = config.Ticklag
|
||||
|
||||
if(!air_master)
|
||||
air_master = new /datum/controller/air_system()
|
||||
air_master.setup()
|
||||
createRandomZlevel()
|
||||
setup_objects()
|
||||
setupgenetics()
|
||||
setupfactions()
|
||||
|
||||
if(!job_master)
|
||||
job_master = new /datum/controller/occupations()
|
||||
if(job_master.SetupOccupations())
|
||||
world << "\red \b Job setup complete"
|
||||
job_master.LoadJobs("config/jobs.txt")
|
||||
for(var/i=0, i<max_secret_rooms, i++)
|
||||
make_mining_asteroid_secret()
|
||||
|
||||
world.tick_lag = config.Ticklag
|
||||
|
||||
createRandomZlevel()
|
||||
|
||||
setup_objects()
|
||||
|
||||
setupgenetics()
|
||||
|
||||
|
||||
for(var/i = 0, i < max_secret_rooms, i++)
|
||||
make_mining_asteroid_secret()
|
||||
|
||||
syndicate_code_phrase = generate_code_phrase()//Sets up code phrase for traitors, for the round.
|
||||
syndicate_code_response = generate_code_phrase()
|
||||
|
||||
emergency_shuttle = new /datum/shuttle_controller/emergency_shuttle()
|
||||
|
||||
if(!ticker)
|
||||
ticker = new /datum/controller/gameticker()
|
||||
|
||||
setupfactions()
|
||||
|
||||
spawn
|
||||
spawn(0)
|
||||
if(ticker)
|
||||
ticker.pregame()
|
||||
|
||||
proc/setup_objects()
|
||||
world << "\red \b Initializing objects"
|
||||
sleep(-1)
|
||||
datum/controller/game_controller/proc/setup_objects()
|
||||
world << "\red \b Initializing objects"
|
||||
sleep(-1)
|
||||
for(var/obj/object in world)
|
||||
object.initialize()
|
||||
|
||||
for(var/obj/object in world)
|
||||
object.initialize()
|
||||
world << "\red \b Initializing pipe networks"
|
||||
sleep(-1)
|
||||
for(var/obj/machinery/atmospherics/machine in world)
|
||||
machine.build_network()
|
||||
|
||||
world << "\red \b Initializing pipe networks"
|
||||
sleep(-1)
|
||||
|
||||
for(var/obj/machinery/atmospherics/machine in world)
|
||||
machine.build_network()
|
||||
|
||||
world << "\red \b Initializing atmos machinery."
|
||||
sleep(-1)
|
||||
for(var/obj/machinery/atmospherics/unary/vent_pump/T in world)
|
||||
world << "\red \b Initializing atmos machinery."
|
||||
sleep(-1)
|
||||
for(var/obj/machinery/atmospherics/unary/U in world)
|
||||
if(istype(U, /obj/machinery/atmospherics/unary/vent_pump))
|
||||
var/obj/machinery/atmospherics/unary/vent_pump/T = U
|
||||
T.broadcast_status()
|
||||
for(var/obj/machinery/atmospherics/unary/vent_scrubber/T in world)
|
||||
else if(istype(U, /obj/machinery/atmospherics/unary/vent_scrubber))
|
||||
var/obj/machinery/atmospherics/unary/vent_scrubber/T = U
|
||||
T.broadcast_status()
|
||||
|
||||
world << "\red \b Initializations complete."
|
||||
world << "\red \b Initializations complete."
|
||||
sleep(-1)
|
||||
|
||||
|
||||
proc/process()
|
||||
processing = 1
|
||||
spawn(0)
|
||||
set background = 1
|
||||
while(1)
|
||||
var/currenttime = world.timeofday
|
||||
var/diff = (currenttime - last_tick_timeofday) / 10
|
||||
last_tick_timeofday = currenttime
|
||||
last_tick_duration = diff
|
||||
datum/controller/game_controller/proc/process()
|
||||
processing = 1
|
||||
spawn(0)
|
||||
set background = 1
|
||||
while(1) //far more efficient than recursively calling ourself
|
||||
if(!Failsafe) new /datum/failsafe()
|
||||
|
||||
if(processing)
|
||||
var/currenttime = world.timeofday
|
||||
|
||||
controller_iteration++
|
||||
last_tick_duration = (currenttime - last_tick_timeofday) / 10
|
||||
last_tick_timeofday = currenttime
|
||||
|
||||
var/start_time = world.timeofday
|
||||
if(processing)
|
||||
var/timer
|
||||
var/start_time = world.timeofday
|
||||
controller_iteration++
|
||||
|
||||
air_master_ready = 0
|
||||
sun_ready = 0
|
||||
mobs_ready = 0
|
||||
diseases_ready = 0
|
||||
machines_ready = 0
|
||||
objects_ready = 0
|
||||
networks_ready = 0
|
||||
powernets_ready = 0
|
||||
ticker_ready = 0
|
||||
timer = world.timeofday
|
||||
air_master.process()
|
||||
air_cost = (world.timeofday - timer) / 10
|
||||
|
||||
spawn(0)
|
||||
air_master.process()
|
||||
air_master_ready = 1
|
||||
sleep(breather_ticks)
|
||||
|
||||
sleep(1)
|
||||
timer = world.timeofday
|
||||
sun.calc_position()
|
||||
sun_cost = (world.timeofday - timer) / 10
|
||||
|
||||
spawn(0)
|
||||
sun.calc_position()
|
||||
sun_ready = 1
|
||||
sleep(breather_ticks)
|
||||
|
||||
sleep(-1)
|
||||
timer = world.timeofday
|
||||
for(var/i=1,i<=mob_list.len,i++)
|
||||
var/mob/M = mob_list[i]
|
||||
if(M)
|
||||
M.Life()
|
||||
continue
|
||||
mob_list.Cut(i,i+1)
|
||||
i--
|
||||
mobs_cost = (world.timeofday - timer) / 10
|
||||
|
||||
spawn(0)
|
||||
for(var/mob/M in world)
|
||||
last_mob_processed = M
|
||||
M.Life()
|
||||
mobs_ready = 1
|
||||
sleep(breather_ticks)
|
||||
|
||||
sleep(-1)
|
||||
timer = world.timeofday
|
||||
for(var/i=1,i<=active_diseases.len,i++)
|
||||
var/datum/disease/Disease = active_diseases[i]
|
||||
if(Disease)
|
||||
last_disease_processed = Disease
|
||||
Disease.process()
|
||||
continue
|
||||
active_diseases.Cut(i,i+1)
|
||||
i--
|
||||
diseases_cost = (world.timeofday - timer) / 10
|
||||
|
||||
spawn(0)
|
||||
for(var/datum/disease/D in active_diseases)
|
||||
last_disease_processed = D
|
||||
D.process()
|
||||
diseases_ready = 1
|
||||
sleep(breather_ticks)
|
||||
|
||||
spawn(0)
|
||||
for(var/obj/machinery/machine in machines)
|
||||
if(machine)
|
||||
last_machine_processed = machine
|
||||
machine.process()
|
||||
if(machine && machine.use_power)
|
||||
machine.auto_use_power()
|
||||
timer = world.timeofday
|
||||
for(var/i=1,i<=machines.len,i++)
|
||||
var/obj/machinery/Machine = machines[i]
|
||||
if(Machine)
|
||||
last_machine_processed = Machine
|
||||
Machine.process()
|
||||
if(Machine)
|
||||
if(Machine.use_power)
|
||||
Machine.auto_use_power()
|
||||
continue
|
||||
machines.Cut(i,i+1)
|
||||
i--
|
||||
machines_cost = (world.timeofday - timer) / 10
|
||||
|
||||
machines_ready = 1
|
||||
sleep(breather_ticks)
|
||||
|
||||
sleep(1)
|
||||
timer = world.timeofday
|
||||
for(var/i=1,i<=processing_objects.len,i++)
|
||||
var/obj/Object = processing_objects[i]
|
||||
if(Object)
|
||||
last_obj_processed = Object
|
||||
Object.process()
|
||||
continue
|
||||
processing_objects.Cut(i,i+1)
|
||||
i--
|
||||
objects_cost = (world.timeofday - timer) / 10
|
||||
|
||||
spawn(-1)
|
||||
for(var/obj/object in processing_objects)
|
||||
last_obj_processed = object
|
||||
object.process()
|
||||
objects_ready = 1
|
||||
sleep(breather_ticks)
|
||||
|
||||
sleep(-1)
|
||||
timer = world.timeofday
|
||||
for(var/i=1,i<=pipe_networks.len,i++)
|
||||
var/datum/pipe_network/Network = pipe_networks[i]
|
||||
if(Network)
|
||||
Network.process()
|
||||
continue
|
||||
pipe_networks.Cut(i,i+1)
|
||||
i--
|
||||
networks_cost = (world.timeofday - timer) / 10
|
||||
|
||||
spawn(-1)
|
||||
for(var/datum/pipe_network/network in pipe_networks)
|
||||
network.process()
|
||||
networks_ready = 1
|
||||
sleep(breather_ticks)
|
||||
|
||||
spawn(-1)
|
||||
for(var/datum/powernet/P in powernets)
|
||||
P.reset()
|
||||
powernets_ready = 1
|
||||
timer = world.timeofday
|
||||
for(var/i=1,i<=powernets.len,i++)
|
||||
var/datum/powernet/Powernet = powernets[i]
|
||||
if(Powernet)
|
||||
Powernet.reset()
|
||||
continue
|
||||
powernets.Cut(i,i+1)
|
||||
i--
|
||||
powernets_cost = (world.timeofday - timer) / 10
|
||||
|
||||
sleep(-1)
|
||||
sleep(breather_ticks)
|
||||
|
||||
spawn(-1)
|
||||
ticker.process()
|
||||
ticker_ready = 1
|
||||
timer = world.timeofday
|
||||
ticker.process()
|
||||
ticker_cost = (world.timeofday - timer) / 10
|
||||
|
||||
var/IL_check = 0 //Infinite loop check (To report when the master controller breaks.)
|
||||
while(!air_master_ready || !sun_ready || !mobs_ready || !diseases_ready || !machines_ready || !objects_ready || !networks_ready || !powernets_ready || !ticker_ready)
|
||||
IL_check++
|
||||
if(IL_check > 600)
|
||||
var/MC_report = "air_master_ready = [air_master_ready]; sun_ready = [sun_ready]; mobs_ready = [mobs_ready]; diseases_ready = [diseases_ready]; machines_ready = [machines_ready]; objects_ready = [objects_ready]; networks_ready = [networks_ready]; powernets_ready = [powernets_ready]; ticker_ready = [ticker_ready];"
|
||||
message_admins("<b><font color='red'>PROC BREAKAGE WARNING:</font> The game's master contorller appears to be stuck in one of it's cycles. It has looped through it's delaying loop [IL_check] times.</b>")
|
||||
message_admins("<b>The master controller reports: [MC_report]</b>")
|
||||
if(!diseases_ready)
|
||||
if(last_disease_processed)
|
||||
message_admins("<b>DISEASE PROCESSING stuck on </b><A HREF='?src=%holder_ref%;adminplayervars=\ref[last_disease_processed]'>[last_disease_processed]</A>", 0, 1)
|
||||
else
|
||||
message_admins("<b>DISEASE PROCESSING stuck on </b>unknown")
|
||||
if(!machines_ready)
|
||||
if(last_machine_processed)
|
||||
message_admins("<b>MACHINE PROCESSING stuck on </b><A HREF='?src=%holder_ref%;adminplayervars=\ref[last_machine_processed]'>[last_machine_processed]</A>", 0, 1)
|
||||
else
|
||||
message_admins("<b>MACHINE PROCESSING stuck on </b>unknown")
|
||||
if(!objects_ready)
|
||||
if(last_obj_processed)
|
||||
message_admins("<b>OBJ PROCESSING stuck on </b><A HREF='?src=ADMINHOLDERREF;adminplayervars=\ref[last_obj_processed]'>[last_obj_processed]</A>", 0, 1)
|
||||
else
|
||||
message_admins("<b>OBJ PROCESSING stuck on </b>unknown")
|
||||
log_admin("PROC BREAKAGE WARNING: infinite_loop_check = [IL_check]; [MC_report];")
|
||||
message_admins("<font color='red'><b>Master controller breaking out of delaying loop. Restarting the round is advised if problem persists. DO NOT manually restart the master controller.</b></font>")
|
||||
break;
|
||||
sleep(1)
|
||||
total_cost = air_cost + sun_cost + mobs_cost + diseases_cost + machines_cost + objects_cost + networks_cost + powernets_cost + ticker_cost
|
||||
|
||||
sleep(world.timeofday+12-start_time)
|
||||
var/end_time = world.timeofday
|
||||
if(end_time < start_time)
|
||||
start_time -= 864000 //deciseconds in a day
|
||||
sleep( round(minimum_ticks - (end_time - start_time),1) )
|
||||
|
||||
else
|
||||
sleep(10)
|
||||
|
||||
datum/controller/game_controller/proc/Recover() //Mostly a placeholder for now.
|
||||
var/msg = "## DEBUG: [time2text(world.timeofday)] MC restarted. Reports:\n"
|
||||
for(var/varname in master_controller.vars)
|
||||
switch(varname)
|
||||
if("tag","bestF","type","parent_type","vars") continue
|
||||
else
|
||||
var/varval = master_controller.vars[varname]
|
||||
if(istype(varval,/datum))
|
||||
var/datum/D = varval
|
||||
msg += "\t [varname] = [D.type]\n"
|
||||
else
|
||||
sleep(10)
|
||||
msg += "\t [varname] = [varval]\n"
|
||||
world.log << msg
|
||||
|
||||
/datum/failsafe // This thing pretty much just keeps poking the master controller
|
||||
var/spinning = 1
|
||||
var/current_iteration = 0
|
||||
var/ticks_per_spin = 100 //poke the MC every 10 seconds
|
||||
var/defcon = 0 //alert level. For every poke that fails this is raised by 1. When it reaches 5 the MC is replaced with a new one. (effectively killing any master_controller.process() and starting a new one)
|
||||
|
||||
/datum/failsafe/New()
|
||||
//There can be only one failsafe. Out with the old in with the new (that way we can restart the Failsafe by spawning a new one)
|
||||
if(Failsafe && (Failsafe != src))
|
||||
del(Failsafe)
|
||||
Failsafe = src
|
||||
|
||||
current_iteration = controller_iteration
|
||||
Failsafe.spin()
|
||||
|
||||
|
||||
/datum/failsafe/proc/spin()
|
||||
spawn(0)
|
||||
set background = 1
|
||||
while(1) //more efficient than recursivly calling ourself over and over. background = 1 ensures we do not trigger an infinite loop
|
||||
if(master_controller)
|
||||
if(spinning && master_controller.processing) //only poke if these overrides aren't in effect
|
||||
if(current_iteration == controller_iteration) //master_controller hasn't finished processing in the defined interval
|
||||
switch(defcon)
|
||||
if(0 to 3)
|
||||
defcon++
|
||||
if(4)
|
||||
defcon = 5
|
||||
for(var/client/C in admin_list)
|
||||
if(C.holder)
|
||||
C << "<font color='red' size='2'><b>Warning. The Master Controller has not fired in the last [defcon*ticks_per_spin] ticks. Automatic restart in [ticks_per_spin] ticks.</b></font>"
|
||||
if(5)
|
||||
for(var/client/C in admin_list)
|
||||
if(C.holder)
|
||||
C << "<font color='red' size='2'><b>Warning. The Master Controller has still not fired within the last [defcon*ticks_per_spin] ticks. Killing and restarting...</b></font>"
|
||||
new /datum/controller/game_controller() //replace the old master_controller (hence killing the old one's process)
|
||||
master_controller.process() //Start it rolling again
|
||||
defcon = 0
|
||||
else
|
||||
defcon = 0
|
||||
current_iteration = controller_iteration
|
||||
else
|
||||
defcon = 0
|
||||
else
|
||||
new /datum/controller/game_controller() //replace the missing master_controller! This should never happen.
|
||||
sleep(ticks_per_spin)
|
||||
|
||||
//DEBUG VERBS
|
||||
/*
|
||||
/client/verb/spawn_MC()
|
||||
new /datum/controller/game_controller()
|
||||
|
||||
|
||||
/client/verb/spawn_FS()
|
||||
new /datum/failsafe()
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//TODO: rewrite and standardise all controller datums to the datum/controller type
|
||||
//TODO: allow all controllers to be deleted for clean restarts (see WIP master controller stuff)
|
||||
//TODO: allow all controllers to be deleted for clean restarts (see WIP master controller stuff) - MC done - lighting done
|
||||
|
||||
/client/proc/restart_controller(controller in list("Master","Lighting","Supply Shuttle"))
|
||||
set category = "Debug"
|
||||
@@ -11,9 +11,11 @@
|
||||
src = null
|
||||
switch(controller)
|
||||
if("Master")
|
||||
new /datum/controller/game_controller()
|
||||
master_controller.process()
|
||||
feedback_add_details("admin_verb","RMC")
|
||||
if("Lighting")
|
||||
new /datum/controller/lighting()
|
||||
lighting_controller.process()
|
||||
feedback_add_details("admin_verb","RLighting")
|
||||
if("Supply Shuttle")
|
||||
|
||||
Reference in New Issue
Block a user