diff --git a/code/controllers/subsystem/persistence.dm b/code/controllers/subsystem/persistence.dm
index 5a390dfc91b..b126a76616c 100644
--- a/code/controllers/subsystem/persistence.dm
+++ b/code/controllers/subsystem/persistence.dm
@@ -33,6 +33,7 @@ SUBSYSTEM_DEF(persistence)
LoadAntagReputation()
LoadRandomizedRecipes()
LoadPaintings()
+ LoadPanicBunker() //SKYRAT EDIT ADDITION - PANICBUNKER
return ..()
/datum/controller/subsystem/persistence/proc/LoadPoly()
@@ -181,6 +182,7 @@ SUBSYSTEM_DEF(persistence)
SaveRandomizedRecipes()
SavePaintings()
SaveScars()
+ SavePanicBunker()//SKYRAT EDIT ADDITION - PANICBUNKER
/datum/controller/subsystem/persistence/proc/GetPhotoAlbums()
var/album_path = file("data/photo_albums.json")
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index 757fac91918..15d095f44af 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -20,7 +20,9 @@ GLOBAL_PROTECT(admin_verbs_default)
/client/proc/stop_sounds,
/client/proc/mark_datum_mapview,
/client/proc/debugstatpanel,
- /client/proc/fix_air /*resets air in designated radius to its default atmos composition*/
+ /client/proc/fix_air, /*resets air in designated radius to its default atmos composition*/
+ /client/proc/revokebunkerbypass, //SKYRAT EDIT ADDITION - PANICBUNKER
+ /client/proc/addbunkerbypass //SKYRAT EDIT ADDITION - PANICBUNKER
)
GLOBAL_LIST_INIT(admin_verbs_admin, world.AVerbsAdmin())
GLOBAL_PROTECT(admin_verbs_admin)
diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm
index 4340dec6006..5a85935ad44 100644
--- a/code/modules/client/client_procs.dm
+++ b/code/modules/client/client_procs.dm
@@ -534,7 +534,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
if(!query_client_in_db.Execute())
qdel(query_client_in_db)
return
-
+/*
//If we aren't an admin, and the flag is set
if(CONFIG_GET(flag/panic_bunker) && !holder && !GLOB.deadmins[ckey])
var/living_recs = CONFIG_GET(number/panic_bunker_living)
@@ -557,8 +557,24 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
qdel(query_client_in_db)
qdel(src)
return
-
+*/
if(!query_client_in_db.NextRow())
+ //SKYRAT EDIT ADDITION BEGIN - PANICBUNKER
+ if (CONFIG_GET(flag/panic_bunker) && !holder && !GLOB.deadmins[ckey] && !(ckey in GLOB.bunker_passthrough))
+ log_access("Failed Login: [key] - [address] - New account attempting to connect during panic bunker")
+ message_admins("Failed Login: [key] - [address] - New account attempting to connect during panic bunker")
+ to_chat(src, {"Hi! We have temporarily enabled safety measures that prevents new players from joining currently.
Please try again later, or contact a staff on Discord if you have any questions.
To join our community, check out our Discord! To gain full access to our Discord, read the rules and post a request in the #access-requests channel under the \"Landing Zone\" category in the Discord server linked here: https://discord.gg/6RpdCgR"}) //skyrat-edit
+ var/list/connectiontopic_a = params2list(connectiontopic)
+ var/list/panic_addr = CONFIG_GET(string/panic_server_address)
+ if(panic_addr && !connectiontopic_a["redirect"])
+ var/panic_name = CONFIG_GET(string/panic_server_name)
+ to_chat(src, "Sending you to [panic_name ? panic_name : panic_addr].")
+ winset(src, null, "command=.options")
+ src << link("[panic_addr]?redirect=1")
+ qdel(query_client_in_db)
+ qdel(src)
+ return
+ //SKYRAT EDIT END
new_player = 1
account_join_date = findJoinDate()
var/datum/db_query/query_add_player = SSdbcore.NewQuery({"
@@ -573,6 +589,10 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
if(!account_join_date)
account_join_date = "Error"
account_age = -1
+ //SKYRAT EDIT ADDITION BEGIN - PANICBUNKER
+ else if(ckey in GLOB.bunker_passthrough)
+ GLOB.bunker_passthrough -= ckey
+ //SKYRAT EDIT END
qdel(query_client_in_db)
var/datum/db_query/query_get_client_age = SSdbcore.NewQuery(
"SELECT firstseen, DATEDIFF(Now(),firstseen), accountjoindate, DATEDIFF(Now(),accountjoindate) FROM [format_table_name("player")] WHERE ckey = :ckey",
diff --git a/modular_skyrat/modules/panicbunker/code/panicbunker.dm b/modular_skyrat/modules/panicbunker/code/panicbunker.dm
new file mode 100644
index 00000000000..3af052d5ec2
--- /dev/null
+++ b/modular_skyrat/modules/panicbunker/code/panicbunker.dm
@@ -0,0 +1,66 @@
+GLOBAL_LIST_EMPTY(bunker_passthrough)
+
+/client/proc/addbunkerbypass(ckeytobypass as text)
+ set category = "Admin"
+ set name = "Add PB Bypass"
+ set desc = "Allows a given ckey to connect despite the panic bunker for a given round."
+ if(!CONFIG_GET(flag/sql_enabled))
+ to_chat(usr, "The Database is not enabled!")
+ return
+
+ GLOB.bunker_passthrough |= ckey(ckeytobypass)
+ GLOB.bunker_passthrough[ckey(ckeytobypass)] = world.realtime
+ SSpersistence.SavePanicBunker() //we can do this every time, it's okay
+ log_admin("[key_name(usr)] has added [ckeytobypass] to the current round's bunker bypass list.")
+ message_admins("[key_name_admin(usr)] has added [ckeytobypass] to the current round's bunker bypass list.")
+
+/client/proc/revokebunkerbypass(ckeytobypass as text)
+ set category = "Admin"
+ set name = "Revoke PB Bypass"
+ set desc = "Revoke's a ckey's permission to bypass the panic bunker for a given round."
+
+ if(!CONFIG_GET(flag/sql_enabled))
+ to_chat(usr, "The Database is not enabled!")
+ return
+
+ GLOB.bunker_passthrough -= ckey(ckeytobypass)
+ SSpersistence.SavePanicBunker()
+ log_admin("[key_name(usr)] has removed [ckeytobypass] from the current round's bunker bypass list.")
+ message_admins("[key_name_admin(usr)] has removed [ckeytobypass] from the current round's bunker bypass list.")
+
+/datum/tgs_chat_command/addbunkerbypass
+ name = "whitelist"
+ help_text = "whitelist "
+ admin_only = TRUE
+
+/datum/tgs_chat_command/addbunkerbypass/Run(datum/tgs_chat_user/sender, params)
+ if(!CONFIG_GET(flag/sql_enabled))
+ return "The Database is not enabled!"
+
+ GLOB.bunker_passthrough |= ckey(params)
+
+ GLOB.bunker_passthrough[ckey(params)] = world.realtime
+ SSpersistence.SavePanicBunker() //we can do this every time, it's okay
+ log_admin("[sender.friendly_name] has added [params] to the current round's bunker bypass list.")
+ message_admins("[sender.friendly_name] has added [params] to the current round's bunker bypass list.")
+ return "[params] has been added to the current round's bunker bypass list."
+
+/datum/controller/subsystem/persistence/proc/LoadPanicBunker()
+ var/bunker_path = file("data/bunker_passthrough.json")
+ if(fexists(bunker_path))
+ var/list/json = json_decode(file2text(bunker_path))
+ GLOB.bunker_passthrough = json["data"]
+ for(var/ckey in GLOB.bunker_passthrough)
+ if(daysSince(GLOB.bunker_passthrough[ckey]) >= CONFIG_GET(number/max_bunker_days))
+ GLOB.bunker_passthrough -= ckey
+
+/datum/controller/subsystem/persistence/proc/SavePanicBunker()
+ var/json_file = file("data/bunker_passthrough.json")
+ var/list/file_data = list()
+ file_data["data"] = GLOB.bunker_passthrough
+ fdel(json_file)
+ WRITE_FILE(json_file,json_encode(file_data))
+
+/datum/config_entry/number/max_bunker_days
+ config_entry_value = 7
+ min_val = 1
diff --git a/modular_skyrat/modules/panicbunker/code/readme.md b/modular_skyrat/modules/panicbunker/code/readme.md
new file mode 100644
index 00000000000..a4a27296f56
--- /dev/null
+++ b/modular_skyrat/modules/panicbunker/code/readme.md
@@ -0,0 +1,28 @@
+## Title: Panic bunker
+
+MODULE ID: PANICBUNKER
+
+### Description:
+
+Adds a system that uses a JSON file to enable bunker bypassing. This is a very much needed update.
+
+### TG Proc Changes:
+
+ .code\controllers\subsystem\persistence.dm > /datum/controller/subsystem/persistence/Initialize() & /datum/controller/subsystem/persistence/proc/CollectData()
+.code\modules\client\client_procs.dm > /client/proc/set_client_age_from_db()
+
+
+### Defines:
+
+ - N/A
+
+### Master file additions
+
+- N/A
+
+### Included files that are not contained in this module:
+
+- N/A
+
+### Credits:
+Gandalf2k15 - Porting
diff --git a/tgstation.dme b/tgstation.dme
index bbceae3c0b4..d420847d313 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -3571,6 +3571,7 @@
#include "modular_skyrat\modules\modular_weapons\code\modules\projectiles\guns\ballistic\rifle.dm"
#include "modular_skyrat\modules\modular_weapons\code\modules\projectiles\projectile\bullets\modular_projectiles.dm"
#include "modular_skyrat\modules\modular_weapons\code\modules\research\designs\autolathe_designs.dm"
+#include "modular_skyrat\modules\panicbunker\code\panicbunker.dm"
#include "modular_skyrat\modules\pixel_shift\code\pixel_shift.dm"
#include "modular_skyrat\modules\QOL\code\_under.dm"
#include "modular_skyrat\modules\radiosound\code\game\objects\items\devices\radio\headset.dm"