From a6d9b47a7dbbba04240e76350a8c6cc646309bb8 Mon Sep 17 00:00:00 2001 From: Zephyr <12817816+ZephyrTFA@users.noreply.github.com> Date: Sat, 21 Oct 2023 15:18:59 -0400 Subject: [PATCH] Updates signaler investigate code | Adds some nice QOL changes for signalers | Enforces cooldown on signaler circuitry (#78974) See title. If someone was abusing signalers previously to cause server lag, going into list signalers would actually cause even worse lag as byond sat there and processed thousands of items into a string over and over, which would cause string format operations on longer and longer strings, resulting in more and more overhead. This is bad. So instead there is now a limit to the size of the list, currently I have that set to 500 although I am open to increasing and even reducing the number. I have also made signalers slightly more intuitive by having the cooldown actually displayed in the ui as a tooltip instead of just being a secret feature you didnt know about unless you code dived. Also made the cooldown actually respected by things such as circuitry where it didnt even implement the cooldown and would happily send as many signals as you had items connected to your proximity circuit. Admins won't accidentally kill the server by trying to parse a lag machines signal list. Players lagging the server? No, how about the admins trying to fix it! :cl: qol: signalers now tell you their cooldown and also use balloon alerts /:cl: --- code/__DEFINES/logging.dm | 3 ++ code/_globalvars/logging.dm | 14 +++++++-- code/modules/admin/verbs/list_exposer.dm | 4 +-- code/modules/assembly/signaler.dm | 30 +++++++++++-------- .../file_system/programs/signalcommander.dm | 19 ++++++++---- .../wiremod/components/action/radio.dm | 16 ++++++++-- tgui/packages/tgui/interfaces/Signaler.jsx | 3 +- 7 files changed, 64 insertions(+), 25 deletions(-) diff --git a/code/__DEFINES/logging.dm b/code/__DEFINES/logging.dm index 8caf205817f6..62c770e6322e 100644 --- a/code/__DEFINES/logging.dm +++ b/code/__DEFINES/logging.dm @@ -5,6 +5,9 @@ /// Admins can still manually request a re-render #define LOG_UPDATE_TIMEOUT 5 SECONDS +// The maximum number of entries allowed in the signaler investigate log, keep this relatively small to prevent performance issues when an admin tries to query it +#define INVESTIGATE_SIGNALER_LOG_MAX_LENGTH 500 + //Investigate logging defines #define INVESTIGATE_ACCESSCHANGES "id_card_changes" #define INVESTIGATE_ATMOS "atmos" diff --git a/code/_globalvars/logging.dm b/code/_globalvars/logging.dm index 914665d17987..8a57ad13ea7e 100644 --- a/code/_globalvars/logging.dm +++ b/code/_globalvars/logging.dm @@ -61,9 +61,17 @@ GLOBAL_PROTECT(admin_activities) GLOBAL_LIST_EMPTY(bombers) GLOBAL_PROTECT(bombers) -/// All signals here in format: "[src] used [REF(src)] @ location [src.loc]: [freq]/[code]" -GLOBAL_LIST_EMPTY(lastsignalers) -GLOBAL_PROTECT(lastsignalers) +/// Investigate log for signaler usage, use the add_to_signaler_investigate_log proc +GLOBAL_LIST_EMPTY(investigate_signaler) +GLOBAL_PROTECT(investigate_signaler) + +/// Used to add a text log to the signaler investigation log. +/// Do not add to the list directly; if the list is too large it can cause lag when an admin tries to view it. +/proc/add_to_signaler_investigate_log(text) + var/log_length = length(GLOB.investigate_signaler) + if(log_length >= INVESTIGATE_SIGNALER_LOG_MAX_LENGTH) + GLOB.investigate_signaler = GLOB.investigate_signaler.Copy((INVESTIGATE_SIGNALER_LOG_MAX_LENGTH - log_length) + 2) + GLOB.investigate_signaler += list(text) /// Stores who uploaded laws to which silicon-based lifeform, and what the law was GLOBAL_LIST_EMPTY(lawchanges) diff --git a/code/modules/admin/verbs/list_exposer.dm b/code/modules/admin/verbs/list_exposer.dm index c2c48963051e..00a5960b3658 100644 --- a/code/modules/admin/verbs/list_exposer.dm +++ b/code/modules/admin/verbs/list_exposer.dm @@ -13,8 +13,8 @@ if(!SSticker.HasRoundStarted()) tgui_alert(usr, "The game hasn't started yet!") return - var/data = "Showing last [length(GLOB.lastsignalers)] signalers.
" - for(var/entry in GLOB.lastsignalers) + var/data = "Showing last [length(GLOB.investigate_signaler)] signalers.
" + for(var/entry in GLOB.investigate_signaler) data += "[entry]
" usr << browse(data, "window=lastsignalers;size=800x500") diff --git a/code/modules/assembly/signaler.dm b/code/modules/assembly/signaler.dm index de9a27404972..d38d20790e14 100644 --- a/code/modules/assembly/signaler.dm +++ b/code/modules/assembly/signaler.dm @@ -10,15 +10,20 @@ drop_sound = 'sound/items/handling/component_drop.ogg' pickup_sound = 'sound/items/handling/component_pickup.ogg' + /// The code sent by this signaler. var/code = DEFAULT_SIGNALER_CODE + /// The frequency this signaler is set to. var/frequency = FREQ_SIGNALER + /// How long of a cooldown exists on this signaller. + var/cooldown_length = 1 SECONDS + /// The radio frequency connection this signaler is using. var/datum/radio_frequency/radio_connection - ///Holds the mind that commited suicide. + /// Holds the mind that commited suicide. var/datum/mind/suicider - ///Holds a reference string to the mob, decides how much of a gamer you are. + /// Holds a reference string to the mob, decides how much of a gamer you are. var/suicide_mob + /// How many tiles away can you hear when this signaler is used or gets activated. var/hearing_range = 1 - /// String containing the last piece of logging data relating to when this signaller has received a signal. var/last_receive_signal_log @@ -77,23 +82,26 @@ /obj/item/assembly/signaler/ui_data(mob/user) var/list/data = list() data["frequency"] = frequency + data["cooldown"] = cooldown_length data["code"] = code data["minFrequency"] = MIN_FREE_FREQ data["maxFrequency"] = MAX_FREE_FREQ return data -/obj/item/assembly/signaler/ui_act(action, params) +/obj/item/assembly/signaler/ui_act(action, params, datum/tgui/ui) . = ..() if(.) return switch(action) if("signal") - if(TIMER_COOLDOWN_CHECK(src, COOLDOWN_SIGNALLER_SEND)) - to_chat(usr, span_warning("[src] is still recharging...")) - return - TIMER_COOLDOWN_START(src, COOLDOWN_SIGNALLER_SEND, 1 SECONDS) + if(cooldown_length > 0) + if(TIMER_COOLDOWN_CHECK(src, COOLDOWN_SIGNALLER_SEND)) + balloon_alert(ui.user, "recharging!") + return + TIMER_COOLDOWN_START(src, COOLDOWN_SIGNALLER_SEND, cooldown_length) INVOKE_ASYNC(src, PROC_REF(signal)) + balloon_alert(ui.user, "signaled") . = TRUE if("freq") var/new_frequency = sanitize_frequency(unformat_frequency(params["freq"]), TRUE) @@ -141,10 +149,8 @@ var/time = time2text(world.realtime,"hh:mm:ss") var/turf/T = get_turf(src) - var/logging_data - if(usr) - logging_data = "[time] : [usr.key] used [src] @ location ([T.x],[T.y],[T.z]) : [format_frequency(frequency)]/[code]" - GLOB.lastsignalers.Add(logging_data) + var/logging_data = "[time] : [key_name(usr)] used [src] @ location ([T.x],[T.y],[T.z]) : [format_frequency(frequency)]/[code]" + add_to_signaler_investigate_log(logging_data) var/datum/signal/signal = new(list("code" = code), logging_data = logging_data) radio_connection.post_signal(src, signal) diff --git a/code/modules/modular_computers/file_system/programs/signalcommander.dm b/code/modules/modular_computers/file_system/programs/signalcommander.dm index 6d636bab370a..e8140b62b17c 100644 --- a/code/modules/modular_computers/file_system/programs/signalcommander.dm +++ b/code/modules/modular_computers/file_system/programs/signalcommander.dm @@ -14,6 +14,10 @@ var/signal_code = DEFAULT_SIGNALER_CODE /// Radio connection datum used by signalers. var/datum/radio_frequency/radio_connection + /// How long do we cooldown before we can send another signal? + var/signal_cooldown_time = 1 SECONDS + /// Cooldown store + COOLDOWN_DECLARE(signal_cooldown) /datum/computer_file/program/signal_commander/on_start(mob/living/user) . = ..() @@ -26,6 +30,7 @@ /datum/computer_file/program/signal_commander/ui_data(mob/user) var/list/data = list() data["frequency"] = signal_frequency + data["cooldown"] = signal_cooldown_time data["code"] = signal_code data["minFrequency"] = MIN_FREE_FREQ data["maxFrequency"] = MAX_FREE_FREQ @@ -55,13 +60,18 @@ if(!radio_connection) return + if(!COOLDOWN_FINISHED(src, signal_cooldown)) + computer.balloon_alert(usr, "cooling down!") + return + + COOLDOWN_START(src, signal_cooldown, signal_cooldown_time) + computer.balloon_alert(usr, "signaled") + var/time = time2text(world.realtime,"hh:mm:ss") var/turf/T = get_turf(computer) - var/logging_data - if(usr) - logging_data = "[time] : [usr.key] used [computer] @ location ([T.x],[T.y],[T.z]) : [format_frequency(signal_frequency)]/[signal_code]" - GLOB.lastsignalers.Add(logging_data) + var/logging_data = "[time] : [key_name(usr)] used the computer '[initial(computer.name)]' @ location ([T.x],[T.y],[T.z]) : [format_frequency(signal_frequency)]/[signal_code]" + add_to_signaler_investigate_log(logging_data) var/datum/signal/signal = new(list("code" = signal_code), logging_data = logging_data) radio_connection.post_signal(computer, signal) @@ -70,4 +80,3 @@ SSradio.remove_object(computer, signal_frequency) signal_frequency = new_frequency radio_connection = SSradio.add_object(computer, signal_frequency, RADIO_SIGNALER) - return diff --git a/code/modules/wiremod/components/action/radio.dm b/code/modules/wiremod/components/action/radio.dm index cd13e0e1e451..74b2c54c1b81 100644 --- a/code/modules/wiremod/components/action/radio.dm +++ b/code/modules/wiremod/components/action/radio.dm @@ -28,8 +28,17 @@ /// The ckey of the user who used the shell we were placed in, important for signalling logs. var/owner_ckey = null + /// The radio connection we are using to receive signals. var/datum/radio_frequency/radio_connection + /// How long of a cooldown we have before we can send another signal. + var/signal_cooldown_time = 1 SECONDS + +/obj/item/circuit_component/radio/Initialize(mapload) + . = ..() + if(signal_cooldown_time > 0) + desc = "[desc] It has a [signal_cooldown_time * 0.1] second cooldown between sending signals." + /obj/item/circuit_component/radio/register_shell(atom/movable/shell) parent_shell = shell var/potential_fingerprints = shell.fingerprintslast @@ -65,8 +74,10 @@ INVOKE_ASYNC(src, PROC_REF(handle_radio_input), port) /obj/item/circuit_component/radio/proc/handle_radio_input(datum/port/input/port) - var/frequency = freq.value + if(!TIMER_COOLDOWN_CHECK(parent, COOLDOWN_SIGNALLER_SEND)) + return + var/frequency = freq.value if(frequency != current_freq) SSradio.remove_object(src, current_freq) radio_connection = SSradio.add_object(src, frequency, RADIO_SIGNALER) @@ -84,7 +95,8 @@ loggable_strings += ": The last fingerprints on the containing shell was [parent_shell.fingerprintslast]." var/loggable_string = loggable_strings.Join(" ") - GLOB.lastsignalers.Add(loggable_string) + add_to_signaler_investigate_log(loggable_string) + TIMER_COOLDOWN_START(parent, COOLDOWN_SIGNALLER_SEND, signal_cooldown_time) var/datum/signal/signal = new(list("code" = signal_code, "key" = parent?.owner_id), logging_data = loggable_string) radio_connection.post_signal(src, signal) diff --git a/tgui/packages/tgui/interfaces/Signaler.jsx b/tgui/packages/tgui/interfaces/Signaler.jsx index 81ee5a370c81..f3348b081c6c 100644 --- a/tgui/packages/tgui/interfaces/Signaler.jsx +++ b/tgui/packages/tgui/interfaces/Signaler.jsx @@ -16,7 +16,7 @@ export const Signaler = (props) => { export const SignalerContent = (props) => { const { act, data } = useBackend(); - const { code, frequency, minFrequency, maxFrequency } = data; + const { code, frequency, cooldown, minFrequency, maxFrequency } = data; const color = 'rgba(13, 13, 213, 0.7)'; const backColor = 'rgba(0, 0, 69, 0.5)'; return ( @@ -94,6 +94,7 @@ export const SignalerContent = (props) => {