Small MC refactor (#20017)

* Small MC refactor

* Order fix

* Nabs tgstation/tgstation#27324

* Oops

* gnarg
This commit is contained in:
AffectedArc07
2023-01-18 12:06:24 -06:00
committed by GitHub
parent ea9e1969a4
commit 946fb4dff6
99 changed files with 337 additions and 465 deletions
@@ -4,10 +4,6 @@
protection_state = PROTECTION_PRIVATE
/// Password for authorising world/Topic requests
var/topic_key = null
/// Medal hub address for lavaland stats
var/medal_hub_address = null
/// Medal hub password for lavaland stats
var/medal_hub_password = null
/// Do we want the server to kill on reboot instead of keeping the same DD session
var/shutdown_on_reboot = FALSE
/// Is this server a production server (Has higher security and requires 2FA)
@@ -41,8 +37,6 @@
CONFIG_LOAD_BOOL(enable_multi_instance_support, data["enable_multi_instance_support"])
CONFIG_LOAD_STR(topic_key, data["communications_password"])
CONFIG_LOAD_STR(medal_hub_address, data["medal_hub_address"])
CONFIG_LOAD_STR(medal_hub_password, data["medal_hub_password"])
CONFIG_LOAD_STR(shutdown_shell_command, data["shutdown_shell_command"])
CONFIG_LOAD_STR(api_host, data["api_host"])
CONFIG_LOAD_STR(api_key, data["api_key"])
+3 -4
View File
@@ -19,7 +19,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
name = "Master"
/// Are we processing (higher values increase the processing delay by n ticks)
var/processing = TRUE
var/processing = 1
/// How many times have we ran
var/iteration = 0
@@ -210,7 +210,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
if(init_sss)
init_subtypes(/datum/controller/subsystem, subsystems)
to_chat(world, "<span class='boldannounce'>Initializing subsystems...</span>")
log_startup_progress("Initializing subsystems...")
// Sort subsystems by init_order, so they initialize in the correct order.
sortTim(subsystems, /proc/cmp_subsystem_init)
@@ -221,8 +221,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
for(var/datum/controller/subsystem/SS in subsystems)
if(SS.flags & SS_NO_INIT)
continue
SS.log_startup_progress("Initializing...")
SS.Initialize(REALTIMEOFDAY)
SS.call_init(REALTIMEOFDAY)
CHECK_TICK
current_ticklimit = TICK_LIMIT_RUNNING
var/time = (REALTIMEOFDAY - start_timeofday) / 10
+17 -3
View File
@@ -19,6 +19,9 @@
/// What are the implications of this SS being offlined?
var/offline_implications = "None. No immediate action is needed."
/// Tab to display in under the MC subtabs
var/cpu_display = SS_CPUDISPLAY_DEFAULT
/// Order of initialization. Higher numbers are initialized first, lower numbers later. Use or create defines such as [INIT_ORDER_DEFAULT] so we can see the order in one file.
var/init_order = INIT_ORDER_DEFAULT
@@ -91,6 +94,9 @@
/// Priority at the time the subsystem entered the queue. Needed to avoid changes in priority (by admins and the like) from breaking things.
var/queued_priority
/// Amount of times the subsystem has slept during fire()
var/fire_sleep_count = 0
/// How many times we suspect a subsystem type has crashed the MC, 3 strikes and you're out!
var/static/list/failure_strikes
@@ -125,8 +131,10 @@
fire(resumed)
. = state
if(state == SS_SLEEPING)
fire_sleep_count++
state = SS_IDLE
if(state == SS_PAUSING)
fire_sleep_count++
var/QT = queued_time
enqueue()
state = SS_PAUSED
@@ -260,11 +268,16 @@
return
//used to initialize the subsystem AFTER the map has loaded
/datum/controller/subsystem/Initialize(start_timeofday)
/datum/controller/subsystem/proc/call_init(start_timeofday)
SHOULD_NOT_OVERRIDE(TRUE)
log_startup_progress("Initializing...")
Initialize()
initialized = TRUE
var/time = (REALTIMEOFDAY - start_timeofday) / 10
log_startup_progress("Initialized within [time] second[time == 1 ? "" : "s"]!")
return time
/datum/controller/subsystem/Initialize()
CRASH("Initialize() not overriden for [type]! Make the subsystem Initialize or add SS_NO_INIT to the flags")
//hook for printing stats to the "MC" statuspanel for admins to see performance and related stats etc.
/datum/controller/subsystem/stat_entry(msg)
@@ -297,7 +310,7 @@
if(SS_SLEEPING)
. = "S"
if(SS_IDLE)
. = " "
. = " "
/datum/controller/subsystem/proc/state_colour()
switch(state)
@@ -342,5 +355,6 @@
var/list/out = list()
out["cost"] = cost
out["tick_usage"] = tick_usage
out["sleep_count"] = fire_sleep_count
out["custom"] = list() // Override as needed on child
return out
+1
View File
@@ -3,6 +3,7 @@ SUBSYSTEM_DEF(acid)
priority = FIRE_PRIORITY_ACID
flags = SS_NO_INIT|SS_BACKGROUND
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
cpu_display = SS_CPUDISPLAY_LOW
offline_implications = "Objects will no longer react to acid. No immediate action is needed."
var/list/currentrun = list()
+1 -2
View File
@@ -6,18 +6,17 @@ SUBSYSTEM_DEF(afk)
name = "AFK Watcher"
wait = 300
flags = SS_BACKGROUND
cpu_display = SS_CPUDISPLAY_LOW
offline_implications = "Players will no longer be marked as AFK. No immediate action is needed."
var/list/afk_players = list() // Associative list. ckey as key and AFK state as value
var/list/non_cryo_antags
/datum/controller/subsystem/afk/Initialize()
if(GLOB.configuration.afk.warning_minutes <= 0 || GLOB.configuration.afk.auto_cryo_minutes <= 0 || GLOB.configuration.afk.auto_despawn_minutes <= 0)
flags |= SS_NO_FIRE
else
non_cryo_antags = list(SPECIAL_ROLE_ABDUCTOR_AGENT, SPECIAL_ROLE_ABDUCTOR_SCIENTIST, SPECIAL_ROLE_WIZARD, SPECIAL_ROLE_WIZARD_APPRENTICE, SPECIAL_ROLE_NUKEOPS)
return ..()
/datum/controller/subsystem/afk/fire()
var/list/toRemove = list()
+2 -2
View File
@@ -15,6 +15,7 @@ SUBSYSTEM_DEF(air)
flags = SS_BACKGROUND
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
offline_implications = "Turfs will no longer process atmos, and all atmospheric machines (including cryotubes) will no longer function. Shuttle call recommended."
cpu_display = SS_CPUDISPLAY_HIGH
var/cost_turfs = 0
var/cost_groups = 0
var/cost_highpressure = 0
@@ -74,7 +75,7 @@ SUBSYSTEM_DEF(air)
cust["hotspots"] = length(hotspots)
.["custom"] = cust
/datum/controller/subsystem/air/Initialize(timeofday)
/datum/controller/subsystem/air/Initialize()
setup_overlays() // Assign icons and such for gas-turf-overlays
icon_manager = new() // Sets up icon manager for pipes
if(length(active_turfs))
@@ -84,7 +85,6 @@ SUBSYSTEM_DEF(air)
setup_pipenets(GLOB.machines)
for(var/obj/machinery/atmospherics/A in machinery_to_construct)
A.initialize_atmos_network()
return ..()
/datum/controller/subsystem/air/fire(resumed = 0)
var/timer = TICK_USAGE_REAL
-34
View File
@@ -1,34 +0,0 @@
// why is this an SS if it has no fire or init
// this should be a global datum for piss sake
// AND YES I KNOW AN SS IS A GLOBAL DATUM, THATS NOT THE POINT
SUBSYSTEM_DEF(alarm)
name = "Alarm"
flags = SS_NO_INIT | SS_NO_FIRE
var/list/alarms = list("Motion" = list(), "Fire" = list(), "Atmosphere" = list(), "Power" = list(), "Burglar" = list())
/datum/controller/subsystem/alarm/proc/triggerAlarm(class, area/A, list/O, obj/alarmsource)
var/list/L = alarms[class]
for(var/I in L)
if(I == A.name)
var/list/alarm = L[I]
var/list/sources = alarm[3]
if(!(alarmsource.UID() in sources))
sources += alarmsource.UID()
return TRUE
L[A.name] = list(get_area_name(A, TRUE), O, list(alarmsource.UID()))
SEND_SIGNAL(SSalarm, COMSIG_TRIGGERED_ALARM, class, A, O, alarmsource)
return TRUE
/datum/controller/subsystem/alarm/proc/cancelAlarm(class, area/A, obj/origin)
var/list/L = alarms[class]
var/cleared = FALSE
for(var/I in L)
if(I == A.name)
var/list/alarm = L[I]
var/list/srcs = alarm[3]
srcs -= origin.UID()
if(!length(srcs))
cleared = TRUE
L -= I
SEND_SIGNAL(SSalarm, COMSIG_CANCELLED_ALARM, class, A, origin, cleared)
+1
View File
@@ -5,6 +5,7 @@ SUBSYSTEM_DEF(ambience)
priority = FIRE_PRIORITY_AMBIENCE
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
wait = 1 SECONDS
cpu_display = SS_CPUDISPLAY_LOW
///Assoc list of listening client - next ambience time
var/list/ambience_listening_clients = list()
+24 -2
View File
@@ -2,12 +2,14 @@
SUBSYSTEM_DEF(blackbox)
name = "Blackbox"
flags = SS_NO_FIRE | SS_NO_INIT
// Even though we dont initialize, we need this init_order
// On Master.Shutdown(), it shuts down subsystems in the REVERSE order
// The database SS has INIT_ORDER_DBCORE=20, and this SS has INIT_ORDER_BLACKBOX=19
// So putting this ensures it shuts down in the right order
init_order = INIT_ORDER_BLACKBOX
wait = 10 MINUTES
runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
offline_implications = "Player count and admin count statistics will no longer be logged to the database. No immediate action is needed."
cpu_display = SS_CPUDISPLAY_LOW
/// List of all recorded feedback
var/list/datum/feedback_variable/feedback = list()
@@ -18,6 +20,26 @@ SUBSYSTEM_DEF(blackbox)
/// Associative list of any feedback variables that have had their format changed since creation and their current version, remember to update this
var/list/versions = list()
/datum/controller/subsystem/blackbox/Initialize()
if(!SSdbcore.IsConnected())
flags |= SS_NO_FIRE // Disable firing if SQL is disabled
/datum/controller/subsystem/blackbox/fire(resumed = 0)
sql_poll_players()
/datum/controller/subsystem/blackbox/proc/sql_poll_players()
var/datum/db_query/statquery = SSdbcore.NewQuery(
"INSERT INTO legacy_population (playercount, admincount, time, server_id) VALUES (:playercount, :admincount, NOW(), :server_id)",
list(
"playercount" = length(GLOB.clients),
"admincount" = length(GLOB.admins),
"server_id" = GLOB.configuration.system.instance_id
)
)
statquery.warn_execute()
qdel(statquery)
/datum/controller/subsystem/blackbox/Recover()
feedback = SSblackbox.feedback
sealed = SSblackbox.sealed
+1
View File
@@ -3,6 +3,7 @@ SUBSYSTEM_DEF(chat_pings)
flags = SS_NO_INIT
runlevels = RUNLEVEL_INIT | RUNLEVEL_LOBBY | RUNLEVEL_SETUP | RUNLEVEL_GAME | RUNLEVEL_POSTGAME // ALL OF THEM
wait = 30 SECONDS // Chat pings every 30 seconds
cpu_display = SS_CPUDISPLAY_LOW
/// List of all held chat datums
var/list/datum/chatOutput/chat_datums = list() // Do NOT put this in Initialize(). You will cause issues.
+2 -2
View File
@@ -18,10 +18,11 @@ SUBSYSTEM_DEF(cleanup)
init_order = INIT_ORDER_CLEANUP
runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
offline_implications = "Certain global lists will no longer be cleared of nulls, which may result in runtimes. No immediate action is needed."
cpu_display = SS_CPUDISPLAY_LOW
/// A list of global lists we want the subsystem to clean.
var/list/lists_to_clean
/datum/controller/subsystem/cleanup/Initialize(start_timeofday)
/datum/controller/subsystem/cleanup/Initialize()
// If you want this subsystem to clean out nulls from a specific list, add it here.
lists_to_clean = list(
GLOB.clients = "clients",
@@ -32,7 +33,6 @@ SUBSYSTEM_DEF(cleanup)
GLOB.human_list = "human_list",
GLOB.carbon_list = "carbon_list"
)
return ..()
/datum/controller/subsystem/cleanup/fire(resumed)
for(var/L in lists_to_clean)
+2 -2
View File
@@ -3,6 +3,7 @@ SUBSYSTEM_DEF(dbcore)
flags = SS_BACKGROUND
wait = 1 MINUTES
init_order = INIT_ORDER_DBCORE
cpu_display = SS_CPUDISPLAY_LOW
/// Is the DB schema valid
var/schema_valid = TRUE
@@ -30,9 +31,8 @@ SUBSYSTEM_DEF(dbcore)
// This is in Initialize() so that its actually seen in chat
/datum/controller/subsystem/dbcore/Initialize()
if(!schema_valid)
to_chat(world, "<span class='boldannounce'>Database schema ([GLOB.configuration.database.version]) doesn't match the latest schema version ([SQL_VERSION]). Roundstart has been delayed.</span>")
log_startup_progress("Database schema ([GLOB.configuration.database.version]) doesn't match the latest schema version ([SQL_VERSION]). Roundstart has been delayed.")
return ..()
/datum/controller/subsystem/dbcore/fire()
for(var/I in active_queries)
+1
View File
@@ -3,6 +3,7 @@ SUBSYSTEM_DEF(debugview)
wait = 1 // SS_TICKER subsystem, so wait is in ticks
flags = SS_TICKER|SS_NO_INIT
offline_implications = "Shift+F3 will no longer show a debug view. No immediate action is needed."
cpu_display = SS_CPUDISPLAY_LOW
/// List of clients currently processing
var/list/client/processing = list()
-121
View File
@@ -1,121 +0,0 @@
SUBSYSTEM_DEF(discord)
name = "Discord"
flags = SS_NO_FIRE
/// Is the SS enabled
var/enabled = FALSE
/// Last time the administrator ping was dropped. This ensures administrators cannot be mass pinged if a large chunk of ahelps go off at once (IE: tesloose)
var/last_administration_ping = 0
/// Last time the mentor ping was dropped. This ensures mentors cannot be mass pinged if a large chunk of mhelps go off at once.
var/last_mentor_ping = 0
/datum/controller/subsystem/discord/Initialize(start_timeofday)
if(GLOB.configuration.discord.webhooks_enabled)
enabled = TRUE
return ..()
// This is designed for ease of simplicity for sending quick messages from parts of the code
/datum/controller/subsystem/discord/proc/send2discord_simple(destination, content)
if(!enabled)
return
var/list/webhook_urls
switch(destination)
if(DISCORD_WEBHOOK_ADMIN)
webhook_urls = GLOB.configuration.discord.admin_webhook_urls
if(DISCORD_WEBHOOK_PRIMARY)
webhook_urls = GLOB.configuration.discord.main_webhook_urls
if(DISCORD_WEBHOOK_MENTOR)
webhook_urls = GLOB.configuration.discord.mentor_webhook_urls
var/datum/discord_webhook_payload/dwp = new()
dwp.webhook_content = "**\[[GLOB.configuration.system.instance_id]]** [content]"
for(var/url in webhook_urls)
SShttp.create_async_request(RUSTG_HTTP_METHOD_POST, url, dwp.serialize2json(), list("content-type" = "application/json"))
// This one is designed to take in a [/datum/discord_webhook_payload] which was prepared beforehand
/datum/controller/subsystem/discord/proc/send2discord_complex(destination, datum/discord_webhook_payload/dwp)
if(!enabled)
return
var/list/webhook_urls
switch(destination)
if(DISCORD_WEBHOOK_ADMIN)
webhook_urls = GLOB.configuration.discord.admin_webhook_urls
if(DISCORD_WEBHOOK_PRIMARY)
webhook_urls = GLOB.configuration.discord.main_webhook_urls
if(DISCORD_WEBHOOK_MENTOR)
webhook_urls = GLOB.configuration.discord.mentor_webhook_urls
for(var/url in webhook_urls)
SShttp.create_async_request(RUSTG_HTTP_METHOD_POST, url, dwp.serialize2json(), list("content-type" = "application/json"))
// This one is for sending messages to the admin channel if no admins are active, complete with a ping to the game admins role
/datum/controller/subsystem/discord/proc/send2discord_simple_noadmins(content, check_send_always = FALSE)
if(!enabled)
return
// Setup some stuff
var/alerttext
var/list/admincounter = staff_countup(R_BAN)
var/active_admins = admincounter[1]
var/inactive_admins = admincounter[3]
var/add_ping = TRUE
if(active_admins <= 0)
if(inactive_admins > 0)
alerttext = " | **ALL ADMINS AFK**"
else
alerttext = " | **NO ADMINS ONLINE**"
else
if(check_send_always && GLOB.configuration.discord.forward_all_ahelps)
// If we are here, there are admins online. We want to forward everything, but obviously dont want to add a ping, so we do this
add_ping = FALSE
else
// We have active admins, we dont care about the rest of this proc
return
var/message = "[content] [alerttext] [add_ping ? handle_administrator_ping() : ""]"
var/datum/discord_webhook_payload/dwp = new()
dwp.webhook_content = "**\[[GLOB.configuration.system.instance_id]]** [message]"
for(var/url in GLOB.configuration.discord.admin_webhook_urls)
SShttp.create_async_request(RUSTG_HTTP_METHOD_POST, url, dwp.serialize2json(), list("content-type" = "application/json"))
/datum/controller/subsystem/discord/proc/send2discord_simple_mentor(content)
var/alerttext
var/list/mentorcounter = staff_countup(R_MENTOR)
var/active_mentors = mentorcounter[1]
var/inactive_mentors = mentorcounter[3]
var/add_ping = FALSE
if(active_mentors <= 0)
add_ping = TRUE
if(inactive_mentors)
alerttext = "| **ALL MENTORS AFK**"
else
alerttext = "| **NO MENTORS ONLINE**"
var/message = "[content] [alerttext][add_ping ? handle_mentor_ping() : ""]"
var/datum/discord_webhook_payload/dwp = new()
dwp.webhook_content = "**\[[GLOB.configuration.system.instance_id]]** [message]"
for(var/url in GLOB.configuration.discord.mentor_webhook_urls)
SShttp.create_async_request(RUSTG_HTTP_METHOD_POST, url, dwp.serialize2json(), list("content-type" = "application/json"))
// Helper to make administrator ping easier
/datum/controller/subsystem/discord/proc/handle_administrator_ping()
// Check if a role is even set
if(GLOB.configuration.discord.admin_role_id)
if(last_administration_ping > world.time)
return "*(Role pinged recently)*"
last_administration_ping = world.time + 60 SECONDS
return "<@&[GLOB.configuration.discord.admin_role_id]>"
return ""
/datum/controller/subsystem/discord/proc/handle_mentor_ping()
if(GLOB.configuration.discord.mentor_role_id)
if(last_mentor_ping > world.time)
return " *(Role pinged recently)*"
last_mentor_ping = world.time + 60 SECONDS
return " <@&[GLOB.configuration.discord.mentor_role_id]>"
return ""
+1 -1
View File
@@ -5,6 +5,7 @@ SUBSYSTEM_DEF(economy)
wait = 30 SECONDS
runlevels = RUNLEVEL_GAME
offline_implications = "Crew wont get their paychecks. No immediate action is needed." // money go down
cpu_display = SS_CPUDISPLAY_LOW
///List of all money account databases existing in the round
var/list/money_account_databases = list()
///Total amount of account created during the round, neccesary for generating unique account ids
@@ -133,7 +134,6 @@ SUBSYSTEM_DEF(economy)
centcom_message = "<center>---[station_time_timestamp()]---</center><br>Remember to stamp and send back the supply manifests.<hr>"
next_paycheck_delay = 30 MINUTES + world.time
return ..()
/datum/controller/subsystem/economy/fire()
if(next_paycheck_delay <= world.time)
+1 -1
View File
@@ -4,6 +4,7 @@ SUBSYSTEM_DEF(events)
runlevels = RUNLEVEL_GAME
flags = SS_KEEP_TIMING
offline_implications = "Random events will no longer happen. No immediate action is needed."
cpu_display = SS_CPUDISPLAY_LOW
// Report events at the end of the rouund
var/report_at_round_end = 0
@@ -31,7 +32,6 @@ SUBSYSTEM_DEF(events)
/datum/controller/subsystem/events/Initialize()
allEvents = subtypesof(/datum/event)
return ..()
/datum/controller/subsystem/events/fire()
for(var/datum/event/E in active_events)
+1
View File
@@ -3,6 +3,7 @@ SUBSYSTEM_DEF(fires)
priority = FIRE_PRIORITY_BURNING
flags = SS_NO_INIT|SS_BACKGROUND
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
cpu_display = SS_CPUDISPLAY_LOW // Trust me, this isnt atmos fires, this is paper and stuff being lit with lighters and stuff
offline_implications = "Objects will no longer react to fires. No immediate action is needed."
var/list/currentrun = list()
+2 -1
View File
@@ -4,8 +4,9 @@ SUBSYSTEM_DEF(garbage)
wait = 2 SECONDS
flags = SS_POST_FIRE_TIMING|SS_BACKGROUND|SS_NO_INIT
runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY
init_order = INIT_ORDER_GARBAGE // Why does this have an init order if it has SS_NO_INIT?
init_order = INIT_ORDER_GARBAGE // AA 2020: Why does this have an init order if it has SS_NO_INIT? | AA 2022: Its used for shutdown
offline_implications = "Garbage collection is no longer functional, and objects will not be qdel'd. Immediate server restart recommended."
cpu_display = SS_CPUDISPLAY_HIGH
var/list/collection_timeout = list(2 MINUTES, 10 SECONDS) // deciseconds to wait before moving something up in the queue to the next level
+2 -2
View File
@@ -1,10 +1,10 @@
SUBSYSTEM_DEF(ghost_spawns)
name = "Ghost Spawns"
init_order = INIT_ORDER_EVENTS
flags = SS_BACKGROUND
flags = SS_BACKGROUND | SS_NO_INIT
wait = 1 SECONDS
runlevels = RUNLEVEL_GAME
offline_implications = "Ghosts will no longer be able to respawn as event mobs (Blob, etc..). Shuttle call recommended."
cpu_display = SS_CPUDISPLAY_LOW
/// List of polls currently ongoing, to be checked on next fire()
var/list/datum/candidate_poll/currently_polling
+3 -3
View File
@@ -1,10 +1,11 @@
SUBSYSTEM_DEF(http)
name = "HTTP"
flags = SS_TICKER | SS_BACKGROUND // Measure in ticks, but also only run if we have the spare CPU. We also dont init.
flags = SS_TICKER | SS_BACKGROUND // Measure in ticks, but also only run if we have the spare CPU.
wait = 1
runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY // All the time
// Assuming for the worst, since only discord is hooked into this for now, but that may change
offline_implications = "The server is no longer capable of making async HTTP requests. Shuttle call recommended."
cpu_display = SS_CPUDISPLAY_LOW
/// List of all async HTTP requests in the processing chain
var/list/datum/http_request/active_async_requests
/// Variable to define if logging is enabled or not. Disabled by default since we know the requests the server is making. Enable with VV if you need to debug requests
@@ -16,9 +17,8 @@ SUBSYSTEM_DEF(http)
. = ..()
rustg_create_async_http_client() // Open the door
/datum/controller/subsystem/http/Initialize(start_timeofday)
/datum/controller/subsystem/http/Initialize()
active_async_requests = list()
return ..()
/datum/controller/subsystem/http/get_stat_details()
return "P: [length(active_async_requests)] | T: [total_requests]"
+1 -1
View File
@@ -5,6 +5,7 @@ SUBSYSTEM_DEF(icon_smooth)
priority = FIRE_PRIORITY_SMOOTHING
flags = SS_TICKER
offline_implications = "Objects will no longer smooth together properly. No immediate action is needed."
cpu_display = SS_CPUDISPLAY_LOW
var/list/smooth_queue = list()
@@ -40,7 +41,6 @@ SUBSYSTEM_DEF(icon_smooth)
A.smooth_icon()
CHECK_TICK
return ..()
/datum/controller/subsystem/icon_smooth/proc/add_to_queue(atom/thing)
if(thing.smoothing_flags & SMOOTH_QUEUED)
+3 -3
View File
@@ -4,6 +4,7 @@ SUBSYSTEM_DEF(idlenpcpool)
priority = FIRE_PRIORITY_IDLE_NPC
wait = 60
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
init_order = INIT_ORDER_IDLENPCS // MUST be after SSmapping since it tracks max Zs
offline_implications = "Idle simple animals will no longer process. Shuttle call recommended."
var/list/currentrun = list()
@@ -12,9 +13,8 @@ SUBSYSTEM_DEF(idlenpcpool)
/datum/controller/subsystem/idlenpcpool/get_stat_details()
return "IdleNPCS:[length(GLOB.simple_animals[AI_IDLE])]|Z:[length(GLOB.simple_animals[AI_Z_OFF])]"
/datum/controller/subsystem/idlenpcpool/Initialize(start_timeofday)
idle_mobs_by_zlevel = new /list(world.maxz,0)
return ..()
/datum/controller/subsystem/idlenpcpool/Initialize()
idle_mobs_by_zlevel = new /list(world.maxz, 0)
/datum/controller/subsystem/idlenpcpool/fire(resumed = FALSE)
if(!resumed)
+1 -2
View File
@@ -10,14 +10,13 @@ SUBSYSTEM_DEF(input)
priority = FIRE_PRIORITY_INPUT
runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY
offline_implications = "Player input will no longer be recognised. Immediate server restart recommended."
cpu_display = SS_CPUDISPLAY_HIGH
/// List of clients whose input to process in loop.
var/list/client/processing = list()
/datum/controller/subsystem/input/Initialize()
initialized = TRUE
refresh_client_macro_sets()
return ..()
/datum/controller/subsystem/input/get_stat_details()
return "P: [length(processing)]"
+3 -3
View File
@@ -3,12 +3,13 @@ SUBSYSTEM_DEF(instancing)
runlevels = RUNLEVEL_INIT | RUNLEVEL_LOBBY | RUNLEVEL_SETUP | RUNLEVEL_GAME | RUNLEVEL_POSTGAME
wait = 30 SECONDS
flags = SS_KEEP_TIMING
cpu_display = SS_CPUDISPLAY_LOW
// This SS has the default init value since it needs to happen after the DB & redis
/// Associative list of registered commands. K = command name | V = command datum
var/list/datum/server_command/registered_commands = list()
/datum/controller/subsystem/instancing/Initialize(start_timeofday)
/datum/controller/subsystem/instancing/Initialize()
// Make sure no one broke things. This check will trip up CI
if(init_order >= SSredis.init_order)
CRASH("SSinstancing was set to init before SSredis. Who broke it?")
@@ -16,7 +17,7 @@ SUBSYSTEM_DEF(instancing)
// Dont even bother if we arent connected to redis or the DB
if(!SSdbcore.IsConnected() || !SSredis.connected || !GLOB.configuration.system.enable_multi_instance_support)
flags |= SS_NO_FIRE
return ..()
return
// Setup our commands
for(var/sct in subtypesof(/datum/server_command))
@@ -36,7 +37,6 @@ SUBSYSTEM_DEF(instancing)
// Announce startup to peers
var/datum/server_command/new_round_announce/NRA = registered_commands["new_round_announce"]
NRA.custom_dispatch(GLOB.configuration.general.server_name, SSmapping.map_datum.fluff_name, SSmapping.map_datum.technical_name)
return ..()
/datum/controller/subsystem/instancing/fire(resumed)
update_heartbeat()
-376
View File
@@ -1,376 +0,0 @@
SUBSYSTEM_DEF(ipintel)
name = "XKeyScore"
wait = 1
flags = SS_NO_FIRE
init_order = INIT_ORDER_XKEYSCORE // 10
// Are we enabled? Auto disable at world init to avoid checking reconnects
var/enabled = FALSE
var/throttle = 0
var/errors = 0
var/list/cache = list()
/datum/controller/subsystem/ipintel/Initialize(timeofday)
enabled = TRUE
return ..()
// Represents an IP intel holder datum
/datum/ipintel
/// The IP being checked
var/ip
/// The current rating, 0-1 float.
var/intel = 0
/// Whether this was loaded from the cache or not
var/cache = FALSE
/// How many minutes ago it was cached
var/cacheminutesago = 0
/// The date it was cached
var/cachedate = ""
/// The real time it was cached
var/cacherealtime = 0
/datum/ipintel/New()
cachedate = SQLtime()
cacherealtime = world.realtime
/datum/ipintel/proc/is_valid()
. = FALSE
if(intel < 0)
return
if(intel <= GLOB.configuration.ipintel.bad_rating)
if(world.realtime < cacherealtime + (GLOB.configuration.ipintel.hours_save_good HOURS))
return TRUE
else
if(world.realtime < cacherealtime + (GLOB.configuration.ipintel.hours_save_bad HOURS))
return TRUE
/**
* Get IP intel
*
* Performs a lookup of the rating for an IP provided
*
* Arguments:
* * ip - The IP to lookup
* * bypasscache - Do we want to bypass the DB cache?
* * updatecache - Do we want to update the DB cache?
*/
/datum/controller/subsystem/ipintel/proc/get_ip_intel(ip, bypasscache = FALSE, updatecache = TRUE)
var/datum/ipintel/res = new()
res.ip = ip
. = res
if(!ip || !GLOB.configuration.ipintel.contact_email || !GLOB.configuration.ipintel.enabled || !enabled)
return
if(!bypasscache)
var/datum/ipintel/cachedintel = cache[ip]
if(cachedintel && cachedintel.is_valid())
cachedintel.cache = TRUE
return cachedintel
if(SSdbcore.IsConnected())
var/datum/db_query/query_get_ip_intel = SSdbcore.NewQuery({"
SELECT date, intel, TIMESTAMPDIFF(MINUTE,date,NOW())
FROM ipintel
WHERE
ip = INET_ATON(:ip)
AND ((
intel < :rating_bad
AND
date + INTERVAL :save_good HOUR > NOW()
) OR (
intel >= :rating_bad
AND
date + INTERVAL :save_bad HOUR > NOW()
))
"}, list(
"ip" = ip,
"rating_bad" = GLOB.configuration.ipintel.bad_rating,
"save_good" = GLOB.configuration.ipintel.hours_save_good,
"save_bad" = GLOB.configuration.ipintel.hours_save_bad,
))
if(!query_get_ip_intel.warn_execute())
qdel(query_get_ip_intel)
return
if(query_get_ip_intel.NextRow())
res.cache = TRUE
res.cachedate = query_get_ip_intel.item[1]
res.intel = text2num(query_get_ip_intel.item[2])
res.cacheminutesago = text2num(query_get_ip_intel.item[3])
res.cacherealtime = world.realtime - (text2num(query_get_ip_intel.item[3])*10*60)
cache[ip] = res
qdel(query_get_ip_intel)
return
qdel(query_get_ip_intel)
res.intel = ip_intel_query(ip)
if(updatecache && res.intel >= 0)
cache[ip] = res
if(SSdbcore.IsConnected())
var/datum/db_query/query_add_ip_intel = SSdbcore.NewQuery({"
INSERT INTO ipintel (ip, intel) VALUES (INET_ATON(:ip), :intel)
ON DUPLICATE KEY UPDATE intel = VALUES(intel), date = NOW()"},
list(
"ip" = ip,
"intel" = res.intel
)
)
query_add_ip_intel.warn_execute()
qdel(query_add_ip_intel)
/**
* Performs the remote IPintel lookup
*
*
*
* Arguments:
* * ip - The IP to lookup
* * retried - Was this attempt retried?
*/
/datum/controller/subsystem/ipintel/proc/ip_intel_query(ip, retried = FALSE)
. = -1 //default
if(!ip)
return
if(throttle > world.timeofday)
return
if(!enabled)
return
// Do not refactor this to use SShttp, because that requires the subsystem to be firing for requests to be made, and this will be triggered before the MC has finished loading
var/list/http[] = HTTPGet("http://[GLOB.configuration.ipintel.ipintel_domain]/check.php?ip=[ip]&contact=[GLOB.configuration.ipintel.contact_email]&format=json&flags=b")
if(http)
var/status = text2num(http["STATUS"])
if(status == 200)
var/response = json_decode(http["CONTENT"])
if(response)
if(response["status"] == "success")
var/intelnum = text2num(response["result"])
if(isnum(intelnum))
return text2num(response["result"])
else
ipintel_handle_error("Bad intel from server: [response["result"]].", ip, retried)
if(!retried)
sleep(25)
return .(ip, 1)
else
ipintel_handle_error("Bad response from server: [response["status"]].", ip, retried)
if(!retried)
sleep(25)
return .(ip, 1)
else if(status == 429)
ipintel_handle_error("Error #429: We have exceeded the rate limit.", ip, 1)
return
else
ipintel_handle_error("Unknown status code: [status].", ip, retried)
if(!retried)
sleep(25)
return .(ip, 1)
else
ipintel_handle_error("Unable to connect to API.", ip, retried)
if(!retried)
sleep(25)
return .(ip, 1)
/**
* Error handler
*
* Handles an IP intel error, also throttling the susbystem if required
*
* Arguments:
* * error - The error description
* * ip - The IP that was tried
* * retried - Was this on a retried attempt
*/
/datum/controller/subsystem/ipintel/proc/ipintel_handle_error(error, ip, retried)
if(retried)
errors++
error += " Could not check [ip]. Disabling IPINTEL for [errors] minute[(errors == 1 ? "" : "s")]"
throttle = world.timeofday + (2 * errors MINUTES)
else
error += " Attempting retry on [ip]."
log_ipintel(error)
/**
* Logs an IPintel error
*
* Pretty self explanatory. Logs errors regarding ipintel.
*
* Arguments:
* * text - Argument 1
*/
/datum/controller/subsystem/ipintel/proc/log_ipintel(text)
log_game("IPINTEL: [text]")
log_debug("IPINTEL: [text]")
/**
* IPIntel Ban Checker
*
* Checks if a user is banned due to IPintel. It will check configuration, DB, whitelist checks, and more
*
* Arguments:
* * t_ckey - The ckey to check
* * t_ip - The IP to check
*/
/datum/controller/subsystem/ipintel/proc/ipintel_is_banned(t_ckey, t_ip)
if(!GLOB.configuration.ipintel.contact_email)
return FALSE
if(!GLOB.configuration.ipintel.enabled)
return FALSE
if(!GLOB.configuration.ipintel.whitelist_mode)
return FALSE
if(!SSdbcore.IsConnected())
return FALSE
if(!ipintel_badip_check(t_ip))
return FALSE
if(vpn_whitelist_check(t_ckey))
return FALSE
return TRUE
/**
* IP Rating Checker
*
* Checks if a provided IP passes the config threshold for denial
*
* Arguments:
* * target_ip - The IP to check
*/
/datum/controller/subsystem/ipintel/proc/ipintel_badip_check(target_ip)
var/rating_bad = GLOB.configuration.ipintel.bad_rating
if(!rating_bad)
log_debug("ipintel_badip_check reports misconfigured rating_bad directive")
return FALSE
var/valid_hours = GLOB.configuration.ipintel.hours_save_bad
if(!valid_hours)
log_debug("ipintel_badip_check reports misconfigured ipintel_save_bad directive")
return FALSE
var/datum/db_query/query_get_ip_intel = SSdbcore.NewQuery({"
SELECT * FROM ipintel WHERE ip = INET_ATON(:target_ip)
AND intel >= :rating_bad AND (date + INTERVAL :valid_hours HOUR) > NOW()"},
list(
"target_ip" = target_ip,
"rating_bad" = rating_bad,
"valid_hours" = valid_hours
)
)
if(!query_get_ip_intel.warn_execute())
log_debug("ipintel_badip_check reports failed query execution")
qdel(query_get_ip_intel)
return FALSE
if(!query_get_ip_intel.NextRow())
qdel(query_get_ip_intel)
return FALSE
qdel(query_get_ip_intel)
return TRUE
/**
* VPN whitelist checker
*
* Checks if a ckey is whitelisted to be using a VPN against the DB
*
* Arguments:
* * target_ckey - The ckey to check
*/
/datum/controller/subsystem/ipintel/proc/vpn_whitelist_check(target_ckey)
if(!GLOB.configuration.ipintel.whitelist_mode)
return FALSE
var/datum/db_query/query_whitelist_check = SSdbcore.NewQuery("SELECT * FROM vpn_whitelist WHERE ckey=:ckey", list(
"ckey" = target_ckey
))
if(!query_whitelist_check.warn_execute())
qdel(query_whitelist_check)
return FALSE
if(query_whitelist_check.NextRow())
qdel(query_whitelist_check)
return TRUE // At least one row in the whitelist names their ckey. That means they are whitelisted.
qdel(query_whitelist_check)
return FALSE
/**
* VPN whitelist adder
*
* Adds a ckey to the VPN whitelist. Asks the admin to also provide a link to their request.
*
* Arguments:
* * target_ckey - The ckey to whitelist
*/
/datum/controller/subsystem/ipintel/proc/vpn_whitelist_add(target_ckey)
var/reason_string = input(usr, "Enter link to the URL of their whitelist request on the forum.","Reason required") as message|null
if(!reason_string)
return FALSE
var/datum/db_query/query_whitelist_add = SSdbcore.NewQuery("INSERT INTO vpn_whitelist (ckey,reason) VALUES (:targetckey, :reason)", list(
"targetckey" = target_ckey,
"reason" = reason_string
))
if(!query_whitelist_add.warn_execute())
qdel(query_whitelist_add)
return FALSE
qdel(query_whitelist_add)
return TRUE
/**
* VPN whitelist remover
*
* Removes a ckey from the VPN whitelist. Pretty simple.
*
* Arguments:
* * target_ckey - The ckey to remove
*/
/datum/controller/subsystem/ipintel/proc/vpn_whitelist_remove(target_ckey)
var/datum/db_query/query_whitelist_remove = SSdbcore.NewQuery("DELETE FROM vpn_whitelist WHERE ckey=:targetckey", list(
"targetckey" = target_ckey
))
if(!query_whitelist_remove.warn_execute())
qdel(query_whitelist_remove)
return FALSE
qdel(query_whitelist_remove)
return TRUE
/**
* VPN whitelist panel
*
* Doesnt actually open a panel, this is just a verb to handle the rest of the whitelist operations
*
* Arguments:
* * target_ckey - The ckey to add/remove
*/
/datum/controller/subsystem/ipintel/proc/vpn_whitelist_panel(target_ckey as text)
if(!check_rights(R_ADMIN))
return
if(!target_ckey)
return
var/is_already_whitelisted = vpn_whitelist_check(target_ckey)
if(is_already_whitelisted)
var/confirm = alert("[target_ckey] is already whitelisted. Remove them?", "Confirm Removal", "No", "Yes")
if(!confirm || confirm != "Yes")
to_chat(usr, "VPN whitelist alteration cancelled.")
return
else if(vpn_whitelist_remove(target_ckey))
to_chat(usr, "[target_ckey] was removed from the VPN whitelist.")
else
to_chat(usr, "VPN whitelist unchanged.")
else
if(vpn_whitelist_add(target_ckey))
to_chat(usr, "[target_ckey] was added to the VPN whitelist.")
else
to_chat(usr, "VPN whitelist unchanged.")
+3 -3
View File
@@ -4,6 +4,7 @@ SUBSYSTEM_DEF(jobs)
wait = 5 MINUTES // Dont ever make this a super low value since EXP updates are calculated from this value
runlevels = RUNLEVEL_GAME
offline_implications = "Job playtime hours will no longer be logged. No immediate action is needed."
cpu_display = SS_CPUDISPLAY_LOW
//List of all jobs
var/list/occupations = list()
@@ -20,13 +21,12 @@ SUBSYSTEM_DEF(jobs)
///list of station departments and their associated roles and economy payments
var/list/station_departments = list()
/datum/controller/subsystem/jobs/Initialize(timeofday)
if(!occupations.len)
/datum/controller/subsystem/jobs/Initialize()
if(!length(occupations))
SetupOccupations()
for(var/department_type in subtypesof(/datum/station_department))
station_departments += new department_type()
LoadJobs(FALSE)
return ..()
// Only fires every 5 minutes
/datum/controller/subsystem/jobs/fire()
+2 -4
View File
@@ -4,6 +4,7 @@ SUBSYSTEM_DEF(lighting)
init_order = INIT_ORDER_LIGHTING
flags = SS_TICKER
offline_implications = "Lighting will no longer update. Shuttle call recommended."
cpu_display = SS_CPUDISPLAY_HIGH
var/static/list/sources_queue = list() // List of lighting sources queued for update.
var/static/list/corners_queue = list() // List of lighting corners queued for update.
var/static/list/objects_queue = list() // List of lighting objects queued for update.
@@ -19,7 +20,7 @@ SUBSYSTEM_DEF(lighting)
cust["objects_queue"] = length(objects_queue)
.["custom"] = cust
/datum/controller/subsystem/lighting/Initialize(timeofday)
/datum/controller/subsystem/lighting/Initialize()
if(!initialized)
if(GLOB.configuration.general.starlight)
for(var/I in GLOB.all_areas)
@@ -28,12 +29,9 @@ SUBSYSTEM_DEF(lighting)
A.luminosity = 0
create_all_lighting_objects()
initialized = TRUE
fire(FALSE, TRUE)
return ..()
/datum/controller/subsystem/lighting/fire(resumed, init_tick_checks)
MC_SPLIT_TICK_INIT(3)
if(!init_tick_checks)
+1 -1
View File
@@ -7,6 +7,7 @@ SUBSYSTEM_DEF(machines)
init_order = INIT_ORDER_MACHINES
flags = SS_KEEP_TIMING
offline_implications = "Machinery will no longer process. Shuttle call recommended."
cpu_display = SS_CPUDISPLAY_HIGH
var/list/processing = list()
var/list/currentrun = list()
@@ -18,7 +19,6 @@ SUBSYSTEM_DEF(machines)
/datum/controller/subsystem/machines/Initialize()
makepowernets()
fire()
return ..()
/datum/controller/subsystem/machines/get_metrics()
. = ..()
-86
View File
@@ -1,86 +0,0 @@
SUBSYSTEM_DEF(medals)
name = "Medals"
flags = SS_NO_FIRE
var/hub_enabled = FALSE
/datum/controller/subsystem/medals/Initialize(timeofday)
if(GLOB.configuration.system.medal_hub_address && GLOB.configuration.system.medal_hub_password)
hub_enabled = TRUE
return ..()
/datum/controller/subsystem/medals/proc/UnlockMedal(medal, client/player)
set waitfor = FALSE
if(!medal || !hub_enabled)
return
if(isnull(world.SetMedal(medal, player, GLOB.configuration.system.medal_hub_address, GLOB.configuration.system.medal_hub_password)))
hub_enabled = FALSE
log_game("MEDAL ERROR: Could not contact hub to award medal [medal] to player [player.ckey].")
message_admins("Error! Failed to contact hub to award [medal] medal to [player.ckey]!")
return
to_chat(player, "<span class='greenannounce'><B>Achievement unlocked: [medal]!</B></span>")
/datum/controller/subsystem/medals/proc/SetScore(score, client/player, increment, force)
set waitfor = FALSE
if(!score || !hub_enabled)
return
var/list/oldscore = GetScore(score, player, TRUE)
if(increment)
if(!oldscore[score])
oldscore[score] = 1
else
oldscore[score] = (text2num(oldscore[score]) + 1)
else
oldscore[score] = force
var/newscoreparam = list2params(oldscore)
if(isnull(world.SetScores(player.ckey, newscoreparam, GLOB.configuration.system.medal_hub_address, GLOB.configuration.system.medal_hub_password)))
hub_enabled = FALSE
log_game("SCORE ERROR: Could not contact hub to set score. Score [score] for player [player.ckey].")
message_admins("Error! Failed to contact hub to set [score] score for [player.ckey]!")
/datum/controller/subsystem/medals/proc/GetScore(score, client/player, returnlist)
if(!score || !hub_enabled)
return
var/scoreget = world.GetScores(player.ckey, score, GLOB.configuration.system.medal_hub_address, GLOB.configuration.system.medal_hub_password)
if(isnull(scoreget))
hub_enabled = FALSE
log_game("SCORE ERROR: Could not contact hub to get score. Score [score] for player [player.ckey].")
message_admins("Error! Failed to contact hub to get score [score] for [player.ckey]!")
return
. = params2list(scoreget)
if(!returnlist)
return .[score]
/datum/controller/subsystem/medals/proc/CheckMedal(medal, client/player)
if(!medal || !hub_enabled)
return
if(isnull(world.GetMedal(medal, player, GLOB.configuration.system.medal_hub_address, GLOB.configuration.system.medal_hub_password)))
hub_enabled = FALSE
log_game("MEDAL ERROR: Could not contact hub to get medal [medal] for player [player.ckey]")
message_admins("Error! Failed to contact hub to get [medal] medal for [player.ckey]!")
return
to_chat(player, "[medal] is unlocked")
/datum/controller/subsystem/medals/proc/LockMedal(medal, client/player)
if(!player || !medal || !hub_enabled)
return
var/result = world.ClearMedal(medal, player, GLOB.configuration.system.medal_hub_address, GLOB.configuration.system.medal_hub_password)
switch(result)
if(null)
hub_enabled = FALSE
log_game("MEDAL ERROR: Could not contact hub to clear medal [medal] for player [player.ckey].")
message_admins("Error! Failed to contact hub to clear [medal] medal for [player.ckey]!")
if(TRUE)
message_admins("Medal: [medal] removed for [player.ckey]")
if(FALSE)
message_admins("Medal: [medal] was not found for [player.ckey]. Unable to clear.")
/datum/controller/subsystem/medals/proc/ClearScore(client/player)
if(isnull(world.SetScores(player.ckey, "", GLOB.configuration.system.medal_hub_address, GLOB.configuration.system.medal_hub_password)))
log_game("MEDAL ERROR: Could not contact hub to clear scores for [player.ckey].")
message_admins("Error! Failed to contact hub to clear scores for [player.ckey]!")
+2 -2
View File
@@ -4,13 +4,13 @@ SUBSYSTEM_DEF(metrics)
offline_implications = "Server metrics will no longer be ingested into monitoring systems. No immediate action is needed."
runlevels = RUNLEVEL_LOBBY | RUNLEVEL_SETUP | RUNLEVEL_GAME | RUNLEVEL_POSTGAME // ALL THE LEVELS
flags = SS_KEEP_TIMING // This needs to ingest every 30 IRL seconds, not ingame seconds.
cpu_display = SS_CPUDISPLAY_LOW
/// The real time of day the server started. Used to calculate time drift
var/world_init_time = 0 // Not set in here. Set in world/New()
/datum/controller/subsystem/metrics/Initialize(start_timeofday)
/datum/controller/subsystem/metrics/Initialize()
if(!GLOB.configuration.metrics.enable_metrics)
flags |= SS_NO_FIRE // Disable firing to save CPU
return ..()
/datum/controller/subsystem/metrics/fire(resumed)
+5 -4
View File
@@ -3,7 +3,9 @@ SUBSYSTEM_DEF(mobs)
priority = FIRE_PRIORITY_MOBS
flags = SS_KEEP_TIMING
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
init_order = INIT_ORDER_MOBS
offline_implications = "Mobs will no longer process. Immediate server restart recommended."
cpu_display = SS_CPUDISPLAY_HIGH
var/list/currentrun = list()
var/static/list/clients_by_zlevel[][]
@@ -21,10 +23,9 @@ SUBSYSTEM_DEF(mobs)
/datum/controller/subsystem/mobs/get_stat_details()
return "P:[length(GLOB.mob_living_list)]"
/datum/controller/subsystem/mobs/Initialize(start_timeofday)
clients_by_zlevel = new /list(world.maxz,0)
dead_players_by_zlevel = new /list(world.maxz,0)
return ..()
/datum/controller/subsystem/mobs/Initialize()
clients_by_zlevel = new /list(world.maxz, 0)
dead_players_by_zlevel = new /list(world.maxz, 0)
/datum/controller/subsystem/mobs/fire(resumed = 0)
var/seconds = wait * 0.1
@@ -1,9 +1,9 @@
SUBSYSTEM_DEF(mob_hunt)
name = "Nano-Mob Hunter GO Server"
init_order = INIT_ORDER_NANOMOB
priority = FIRE_PRIORITY_NANOMOB // Low priority, no need for MC_TICK_CHECK due to extremely low performance impact.
flags = SS_NO_INIT
offline_implications = "Nano-Mob Hunter will no longer spawn mobs. No immediate action is needed."
cpu_display = SS_CPUDISPLAY_LOW
var/max_normal_spawns = 15 //change this to adjust the number of normal spawns that can exist at one time. trapped spawns (from traitors) don't count towards this
var/list/normal_spawns = list()
var/max_trap_spawns = 15 //change this to adjust the number of trap spawns that can exist at one time. traps spawned beyond this point clear the oldest traps
+2 -2
View File
@@ -5,6 +5,7 @@ SUBSYSTEM_DEF(nightshift)
wait = 600
flags = SS_NO_TICK_CHECK
offline_implications = "The game will no longer shift between day and night lighting. No immediate action is needed."
cpu_display = SS_CPUDISPLAY_LOW
var/nightshift_active = FALSE
var/nightshift_start_time = 702000 //7:30 PM, station time
@@ -15,10 +16,9 @@ SUBSYSTEM_DEF(nightshift)
/datum/controller/subsystem/nightshift/Initialize()
if(!GLOB.configuration.general.enable_night_shifts)
can_fire = FALSE
flags |= SS_NO_FIRE
if(GLOB.configuration.general.randomise_shift_time)
GLOB.gametime_offset = rand(0, 23) HOURS
return ..()
/datum/controller/subsystem/nightshift/fire(resumed = FALSE)
if(world.time - SSticker.round_start_time < nightshift_first_check)
@@ -5,7 +5,7 @@ SUBSYSTEM_DEF(assets)
var/list/cache = list()
var/list/preload = list()
/datum/controller/subsystem/assets/Initialize(timeofday)
/datum/controller/subsystem/assets/Initialize()
for(var/type in typesof(/datum/asset) - list(/datum/asset, /datum/asset/simple))
var/datum/asset/A = new type()
A.register()
@@ -14,4 +14,3 @@ SUBSYSTEM_DEF(assets)
for(var/client/C in GLOB.clients)
addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(getFilesSlow), C, preload, FALSE), 10)
return ..()
@@ -15,13 +15,10 @@ SUBSYSTEM_DEF(atoms)
var/list/BadInitializeCalls = list()
/datum/controller/subsystem/atoms/Initialize(timeofday)
/datum/controller/subsystem/atoms/Initialize()
setupgenetics()
initialized = INITIALIZATION_INNEW_MAPLOAD
InitializeAtoms()
return ..()
/datum/controller/subsystem/atoms/proc/InitializeAtoms(list/atoms, noisy = TRUE)
if(initialized == INITIALIZATION_INSSATOMS)
@@ -21,13 +21,13 @@ SUBSYSTEM_DEF(changelog)
/datum/controller/subsystem/changelog/Initialize()
// This entire subsystem relies on SQL being here.
if(!SSdbcore.IsConnected())
return ..()
return
var/datum/db_query/latest_cl_date = SSdbcore.NewQuery("SELECT CAST(UNIX_TIMESTAMP(date_merged) AS CHAR) AS ut FROM changelog ORDER BY date_merged DESC LIMIT 1")
if(!latest_cl_date.warn_execute())
qdel(latest_cl_date)
// Abort if we cant do this
return ..()
return
while(latest_cl_date.NextRow())
current_cl_timestamp = latest_cl_date.item[1]
@@ -48,8 +48,6 @@ SUBSYSTEM_DEF(changelog)
for(var/client/C as anything in startup_clients_open)
OpenChangelog(C)
return ..()
/datum/controller/subsystem/changelog/proc/UpdatePlayerChangelogDate(client/C)
if(!ss_ready)
@@ -4,9 +4,9 @@ SUBSYSTEM_DEF(holiday)
flags = SS_NO_FIRE
var/list/holidays
/datum/controller/subsystem/holiday/Initialize(start_timeofday)
/datum/controller/subsystem/holiday/Initialize()
if(!GLOB.configuration.general.allow_holidays)
return ..() //Holiday stuff was not enabled in the config!
return //Holiday stuff was not enabled in the config!
var/YY = text2num(time2text(world.timeofday, "YY")) // get the current year
var/MM = text2num(time2text(world.timeofday, "MM")) // get the current month
@@ -27,5 +27,3 @@ SUBSYSTEM_DEF(holiday)
if(H.eventChance)
if(prob(H.eventChance))
H.handle_event()
return ..()
@@ -9,10 +9,9 @@ SUBSYSTEM_DEF(late_mapping)
/// List of all maze generators to process
var/list/obj/effect/mazegen/generator/maze_generators = list()
/datum/controller/subsystem/late_mapping/Initialize(start_timeofday)
/datum/controller/subsystem/late_mapping/Initialize()
if(length(maze_generators))
log_startup_progress("Generating mazes...")
for(var/i in maze_generators)
var/obj/effect/mazegen/generator/MG = i
MG.run_generator()
return ..()
@@ -35,7 +35,7 @@ SUBSYSTEM_DEF(mapping)
var/F = file("data/next_map.txt")
F << next_map.type
/datum/controller/subsystem/mapping/Initialize(timeofday)
/datum/controller/subsystem/mapping/Initialize()
// Load all Z level templates
preloadTemplates()
@@ -111,8 +111,6 @@ SUBSYSTEM_DEF(mapping)
else
world.name = station_name()
return ..()
// Do not confuse with seedRuins()
/datum/controller/subsystem/mapping/proc/handleRuins()
// load in extra levels of space ruins
@@ -12,9 +12,9 @@ SUBSYSTEM_DEF(maprotate)
. = ..()
/datum/controller/subsystem/maprotate/Initialize(start_timeofday)
/datum/controller/subsystem/maprotate/Initialize()
if(!SSdbcore.IsConnected())
return ..()
return
// Make a quick list for number to date lookups
var/list/days = list("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday")
@@ -37,7 +37,7 @@ SUBSYSTEM_DEF(maprotate)
var/datum/db_query/dbq = SSdbcore.NewQuery("SELECT WEEKDAY(NOW()) AS d")
if(!dbq.warn_execute())
log_startup_progress("Somehow, we failed to extract a numerical day from the DB. ?????????????")
return ..()
return
var/day_index = 0
@@ -50,7 +50,7 @@ SUBSYSTEM_DEF(maprotate)
if(!day_index)
log_startup_progress("Somehow, we failed to extract a valid numerical day from the DB. ?????????????")
return ..()
return
// String interpolation is faster than num2text() for some reason
@@ -74,5 +74,3 @@ SUBSYSTEM_DEF(maprotate)
log_startup_progress("There is no special rotation defined for this day")
return ..()
@@ -8,7 +8,6 @@ SUBSYSTEM_DEF(pathfinder)
/datum/controller/subsystem/pathfinder/Initialize()
space_type_cache = typecacheof(/turf/space)
mobs = new(10)
return ..()
/datum/flowcache
var/lcount
@@ -18,7 +18,6 @@ SUBSYSTEM_DEF(persistent_data)
// Load all the data of registered atoms
for(var/atom/A in registered_atoms)
A.persistent_load()
return ..()
/datum/controller/subsystem/persistent_data/Shutdown()
// Save all the data of registered atoms
@@ -1,6 +1,6 @@
SUBSYSTEM_DEF(radio)
name = "Radio"
flags = SS_NO_INIT | SS_NO_FIRE
flags = SS_NO_FIRE
var/list/radiochannels = list(
"Common" = PUB_FREQ,
@@ -25,6 +25,10 @@ SUBSYSTEM_DEF(radio)
var/list/DEPT_FREQS = list(AI_FREQ, COMM_FREQ, ENG_FREQ, MED_FREQ, SEC_FREQ, SCI_FREQ, SRV_FREQ, SUP_FREQ, PROC_FREQ)
var/list/datum/radio_frequency/frequencies = list()
// This is a disgusting hack to stop this tripping CI when this thing needs to FUCKING DIE
/datum/controller/subsystem/radio/Initialize()
return
// This is fucking disgusting and needs to die
/datum/controller/subsystem/radio/proc/frequency_span_class(frequency)
// Antags!
@@ -19,7 +19,7 @@ SUBSYSTEM_DEF(queue)
/// Last world.time we let a ckey in. 3 second delay between each letin to avoid a mass bubble
var/last_letin_time = 0
/datum/controller/subsystem/queue/Initialize(start_timeofday)
/datum/controller/subsystem/queue/Initialize()
if(fexists(QUEUE_DATA_FILE))
try
var/F = file2text(QUEUE_DATA_FILE)
@@ -30,7 +30,6 @@ SUBSYSTEM_DEF(queue)
catch
stack_trace("Failed to load [QUEUE_DATA_FILE] from disk due to malformed JSON. You may need to setup the queue again.")
return ..()
/datum/controller/subsystem/queue/Shutdown()
// Save if persistent
@@ -26,7 +26,6 @@ SUBSYSTEM_DEF(sounds)
/datum/controller/subsystem/sounds/Initialize()
setup_available_channels()
return ..()
/**
* Sets up all available sound channels
@@ -32,5 +32,3 @@ SUBSYSTEM_DEF(title)
for(var/turf/simulated/wall/indestructible/splashscreen/splash in world)
splash.icon = icon
return ..()
-3
View File
@@ -18,10 +18,7 @@ SUBSYSTEM_DEF(overlays)
stats = list()
/datum/controller/subsystem/overlays/Initialize()
initialized = TRUE
fire(mc_check = FALSE)
return ..()
/datum/controller/subsystem/overlays/get_stat_details()
return "Ov:[length(queue)]"
+1
View File
@@ -5,6 +5,7 @@ SUBSYSTEM_DEF(parallax)
priority = FIRE_PRIORITY_PARALLAX
runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
offline_implications = "Space parallax will no longer move around. No immediate action is needed."
cpu_display = SS_CPUDISPLAY_HIGH
var/list/currentrun
var/planet_x_offset = 128
var/planet_y_offset = 128
@@ -25,7 +25,6 @@ PROCESSING_SUBSYSTEM_DEF(instruments)
/datum/controller/subsystem/processing/instruments/Initialize()
initialize_instrument_data()
synthesizer_instrument_ids = get_allowed_instrument_ids()
return ..()
/**
* Initializes all instrument datums
@@ -3,6 +3,7 @@ PROCESSING_SUBSYSTEM_DEF(projectiles)
wait = 1
flags = SS_NO_INIT|SS_TICKER
offline_implications = "Projectiles will no longer move. Shuttle call recommended."
cpu_display = SS_CPUDISPLAY_HIGH
/// Maximum moves a projectile can make per tick.
var/global_max_tick_moves = 10
+1 -1
View File
@@ -4,6 +4,7 @@ SUBSYSTEM_DEF(profiler)
runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY
wait = 5 MINUTES
flags = SS_NO_TICK_CHECK
cpu_display = SS_CPUDISPLAY_LOW // its usage itself is high but its every 5 mins so
/// Time it took to fetch normal profile data (ms)
var/nfetch_cost = 0
/// Time it took to write the normal file (ms)
@@ -24,7 +25,6 @@ SUBSYSTEM_DEF(profiler)
if(!GLOB.configuration.general.enable_auto_profiler)
StopProfiling() //Stop the early start profiler if we dont want it on in the config
flags |= SS_NO_FIRE
return ..()
/datum/controller/subsystem/profiler/fire()
DumpFile()
+1
View File
@@ -3,6 +3,7 @@ PROCESSING_SUBSYSTEM_DEF(radiation)
flags = SS_BACKGROUND | SS_NO_INIT
wait = 1 SECONDS
offline_implications = "Radiation will no longer function; power generation may not happen. A restart may or may not be required, depending on the situation."
cpu_display = SS_CPUDISPLAY_HIGH
var/list/warned_atoms = list()
// Cache radiation levels for each turf so it doesn't need to be done iteratively
// turf_rad_cache is the state in the current loop, and may not be 100% representative
+1 -1
View File
@@ -11,6 +11,7 @@ SUBSYSTEM_DEF(redis)
/// Message queue (If messages are sent before the SS has init'd)
var/list/datum/redis_message/queue = list()
offline_implications = "The server will no longer be able to send or receive redis messages. Shuttle call recommended (Potential server crash inbound)."
cpu_display = SS_CPUDISPLAY_LOW
// SS meta procs
/datum/controller/subsystem/redis/get_stat_details()
@@ -41,7 +42,6 @@ SUBSYSTEM_DEF(redis)
var/amount_registered = length(subbed_channels)
log_startup_progress("Registered [amount_registered] callback[amount_registered == 1 ? "" : "s"].")
return ..()
/datum/controller/subsystem/redis/fire()
check_messages()
+1
View File
@@ -27,6 +27,7 @@ SUBSYSTEM_DEF(runechat)
wait = 1
priority = FIRE_PRIORITY_RUNECHAT
offline_implications = "Runechat messages will no longer clear. Shuttle call recommended."
cpu_display = SS_CPUDISPLAY_HIGH
/// world.time of the first entry in the bucket list, effectively the 'start time' of the current buckets
var/head_offset = 0
+2 -3
View File
@@ -6,6 +6,7 @@ SUBSYSTEM_DEF(shuttle)
flags = SS_KEEP_TIMING|SS_NO_TICK_CHECK
runlevels = RUNLEVEL_SETUP | RUNLEVEL_GAME
offline_implications = "Shuttles will no longer function. Immediate server restart recommended."
cpu_display = SS_CPUDISPLAY_LOW
var/list/mobile = list()
var/list/stationary = list()
var/list/transit = list()
@@ -28,7 +29,7 @@ SUBSYSTEM_DEF(shuttle)
/// Default refuel delay
var/refuel_delay = 20 MINUTES
/datum/controller/subsystem/shuttle/Initialize(start_timeofday)
/datum/controller/subsystem/shuttle/Initialize()
if(!emergency)
WARNING("No /obj/docking_port/mobile/emergency placed on the map!")
if(!backup_shuttle)
@@ -39,8 +40,6 @@ SUBSYSTEM_DEF(shuttle)
initial_load()
initial_move()
return ..()
/datum/controller/subsystem/shuttle/get_stat_details()
return "M:[length(mobile)] S:[length(stationary)] T:[length(transit)]"
+1
View File
@@ -5,6 +5,7 @@ SUBSYSTEM_DEF(spacedrift)
flags = SS_NO_INIT|SS_KEEP_TIMING
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
offline_implications = "Mobs will no longer respect a lack of gravity. No immediate action is needed."
cpu_display = SS_CPUDISPLAY_LOW
var/list/currentrun = list()
var/list/processing = list()
-29
View File
@@ -1,29 +0,0 @@
SUBSYSTEM_DEF(statistics)
name = "Statistics"
wait = 6000 // 10 minute delay between fires
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME // Only count time actually ingame to avoid logging pre-round dips
offline_implications = "Player count and admin count statistics will no longer be logged to the database. No immediate action is needed."
/datum/controller/subsystem/statistics/Initialize(start_timeofday)
if(!SSdbcore.IsConnected())
flags |= SS_NO_FIRE // Disable firing if SQL is disabled
return ..()
/datum/controller/subsystem/statistics/fire(resumed = 0)
sql_poll_players()
/datum/controller/subsystem/statistics/proc/sql_poll_players()
if(!SSdbcore.IsConnected())
return
else
var/datum/db_query/statquery = SSdbcore.NewQuery(
"INSERT INTO legacy_population (playercount, admincount, time, server_id) VALUES (:playercount, :admincount, NOW(), :server_id)",
list(
"playercount" = length(GLOB.clients),
"admincount" = length(GLOB.admins),
"server_id" = GLOB.configuration.system.instance_id
)
)
statquery.warn_execute()
qdel(statquery)
+2 -3
View File
@@ -4,6 +4,7 @@ SUBSYSTEM_DEF(sun)
flags = SS_NO_TICK_CHECK
init_order = INIT_ORDER_SUN
offline_implications = "Solar panels will no longer rotate. No immediate action is needed."
cpu_display = SS_CPUDISPLAY_LOW
var/angle
var/dx
var/dy
@@ -11,7 +12,7 @@ SUBSYSTEM_DEF(sun)
var/list/solars = list()
var/solar_gen_rate = 1500
/datum/controller/subsystem/sun/Initialize(start_timeofday)
/datum/controller/subsystem/sun/Initialize()
// Lets work out an angle for the "sun" to rotate around the station
angle = rand (0,360) // the station position to the sun is randomised at round start
rate = rand(50,200)/100 // 50% - 200% of standard rotation
@@ -22,8 +23,6 @@ SUBSYSTEM_DEF(sun)
for(var/obj/machinery/power/solar_control/SC in solars)
SC.setup()
return ..()
/datum/controller/subsystem/sun/get_stat_details()
return "P:[length(solars)]"
+1
View File
@@ -8,6 +8,7 @@ SUBSYSTEM_DEF(throwing)
flags = SS_NO_INIT|SS_KEEP_TIMING|SS_TICKER
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
offline_implications = "Thrown objects may not react properly. Shuttle call recommended."
cpu_display = SS_CPUDISPLAY_LOW
var/list/currentrun
var/list/processing = list()
+2 -3
View File
@@ -6,6 +6,7 @@ SUBSYSTEM_DEF(ticker)
flags = SS_KEEP_TIMING
runlevels = RUNLEVEL_LOBBY | RUNLEVEL_SETUP | RUNLEVEL_GAME
offline_implications = "The game is no longer aware of when the round ends. Immediate server restart recommended."
cpu_display = SS_CPUDISPLAY_LOW
/// Time the game should start, relative to world.time
var/round_start_time = 0
@@ -76,8 +77,6 @@ SUBSYSTEM_DEF(ticker)
'sound/music/title2.ogg',\
'sound/music/title3.ogg',)
return ..()
/datum/controller/subsystem/ticker/fire()
switch(current_state)
@@ -307,7 +306,7 @@ SUBSYSTEM_DEF(ticker)
var/datum/holiday/holiday = SSholiday.holidays[holidayname]
to_chat(world, "<h4>[holiday.greet()]</h4>")
SSdiscord.send2discord_simple_noadmins("**\[Info]** Round has started")
GLOB.discord_manager.send2discord_simple_noadmins("**\[Info]** Round has started")
auto_toggle_ooc(FALSE) // Turn it off
time_game_started = world.time
@@ -21,10 +21,10 @@ GLOBAL_REAL(SSmentor_tickets, /datum/controller/subsystem/tickets/mentor_tickets
db_save_id = "MENTOR"
/datum/controller/subsystem/tickets/mentor_tickets/Initialize()
..()
close_messages = list("<font color='red' size='3'><b>- [ticket_name] Closed -</b></font>",
"<span class='boldmessage'>Please try to be as descriptive as possible in mentor helps. Mentors do not know the full situation you're in and need more information to give you a helpful response.</span>",
"<span class='[span_class]'>Your [ticket_name] has now been closed.</span>")
return ..()
/datum/controller/subsystem/tickets/mentor_tickets/message_staff(msg, prefix_type = NONE, important = FALSE)
message_mentorTicket(msg, important)
@@ -51,11 +51,9 @@ SUBSYSTEM_DEF(tickets)
.["custom"] = cust
/datum/controller/subsystem/tickets/Initialize()
if(!close_messages)
close_messages = list("<font color='red' size='4'><b>- [ticket_name] Rejected! -</b></font>",
"<span class='boldmessage'>Please try to be calm, clear, and descriptive in admin helps, do not assume the staff member has seen any related events, and clearly state the names of anybody you are reporting. If you asked a question, please ensure it was clear what you were asking.</span>",
"<span class='[span_class]'>Your [ticket_name] has now been closed.</span>")
return ..()
close_messages = list("<font color='red' size='4'><b>- [ticket_name] Rejected! -</b></font>",
"<span class='boldmessage'>Please try to be calm, clear, and descriptive in admin helps, do not assume the staff member has seen any related events, and clearly state the names of anybody you are reporting. If you asked a question, please ensure it was clear what you were asking.</span>",
"<span class='[span_class]'>Your [ticket_name] has now been closed.</span>")
/datum/controller/subsystem/tickets/fire()
var/stales = checkStaleness()
+1
View File
@@ -14,6 +14,7 @@ SUBSYSTEM_DEF(time_track)
var/last_tick_realtime = 0
var/last_tick_byond_time = 0
var/last_tick_tickcount = 0
cpu_display = SS_CPUDISPLAY_LOW
/datum/controller/subsystem/time_track/fire()
var/current_realtime = REALTIMEOFDAY
+1
View File
@@ -23,6 +23,7 @@ SUBSYSTEM_DEF(timer)
flags = SS_TICKER|SS_NO_INIT
offline_implications = "The game will no longer process timers. Immediate server restart recommended."
cpu_display = SS_CPUDISPLAY_HIGH
/// Queue used for storing timers that do not fit into the current buckets
var/list/datum/timedevent/second_queue = list()
+1
View File
@@ -4,6 +4,7 @@ SUBSYSTEM_DEF(vote)
flags = SS_KEEP_TIMING|SS_NO_INIT
runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
offline_implications = "Votes (Endround shuttle) will no longer function. Shuttle call recommended."
cpu_display = SS_CPUDISPLAY_LOW
/// Active vote, if any
var/datum/vote/active_vote
+2 -2
View File
@@ -13,6 +13,7 @@ SUBSYSTEM_DEF(weather)
var/list/processing = list()
var/list/eligible_zlevels = list()
var/list/next_hit_by_zlevel = list() //Used by barometers to know when the next storm is coming
cpu_display = SS_CPUDISPLAY_LOW
/datum/controller/subsystem/weather/get_metrics()
. = ..()
@@ -41,7 +42,7 @@ SUBSYSTEM_DEF(weather)
addtimer(CALLBACK(src, PROC_REF(make_eligible), z, possible_weather), randTime + initial(W.weather_duration_upper), TIMER_UNIQUE) //Around 5-10 minutes between weathers
next_hit_by_zlevel["[z]"] = world.time + randTime + initial(W.telegraph_duration)
/datum/controller/subsystem/weather/Initialize(start_timeofday)
/datum/controller/subsystem/weather/Initialize()
for(var/V in subtypesof(/datum/weather))
var/datum/weather/W = V
var/probability = initial(W.probability)
@@ -52,7 +53,6 @@ SUBSYSTEM_DEF(weather)
for(var/z in levels_by_trait(target_trait))
LAZYINITLIST(eligible_zlevels["[z]"])
eligible_zlevels["[z]"][W] = probability
return ..()
/datum/controller/subsystem/weather/proc/run_weather(datum/weather/weather_datum_type, z_levels)
if(istext(weather_datum_type))