diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm index ed76f6fd3ff..ac0972850ea 100644 --- a/code/__DEFINES/subsystems.dm +++ b/code/__DEFINES/subsystems.dm @@ -45,7 +45,8 @@ // Subsystems shutdown in the reverse of the order they initialize in // The numbers just define the ordering, they are meaningless otherwise. #define INIT_ORDER_PROFILER 101 -#define INIT_ORDER_TITLE 100 // Load this quickly so people dont see a blank lobby screen +#define INIT_ORDER_QUEUE 100 // Load this quickly so people cant queue skip +#define INIT_ORDER_TITLE 99 // Load this quickly so people dont see a blank lobby screen #define INIT_ORDER_GARBAGE 21 #define INIT_ORDER_DBCORE 20 #define INIT_ORDER_BLACKBOX 19 diff --git a/code/_globalvars/misc.dm b/code/_globalvars/misc.dm index 40dfb374170..49bef9c90cd 100644 --- a/code/_globalvars/misc.dm +++ b/code/_globalvars/misc.dm @@ -50,8 +50,6 @@ GLOBAL_VAR_INIT(copier_items_printed_logged, FALSE) GLOBAL_DATUM_INIT(data_core, /datum/datacore, new) // Station datacore, manifest, etc -GLOBAL_VAR_INIT(panic_bunker_enabled, FALSE) // Is the panic bunker enabled - GLOBAL_LIST_EMPTY(ability_verbs) // Create-level abilities GLOBAL_LIST_INIT(pipe_colors, list("grey" = PIPE_COLOR_GREY, "red" = PIPE_COLOR_RED, "blue" = PIPE_COLOR_BLUE, "cyan" = PIPE_COLOR_CYAN, "green" = PIPE_COLOR_GREEN, "yellow" = PIPE_COLOR_YELLOW, "purple" = PIPE_COLOR_PURPLE)) diff --git a/code/controllers/configuration/sections/general_configuration.dm b/code/controllers/configuration/sections/general_configuration.dm index 296304c28b7..816775fa6d9 100644 --- a/code/controllers/configuration/sections/general_configuration.dm +++ b/code/controllers/configuration/sections/general_configuration.dm @@ -14,8 +14,6 @@ var/lobby_time = 240 /// Ban all Guest BYOND accounts var/guest_ban = TRUE - /// Player threshold to automatically enable panic bunker - var/panic_bunker_threshold = 150 /// Allow players to use AntagHUD? var/allow_antag_hud = TRUE /// Forbid players from rejoining if they use AntagHUD? @@ -121,7 +119,6 @@ // Numbers CONFIG_LOAD_NUM(lobby_time, data["lobby_time"]) - CONFIG_LOAD_NUM(panic_bunker_threshold, data["panic_bunker_threshold"]) CONFIG_LOAD_NUM(base_loadout_points, data["base_loadout_points"]) CONFIG_LOAD_NUM(cryo_penalty_period, data["cryo_penalty_period"]) CONFIG_LOAD_NUM(minimum_client_build, data["minimum_client_build"]) diff --git a/code/controllers/subsystem/server_queue.dm b/code/controllers/subsystem/server_queue.dm new file mode 100644 index 00000000000..7855c870918 --- /dev/null +++ b/code/controllers/subsystem/server_queue.dm @@ -0,0 +1,45 @@ +#define QUEUE_DATA_FILE "data/queue_data.json" +// These are defines for the sake of making sure we get the right keys +#define QUEUE_DATA_FILE_THRESHOLD_KEY "threshold" +#define QUEUE_DATA_FILE_ENABLED_KEY "enabled" +#define QUEUE_DATA_FILE_PERSISTENT_KEY "persistent" + +SUBSYSTEM_DEF(queue) + name = "Server Queue" + init_order = INIT_ORDER_QUEUE // 100 + flags = SS_NO_FIRE + /// Threshold of players to queue new people + var/queue_threshold = 0 + /// Whether the queue is enabled or not + var/queue_enabled = FALSE + /// Whether to persist these settings over multiple rounds + var/persist_queue = FALSE + /// List of ckeys allowed to bypass queue this round + var/list/queue_bypass_list = list() + /// 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) + if(fexists(QUEUE_DATA_FILE)) + try + var/F = file2text(QUEUE_DATA_FILE) + var/list/data = json_decode(F) + queue_threshold = data[QUEUE_DATA_FILE_THRESHOLD_KEY] + queue_enabled = data[QUEUE_DATA_FILE_ENABLED_KEY] + persist_queue = data[QUEUE_DATA_FILE_PERSISTENT_KEY] + 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 + if(persist_queue) + if(fexists(QUEUE_DATA_FILE)) + fdel(QUEUE_DATA_FILE) + var/data = list() + data[QUEUE_DATA_FILE_THRESHOLD_KEY] = queue_threshold + data[QUEUE_DATA_FILE_ENABLED_KEY] = queue_enabled + data[QUEUE_DATA_FILE_PERSISTENT_KEY] = persist_queue + var/json_data = json_encode(data) + text2file(json_data, QUEUE_DATA_FILE) diff --git a/code/modules/admin/IsBanned.dm b/code/modules/admin/IsBanned.dm index 15decbb6848..428241409e4 100644 --- a/code/modules/admin/IsBanned.dm +++ b/code/modules/admin/IsBanned.dm @@ -97,10 +97,9 @@ qdel(exist_query) else if(!exist_query.NextRow()) // If there isnt a row, they aint been seen before - if(GLOB.panic_bunker_enabled) + if(SSqueue && SSqueue.queue_enabled && (length(GLOB.clients) > SSqueue.queue_threshold) && !(ckey in SSqueue.queue_bypass_list)) // To the person who tells me in code review "Oh you should use ?. here". No. That logic isnt appropriate here. It needs a dedicated null check due to the length comparison. qdel(exist_query) - var/threshold = GLOB.configuration.general.panic_bunker_threshold - return list("reason" = "panic bunker", "desc" = "Server is not accepting connections from never-before-seen players until player count is less than [threshold]. Please try again later.") + return list("reason" = "server queue", "desc" = "You seem to have managed to skip the server queue, possibly due to connecting during a restart. Please reconnect in 10 minutes. If you still cant connect, please inform the server host.") qdel(exist_query) diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 598705668ae..485b0f22cc3 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -137,7 +137,9 @@ GLOBAL_LIST_INIT(admin_verbs_server, list( /client/proc/toggle_antagHUD_restrictions, /client/proc/set_ooc, /client/proc/reset_ooc, - /client/proc/set_next_map + /client/proc/set_next_map, + /client/proc/manage_queue, + /client/proc/add_queue_server_bypass )) GLOBAL_LIST_INIT(admin_verbs_debug, list( /client/proc/cmd_admin_list_open_jobs, diff --git a/code/modules/admin/verbs/manage_queue.dm b/code/modules/admin/verbs/manage_queue.dm new file mode 100644 index 00000000000..cc0f690a12b --- /dev/null +++ b/code/modules/admin/verbs/manage_queue.dm @@ -0,0 +1,58 @@ +/client/proc/manage_queue() + set name = "Manage Queue Server" + set desc = "Manage the queue server and its settings" + set category = "Server" + + if(!check_rights(R_SERVER)) + return + + var/list/choices = list("Show Status", "Toggle Queue Server", "Set Threshold", "Toggle Setting Persistence") + var/choice = input(usr, "Please, select an option", "Queue Server Manipulation") as null|anything in choices + + switch(choice) + if("Show Status") + to_chat(usr, "Queue Server Status") + to_chat(usr, "Enabled: [SSqueue.queue_enabled ? "Yes" : "No"]") + to_chat(usr, "Queue Threshold: [SSqueue.queue_threshold]") + to_chat(usr, "Setting Persistence: [SSqueue.persist_queue ? "Yes" : "No"]") + if("Toggle Queue Server") + SSqueue.queue_enabled = !SSqueue.queue_enabled + to_chat(usr, "Queue server is now [SSqueue.queue_enabled ? "Enabled" : "Disabled"]") + message_admins("[key_name_admin(usr)] has [SSqueue.queue_enabled ? "enabled" : "disabled"] the server queue.") + log_admin("[key_name(usr)] has [SSqueue.queue_enabled ? "enabled" : "disabled"] the server queue.") + if("Set Threshold") + var/new_threshold = input(usr, "Enter new threshold", "Queue Server Manipulation", SSqueue.queue_threshold) as num|null + if(!new_threshold) + return + SSqueue.queue_threshold = new_threshold + to_chat(usr, "Queue threshold is now [SSqueue.queue_threshold]") + message_admins("[key_name_admin(usr)] has set the queue threshold to [SSqueue.queue_threshold].") + log_admin("[key_name(usr)] has set the queue threshold to [SSqueue.queue_threshold].") + if("Toggle Setting Persistence") + SSqueue.persist_queue = !SSqueue.persist_queue + to_chat(usr, "Queue server setting persistence is now [SSqueue.persist_queue ? "Enabled" : "Disabled"]") + message_admins("[key_name_admin(usr)] has [SSqueue.persist_queue ? "enabled" : "disabled"] the server queue settings persistence.") + log_admin("[key_name(usr)] has [SSqueue.persist_queue ? "enabled" : "disabled"] the server queue settings persistence.") + +/client/proc/add_queue_server_bypass() + set name = "Add Queue Server Bypass" + set desc = "Allow a ckey to bypass the server queue" + set category = "Server" + + if(!check_rights(R_SERVER)) + return + + var/bypass_ckey = input(usr, "Please, enter a ckey", "Queue Server Bypass") + + if(!bypass_ckey) + return + + var/clean_ckey = ckey(bypass_ckey) + + if(!clean_ckey) + to_chat(usr, "Invalid ckey supplied") + return + + SSqueue.queue_bypass_list.Add(clean_ckey) + message_admins("[key_name_admin(usr)] has added the ckey [clean_ckey] to the queue bypass list.") + log_admin("[key_name(usr)] has added the ckey [clean_ckey] to the queue bypass list.") diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index 073e74caf26..1388601dc3f 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -379,17 +379,6 @@ if(M.client) playercount += 1 - // Update the state of the panic bunker based on current playercount - var/threshold = GLOB.configuration.general.panic_bunker_threshold - - if((playercount > threshold) && (GLOB.panic_bunker_enabled == FALSE)) - GLOB.panic_bunker_enabled = TRUE - message_admins("Panic bunker has been automatically enabled due to playercount rising above [threshold]") - - if((playercount < threshold) && (GLOB.panic_bunker_enabled == TRUE)) - GLOB.panic_bunker_enabled = FALSE - message_admins("Panic bunker has been automatically disabled due to playercount dropping below [threshold]") - // Tell clients about active testmerges if(world.TgsAvailable() && length(GLOB.revision_info.testmerges)) to_chat(src, GLOB.revision_info.get_testmerge_chatmessage(TRUE)) diff --git a/code/modules/world_topic/queue_status.dm b/code/modules/world_topic/queue_status.dm new file mode 100644 index 00000000000..02649e61fa8 --- /dev/null +++ b/code/modules/world_topic/queue_status.dm @@ -0,0 +1,36 @@ +/datum/world_topic_handler/queue_status + topic_key = "queue_status" + requires_commskey = TRUE + +// This topic is sent every 10 seconds from the bouncer +/datum/world_topic_handler/queue_status/execute(list/input, key_valid) + var/ckey_check = input["ckey_check"] + + if(!ckey_check) + return json_encode(list("error" = "No ckey supplied")) + + var/list/output_data = list() + output_data["queue_enabled"] = SSqueue.queue_enabled + + // Decide whether we should hold the player in queue + // NOTE: We only queue never seen before players + if(SSqueue.queue_enabled) + // If they are in the bypass list, let em in + if(ckey_check in SSqueue.queue_bypass_list) + output_data["allow_player"] = TRUE + else // Otherwise + // If we have more than the threshold, queue + if(length(GLOB.clients) > SSqueue.queue_threshold) + output_data["allow_player"] = FALSE + else // We have less than the threshold, allow if were in the timeframe + if(world.time > (SSqueue.last_letin_time + 3 SECONDS)) + output_data["allow_player"] = TRUE + SSqueue.last_letin_time = world.time + else + output_data["allow_player"] = FALSE + + else + // We arent enabled. Just let them in anyway. + output_data["allow_player"] = TRUE + + return json_encode(output_data) diff --git a/config/example/config.toml b/config/example/config.toml index 254f793221e..e1cd5f2b49d 100644 --- a/config/example/config.toml +++ b/config/example/config.toml @@ -301,8 +301,6 @@ allow_character_metadata = true lobby_time = 240 # Forbid people without a BYOND account joining the server guest_ban = true -# Player threshold before the automatic panic bunker engages -panic_bunker_threshold = 150 # Allow players to use antagHUD? allow_antag_hud = true # Forbid players from rejoining if they use antag hud diff --git a/paradise.dme b/paradise.dme index 11176b1befe..bf1bb831dfa 100644 --- a/paradise.dme +++ b/paradise.dme @@ -246,6 +246,7 @@ #include "code\controllers\subsystem\radiation.dm" #include "code\controllers\subsystem\radio.dm" #include "code\controllers\subsystem\runechat.dm" +#include "code\controllers\subsystem\server_queue.dm" #include "code\controllers\subsystem\shuttles.dm" #include "code\controllers\subsystem\sounds.dm" #include "code\controllers\subsystem\spacedrift.dm" @@ -1203,6 +1204,7 @@ #include "code\modules\admin\verbs\gimmick_team.dm" #include "code\modules\admin\verbs\infiltratorteam_syndicate.dm" #include "code\modules\admin\verbs\logging_view.dm" +#include "code\modules\admin\verbs\manage_queue.dm" #include "code\modules\admin\verbs\map_template_loadverb.dm" #include "code\modules\admin\verbs\mapping.dm" #include "code\modules\admin\verbs\massmodvar.dm" @@ -2508,6 +2510,7 @@ #include "code\modules\world_topic\manifest.dm" #include "code\modules\world_topic\ping.dm" #include "code\modules\world_topic\players.dm" +#include "code\modules\world_topic\queue_status.dm" #include "code\modules\world_topic\status.dm" #include "goon\code\datums\browserOutput.dm" #include "interface\interface.dm"