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"