[MIRROR] Adds sanity checking to prefs checks, fixing a bug that can cause emotes to stop displaying intermittently [MDB IGNORE] (#23081)

* Adds sanity checking to prefs checks, fixing a bug that can cause emotes to stop displaying intermittently

* Update vox_procs.dm

---------

Co-authored-by: Bloop <13398309+vinylspiders@users.noreply.github.com>
This commit is contained in:
SkyratBot
2023-08-15 01:40:51 +02:00
committed by GitHub
parent 2b205d167b
commit 2ac66a8a4a
15 changed files with 71 additions and 44 deletions
+6 -6
View File
@@ -194,7 +194,7 @@
return ..()
/mob/camera/imaginary_friend/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, list/message_mods = list(), message_range)
if (client?.prefs.read_preference(/datum/preference/toggle/enable_runechat) && (client.prefs.read_preference(/datum/preference/toggle/enable_runechat_non_mobs) || ismob(speaker)))
if (safe_read_pref(client, /datum/preference/toggle/enable_runechat) && (safe_read_pref(client, /datum/preference/toggle/enable_runechat_non_mobs) || ismob(speaker)))
create_chat_message(speaker, message_language, raw_message, spans)
to_chat(src, compose_message(speaker, message_language, raw_message, radio_freq, spans, message_mods))
@@ -252,7 +252,7 @@
// Speech bubble, but only for those who have runechat off
var/list/speech_bubble_recipients = list()
for(var/mob/user as anything in (group + src)) // Add ourselves back in
if(user.client && (!user.client.prefs.read_preference(/datum/preference/toggle/enable_runechat) || (SSlag_switch.measures[DISABLE_RUNECHAT] && !HAS_TRAIT(src, TRAIT_BYPASS_MEASURES))))
if((safe_read_pref(user.client, /datum/preference/toggle/enable_runechat) || (SSlag_switch.measures[DISABLE_RUNECHAT] && !HAS_TRAIT(src, TRAIT_BYPASS_MEASURES))))
speech_bubble_recipients.Add(user.client)
var/image/bubble = image('icons/mob/effects/talk.dmi', src, "[bubble_type][say_test(message)]", FLY_LAYER)
@@ -269,9 +269,9 @@
for(var/mob/dead_player in GLOB.dead_mob_list)
if(dead_player.z != z || get_dist(src, dead_player) > 7)
if(eavesdrop_range)
if(!(dead_player.client?.prefs.chat_toggles & CHAT_GHOSTWHISPER))
if(!(get_chat_toggles(dead_player.client) & CHAT_GHOSTWHISPER))
continue
else if(!(dead_player.client?.prefs.chat_toggles & CHAT_GHOSTEARS))
else if(!(get_chat_toggles(dead_player.client) & CHAT_GHOSTEARS))
continue
var/link = FOLLOW_LINK(dead_player, owner)
to_chat(dead_player, "[link] [dead_rendered]")
@@ -311,12 +311,12 @@
for(var/mob/ghost as anything in GLOB.dead_mob_list)
if(!ghost.client || isnewplayer(ghost))
continue
if(ghost.client.prefs.chat_toggles & CHAT_GHOSTSIGHT && !(ghost in viewers(user_turf, null)))
if(get_chat_toggles(ghost.client) & CHAT_GHOSTSIGHT && !(ghost in viewers(user_turf, null)))
ghost.show_message("[FOLLOW_LINK(ghost, user)] [dchatmsg]")
for(var/mob/person in friend.owner.imaginary_group)
to_chat(person, message)
if(person.client?.prefs.read_preference(/datum/preference/toggle/enable_runechat))
if(safe_read_pref(person.client, /datum/preference/toggle/enable_runechat))
person.create_chat_message(friend, raw_message = msg, runechat_flags = EMOTE_MESSAGE)
return TRUE
+2 -2
View File
@@ -122,7 +122,7 @@
for(var/mob/ghost as anything in GLOB.dead_mob_list)
if(!ghost.client || isnewplayer(ghost))
continue
if(ghost.client.prefs.chat_toggles & CHAT_GHOSTSIGHT && !(ghost in viewers(user_turf, null)))
if(get_chat_toggles(ghost.client) & CHAT_GHOSTSIGHT && !(ghost in viewers(user_turf, null)))
ghost.show_message("<span class='emote'>[FOLLOW_LINK(ghost, user)] [dchatmsg]</span>")
if(emote_type & (EMOTE_AUDIBLE | EMOTE_VISIBLE)) //emote is audible and visible
user.audible_message(msg, deaf_message = "<span class='emote'>You see how <b>[user]</b> [msg]</span>", audible_message_flags = EMOTE_MESSAGE)
@@ -351,6 +351,6 @@
for(var/mob/ghost as anything in GLOB.dead_mob_list)
if(!ghost.client || isnewplayer(ghost))
continue
if(ghost.client.prefs.chat_toggles & CHAT_GHOSTSIGHT && !(ghost in viewers(origin_turf, null)))
if(get_chat_toggles(ghost.client) & CHAT_GHOSTSIGHT && !(ghost in viewers(origin_turf, null)))
ghost.show_message("[FOLLOW_LINK(ghost, src)] [ghost_text]")
return TRUE
@@ -183,11 +183,7 @@
// Add observers who have ghost radio enabled.
for(var/mob/dead/observer/ghost in GLOB.player_list)
if(ghost.client && !ghost.client.prefs)
stack_trace("[ghost] ([ghost.ckey]) had null prefs, which shouldn't be possible!")
continue
if(ghost.client?.prefs.chat_toggles & CHAT_GHOSTRADIO)
if(get_chat_toggles(ghost.client) & CHAT_GHOSTRADIO)
receive |= ghost
// Render the message and have everybody hear it.
+1 -1
View File
@@ -43,7 +43,7 @@
GLOB.requests.pray(usr.client, msg, usr.job == JOB_CHAPLAIN)
msg = span_adminnotice("[icon2html(cross, GLOB.admins)]<b><font color=[font_color]>[prayer_type][deity ? " (to [deity])" : ""]: </font>[ADMIN_FULLMONTY(src)] [ADMIN_SC(src)]:</b> [span_linkify(msg)]")
for(var/client/C in GLOB.admins)
if(C.prefs.chat_toggles & CHAT_PRAYER)
if(get_chat_toggles(C) & CHAT_PRAYER)
to_chat(C, msg, type = MESSAGE_TYPE_PRAYER, confidential = TRUE)
to_chat(usr, span_info("You pray to the gods: \"[msg_tmp]\""), confidential = TRUE)
@@ -41,7 +41,7 @@
to_chat(usr, span_info("You requested: \"[request_url]\" to be played."), confidential = TRUE)
request_url = span_adminnotice("<b><font color='cyan'>MUSIC REQUEST: </font>[ADMIN_FULLMONTY(src)] [ADMIN_SC(src)]:</b> [span_linkify(request_url)] [ADMIN_PLAY_INTERNET(request_url, credit)]")
for(var/client/admin_client in GLOB.admins)
if(admin_client.prefs.chat_toggles & CHAT_PRAYER)
if(get_chat_toggles(admin_client) & CHAT_PRAYER)
to_chat(admin_client, request_url, type = MESSAGE_TYPE_PRAYER, confidential = TRUE)
SSblackbox.record_feedback("tally", "music_request", 1, "Music Request") // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc!
+1 -1
View File
@@ -1069,7 +1069,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
void.UpdateGreed(actualview[1],actualview[2])
/client/proc/AnnouncePR(announcement)
if(prefs && prefs.chat_toggles & CHAT_PULLR)
if(get_chat_toggles(src) & CHAT_PULLR)
to_chat(src, announcement)
///Redirect proc that makes it easier to call the unlock achievement proc. Achievement type is the typepath to the award, user is the mob getting the award, and value is an optional variable used for leaderboard value increments
+43
View File
@@ -539,6 +539,49 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(GetQuirkBalance() < 0)
all_quirks = list()
/**
* Safely read a given preference datum from a given client.
*
* Reads the given preference datum from the given client, and guards against null client and null prefs.
* The client object is fickle and can go null at times, so use this instead of read_preference() if you
* want to ensure no runtimes.
*
* returns client.prefs.read_preference(prefs_to_read) or FALSE if something went wrong.
*
* Arguments:
* * client/prefs_holder - the client to read the pref from
* * datum/preference/pref_to_read - the type of preference datum to read.
*/
/proc/safe_read_pref(client/prefs_holder, datum/preference/pref_to_read)
if(!prefs_holder)
return FALSE
if(prefs_holder && !prefs_holder?.prefs)
stack_trace("[prefs_holder?.mob] ([prefs_holder?.ckey]) had null prefs, which shouldn't be possible!")
return FALSE
return prefs_holder?.prefs.read_preference(pref_to_read)
/**
* Get the given client's chat toggle prefs.
*
* Getter function for prefs.chat_toggles which guards against null client and null prefs.
* The client object is fickle and can go null at times, so use this instead of directly accessing the var
* if you want to ensure no runtimes.
*
* returns client.prefs.chat_toggles or FALSE if something went wrong.
*
* Arguments:
* * client/prefs_holder - the client to get the chat_toggles pref from.
*/
/proc/get_chat_toggles(client/prefs_holder)
if(!prefs_holder)
return FALSE
if(prefs_holder && !prefs_holder?.prefs)
stack_trace("[prefs_holder?.mob] ([prefs_holder?.ckey]) had null prefs, which shouldn't be possible!")
return FALSE
return prefs_holder?.prefs.chat_toggles
/// Sanitizes the preferences, applies the randomization prefs, and then applies the preference to the human mob.
/datum/preferences/proc/safe_transfer_prefs_to(mob/living/carbon/human/character, icon_updates = TRUE, is_antag = FALSE)
apply_character_randomization_prefs(is_antag)
+2 -2
View File
@@ -68,7 +68,7 @@ GLOBAL_VAR_INIT(normal_ooc_colour, "#002eb8")
message_admins("[key_name_admin(src)] has attempted to advertise in OOC: [msg]")
return
if(!(prefs.chat_toggles & CHAT_OOC))
if(!(get_chat_toggles(src) & CHAT_OOC))
to_chat(src, span_danger("You have OOC muted."))
return
@@ -90,7 +90,7 @@ GLOBAL_VAR_INIT(normal_ooc_colour, "#002eb8")
for(var/client/receiver as anything in GLOB.clients)
if(!receiver.prefs) // Client being created or deleted. Despite all, this can be null.
continue
if(!(receiver.prefs.chat_toggles & CHAT_OOC))
if(!(get_chat_toggles(receiver) & CHAT_OOC))
continue
if(holder?.fakekey in receiver.prefs.ignoring)
continue
+3 -3
View File
@@ -205,7 +205,7 @@
icon_source = id_card.get_cached_flat_icon()
var/mob/card_holder = recursive_loc_check(card, /mob)
if(ismob(card_holder)) //If on a mob
if(!card_holder.client || (!(card_holder.client.prefs.chat_toggles & CHAT_BANKCARD) && !force))
if(!card_holder.client || (!(get_chat_toggles(card_holder.client) & CHAT_BANKCARD) && !force))
return
if(card_holder.can_hear())
@@ -214,7 +214,7 @@
else if(isturf(card.loc)) //If on the ground
var/turf/card_location = card.loc
for(var/mob/potential_hearer in hearers(1,card_location))
if(!potential_hearer.client || (!(potential_hearer.client.prefs.chat_toggles & CHAT_BANKCARD) && !force))
if(!potential_hearer.client || (!(get_chat_toggles(potential_hearer.client) & CHAT_BANKCARD) && !force))
continue
if(potential_hearer.can_hear())
potential_hearer.playsound_local(card_location, 'sound/machines/twobeep_high.ogg', 50, TRUE)
@@ -222,7 +222,7 @@
else
var/atom/sound_atom
for(var/mob/potential_hearer in card.loc) //If inside a container with other mobs (e.g. locker)
if(!potential_hearer.client || (!(potential_hearer.client.prefs.chat_toggles & CHAT_BANKCARD) && !force))
if(!potential_hearer.client || (!(get_chat_toggles(potential_hearer.client) & CHAT_BANKCARD) && !force))
continue
if(!sound_atom)
sound_atom = card.drop_location() //in case we're inside a bodybag in a crate or something. doing this here to only process it if there's a valid mob who can hear the sound.
@@ -60,7 +60,7 @@
to_follow = V.source
var/link = FOLLOW_LINK(src, to_follow)
// Create map text prior to modifying message for goonchat
if (client?.prefs.read_preference(/datum/preference/toggle/enable_runechat) && (client.prefs.read_preference(/datum/preference/toggle/enable_runechat_non_mobs) || ismob(speaker)))
if (safe_read_pref(client, /datum/preference/toggle/enable_runechat) && (safe_read_pref(client, /datum/preference/toggle/enable_runechat_non_mobs) || ismob(speaker)))
create_chat_message(speaker, message_language, raw_message, spans)
// Recompose the message, because it's scrambled by default
message = compose_message(speaker, message_language, raw_message, radio_freq, spans, message_mods)
+2 -6
View File
@@ -359,14 +359,10 @@ GLOBAL_LIST_INIT(message_modes_stat_limits, list(
if(player_mob.stat != DEAD) //not dead, not important
continue
if(player_mob.z != z || get_dist(player_mob, src) > 7) //they're out of range of normal hearing
if(player_mob.client && !player_mob.client?.prefs)
stack_trace("[player_mob] ([player_mob.ckey]) had null prefs, which shouldn't be possible!")
continue
if(is_speaker_whispering)
if(!(player_mob.client?.prefs.chat_toggles & CHAT_GHOSTWHISPER)) //they're whispering and we have hearing whispers at any range off
if(!(get_chat_toggles(player_mob.client) & CHAT_GHOSTWHISPER)) //they're whispering and we have hearing whispers at any range off
continue
else if(!(player_mob.client?.prefs.chat_toggles & CHAT_GHOSTEARS)) //they're talking normally and we have hearing at any range off
else if(!(get_chat_toggles(player_mob.client) & CHAT_GHOSTEARS)) //they're talking normally and we have hearing at any range off
continue
listening |= player_mob
+1 -5
View File
@@ -156,11 +156,7 @@
if(!only_listener)
// Play voice for all mobs in the z level
for(var/mob/player_mob as anything in GLOB.player_list)
if(player_mob.client && !player_mob.client?.prefs)
stack_trace("[player_mob] ([player_mob.ckey]) has null prefs, which shouldn't be possible!")
continue
if(!player_mob.can_hear() || !(player_mob.client?.prefs.read_preference(/datum/preference/toggle/sound_announcements)))
if(!player_mob.can_hear() || !(safe_read_pref(player_mob.client, /datum/preference/toggle/sound_announcements)))
continue
var/turf/player_turf = get_turf(player_mob)
@@ -615,10 +615,6 @@
var/ghost_message = span_game_say("[span_name("[sender]")] [rigged ? "(as [span_name(fake_name)]) Rigged " : ""]PDA Message --> [span_name("[signal.format_target()]")]: \"[signal.format_message()]\"")
var/list/ghosts = GLOB.dead_player_list + GLOB.current_observers_list
for(var/mob/player_mob as anything in ghosts)
if(player_mob.client && !player_mob.client?.prefs)
stack_trace("[player_mob] ([player_mob.ckey]) had null prefs, which shouldn't be possible!")
continue
if(isobserver(player_mob) && (player_mob.client?.prefs.chat_toggles & CHAT_GHOSTPDA))
to_chat(player_mob, "[FOLLOW_LINK(player_mob, sender)] [ghost_message]")
+1 -1
View File
@@ -66,7 +66,7 @@ GLOBAL_DATUM_INIT(requests, /datum/request_manager, new)
/datum/request_manager/proc/pray(client/C, message, is_chaplain)
request_for_client(C, REQUEST_PRAYER, message)
for(var/client/admin in GLOB.admins)
if(is_chaplain && admin.prefs.chat_toggles & CHAT_PRAYER && admin.prefs.toggles & SOUND_PRAYERS)
if(is_chaplain && get_chat_toggles(admin) & CHAT_PRAYER && admin.prefs.toggles & SOUND_PRAYERS)
SEND_SOUND(admin, sound('sound/effects/pray.ogg'))
/**
@@ -168,14 +168,14 @@
if(!only_listener)
// Play voice for all mobs in the z level
for(var/mob/player_mob in GLOB.player_list)
if(player_mob.client && !player_mob.client?.prefs)
stack_trace("[player_mob] ([player_mob.ckey]) has null prefs, which shouldn't be possible!")
if(!player_mob.can_hear() || !(safe_read_pref(player_mob.client, /datum/preference/toggle/sound_announcements)))
continue
if(player_mob.can_hear() && (player_mob.client?.prefs.read_preference(/datum/preference/toggle/sound_announcements)))
var/turf/player_turf = get_turf(player_mob)
if(player_turf.z == z_level)
SEND_SOUND(player_mob, voice)
var/turf/player_turf = get_turf(player_mob)
if(player_turf.z != z_level)
continue
SEND_SOUND(player_mob, voice)
else
SEND_SOUND(only_listener, voice)