From ab2292dfd5903378d26afe29c144eb66ce7f1f94 Mon Sep 17 00:00:00 2001 From: kevinz000 <2003111+kevinz000@users.noreply.github.com> Date: Tue, 7 Jan 2020 04:48:39 -0800 Subject: [PATCH 01/11] Fail2Topic --- code/__HELPERS/_logging.dm | 5 +- .../configuration/entries/fail2topic.dm | 15 +++ code/controllers/master.dm | 4 +- code/controllers/subsystem.dm | 4 +- code/controllers/subsystem/fail2topic.dm | 107 ++++++++++++++++++ code/game/world.dm | 10 ++ code/modules/tgs/v3210/commands.dm | 32 +++--- config/config.txt | 12 ++ tgstation.dme | 4 +- 9 files changed, 171 insertions(+), 22 deletions(-) create mode 100644 code/controllers/configuration/entries/fail2topic.dm create mode 100644 code/controllers/subsystem/fail2topic.dm diff --git a/code/__HELPERS/_logging.dm b/code/__HELPERS/_logging.dm index 3ee77d3edc..241e9b906e 100644 --- a/code/__HELPERS/_logging.dm +++ b/code/__HELPERS/_logging.dm @@ -78,7 +78,6 @@ if (CONFIG_GET(flag/log_manifest)) WRITE_LOG(GLOB.world_manifest_log, "[ckey] \\ [body.real_name] \\ [mind.assigned_role] \\ [mind.special_role ? mind.special_role : "NONE"] \\ [latejoin ? "LATEJOIN":"ROUNDSTART"]") - /proc/log_say(text) if (CONFIG_GET(flag/log_say)) WRITE_LOG(GLOB.world_game_log, "SAY: [text]") @@ -121,7 +120,6 @@ if (CONFIG_GET(flag/log_vote)) WRITE_LOG(GLOB.world_game_log, "VOTE: [text]") - /proc/log_topic(text) WRITE_LOG(GLOB.world_game_log, "TOPIC: [text]") @@ -141,6 +139,9 @@ if (CONFIG_GET(flag/log_job_debug)) WRITE_LOG(GLOB.world_job_debug_log, "JOB: [text]") +/proc/log_ss(subsystem, text) + WRITE_LOG(GLOB.subsystem_log, "[subsystem]: [text]") + /* Log to both DD and the logfile. */ /proc/log_world(text) #ifdef USE_CUSTOM_ERROR_HANDLER diff --git a/code/controllers/configuration/entries/fail2topic.dm b/code/controllers/configuration/entries/fail2topic.dm new file mode 100644 index 0000000000..665a55dd0f --- /dev/null +++ b/code/controllers/configuration/entries/fail2topic.dm @@ -0,0 +1,15 @@ +/datum/config_entry/number/fail2topic_rate_limit + config_entry_value = 10 //deciseconds + +/datum/config_entry/number/fail2topic_max_fails + config_entry_value = 5 + +/datum/config_entry/string/fail2topic_rule_name + config_entry_value = "_dd_fail2topic" + protection = CONFIG_ENTRY_LOCKED //affects physical server configuration, no touchies!! + +/datum/config_entry/flag/fail2topic_enabled + config_entry_value = TRUE + +/datum/config_entry/number/topic_max_size + config_entry_value = 8192 diff --git a/code/controllers/master.dm b/code/controllers/master.dm index 125da84a30..7244212630 100644 --- a/code/controllers/master.dm +++ b/code/controllers/master.dm @@ -54,7 +54,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new var/static/restart_clear = 0 var/static/restart_timeout = 0 var/static/restart_count = 0 - + var/static/random_seed //current tick limit, assigned before running a subsystem. @@ -69,7 +69,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new if(!random_seed) random_seed = (TEST_RUN_PARAMETER in world.params) ? 29051994 : rand(1, 1e9) rand_seed(random_seed) - + var/list/_subsystems = list() subsystems = _subsystems if (Master != src) diff --git a/code/controllers/subsystem.dm b/code/controllers/subsystem.dm index 4fe0812c56..3be4f36270 100644 --- a/code/controllers/subsystem.dm +++ b/code/controllers/subsystem.dm @@ -155,6 +155,8 @@ if(SS_SLEEPING) state = SS_PAUSING +/datum/controller/subsystem/proc/subsystem_log(msg) + return log_subsystem(name, msg) //used to initialize the subsystem AFTER the map has loaded /datum/controller/subsystem/Initialize(start_timeofday) @@ -162,7 +164,7 @@ var/time = (REALTIMEOFDAY - start_timeofday) / 10 var/msg = "Initialized [name] subsystem within [time] second[time == 1 ? "" : "s"]!" to_chat(world, "[msg]") - log_world(msg) + log_subsystem("INIT", msg) return time //hook for printing stats to the "MC" statuspanel for admins to see performance and related stats etc. diff --git a/code/controllers/subsystem/fail2topic.dm b/code/controllers/subsystem/fail2topic.dm new file mode 100644 index 0000000000..01b6d225b9 --- /dev/null +++ b/code/controllers/subsystem/fail2topic.dm @@ -0,0 +1,107 @@ +SUBSYSTEM_DEF(fail2topic) + name = "Fail2Topic" + init_order = SS_INIT_MISC_FIRST + flags = SS_FIRE_IN_LOBBY | SS_BACKGROUND + + var/list/rate_limiting = list() + var/list/fail_counts = list() + var/list/active_bans = list() + + var/rate_limit + var/max_fails + var/rule_name + var/enabled = FALSE + +/datum/controller/subsystem/fail2topic/Initialize(timeofday) + rate_limit = CONFIG_GET(number/fail2topic_rate_limit) + max_fails = CONFIG_GET(number/fail2topic_max_fails) + rule_name = CONFIG_GET(string/fail2topic_rule_name) + enabled = CONFIG_GET(flag/fail2topic_enabled) + + DropFirewallRule() // Clear the old bans if any still remain + + if (world.system_type == UNIX && enabled) + enabled = FALSE + subsystem_log("DISABLED - UNIX systems are not supported.") + if(!enabled) + flags |= SS_NO_FIRE + can_fire = FALSE + + return ..() + +/datum/controller/subsystem/fail2topic/fire() + while (rate_limiting.len) + var/ip = rate_limiting[1] + var/last_attempt = rate_limiting[ip] + + if (world.time - last_attempt > rate_limit) + rate_limiting -= ip + fail_counts -= ip + + if (MC_TICK_CHECK) + return + +/datum/controller/subsystem/fail2topic/Shutdown() + DropFirewallRule() + +/datum/controller/subsystem/fail2topic/proc/IsRateLimited(ip) + var/last_attempt = rate_limiting[ip] + + if (config?.api_rate_limit_whitelist[ip]) + return FALSE + + if (active_bans[ip]) + return TRUE + + rate_limiting[ip] = world.time + + if (isnull(last_attempt)) + return FALSE + + if (world.time - last_attempt > rate_limit) + fail_counts -= ip + return FALSE + else + var/failures = fail_counts[ip] + + if (isnull(failures)) + fail_counts[ip] = 1 + return FALSE + else if (failures > max_fails) + BanFromFirewall(ip) + return TRUE + else + fail_counts[ip] = failures + 1 + return TRUE + +/datum/controller/subsystem/fail2topic/proc/BanFromFirewall(ip) + if (!enabled) + return + + active_bans[ip] = world.time + fail_counts -= ip + rate_limiting -= ip + + . = shell("netsh advfirewall firewall add rule name=\"[rule_name]\" dir=in interface=any action=block remoteip=[ip]") + + if (.) + subsystem_log("Failed to ban [ip]. Exit code: [.].") + else if (isnull(.)) + subsystem_log("Failed to invoke shell to ban [ip].") + else + subsystem_log("Banned [ip].") + +/datum/controller/subsystem/fail2topic/proc/DropFirewallRule() + if (!enabled) + return + + active_bans = list() + + . = shell("netsh advfirewall firewall delete rule name=\"[rule_name]\"") + + if (.) + subsystem_log("Failed to drop firewall rule. Exit code: [.].") + else if (isnull(.)) + subsystem_log("Failed to invoke shell for firewall rule drop.") + else + subsystem_log("Firewall rule dropped.") diff --git a/code/game/world.dm b/code/game/world.dm index 4043f15f6f..99701c34dd 100644 --- a/code/game/world.dm +++ b/code/game/world.dm @@ -112,6 +112,7 @@ GLOBAL_VAR(restart_counter) GLOB.world_runtime_log = "[GLOB.log_directory]/runtime.log" GLOB.query_debug_log = "[GLOB.log_directory]/query_debug.log" GLOB.world_job_debug_log = "[GLOB.log_directory]/job_debug.log" + GLOB.subsystem_log = "[GLOB.log_directory]/subsystem.log" #ifdef UNIT_TESTS GLOB.test_log = file("[GLOB.log_directory]/tests.log") @@ -126,6 +127,7 @@ GLOBAL_VAR(restart_counter) start_log(GLOB.world_qdel_log) start_log(GLOB.world_runtime_log) start_log(GLOB.world_job_debug_log) + start_log(GLOB.subsystem_log) GLOB.changelog_hash = md5('html/changelog.html') //for telling if the changelog has changed recently if(fexists(GLOB.config_error_log)) @@ -143,6 +145,14 @@ GLOBAL_VAR(restart_counter) /world/Topic(T, addr, master, key) TGS_TOPIC //redirect to server tools if necessary + if(!SSfail2topic) + return "Server not initialized." + else if(!SSfail2topic.IsRateLimited(addr)) + return "Rate limited." + + if(length(T) > CONFIG_GET(number/topic_max_size)) + return "Payload too large!" + var/static/list/topic_handlers = TopicHandlers() var/list/input = params2list(T) diff --git a/code/modules/tgs/v3210/commands.dm b/code/modules/tgs/v3210/commands.dm index 71d7e32366..e674fd4e78 100644 --- a/code/modules/tgs/v3210/commands.dm +++ b/code/modules/tgs/v3210/commands.dm @@ -19,7 +19,7 @@ TGS_ERROR_LOG("Custom command [command_name] can't be used as it is empty or contains illegal characters!") warned_command_names[command_name] = TRUE continue - + if(command_name_types[command_name]) if(warnings_only) TGS_ERROR_LOG("Custom commands [command_name_types[command_name]] and [stc] have the same name, only [command_name_types[command_name]] will be available!") @@ -55,24 +55,24 @@ The MIT License Copyright (c) 2017 Jordan Brown -Permission is hereby granted, free of charge, -to any person obtaining a copy of this software and -associated documentation files (the "Software"), to -deal in the Software without restriction, including -without limitation the rights to use, copy, modify, -merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom -the Software is furnished to do so, +Permission is hereby granted, free of charge, +to any person obtaining a copy of this software and +associated documentation files (the "Software"), to +deal in the Software without restriction, including +without limitation the rights to use, copy, modify, +merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ diff --git a/config/config.txt b/config/config.txt index e71c2587b7..fafb3e5791 100644 --- a/config/config.txt +++ b/config/config.txt @@ -473,3 +473,15 @@ DISABLE_HIGH_POP_MC_MODE_AMOUNT 60 ## For reference, Goonstation uses a resolution of 21x15 for it's widescreen mode. ## Do note that changing this value will affect the title screen. The title screen will have to be updated manually if this is changed. DEFAULT_VIEW 21x15 + +### FAIL2TOPIC: +### Automated IP bans for world/Topic() spammers +## Enabled +FAIL2TOPIC_ENABLED +## Minimum wait time in deciseconds between valid requests +FAIL2TOPIC_RATE_LIMIT 10 +## Number of requests after breaching rate limit that triggers a ban +FAIL2TOPIC_MAX_FAILS 5 +## Firewall rule name used on physical server +FAIL2TOPIC_RULE_NAME _dd_fail2topic + diff --git a/tgstation.dme b/tgstation.dme index 1a79c32dcb..38645a3030 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -229,6 +229,7 @@ #include "code\controllers\configuration\entries\dbconfig.dm" #include "code\controllers\configuration\entries\donator.dm" #include "code\controllers\configuration\entries\dynamic.dm" +#include "code\controllers\configuration\entries\fail2topic.dm" #include "code\controllers\configuration\entries\game_options.dm" #include "code\controllers\configuration\entries\general.dm" #include "code\controllers\subsystem\acid.dm" @@ -245,6 +246,7 @@ #include "code\controllers\subsystem\dcs.dm" #include "code\controllers\subsystem\disease.dm" #include "code\controllers\subsystem\events.dm" +#include "code\controllers\subsystem\fail2topic.dm" #include "code\controllers\subsystem\fire_burning.dm" #include "code\controllers\subsystem\garbage.dm" #include "code\controllers\subsystem\icon_smooth.dm" @@ -470,8 +472,8 @@ #include "code\datums\elements\_element.dm" #include "code\datums\elements\cleaning.dm" #include "code\datums\elements\earhealing.dm" -#include "code\datums\elements\wuv.dm" #include "code\datums\elements\ghost_role_eligibility.dm" +#include "code\datums\elements\wuv.dm" #include "code\datums\helper_datums\events.dm" #include "code\datums\helper_datums\getrev.dm" #include "code\datums\helper_datums\icon_snapshot.dm" From fa7dcad49a884ae23b3392bf9ade24e971e6c3fd Mon Sep 17 00:00:00 2001 From: kevinz000 <2003111+kevinz000@users.noreply.github.com> Date: Tue, 7 Jan 2020 04:54:11 -0800 Subject: [PATCH 02/11] compile --- code/__DEFINES/subsystems.dm | 1 + code/__HELPERS/_logging.dm | 2 +- code/_globalvars/logging.dm | 2 ++ .../configuration/entries/fail2topic.dm | 4 ++++ code/controllers/subsystem/fail2topic.dm | 14 ++++++++++---- 5 files changed, 18 insertions(+), 5 deletions(-) diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm index c194e578c9..5c54843df2 100644 --- a/code/__DEFINES/subsystems.dm +++ b/code/__DEFINES/subsystems.dm @@ -47,6 +47,7 @@ // Subsystems shutdown in the reverse of the order they initialize in // The numbers just define the ordering, they are meaningless otherwise. +#define INIT_ORDER_FAIL2TOPIC 22 #define INIT_ORDER_TITLE 20 #define INIT_ORDER_GARBAGE 19 #define INIT_ORDER_DBCORE 18 diff --git a/code/__HELPERS/_logging.dm b/code/__HELPERS/_logging.dm index 241e9b906e..4dd590d9a1 100644 --- a/code/__HELPERS/_logging.dm +++ b/code/__HELPERS/_logging.dm @@ -139,7 +139,7 @@ if (CONFIG_GET(flag/log_job_debug)) WRITE_LOG(GLOB.world_job_debug_log, "JOB: [text]") -/proc/log_ss(subsystem, text) +/proc/log_subsystem(subsystem, text) WRITE_LOG(GLOB.subsystem_log, "[subsystem]: [text]") /* Log to both DD and the logfile. */ diff --git a/code/_globalvars/logging.dm b/code/_globalvars/logging.dm index 5ca3513e66..01d5051dba 100644 --- a/code/_globalvars/logging.dm +++ b/code/_globalvars/logging.dm @@ -30,6 +30,8 @@ GLOBAL_VAR(world_virus_log) GLOBAL_PROTECT(world_virus_log) GLOBAL_VAR(world_map_error_log) GLOBAL_PROTECT(world_map_error_log) +GLOBAL_VAR(subsystem_log) +GLOBAL_PROTECT(subsystem_log) GLOBAL_LIST_EMPTY(bombers) GLOBAL_PROTECT(bombers) diff --git a/code/controllers/configuration/entries/fail2topic.dm b/code/controllers/configuration/entries/fail2topic.dm index 665a55dd0f..7e5bfd7ee8 100644 --- a/code/controllers/configuration/entries/fail2topic.dm +++ b/code/controllers/configuration/entries/fail2topic.dm @@ -13,3 +13,7 @@ /datum/config_entry/number/topic_max_size config_entry_value = 8192 + +/datum/config_entry/keyed_list/topic_rate_limit_whitelist + key_type = KEY_MODE_TEXT + value_type = VALUE_MODE_FLAG diff --git a/code/controllers/subsystem/fail2topic.dm b/code/controllers/subsystem/fail2topic.dm index 01b6d225b9..0c2936e936 100644 --- a/code/controllers/subsystem/fail2topic.dm +++ b/code/controllers/subsystem/fail2topic.dm @@ -1,7 +1,8 @@ SUBSYSTEM_DEF(fail2topic) name = "Fail2Topic" - init_order = SS_INIT_MISC_FIRST - flags = SS_FIRE_IN_LOBBY | SS_BACKGROUND + init_order = INIT_ORDER_FAIL2TOPIC + flags = SS_BACKGROUND + runlevels = ALL var/list/rate_limiting = list() var/list/fail_counts = list() @@ -47,8 +48,13 @@ SUBSYSTEM_DEF(fail2topic) /datum/controller/subsystem/fail2topic/proc/IsRateLimited(ip) var/last_attempt = rate_limiting[ip] - if (config?.api_rate_limit_whitelist[ip]) - return FALSE + var/static/datum/config_entry/keyed_list/topic_rate_limit_whitelist/cached_whitelist_entry + if(!istype(cached_whitelist_entry)) + cached_whitelist_entry = CONFIG_GET(keyed_list/topic_rate_limit_whitelist) + + if(istype(cached_whitelist_entry)) + if(cached_whitelist_entry.config_entry_value[ip]) + return FALSE if (active_bans[ip]) return TRUE From 0114f9e2236091b900f3d220d56108a05d279346 Mon Sep 17 00:00:00 2001 From: kevinz000 <2003111+kevinz000@users.noreply.github.com> Date: Tue, 7 Jan 2020 04:54:32 -0800 Subject: [PATCH 03/11] whitelist --- code/controllers/configuration/entries/fail2topic.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/controllers/configuration/entries/fail2topic.dm b/code/controllers/configuration/entries/fail2topic.dm index 7e5bfd7ee8..7ed09b378a 100644 --- a/code/controllers/configuration/entries/fail2topic.dm +++ b/code/controllers/configuration/entries/fail2topic.dm @@ -15,5 +15,5 @@ config_entry_value = 8192 /datum/config_entry/keyed_list/topic_rate_limit_whitelist - key_type = KEY_MODE_TEXT - value_type = VALUE_MODE_FLAG + key_mode = KEY_MODE_TEXT + value_mode = VALUE_MODE_FLAG From 686601334eddc706525b8ce00c9aeafbb9bfd58b Mon Sep 17 00:00:00 2001 From: deathride58 Date: Tue, 7 Jan 2020 08:52:13 -0500 Subject: [PATCH 04/11] suggested changes --- code/controllers/subsystem/fail2topic.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/controllers/subsystem/fail2topic.dm b/code/controllers/subsystem/fail2topic.dm index 0c2936e936..a589ae2462 100644 --- a/code/controllers/subsystem/fail2topic.dm +++ b/code/controllers/subsystem/fail2topic.dm @@ -72,7 +72,7 @@ SUBSYSTEM_DEF(fail2topic) if (isnull(failures)) fail_counts[ip] = 1 - return FALSE + return TRUE else if (failures > max_fails) BanFromFirewall(ip) return TRUE From cde9946e2569c9c95edaefa5798bb7b5dc0c0ac7 Mon Sep 17 00:00:00 2001 From: deathride58 Date: Tue, 7 Jan 2020 09:00:30 -0500 Subject: [PATCH 05/11] is this why wrench refuses to work --- code/game/world.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/world.dm b/code/game/world.dm index 99701c34dd..86de9c53d0 100644 --- a/code/game/world.dm +++ b/code/game/world.dm @@ -147,7 +147,7 @@ GLOBAL_VAR(restart_counter) if(!SSfail2topic) return "Server not initialized." - else if(!SSfail2topic.IsRateLimited(addr)) + else if(SSfail2topic.IsRateLimited(addr)) return "Rate limited." if(length(T) > CONFIG_GET(number/topic_max_size)) From 633294c590e363007282466bca57c935b2976dbb Mon Sep 17 00:00:00 2001 From: deathride58 Date: Tue, 7 Jan 2020 20:03:44 -0500 Subject: [PATCH 06/11] adds a basic sanity check to server_hop --- code/datums/world_topic.dm | 30 +++++++++++++++--------------- code/game/world.dm | 2 +- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/code/datums/world_topic.dm b/code/datums/world_topic.dm index 0c43d33a4b..74b5222950 100644 --- a/code/datums/world_topic.dm +++ b/code/datums/world_topic.dm @@ -25,16 +25,16 @@ var/key_valid var/require_comms_key = FALSE -/datum/world_topic/proc/TryRun(list/input) +/datum/world_topic/proc/TryRun(list/input, addr) key_valid = config && (CONFIG_GET(string/comms_key) == input["key"]) if(require_comms_key && !key_valid) return "Bad Key" input -= "key" - . = Run(input) + . = Run(input, addr) if(islist(.)) . = list2params(.) -/datum/world_topic/proc/Run(list/input) +/datum/world_topic/proc/Run(list/input, addr) CRASH("Run() not implemented for [type]!") // TOPICS @@ -43,7 +43,7 @@ keyword = "ping" log = FALSE -/datum/world_topic/ping/Run(list/input) +/datum/world_topic/ping/Run(list/input, addr) . = 0 for (var/client/C in GLOB.clients) ++. @@ -52,7 +52,7 @@ keyword = "playing" log = FALSE -/datum/world_topic/playing/Run(list/input) +/datum/world_topic/playing/Run(list/input, addr) return GLOB.player_list.len /datum/world_topic/pr_announce @@ -60,7 +60,7 @@ require_comms_key = TRUE var/static/list/PRcounts = list() //PR id -> number of times announced this round -/datum/world_topic/pr_announce/Run(list/input) +/datum/world_topic/pr_announce/Run(list/input, addr) var/list/payload = json_decode(input["payload"]) var/id = "[payload["pull_request"]["id"]]" if(!PRcounts[id]) @@ -78,14 +78,14 @@ keyword = "Ahelp" require_comms_key = TRUE -/datum/world_topic/ahelp_relay/Run(list/input) +/datum/world_topic/ahelp_relay/Run(list/input, addr) relay_msg_admins("HELP: [input["source"]] [input["message_sender"]]: [input["message"]]") /datum/world_topic/comms_console keyword = "Comms_Console" require_comms_key = TRUE -/datum/world_topic/comms_console/Run(list/input) +/datum/world_topic/comms_console/Run(list/input, addr) minor_announce(input["message"], "Incoming message from [input["message_sender"]]") for(var/obj/machinery/computer/communications/CM in GLOB.machines) CM.overrideCooldown() @@ -94,16 +94,16 @@ keyword = "News_Report" require_comms_key = TRUE -/datum/world_topic/news_report/Run(list/input) +/datum/world_topic/news_report/Run(list/input, addr) minor_announce(input["message"], "Breaking Update From [input["message_sender"]]") /datum/world_topic/server_hop keyword = "server_hop" -/datum/world_topic/server_hop/Run(list/input) +/datum/world_topic/server_hop/Run(list/input, addr) var/expected_key = input[keyword] for(var/mob/dead/observer/O in GLOB.player_list) - if(O.key == expected_key) + if(O.key == expected_key && O?.client.address == addr) if(O.client) new /obj/screen/splash(O.client, TRUE) break @@ -112,14 +112,14 @@ keyword = "adminmsg" require_comms_key = TRUE -/datum/world_topic/adminmsg/Run(list/input) +/datum/world_topic/adminmsg/Run(list/input, addr) return IrcPm(input[keyword], input["msg"], input["sender"]) /datum/world_topic/namecheck keyword = "namecheck" require_comms_key = TRUE -/datum/world_topic/namecheck/Run(list/input) +/datum/world_topic/namecheck/Run(list/input, addr) //Oh this is a hack, someone refactor the functionality out of the chat command PLS var/datum/tgs_chat_command/namecheck/NC = new var/datum/tgs_chat_user/user = new @@ -131,13 +131,13 @@ keyword = "adminwho" require_comms_key = TRUE -/datum/world_topic/adminwho/Run(list/input) +/datum/world_topic/adminwho/Run(list/input, addr) return ircadminwho() /datum/world_topic/status keyword = "status" -/datum/world_topic/status/Run(list/input) +/datum/world_topic/status/Run(list/input, addr) . = list() .["version"] = GLOB.game_version .["mode"] = "hidden" //CIT CHANGE - hides the gamemode in topic() calls to prevent meta'ing the gamemode diff --git a/code/game/world.dm b/code/game/world.dm index 4043f15f6f..2700746220 100644 --- a/code/game/world.dm +++ b/code/game/world.dm @@ -159,7 +159,7 @@ GLOBAL_VAR(restart_counter) return handler = new handler() - return handler.TryRun(input) + return handler.TryRun(input, addr) /world/proc/AnnouncePR(announcement, list/payload) var/static/list/PRcounts = list() //PR id -> number of times announced this round From f0af57d7d66aa2c72c020b4b59afbf4f432d2c6c Mon Sep 17 00:00:00 2001 From: deathride58 Date: Tue, 7 Jan 2020 20:22:06 -0500 Subject: [PATCH 07/11] wrong question mark place aaa --- code/datums/world_topic.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/datums/world_topic.dm b/code/datums/world_topic.dm index 74b5222950..602ef7f5f5 100644 --- a/code/datums/world_topic.dm +++ b/code/datums/world_topic.dm @@ -103,7 +103,7 @@ /datum/world_topic/server_hop/Run(list/input, addr) var/expected_key = input[keyword] for(var/mob/dead/observer/O in GLOB.player_list) - if(O.key == expected_key && O?.client.address == addr) + if(O.key == expected_key && O.client?.address == addr) if(O.client) new /obj/screen/splash(O.client, TRUE) break From 89fcde9927147c6b6d23aaf16e5d1e3a5481f6ca Mon Sep 17 00:00:00 2001 From: deathride58 Date: Tue, 7 Jan 2020 20:24:08 -0500 Subject: [PATCH 08/11] im like 3 iq dont bulli --- code/datums/world_topic.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/datums/world_topic.dm b/code/datums/world_topic.dm index 602ef7f5f5..e01b525e02 100644 --- a/code/datums/world_topic.dm +++ b/code/datums/world_topic.dm @@ -103,8 +103,8 @@ /datum/world_topic/server_hop/Run(list/input, addr) var/expected_key = input[keyword] for(var/mob/dead/observer/O in GLOB.player_list) - if(O.key == expected_key && O.client?.address == addr) - if(O.client) + if(O.key == expected_key) + if(O.client?.address == addr) new /obj/screen/splash(O.client, TRUE) break From df572996b366b84063e994875aa1adf8af37a64e Mon Sep 17 00:00:00 2001 From: Putnam Date: Wed, 8 Jan 2020 15:40:35 -0800 Subject: [PATCH 09/11] fix limb damage --- code/modules/surgery/bodyparts/bodyparts.dm | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/code/modules/surgery/bodyparts/bodyparts.dm b/code/modules/surgery/bodyparts/bodyparts.dm index a1b74942e0..63a392bf06 100644 --- a/code/modules/surgery/bodyparts/bodyparts.dm +++ b/code/modules/surgery/bodyparts/bodyparts.dm @@ -172,9 +172,8 @@ var/total_damage = brute + burn if(total_damage > can_inflict) - var/excess = total_damage - can_inflict - brute = round(brute * (excess / total_damage),DAMAGE_PRECISION) - burn = round(burn * (excess / total_damage),DAMAGE_PRECISION) + brute = round(brute * (max_damage / total_damage),DAMAGE_PRECISION) + burn = round(burn * (max_damage / total_damage),DAMAGE_PRECISION) brute_dam += brute burn_dam += burn From 5dd58950abfde504abd76ed553539b3262951b3b Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Wed, 8 Jan 2020 20:04:47 -0600 Subject: [PATCH 10/11] Automatic changelog generation for PR #10483 [ci skip] --- html/changelogs/AutoChangeLog-pr-10483.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-10483.yml diff --git a/html/changelogs/AutoChangeLog-pr-10483.yml b/html/changelogs/AutoChangeLog-pr-10483.yml new file mode 100644 index 0000000000..1f016b1591 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10483.yml @@ -0,0 +1,4 @@ +author: "Putnam3145" +delete-after: True +changes: + - bugfix: "Limb damage works now" From f4e508615dc902227644ac88bac35b17e575af7e Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Wed, 8 Jan 2020 21:16:06 -0600 Subject: [PATCH 11/11] Automatic changelog generation for PR #10473 [ci skip] --- html/changelogs/AutoChangeLog-pr-10473.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-10473.yml diff --git a/html/changelogs/AutoChangeLog-pr-10473.yml b/html/changelogs/AutoChangeLog-pr-10473.yml new file mode 100644 index 0000000000..f1821a3cce --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10473.yml @@ -0,0 +1,4 @@ +author: "Bhijn" +delete-after: True +changes: + - bugfix: "server_hop can no longer be used to remotely lobotomize a spaceman"