Skip to content

Commit

Permalink
Updates signaler investigate code | Adds some nice QOL changes for si…
Browse files Browse the repository at this point in the history
…gnalers | Enforces cooldown on signaler circuitry (tgstation#78974)

## About The Pull Request

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.
## Why It's Good For The Game

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!

## Changelog

:cl:
qol: signalers now tell you their cooldown and also use balloon alerts
/:cl:
  • Loading branch information
ZephyrTFA authored Oct 21, 2023
1 parent 14f0001 commit e9448ad
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 25 deletions.
3 changes: 3 additions & 0 deletions code/__DEFINES/logging.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
14 changes: 11 additions & 3 deletions code/_globalvars/logging.dm
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,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)
Expand Down
4 changes: 2 additions & 2 deletions code/modules/admin/verbs/list_exposer.dm
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
if(!SSticker.HasRoundStarted())
tgui_alert(usr, "The game hasn't started yet!")
return
var/data = "<b>Showing last [length(GLOB.lastsignalers)] signalers.</b><hr>"
for(var/entry in GLOB.lastsignalers)
var/data = "<b>Showing last [length(GLOB.investigate_signaler)] signalers.</b><hr>"
for(var/entry in GLOB.investigate_signaler)
data += "[entry]<BR>"
usr << browse(data, "window=lastsignalers;size=800x500")

Expand Down
30 changes: 18 additions & 12 deletions code/modules/assembly/signaler.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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] <B>:</B> [usr.key] used [src] @ location ([T.x],[T.y],[T.z]) <B>:</B> [format_frequency(frequency)]/[code]"
GLOB.lastsignalers.Add(logging_data)
var/logging_data = "[time] <B>:</B> [key_name(usr)] used [src] @ location ([T.x],[T.y],[T.z]) <B>:</B> [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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
. = ..()
Expand All @@ -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
Expand Down Expand Up @@ -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] <B>:</B> [usr.key] used [computer] @ location ([T.x],[T.y],[T.z]) <B>:</B> [format_frequency(signal_frequency)]/[signal_code]"
GLOB.lastsignalers.Add(logging_data)
var/logging_data = "[time] <B>:</B> [key_name(usr)] used the computer '[initial(computer.name)]' @ location ([T.x],[T.y],[T.z]) <B>:</B> [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)
Expand All @@ -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
16 changes: 14 additions & 2 deletions code/modules/wiremod/components/action/radio.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand All @@ -84,7 +95,8 @@
loggable_strings += "<B>:</B> 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)
Expand Down
3 changes: 2 additions & 1 deletion tgui/packages/tgui/interfaces/Signaler.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export const Signaler = (props, context) => {

export const SignalerContent = (props, context) => {
const { act, data } = useBackend(context);
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 (
Expand Down Expand Up @@ -94,6 +94,7 @@ export const SignalerContent = (props, context) => {
<Button
mb={-0.1}
fluid
tooltip={cooldown && `Cooldown: ${cooldown * 0.1} seconds`}
icon="arrow-up"
content="Send Signal"
textAlign="center"
Expand Down

0 comments on commit e9448ad

Please sign in to comment.