diff --git a/code/controllers/configuration/entries/connections.dm b/code/controllers/configuration/entries/connections.dm index acdf588e5a..6ec41590f2 100644 --- a/code/controllers/configuration/entries/connections.dm +++ b/code/controllers/configuration/entries/connections.dm @@ -1,6 +1,12 @@ /datum/config_entry/flag/panic_bunker // prevents people the server hasn't seen before from connecting -/datum/config_entry/number/panic_bunker_living // living time in minutes that a player needs to pass the panic bunker +/datum/config_entry/number/panic_bunker_living // living time in minutes that a player needs to pass the panic bunker. they pass **if they are above this amount** + config_entry_value = 0 // default: <= 0 meaning any playtime works. -1 to disable criteria. + integer = TRUE + +/datum/config_entry/number/panic_bunker_living_vpn + config_entry_value = 0 // default: <= 0 meaning anytime works. -1 to disable criteria. + integer = TRUE /datum/config_entry/string/panic_bunker_message config_entry_value = "Sorry but the server is currently not accepting connections from never before seen players." diff --git a/code/modules/client/client_defines.dm b/code/modules/client/client_defines.dm index 99f24107c7..950b2b5b25 100644 --- a/code/modules/client/client_defines.dm +++ b/code/modules/client/client_defines.dm @@ -187,3 +187,6 @@ var/list/block_parry_hinted = list() /// moused over objects, currently capped at 7. this is awful, and should be replaced with a component to track it using signals for parrying at some point. var/list/moused_over_objects = list() + + /// AFK tracking + var/last_activity = 0 diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index 735fdb592e..0ab198fa79 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -85,6 +85,8 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( log_href("[src] (usr:[usr]\[[COORD(usr)]\]) : [hsrc ? "[hsrc] " : ""][href]") return + last_activity = world.time + //Logs all hrefs log_href("[src] (usr:[usr]\[[COORD(usr)]\]) : [hsrc ? "[hsrc] " : ""][href]") @@ -227,6 +229,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( /////////// /client/New(TopicData) + last_activity = world.time world.SetConfig("APP/admin", ckey, "role=admin") var/tdata = TopicData //save this for later use TopicData = null //Prevent calls to client.Topic from connect @@ -583,9 +586,10 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( //If we aren't an admin, and the flag is set if(CONFIG_GET(flag/panic_bunker) && !holder && !GLOB.deadmins[ckey] && !(ckey in GLOB.bunker_passthrough)) var/living_recs = CONFIG_GET(number/panic_bunker_living) + var/vpn_living_recs = CONFIG_GET(number/panic_bunker_living_vpn) //Relies on pref existing, but this proc is only called after that occurs, so we're fine. var/minutes = get_exp_living(pure_numeric = TRUE) - if(minutes <= living_recs) // && !CONFIG_GET(flag/panic_bunker_interview) + if((minutes <= living_recs) || (IsVPN() && (minutes < vpn_living_recs))) var/reject_message = "Failed Login: [key] - Account attempting to connect during panic bunker, but they do not have the required living time [minutes]/[living_recs]" log_access(reject_message) message_admins("[reject_message]") @@ -855,6 +859,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( /client/Click(atom/object, atom/location, control, params, ignore_spam = FALSE, extra_info) if(last_click > world.time - world.tick_lag) return + last_activity = world.time last_click = world.time var/ab = FALSE var/list/L = params2list(params) @@ -927,6 +932,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( //checks if a client is afk //3000 frames = 5 minutes /client/proc/is_afk(duration = CONFIG_GET(number/inactivity_period)) + var/inactivity = world.time - last_activity if(inactivity > duration) return inactivity return FALSE diff --git a/code/modules/client/client_vpn_detect.dm b/code/modules/client/client_vpn_detect.dm new file mode 100644 index 0000000000..bd35a65ef2 --- /dev/null +++ b/code/modules/client/client_vpn_detect.dm @@ -0,0 +1,3 @@ +/client/proc/IsVPN() + var/datum/ipintel/res = get_ip_intel(address) + return res.intel >= CONFIG_GET(number/ipintel_rating_bad) diff --git a/code/modules/keybindings/bindings_client.dm b/code/modules/keybindings/bindings_client.dm index ca548c85ed..695617d2fc 100644 --- a/code/modules/keybindings/bindings_client.dm +++ b/code/modules/keybindings/bindings_client.dm @@ -6,6 +6,7 @@ set hidden = TRUE client_keysend_amount += 1 + last_activity = world.time var/cache = client_keysend_amount @@ -90,6 +91,7 @@ set hidden = TRUE keys_held -= _key + last_activity = world.time var/movement = movement_keys[_key] if(!(next_move_dir_add & movement)) next_move_dir_sub |= movement diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index fb2d034e22..bc6cb75d03 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1111,10 +1111,10 @@ return if(!HAS_TRAIT(src, TRAIT_IGNOREDAMAGESLOWDOWN)) //if we want to ignore slowdown from damage, but not from equipment var/scaling = maxHealth / 100 - var/health_deficiency = max(((maxHealth / scaling) - (health / scaling)), (getStaminaLoss()*0.75)) + var/health_deficiency = max(((maxHealth / scaling) - (health / scaling)), max(0, getStaminaLoss() - 39)) if(health_deficiency >= 40) - add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown, TRUE, (health_deficiency - 15) / 75) - add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown_flying, TRUE, (health_deficiency - 15) / 25) + add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown, TRUE, health_deficiency / 75) + add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown_flying, TRUE, health_deficiency / 25) else remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown) remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown_flying) diff --git a/code/modules/mob/say.dm b/code/modules/mob/say.dm index d3305c0c62..c622ebbd4b 100644 --- a/code/modules/mob/say.dm +++ b/code/modules/mob/say.dm @@ -4,6 +4,7 @@ set name = "say_indicator" set hidden = TRUE set category = "IC" + client?.last_activity = world.time display_typing_indicator() var/message = input(usr, "", "say") as text|null // If they don't type anything just drop the message. @@ -21,12 +22,16 @@ to_chat(usr, "Speech is currently admin-disabled.") return clear_typing_indicator() // clear it immediately! + + client?.last_activity = world.time + say(message) /mob/verb/me_typing_indicator() set name = "me_indicator" set hidden = TRUE set category = "IC" + client?.last_activity = world.time display_typing_indicator() var/message = input(usr, "", "me") as message|null // If they don't type anything just drop the message. @@ -52,6 +57,8 @@ message = trim(copytext_char(sanitize(message), 1, MAX_MESSAGE_LEN)) clear_typing_indicator() // clear it immediately! + client?.last_activity = world.time + usr.emote("me",1,message,TRUE) /mob/say_mod(input, message_mode) @@ -73,6 +80,7 @@ return lowertext(copytext_char(input, 1, customsayverb)) /mob/proc/whisper_keybind() + client?.last_activity = world.time var/message = input(src, "", "whisper") as text|null if(!length(message)) return @@ -89,6 +97,7 @@ whisper(message) /mob/proc/whisper(message, datum/language/language=null) + client?.last_activity = world.time say(message, language) //only living mobs actually whisper, everything else just talks /mob/proc/say_dead(var/message) @@ -132,6 +141,7 @@ message = emoji_parse(message) var/rendered = "DEAD: [name][alt_name] [emoji_parse(spanned)]" log_talk(message, LOG_SAY, tag="DEAD") + client?.last_activity = world.time deadchat_broadcast(rendered, follow_target = src, speaker_key = key) /mob/proc/check_emote(message) diff --git a/code/modules/tgui/tgui.dm b/code/modules/tgui/tgui.dm index a0c39258b9..c739d69d0b 100644 --- a/code/modules/tgui/tgui.dm +++ b/code/modules/tgui/tgui.dm @@ -300,6 +300,7 @@ process_status() if(src_object.ui_act(act_type, payload, src, state)) SStgui.update_uis(src_object) + usr?.client?.last_activity = world.time return FALSE switch(type) if("ready") diff --git a/config/entries/connections.txt b/config/entries/connections.txt index 6351a77fcf..41df00bc40 100644 --- a/config/entries/connections.txt +++ b/config/entries/connections.txt @@ -2,9 +2,12 @@ ## Requires database #PANIC_BUNKER -## If a player connects during a bunker with less then or this amount of living time (Minutes), we deny the connection +## If a player connects during a bunker with less then or this amount of living time (Minutes), we deny the connection. Set to -1 to disable criteria. #PANIC_BUNKER_LIVING 90 +## The above but for VPN connections. Set to -1 to disable criteria. You can set the above to disabled and set this to only enforce bunker on VPNs. +#PANIC_BUNKER_LIVING_VPN 120 + ## The message the Panic Bunker gives when someone is rejected by it ## %minutes% is replaced with PANIC_BUNKER_LIVING on runtime, remove it if you don't want this #PANIC_BUNKER_MESSAGE Sorry, but the server is currently not accepting connections from players with less than %minutes% minutes of living time. diff --git a/tgstation.dme b/tgstation.dme index 0ed28d6f8a..2bc4008796 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -1984,6 +1984,7 @@ #include "code\modules\client\client_colour.dm" #include "code\modules\client\client_defines.dm" #include "code\modules\client\client_procs.dm" +#include "code\modules\client\client_vpn_detect.dm" #include "code\modules\client\message.dm" #include "code\modules\client\player_details.dm" #include "code\modules\client\preferences.dm"