mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-10 10:12:45 +00:00
[MIRROR] Verb manager subsystem & Speech controller (#9559)
Co-authored-by: Heroman3003 <31296024+Heroman3003@users.noreply.github.com> Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
d0b64d915e
commit
06f69815dd
@@ -18,16 +18,14 @@
|
|||||||
#define MC_AVG_FAST_UP_SLOW_DOWN(average, current) (average > current ? MC_AVERAGE_SLOW(average, current) : MC_AVERAGE_FAST(average, current))
|
#define MC_AVG_FAST_UP_SLOW_DOWN(average, current) (average > current ? MC_AVERAGE_SLOW(average, current) : MC_AVERAGE_FAST(average, current))
|
||||||
#define MC_AVG_SLOW_UP_FAST_DOWN(average, current) (average < current ? MC_AVERAGE_SLOW(average, current) : MC_AVERAGE_FAST(average, current))
|
#define MC_AVG_SLOW_UP_FAST_DOWN(average, current) (average < current ? MC_AVERAGE_SLOW(average, current) : MC_AVERAGE_FAST(average, current))
|
||||||
|
|
||||||
// CHOMPEdit Start
|
|
||||||
///creates a running average of "things elapsed" per time period when you need to count via a smaller time period.
|
///creates a running average of "things elapsed" per time period when you need to count via a smaller time period.
|
||||||
///eg you want an average number of things happening per second but you measure the event every tick (50 milliseconds).
|
///eg you want an average number of things happening per second but you measure the event every tick (50 milliseconds).
|
||||||
///make sure both time intervals are in the same units. doesnt work if current_duration > total_duration or if total_duration == 0
|
///make sure both time intervals are in the same units. doesn't work if current_duration > total_duration or if total_duration == 0
|
||||||
#define MC_AVG_OVER_TIME(average, current, total_duration, current_duration) ((((total_duration) - (current_duration)) / (total_duration)) * (average) + (current))
|
#define MC_AVG_OVER_TIME(average, current, total_duration, current_duration) ((((total_duration) - (current_duration)) / (total_duration)) * (average) + (current))
|
||||||
|
|
||||||
#define MC_AVG_MINUTES(average, current, current_duration) (MC_AVG_OVER_TIME(average, current, 1 MINUTES, current_duration))
|
#define MC_AVG_MINUTES(average, current, current_duration) (MC_AVG_OVER_TIME(average, current, 1 MINUTES, current_duration))
|
||||||
|
|
||||||
#define MC_AVG_SECONDS(average, current, current_duration) (MC_AVG_OVER_TIME(average, current, 1 SECONDS, current_duration))
|
#define MC_AVG_SECONDS(average, current, current_duration) (MC_AVG_OVER_TIME(average, current, 1 SECONDS, current_duration))
|
||||||
// CHOMPEdit End
|
|
||||||
|
|
||||||
#define NEW_SS_GLOBAL(varname) if(varname != src){if(istype(varname)){Recover();qdel(varname);}varname = src;}
|
#define NEW_SS_GLOBAL(varname) if(varname != src){if(istype(varname)){Recover();qdel(varname);}varname = src;}
|
||||||
|
|
||||||
@@ -81,18 +79,35 @@
|
|||||||
|
|
||||||
#define SUBSYSTEM_DEF(X) GLOBAL_REAL(SS##X, /datum/controller/subsystem/##X);\
|
#define SUBSYSTEM_DEF(X) GLOBAL_REAL(SS##X, /datum/controller/subsystem/##X);\
|
||||||
/datum/controller/subsystem/##X/New(){\
|
/datum/controller/subsystem/##X/New(){\
|
||||||
NEW_SS_GLOBAL(SS##X);\
|
NEW_SS_GLOBAL(SS##X);\
|
||||||
PreInit();\
|
PreInit();\
|
||||||
}\
|
}\
|
||||||
/datum/controller/subsystem/##X
|
/datum/controller/subsystem/##X
|
||||||
|
|
||||||
|
#define TIMER_SUBSYSTEM_DEF(X) GLOBAL_REAL(SS##X, /datum/controller/subsystem/timer/##X);\
|
||||||
|
/datum/controller/subsystem/timer/##X/New(){\
|
||||||
|
NEW_SS_GLOBAL(SS##X);\
|
||||||
|
PreInit();\
|
||||||
|
}\
|
||||||
|
/datum/controller/subsystem/timer/##X/fire() {..() /*just so it shows up on the profiler*/} \
|
||||||
|
/datum/controller/subsystem/timer/##X
|
||||||
|
|
||||||
#define PROCESSING_SUBSYSTEM_DEF(X) GLOBAL_REAL(SS##X, /datum/controller/subsystem/processing/##X);\
|
#define PROCESSING_SUBSYSTEM_DEF(X) GLOBAL_REAL(SS##X, /datum/controller/subsystem/processing/##X);\
|
||||||
/datum/controller/subsystem/processing/##X/New(){\
|
/datum/controller/subsystem/processing/##X/New(){\
|
||||||
NEW_SS_GLOBAL(SS##X);\
|
NEW_SS_GLOBAL(SS##X);\
|
||||||
PreInit();\
|
PreInit();\
|
||||||
}\
|
}\
|
||||||
|
/datum/controller/subsystem/processing/##X/fire() {..() /*just so it shows up on the profiler*/} \
|
||||||
/datum/controller/subsystem/processing/##X
|
/datum/controller/subsystem/processing/##X
|
||||||
|
|
||||||
|
#define VERB_MANAGER_SUBSYSTEM_DEF(X) GLOBAL_REAL(SS##X, /datum/controller/subsystem/verb_manager/##X);\
|
||||||
|
/datum/controller/subsystem/verb_manager/##X/New(){\
|
||||||
|
NEW_SS_GLOBAL(SS##X);\
|
||||||
|
PreInit();\
|
||||||
|
}\
|
||||||
|
/datum/controller/subsystem/verb_manager/##X/fire() {..() /*just so it shows up on the profiler*/} \
|
||||||
|
/datum/controller/subsystem/verb_manager/##X
|
||||||
|
|
||||||
// Boilerplate code for multi-step processors. See machines.dm for example use.
|
// Boilerplate code for multi-step processors. See machines.dm for example use.
|
||||||
#define INTERNAL_PROCESS_STEP(this_step, initial_step, proc_to_call, cost_var, next_step)\
|
#define INTERNAL_PROCESS_STEP(this_step, initial_step, proc_to_call, cost_var, next_step)\
|
||||||
if(current_step == this_step || (initial_step && !resumed)) /* So we start at step 1 if not resumed.*/ {\
|
if(current_step == this_step || (initial_step && !resumed)) /* So we start at step 1 if not resumed.*/ {\
|
||||||
@@ -105,13 +120,3 @@ if(current_step == this_step || (initial_step && !resumed)) /* So we start at st
|
|||||||
resumed = 0;\
|
resumed = 0;\
|
||||||
current_step = next_step;\
|
current_step = next_step;\
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHOMPEdit Start
|
|
||||||
#define VERB_MANAGER_SUBSYSTEM_DEF(X) GLOBAL_REAL(SS##X, /datum/controller/subsystem/verb_manager/##X);\
|
|
||||||
/datum/controller/subsystem/verb_manager/##X/New(){\
|
|
||||||
NEW_SS_GLOBAL(SS##X);\
|
|
||||||
PreInit();\
|
|
||||||
}\
|
|
||||||
/datum/controller/subsystem/verb_manager/##X/fire() {..() /*just so it shows up on the profiler*/} \
|
|
||||||
/datum/controller/subsystem/verb_manager/##X
|
|
||||||
// CHOMPEdit End
|
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
#define GLOBAL_PROC "some_magic_bullshit"
|
#define GLOBAL_PROC "some_magic_bullshit"
|
||||||
|
/// A shorthand for the callback datum, [documented here](datum/callback.html)
|
||||||
#define CALLBACK new /datum/callback
|
#define CALLBACK new /datum/callback
|
||||||
|
|
||||||
#define INVOKE_ASYNC world.ImmediateInvokeAsync
|
#define INVOKE_ASYNC world.ImmediateInvokeAsync
|
||||||
|
|
||||||
// CHOMPEdit Start
|
|
||||||
/// like CALLBACK but specifically for verb callbacks
|
/// like CALLBACK but specifically for verb callbacks
|
||||||
#define VERB_CALLBACK new /datum/callback/verb_callback
|
#define VERB_CALLBACK new /datum/callback/verb_callback
|
||||||
// CHOMPEdit End
|
|
||||||
|
|||||||
@@ -191,8 +191,8 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G
|
|||||||
#define FIRE_PRIORITY_CHAT 400
|
#define FIRE_PRIORITY_CHAT 400
|
||||||
#define FIRE_PRIORITY_OVERLAYS 500
|
#define FIRE_PRIORITY_OVERLAYS 500
|
||||||
#define FIRE_PRIORITY_TIMER 700
|
#define FIRE_PRIORITY_TIMER 700
|
||||||
#define FIRE_PRIORITY_SPEECH_CONTROLLER 900 // CHOMPEdit
|
#define FIRE_PRIORITY_SPEECH_CONTROLLER 900
|
||||||
#define FIRE_PRIORITY_DELAYED_VERBS 950 // CHOMPEdit
|
#define FIRE_PRIORITY_DELAYED_VERBS 950
|
||||||
#define FIRE_PRIORITY_INPUT 1000 // This must always always be the max highest priority. Player input must never be lost.
|
#define FIRE_PRIORITY_INPUT 1000 // This must always always be the max highest priority. Player input must never be lost.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,64 +0,0 @@
|
|||||||
//
|
|
||||||
// Lets read our settings from the configuration file on startup too!
|
|
||||||
//
|
|
||||||
|
|
||||||
/datum/configuration
|
|
||||||
var/static/time_off = FALSE
|
|
||||||
var/static/pto_job_change = FALSE
|
|
||||||
var/static/limit_interns = -1 //Unlimited by default
|
|
||||||
var/static/limit_visitors = -1 //Unlimited by default
|
|
||||||
var/static/pto_cap = 100 //Hours
|
|
||||||
var/static/require_flavor = FALSE
|
|
||||||
var/static/ipqualityscore_apikey //API key for ipqualityscore.com
|
|
||||||
var/static/use_playtime_restriction_for_jobs = FALSE
|
|
||||||
|
|
||||||
/hook/startup/proc/read_vs_config()
|
|
||||||
var/list/Lines = file2list("config/config.txt")
|
|
||||||
for(var/t in Lines)
|
|
||||||
if(!t) continue
|
|
||||||
|
|
||||||
t = trim(t)
|
|
||||||
if (length(t) == 0)
|
|
||||||
continue
|
|
||||||
else if (copytext(t, 1, 2) == "#")
|
|
||||||
continue
|
|
||||||
|
|
||||||
var/pos = findtext(t, " ")
|
|
||||||
var/name = null
|
|
||||||
var/value = null
|
|
||||||
|
|
||||||
if (pos)
|
|
||||||
name = lowertext(copytext(t, 1, pos))
|
|
||||||
value = copytext(t, pos + 1)
|
|
||||||
else
|
|
||||||
name = lowertext(t)
|
|
||||||
|
|
||||||
if (!name)
|
|
||||||
continue
|
|
||||||
|
|
||||||
switch (name)
|
|
||||||
if ("chat_webhook_url")
|
|
||||||
config.chat_webhook_url = value
|
|
||||||
if ("chat_webhook_key")
|
|
||||||
config.chat_webhook_key = value
|
|
||||||
if ("fax_export_dir")
|
|
||||||
config.fax_export_dir = value
|
|
||||||
if ("items_survive_digestion")
|
|
||||||
config.items_survive_digestion = 1
|
|
||||||
if ("limit_interns")
|
|
||||||
config.limit_interns = text2num(value)
|
|
||||||
if ("limit_visitors")
|
|
||||||
config.limit_visitors = text2num(value)
|
|
||||||
if ("pto_cap")
|
|
||||||
config.pto_cap = text2num(value)
|
|
||||||
if ("time_off")
|
|
||||||
config.time_off = TRUE
|
|
||||||
if ("pto_job_change")
|
|
||||||
config.pto_job_change = TRUE
|
|
||||||
if ("require_flavor")
|
|
||||||
config.require_flavor = TRUE
|
|
||||||
if ("ipqualityscore_apikey")
|
|
||||||
config.ipqualityscore_apikey = value
|
|
||||||
if ("use_playtime_restriction_for_jobs")
|
|
||||||
config.use_playtime_restriction_for_jobs = TRUE
|
|
||||||
return 1
|
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
/**
|
/**
|
||||||
* Failsafe
|
* Failsafe
|
||||||
*
|
*
|
||||||
* Pretty much pokes the MC to make sure it's still alive.
|
* Pretty much pokes the MC to make sure it's still alive.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
GLOBAL_REAL(Failsafe, /datum/controller/failsafe) // CHOMPEdit - Managed Globals
|
// See initialization order in /code/game/world.dm
|
||||||
|
GLOBAL_REAL(Failsafe, /datum/controller/failsafe)
|
||||||
|
|
||||||
/datum/controller/failsafe // This thing pretty much just keeps poking the master controller
|
/datum/controller/failsafe // This thing pretty much just keeps poking the master controller
|
||||||
name = "Failsafe"
|
name = "Failsafe"
|
||||||
@@ -15,7 +16,7 @@ GLOBAL_REAL(Failsafe, /datum/controller/failsafe) // CHOMPEdit - Managed Globals
|
|||||||
// The alert level. For every failed poke, we drop a DEFCON level. Once we hit DEFCON 1, restart the MC.
|
// The alert level. For every failed poke, we drop a DEFCON level. Once we hit DEFCON 1, restart the MC.
|
||||||
var/defcon = 5
|
var/defcon = 5
|
||||||
//the world.time of the last check, so the mc can restart US if we hang.
|
//the world.time of the last check, so the mc can restart US if we hang.
|
||||||
// (Real friends look out for *eachother*)
|
// (Real friends look out for *each other*)
|
||||||
var/lasttick = 0
|
var/lasttick = 0
|
||||||
|
|
||||||
// Track the MC iteration to make sure its still on track.
|
// Track the MC iteration to make sure its still on track.
|
||||||
@@ -31,8 +32,24 @@ GLOBAL_REAL(Failsafe, /datum/controller/failsafe) // CHOMPEdit - Managed Globals
|
|||||||
Initialize()
|
Initialize()
|
||||||
|
|
||||||
/datum/controller/failsafe/Initialize()
|
/datum/controller/failsafe/Initialize()
|
||||||
set waitfor = 0
|
set waitfor = FALSE
|
||||||
Failsafe.Loop()
|
Failsafe.Loop()
|
||||||
|
if (!Master || defcon == 0) //Master is gone/not responding and Failsafe just exited its loop
|
||||||
|
defcon = 3 //Reset defcon level as its used inside the emergency loop
|
||||||
|
while (defcon > 0)
|
||||||
|
var/recovery_result = emergency_loop()
|
||||||
|
if (recovery_result == 1) //Exit emergency loop and delete self if it was able to recover MC
|
||||||
|
break
|
||||||
|
else if (defcon == 1) //Exit Failsafe if we weren't able to recover the MC in the last stage
|
||||||
|
log_game("FailSafe: Failed to recover MC while in emergency state. Failsafe exiting.")
|
||||||
|
message_admins(span_boldannounce("Failsafe failed critically while trying to recreate broken MC. Please manually fix the MC or reboot the server. Failsafe exiting now."))
|
||||||
|
message_admins(span_boldannounce("You can try manually calling these two procs:."))
|
||||||
|
message_admins(span_boldannounce("/proc/recover_all_SS_and_recreate_master: Most stuff should still function but expect instability/runtimes/broken stuff."))
|
||||||
|
message_admins(span_boldannounce("/proc/delete_all_SS_and_recreate_master: Most stuff will be broken but basic stuff like movement and chat should still work."))
|
||||||
|
else if (recovery_result == -1) //Failed to recreate MC
|
||||||
|
defcon--
|
||||||
|
sleep(initial(processing_interval)) //Wait a bit until the next try
|
||||||
|
|
||||||
if(!QDELETED(src))
|
if(!QDELETED(src))
|
||||||
qdel(src) //when Loop() returns, we delete ourselves and let the mc recreate us
|
qdel(src) //when Loop() returns, we delete ourselves and let the mc recreate us
|
||||||
|
|
||||||
@@ -45,43 +62,56 @@ GLOBAL_REAL(Failsafe, /datum/controller/failsafe) // CHOMPEdit - Managed Globals
|
|||||||
while(running)
|
while(running)
|
||||||
lasttick = world.time
|
lasttick = world.time
|
||||||
if(!Master)
|
if(!Master)
|
||||||
// Replace the missing Master! This should never, ever happen.
|
// Break out of the main loop so we go into emergency state
|
||||||
new /datum/controller/master()
|
break
|
||||||
// Only poke it if overrides are not in effect.
|
// Only poke it if overrides are not in effect.
|
||||||
if(processing_interval > 0)
|
if(processing_interval > 0)
|
||||||
if(Master.processing && Master.iteration)
|
if(Master.processing && Master.iteration)
|
||||||
|
if (defcon > 1 && (!Master.stack_end_detector || !Master.stack_end_detector.check()))
|
||||||
|
|
||||||
|
to_chat(GLOB.admins, span_boldannounce("ERROR: The Master Controller code stack has exited unexpectedly, Restarting..."))
|
||||||
|
defcon = 0
|
||||||
|
var/rtn = Recreate_MC()
|
||||||
|
if(rtn > 0)
|
||||||
|
master_iteration = 0
|
||||||
|
to_chat(GLOB.admins, span_adminnotice("MC restarted successfully"))
|
||||||
|
else if(rtn < 0)
|
||||||
|
log_game("FailSafe: Could not restart MC, runtime encountered. Entering defcon 0")
|
||||||
|
to_chat(GLOB.admins, span_boldannounce("ERROR: DEFCON [defcon_pretty()]. Could not restart MC, runtime encountered. I will silently keep retrying."))
|
||||||
// Check if processing is done yet.
|
// Check if processing is done yet.
|
||||||
if(Master.iteration == master_iteration)
|
if(Master.iteration == master_iteration)
|
||||||
log_debug("DEFCON [defcon]: Master.iteration=[Master.iteration] Master.last_run=[Master.last_run] world.time=[world.time]")
|
|
||||||
switch(defcon)
|
switch(defcon)
|
||||||
if(4,5)
|
if(4,5)
|
||||||
--defcon
|
--defcon
|
||||||
if(3)
|
|
||||||
log_and_message_admins(span_adminnotice("SSfailsafe Notice: DEFCON [defcon_pretty()]. The Master Controller (\ref[Master]) has not fired in the last [(5-defcon) * processing_interval] ticks."))
|
|
||||||
--defcon
|
|
||||||
if(2)
|
|
||||||
log_and_message_admins(span_boldannounce("SSfailsafe Warning: DEFCON [defcon_pretty()]. The Master Controller (\ref[Master]) has not fired in the last [(5-defcon) * processing_interval] ticks. Automatic restart in [processing_interval] ticks."))
|
|
||||||
--defcon
|
|
||||||
if(1)
|
|
||||||
|
|
||||||
log_and_message_admins(span_boldannounce("SSfailsafe Warning: DEFCON [defcon_pretty()]. The Master Controller (\ref[Master]) has still not fired within the last [(5-defcon) * processing_interval] ticks. Killing and restarting..."))
|
if(3)
|
||||||
|
message_admins(span_adminnotice("Notice: DEFCON [defcon_pretty()]. The Master Controller has not fired in the last [(5-defcon) * processing_interval] ticks."))
|
||||||
|
--defcon
|
||||||
|
|
||||||
|
if(2)
|
||||||
|
to_chat(GLOB.admins, span_boldannounce("Warning: DEFCON [defcon_pretty()]. The Master Controller has not fired in the last [(5-defcon) * processing_interval] ticks. Automatic restart in [processing_interval] ticks."))
|
||||||
|
--defcon
|
||||||
|
|
||||||
|
if(1)
|
||||||
|
to_chat(GLOB.admins, span_boldannounce("Warning: DEFCON [defcon_pretty()]. The Master Controller has still not fired within the last [(5-defcon) * processing_interval] ticks. Killing and restarting..."))
|
||||||
--defcon
|
--defcon
|
||||||
var/rtn = Recreate_MC()
|
var/rtn = Recreate_MC()
|
||||||
if(rtn > 0)
|
if(rtn > 0)
|
||||||
defcon = 4
|
defcon = 4
|
||||||
master_iteration = 0
|
master_iteration = 0
|
||||||
log_and_message_admins(span_adminnotice("SSfailsafe Notice: MC (New:\ref[Master]) restarted successfully"))
|
to_chat(GLOB.admins, span_adminnotice("MC restarted successfully"))
|
||||||
else if(rtn < 0)
|
else if(rtn < 0)
|
||||||
log_game("SSfailsafe Notice: Could not restart MC (\ref[Master]), runtime encountered. Entering defcon 0")
|
log_game("FailSafe: Could not restart MC, runtime encountered. Entering defcon 0")
|
||||||
log_and_message_admins(span_boldannounce("SSFAILSAFE ERROR: DEFCON [defcon_pretty()]. Could not restart MC (\ref[Master]), runtime encountered. I will silently keep retrying."))
|
to_chat(GLOB.admins, span_boldannounce("ERROR: DEFCON [defcon_pretty()]. Could not restart MC, runtime encountered. I will silently keep retrying."))
|
||||||
//if the return number was 0, it just means the mc was restarted too recently, and it just needs some time before we try again
|
//if the return number was 0, it just means the mc was restarted too recently, and it just needs some time before we try again
|
||||||
//no need to handle that specially when defcon 0 can handle it
|
//no need to handle that specially when defcon 0 can handle it
|
||||||
|
|
||||||
if(0) //DEFCON 0! (mc failed to restart)
|
if(0) //DEFCON 0! (mc failed to restart)
|
||||||
var/rtn = Recreate_MC()
|
var/rtn = Recreate_MC()
|
||||||
if(rtn > 0)
|
if(rtn > 0)
|
||||||
defcon = 4
|
defcon = 4
|
||||||
master_iteration = 0
|
master_iteration = 0
|
||||||
log_and_message_admins(span_adminnotice("SSfailsafe Notice: MC (New:\ref[Master]) restarted successfully"))
|
to_chat(GLOB.admins, span_adminnotice("MC restarted successfully"))
|
||||||
else
|
else
|
||||||
defcon = min(defcon + 1,5)
|
defcon = min(defcon + 1,5)
|
||||||
master_iteration = Master.iteration
|
master_iteration = Master.iteration
|
||||||
@@ -93,12 +123,60 @@ GLOBAL_REAL(Failsafe, /datum/controller/failsafe) // CHOMPEdit - Managed Globals
|
|||||||
defcon = 5
|
defcon = 5
|
||||||
sleep(initial(processing_interval))
|
sleep(initial(processing_interval))
|
||||||
|
|
||||||
|
//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
|
||||||
|
master_iteration = 0
|
||||||
|
SSticker.Recover(); //Recover the ticket system so the Masters runlevel gets set
|
||||||
|
Master.Initialize(10, FALSE, FALSE) //Need to manually start the MC, normally world.new would do this
|
||||||
|
to_chat(GLOB.admins, span_adminnotice("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(span_boldannounce("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, GLOBAL_PROC_REF(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, FALSE) //Need to manually start the MC, normally world.new would do this
|
||||||
|
to_chat(GLOB.admins, span_adminnotice("MC successfully recreated after recovering all subsystems!"))
|
||||||
|
else
|
||||||
|
message_admins(span_boldannounce("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, FALSE) //Need to manually start the MC, normally world.new would do this
|
||||||
|
to_chat(GLOB.admins, span_adminnotice("MC successfully recreated after deleting and recreating all subsystems!"))
|
||||||
|
else
|
||||||
|
message_admins(span_boldannounce("Failed to create new MC!"))
|
||||||
|
|
||||||
/datum/controller/failsafe/proc/defcon_pretty()
|
/datum/controller/failsafe/proc/defcon_pretty()
|
||||||
return defcon
|
return defcon
|
||||||
|
|
||||||
/datum/controller/failsafe/stat_entry(msg)
|
/datum/controller/failsafe/stat_entry(msg)
|
||||||
if(!statclick)
|
msg = "Defcon: [defcon_pretty()] (Interval: [Failsafe.processing_interval] | Iteration: [Failsafe.master_iteration])"
|
||||||
statclick = new/obj/effect/statclick/debug(null, "Initializing...", src)
|
|
||||||
|
|
||||||
msg = "Failsafe Controller: [statclick.update("Defcon: [defcon_pretty()] (Interval: [Failsafe.processing_interval] | Iteration: [Failsafe.master_iteration])")]"
|
|
||||||
return msg
|
return msg
|
||||||
|
|||||||
@@ -1,19 +1,14 @@
|
|||||||
/**
|
/**
|
||||||
* StonedMC
|
* StonedMC
|
||||||
*
|
*
|
||||||
* Designed to properly split up a given tick among subsystems
|
* Designed to properly split up a given tick among subsystems
|
||||||
* Note: if you read parts of this code and think "why is it doing it that way"
|
* Note: if you read parts of this code and think "why is it doing it that way"
|
||||||
* Odds are, there is a reason
|
* Odds are, there is a reason
|
||||||
*
|
*
|
||||||
**/
|
**/
|
||||||
|
|
||||||
//This is the ABSOLUTE ONLY THING that should init globally like this
|
// See initialization order in /code/game/world.dm
|
||||||
GLOBAL_REAL(Master, /datum/controller/master) = new
|
GLOBAL_REAL(Master, /datum/controller/master) = new
|
||||||
|
|
||||||
//THIS IS THE INIT ORDER
|
|
||||||
//Master -> SSPreInit -> GLOB -> world -> config -> SSInit -> Failsafe
|
|
||||||
//GOT IT MEMORIZED?
|
|
||||||
|
|
||||||
/datum/controller/master
|
/datum/controller/master
|
||||||
name = "Master"
|
name = "Master"
|
||||||
|
|
||||||
|
|||||||
@@ -8,15 +8,15 @@
|
|||||||
* plus TICK_BYOND_RESERVE from the tick and uses up to that amount of time (minus the percentage of the tick used by the time it executes subsystems)
|
* plus TICK_BYOND_RESERVE from the tick and uses up to that amount of time (minus the percentage of the tick used by the time it executes subsystems)
|
||||||
* on subsystems running cool things like atmospherics or Life or SSInput or whatever.
|
* on subsystems running cool things like atmospherics or Life or SSInput or whatever.
|
||||||
*
|
*
|
||||||
* Without this subsystem, verbs are likely to cause overtime if the MC uses all of the time it has alloted for itself in the tick, and SendMaps
|
* Without this subsystem, verbs are likely to cause overtime if the MC uses all of the time it has allotted for itself in the tick, and SendMaps
|
||||||
* uses as much as its expected to, and an expensive verb ends up executing that tick. This is because the MC is completely blind to the cost of
|
* uses as much as its expected to, and an expensive verb ends up executing that tick. This is because the MC is completely blind to the cost of
|
||||||
* verbs, it can't account for it at all. The only chance for verbs to not cause overtime in a tick where the MC used as much of the tick
|
* verbs, it can't account for it at all. The only chance for verbs to not cause overtime in a tick where the MC used as much of the tick
|
||||||
* as it alloted itself and where SendMaps costed as much as it was expected to is if the verb(s) take less than TICK_BYOND_RESERVE percent of
|
* as it allotted itself and where SendMaps costed as much as it was expected to is if the verb(s) take less than TICK_BYOND_RESERVE percent of
|
||||||
* the tick, which isnt much. Not to mention if SendMaps takes more than 30% of the tick and the MC forces itself to take at least 70% of the
|
* the tick, which isn't much. Not to mention if SendMaps takes more than 30% of the tick and the MC forces itself to take at least 70% of the
|
||||||
* normal tick duration which causes ticks to naturally overrun even in the absence of verbs.
|
* normal tick duration which causes ticks to naturally overrun even in the absence of verbs.
|
||||||
*
|
*
|
||||||
* With this subsystem, the MC can account for the cost of verbs and thus stop major overruns of ticks. This means that the most important subsystems
|
* With this subsystem, the MC can account for the cost of verbs and thus stop major overruns of ticks. This means that the most important subsystems
|
||||||
* like SSinput can start at the same time they were supposed to, leading to a smoother experience for the player since ticks arent riddled with
|
* like SSinput can start at the same time they were supposed to, leading to a smoother experience for the player since ticks aren't riddled with
|
||||||
* minor hangs over and over again.
|
* minor hangs over and over again.
|
||||||
*/
|
*/
|
||||||
SUBSYSTEM_DEF(verb_manager)
|
SUBSYSTEM_DEF(verb_manager)
|
||||||
@@ -36,17 +36,17 @@ SUBSYSTEM_DEF(verb_manager)
|
|||||||
///if TRUE we treat usr's with holders just like usr's without holders. otherwise they always execute immediately
|
///if TRUE we treat usr's with holders just like usr's without holders. otherwise they always execute immediately
|
||||||
var/can_queue_admin_verbs = FALSE
|
var/can_queue_admin_verbs = FALSE
|
||||||
|
|
||||||
///if this is true all verbs immediately execute and dont queue. in case the mc is fucked or something
|
///if this is true all verbs immediately execute and don't queue. in case the mc is fucked or something
|
||||||
var/FOR_ADMINS_IF_VERBS_FUCKED_immediately_execute_all_verbs = FALSE
|
var/FOR_ADMINS_IF_VERBS_FUCKED_immediately_execute_all_verbs = FALSE
|
||||||
|
|
||||||
///used for subtypes to determine if they use their own stats for the stat entry
|
///used for subtypes to determine if they use their own stats for the stat entry
|
||||||
var/use_default_stats = TRUE
|
var/use_default_stats = TRUE
|
||||||
|
|
||||||
///if TRUE this will... message admins every time a verb is queued to this subsystem for the next tick with stats.
|
///if TRUE this will... message admins every time a verb is queued to this subsystem for the next tick with stats.
|
||||||
///for obvious reasons dont make this be TRUE on the code level this is for admins to turn on
|
///for obvious reasons don't make this be TRUE on the code level this is for admins to turn on
|
||||||
var/message_admins_on_queue = FALSE
|
var/message_admins_on_queue = FALSE
|
||||||
|
|
||||||
///always queue if possible. overides can_queue_admin_verbs but not FOR_ADMINS_IF_VERBS_FUCKED_immediately_execute_all_verbs
|
///always queue if possible. overrides can_queue_admin_verbs but not FOR_ADMINS_IF_VERBS_FUCKED_immediately_execute_all_verbs
|
||||||
var/always_queue = FALSE
|
var/always_queue = FALSE
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -87,7 +87,7 @@ SUBSYSTEM_DEF(verb_manager)
|
|||||||
#else
|
#else
|
||||||
|
|
||||||
if(QDELETED(usr) || isnull(usr.client))
|
if(QDELETED(usr) || isnull(usr.client))
|
||||||
stack_trace("_queue_verb() returned false because it wasnt called from player input!")
|
stack_trace("_queue_verb() returned false because it wasn't called from player input!")
|
||||||
return FALSE
|
return FALSE
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -163,5 +163,5 @@ SUBSYSTEM_DEF(verb_manager)
|
|||||||
|
|
||||||
/datum/controller/subsystem/verb_manager/stat_entry(msg)
|
/datum/controller/subsystem/verb_manager/stat_entry(msg)
|
||||||
. = ..()
|
. = ..()
|
||||||
if (use_default_stats)
|
if(use_default_stats)
|
||||||
. += "V/S: [round(verbs_executed_per_second, 0.01)]"
|
. += "V/S: [round(verbs_executed_per_second, 0.01)]"
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
creation_time = DS2TICKS(world.time)
|
creation_time = DS2TICKS(world.time)
|
||||||
. = ..()
|
. = ..()
|
||||||
|
|
||||||
#ifndef UNIT_TESTS
|
#ifndef UNIT_TEST
|
||||||
/datum/callback/verb_callback/Invoke(...)
|
/datum/callback/verb_callback/Invoke(...)
|
||||||
var/mob/our_user = user?.resolve()
|
var/mob/our_user = user?.resolve()
|
||||||
if(QDELETED(our_user) || isnull(our_user.client))
|
if(QDELETED(our_user) || isnull(our_user.client))
|
||||||
@@ -148,7 +148,6 @@
|
|||||||
if("openLink")
|
if("openLink")
|
||||||
src << link(href_list["link"])
|
src << link(href_list["link"])
|
||||||
|
|
||||||
// CHOMPEdit Start
|
|
||||||
if (hsrc)
|
if (hsrc)
|
||||||
var/datum/real_src = hsrc
|
var/datum/real_src = hsrc
|
||||||
if(QDELETED(real_src))
|
if(QDELETED(real_src))
|
||||||
@@ -158,13 +157,12 @@
|
|||||||
//overloaded
|
//overloaded
|
||||||
if(hsrc && hsrc != holder && DEFAULT_TRY_QUEUE_VERB(VERB_CALLBACK(src, PROC_REF(_Topic), hsrc, href, href_list)))
|
if(hsrc && hsrc != holder && DEFAULT_TRY_QUEUE_VERB(VERB_CALLBACK(src, PROC_REF(_Topic), hsrc, href, href_list)))
|
||||||
return
|
return
|
||||||
..() //redirect to hsrc.Topic()
|
..() //redirect to hsrc.Topic()
|
||||||
|
|
||||||
///dumb workaround because byond doesnt seem to recognize the Topic() typepath for /datum/proc/Topic() from the client Topic,
|
///dumb workaround because byond doesnt seem to recognize the Topic() typepath for /datum/proc/Topic() from the client Topic,
|
||||||
///so we cant queue it without this
|
///so we cant queue it without this
|
||||||
/client/proc/_Topic(datum/hsrc, href, list/href_list)
|
/client/proc/_Topic(datum/hsrc, href, list/href_list)
|
||||||
return hsrc.Topic(href, href_list)
|
return hsrc.Topic(href, href_list)
|
||||||
// CHOMPEdit End
|
|
||||||
|
|
||||||
//This stops files larger than UPLOAD_LIMIT being sent from client to server via input(), client.Import() etc.
|
//This stops files larger than UPLOAD_LIMIT being sent from client to server via input(), client.Import() etc.
|
||||||
/client/AllowUpload(filename, filelength)
|
/client/AllowUpload(filename, filelength)
|
||||||
|
|||||||
@@ -18,6 +18,8 @@
|
|||||||
// set category = "IC.Chat" //CHOMPEdit
|
// set category = "IC.Chat" //CHOMPEdit
|
||||||
set instant = TRUE // CHOMPEdit
|
set instant = TRUE // CHOMPEdit
|
||||||
set hidden = 1
|
set hidden = 1
|
||||||
|
set instant = TRUE
|
||||||
|
|
||||||
//VOREStation Addition Start
|
//VOREStation Addition Start
|
||||||
if(forced_psay)
|
if(forced_psay)
|
||||||
psay(message)
|
psay(message)
|
||||||
@@ -25,12 +27,10 @@
|
|||||||
//VOREStation Addition End
|
//VOREStation Addition End
|
||||||
|
|
||||||
client?.stop_thinking()
|
client?.stop_thinking()
|
||||||
// CHOMPEdit Start
|
|
||||||
//queue this message because verbs are scheduled to process after SendMaps in the tick and speech is pretty expensive when it happens.
|
//queue this message because verbs are scheduled to process after SendMaps in the tick and speech is pretty expensive when it happens.
|
||||||
//by queuing this for next tick the mc can compensate for its cost instead of having speech delay the start of the next tick
|
//by queuing this for next tick the mc can compensate for its cost instead of having speech delay the start of the next tick
|
||||||
if(message)
|
if(message)
|
||||||
QUEUE_OR_CALL_VERB_FOR(VERB_CALLBACK(src, TYPE_PROC_REF(/mob, say), message), SSspeech_controller)
|
QUEUE_OR_CALL_VERB_FOR(VERB_CALLBACK(src, TYPE_PROC_REF(/mob, say), message), SSspeech_controller)
|
||||||
// CHOMPEdit End
|
|
||||||
|
|
||||||
/mob/verb/me_verb(message as message) //CHOMPEdit
|
/mob/verb/me_verb(message as message) //CHOMPEdit
|
||||||
set name = "Me"
|
set name = "Me"
|
||||||
|
|||||||
@@ -163,7 +163,7 @@
|
|||||||
#include "code\__defines\typeids.dm"
|
#include "code\__defines\typeids.dm"
|
||||||
#include "code\__defines\unit_tests.dm"
|
#include "code\__defines\unit_tests.dm"
|
||||||
#include "code\__defines\update_icons.dm"
|
#include "code\__defines\update_icons.dm"
|
||||||
#include "code\__defines\verb_manager_ch.dm"
|
#include "code\__defines\verb_manager.dm"
|
||||||
#include "code\__defines\vore.dm"
|
#include "code\__defines\vore.dm"
|
||||||
#include "code\__defines\vote.dm"
|
#include "code\__defines\vote.dm"
|
||||||
#include "code\__defines\vv.dm"
|
#include "code\__defines\vv.dm"
|
||||||
@@ -409,7 +409,7 @@
|
|||||||
#include "code\controllers\subsystems\shuttles.dm"
|
#include "code\controllers\subsystems\shuttles.dm"
|
||||||
#include "code\controllers\subsystems\skybox.dm"
|
#include "code\controllers\subsystems\skybox.dm"
|
||||||
#include "code\controllers\subsystems\sounds.dm"
|
#include "code\controllers\subsystems\sounds.dm"
|
||||||
#include "code\controllers\subsystems\speech_controller_ch.dm"
|
#include "code\controllers\subsystems\speech_controller.dm"
|
||||||
#include "code\controllers\subsystems\sqlite.dm"
|
#include "code\controllers\subsystems\sqlite.dm"
|
||||||
#include "code\controllers\subsystems\SSvote.dm"
|
#include "code\controllers\subsystems\SSvote.dm"
|
||||||
#include "code\controllers\subsystems\statpanel.dm"
|
#include "code\controllers\subsystems\statpanel.dm"
|
||||||
@@ -422,7 +422,7 @@
|
|||||||
#include "code\controllers\subsystems\timer.dm"
|
#include "code\controllers\subsystems\timer.dm"
|
||||||
#include "code\controllers\subsystems\title_ch.dm"
|
#include "code\controllers\subsystems\title_ch.dm"
|
||||||
#include "code\controllers\subsystems\transcore_vr.dm"
|
#include "code\controllers\subsystems\transcore_vr.dm"
|
||||||
#include "code\controllers\subsystems\verb_manager_ch.dm"
|
#include "code\controllers\subsystems\verb_manager.dm"
|
||||||
#include "code\controllers\subsystems\vis_overlays.dm"
|
#include "code\controllers\subsystems\vis_overlays.dm"
|
||||||
#include "code\controllers\subsystems\vote.dm"
|
#include "code\controllers\subsystems\vote.dm"
|
||||||
#include "code\controllers\subsystems\webhooks.dm"
|
#include "code\controllers\subsystems\webhooks.dm"
|
||||||
@@ -471,7 +471,7 @@
|
|||||||
#include "code\datums\signals.dm"
|
#include "code\datums\signals.dm"
|
||||||
#include "code\datums\soul_link.dm"
|
#include "code\datums\soul_link.dm"
|
||||||
#include "code\datums\sun.dm"
|
#include "code\datums\sun.dm"
|
||||||
#include "code\datums\verb_callbacks_ch.dm"
|
#include "code\datums\verb_callbacks.dm"
|
||||||
#include "code\datums\weakrefs.dm"
|
#include "code\datums\weakrefs.dm"
|
||||||
#include "code\datums\autolathe\arms_ch.dm"
|
#include "code\datums\autolathe\arms_ch.dm"
|
||||||
#include "code\datums\autolathe\arms_yw.dm"
|
#include "code\datums\autolathe\arms_yw.dm"
|
||||||
@@ -554,7 +554,7 @@
|
|||||||
#include "code\datums\helper_datums\construction_datum.dm"
|
#include "code\datums\helper_datums\construction_datum.dm"
|
||||||
#include "code\datums\helper_datums\events.dm"
|
#include "code\datums\helper_datums\events.dm"
|
||||||
#include "code\datums\helper_datums\getrev.dm"
|
#include "code\datums\helper_datums\getrev.dm"
|
||||||
#include "code\datums\helper_datums\stack_end_detector_ch.dm"
|
#include "code\datums\helper_datums\stack_end_detector.dm"
|
||||||
#include "code\datums\helper_datums\teleport.dm"
|
#include "code\datums\helper_datums\teleport.dm"
|
||||||
#include "code\datums\helper_datums\teleport_vr.dm"
|
#include "code\datums\helper_datums\teleport_vr.dm"
|
||||||
#include "code\datums\helper_datums\topic_input.dm"
|
#include "code\datums\helper_datums\topic_input.dm"
|
||||||
|
|||||||
Reference in New Issue
Block a user