mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-08-30 15:37:36 +01:00
Refactors stack traces, tiny bit of cleanup (#18773)
This commit is contained in:
@@ -47,14 +47,10 @@
|
||||
hsrc = locate(href_list["src"])
|
||||
if(hsrc)
|
||||
var/hsrc_info = datum_info_line(hsrc) || "[hsrc]"
|
||||
log_runtime(EXCEPTION("Got \\ref-based src in topic from [src] for [hsrc_info], should be UID: [href]"))
|
||||
stack_trace("Got \\ref-based src in topic from [src] for [hsrc_info], should be UID: [href]")
|
||||
|
||||
#if defined(TOPIC_DEBUGGING)
|
||||
to_chat(world, "[src]'s Topic: [href] destined for [hsrc].")
|
||||
#endif
|
||||
|
||||
if(href_list["asset_cache_confirm_arrival"])
|
||||
// to_chat(src, "ASSET JOB [href_list["asset_cache_confirm_arrival"]] ARRIVED.")
|
||||
var/job = text2num(href_list["asset_cache_confirm_arrival"])
|
||||
completed_asset_jobs += job
|
||||
return
|
||||
@@ -64,17 +60,19 @@
|
||||
|
||||
// Rate limiting
|
||||
var/mtl = 100 // 100 topics per minute
|
||||
if (!holder) // Admins are allowed to spam click, deal with it.
|
||||
if(!holder) // Admins are allowed to spam click, deal with it.
|
||||
var/minute = round(world.time, 600)
|
||||
if (!topiclimiter)
|
||||
if(!topiclimiter)
|
||||
topiclimiter = new(LIMITER_SIZE)
|
||||
if (minute != topiclimiter[CURRENT_MINUTE])
|
||||
|
||||
if(minute != topiclimiter[CURRENT_MINUTE])
|
||||
topiclimiter[CURRENT_MINUTE] = minute
|
||||
topiclimiter[MINUTE_COUNT] = 0
|
||||
|
||||
topiclimiter[MINUTE_COUNT] += 1
|
||||
if (topiclimiter[MINUTE_COUNT] > mtl)
|
||||
if(topiclimiter[MINUTE_COUNT] > mtl)
|
||||
var/msg = "Your previous action was ignored because you've done too many in a minute."
|
||||
if (minute != topiclimiter[ADMINSWARNED_AT]) //only one admin message per-minute. (if they spam the admins can just boot/ban them)
|
||||
if(minute != topiclimiter[ADMINSWARNED_AT]) //only one admin message per-minute. (if they spam the admins can just boot/ban them)
|
||||
topiclimiter[ADMINSWARNED_AT] = minute
|
||||
msg += " Administrators have been informed."
|
||||
log_game("[key_name(src)] Has hit the per-minute topic limit of [mtl] topic calls in a given game minute")
|
||||
@@ -83,22 +81,24 @@
|
||||
return
|
||||
|
||||
var/stl = 10 // 10 topics a second
|
||||
if (!holder) // Admins are allowed to spam click, deal with it.
|
||||
if(!holder) // Admins are allowed to spam click, deal with it.
|
||||
var/second = round(world.time, 10)
|
||||
if (!topiclimiter)
|
||||
if(!topiclimiter)
|
||||
topiclimiter = new(LIMITER_SIZE)
|
||||
if (second != topiclimiter[CURRENT_SECOND])
|
||||
|
||||
if(second != topiclimiter[CURRENT_SECOND])
|
||||
topiclimiter[CURRENT_SECOND] = second
|
||||
topiclimiter[SECOND_COUNT] = 0
|
||||
|
||||
topiclimiter[SECOND_COUNT] += 1
|
||||
if (topiclimiter[SECOND_COUNT] > stl)
|
||||
if(topiclimiter[SECOND_COUNT] > stl)
|
||||
to_chat(src, "<span class='danger'>Your previous action was ignored because you've done too many in a second</span>")
|
||||
return
|
||||
|
||||
//search the href for script injection
|
||||
if( findtext(href,"<script",1,0) )
|
||||
if(findtext(href, "<script", 1, 0))
|
||||
log_world("Attempted use of scripts within a topic call, by [src]")
|
||||
log_runtime(EXCEPTION("Attempted use of scripts within a topic call, by [src]"), src)
|
||||
stack_trace("Attempted use of scripts within a topic call, by [src]")
|
||||
message_admins("Attempted use of scripts within a topic call, by [src]")
|
||||
return
|
||||
|
||||
@@ -119,8 +119,6 @@
|
||||
cmd_admin_discord_pm()
|
||||
return
|
||||
|
||||
|
||||
|
||||
//Logs all hrefs
|
||||
if(GLOB.configuration.logging.href_logging)
|
||||
log_href("[src] (usr:[usr]\[[COORD(usr)]\]) : [hsrc ? "[hsrc] " : ""][href]")
|
||||
@@ -135,9 +133,11 @@
|
||||
ssd_warning_acknowledged = TRUE
|
||||
to_chat(src, "<span class='notice'>SSD warning acknowledged.</span>")
|
||||
return
|
||||
|
||||
if(href_list["link_forum_account"])
|
||||
link_forum_account()
|
||||
return // prevents a recursive loop where the ..() 5 lines after this makes the proc endlessly re-call itself
|
||||
|
||||
if(href_list["withdraw_consent"])
|
||||
var/choice = alert(usr, "Are you SURE you want to withdraw your consent to the Terms of Service?\nYou will be instantaneously removed from the server and will have to re-accept the Terms of Service.", "Warning", "Yes", "No")
|
||||
if(choice == "Yes")
|
||||
@@ -145,6 +145,7 @@
|
||||
var/datum/db_query/query = SSdbcore.NewQuery("REPLACE INTO privacy (ckey, datetime, consent) VALUES (:ckey, Now(), 0)", list(
|
||||
"ckey" = ckey
|
||||
))
|
||||
|
||||
if(!query.warn_execute())
|
||||
to_chat(usr, "Well, this is embarassing. We tried to save your ToS withdrawal but the DB failed. Please contact the server host")
|
||||
return
|
||||
@@ -153,6 +154,7 @@
|
||||
message_admins("[key_name_admin(usr)] was disconnected due to withdrawing their ToS consent.")
|
||||
to_chat(usr, "<span class='boldannounce'>Your ToS consent has been withdrawn. You have been kicked from the server</span>")
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
if(href_list["__keydown"])
|
||||
var/keycode = href_list["__keydown"]
|
||||
@@ -178,12 +180,6 @@
|
||||
var/fakekey = holder?.fakekey
|
||||
return fakekey ? fakekey : key
|
||||
|
||||
/client/proc/is_content_unlocked()
|
||||
if(!prefs.unlock_content)
|
||||
to_chat(src, "Become a BYOND member to access member-perks and features, as well as support the engine that makes this game possible. <a href='http://www.byond.com/membership'>Click here to find out more</a>.")
|
||||
return 0
|
||||
return 1
|
||||
|
||||
//Like for /atoms, but clients are their own snowflake FUCK
|
||||
/client/proc/setDir(newdir)
|
||||
dir = newdir
|
||||
@@ -195,25 +191,28 @@
|
||||
to_chat(src, "<span class='danger'>You are sending messages to quickly. Please wait [wait_time] [wait_time == 1 ? "second" : "seconds"] before sending another message.</span>")
|
||||
return 1
|
||||
last_message_time = world.time
|
||||
|
||||
if(GLOB.configuration.general.enable_auto_mute && !check_rights(R_ADMIN, 0) && last_message == message)
|
||||
last_message_count++
|
||||
if(last_message_count >= SPAM_TRIGGER_AUTOMUTE)
|
||||
to_chat(src, "<span class='danger'>You have exceeded the spam filter limit for identical messages. An auto-mute was applied.</span>")
|
||||
cmd_admin_mute(mob, mute_type, 1)
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
if(last_message_count >= SPAM_TRIGGER_WARNING)
|
||||
to_chat(src, "<span class='danger'>You are nearing the spam filter limit for identical messages.</span>")
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
else
|
||||
last_message = message
|
||||
last_message_count = 0
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
//This stops files larger than UPLOAD_LIMIT being sent from client to server via input(), client.Import() etc.
|
||||
/client/AllowUpload(filename, filelength)
|
||||
if(filelength > UPLOAD_LIMIT)
|
||||
to_chat(src, "<font color='red'>Error: AllowUpload(): File Upload too large. Upload Limit: [UPLOAD_LIMIT/1024]KiB.</font>")
|
||||
return 0
|
||||
return FALSE
|
||||
/* //Don't need this at the moment. But it's here if it's needed later.
|
||||
//Helps prevent multiple files being uploaded at once. Or right after eachother.
|
||||
var/time_to_wait = fileaccess_timer - world.time
|
||||
@@ -221,7 +220,7 @@
|
||||
to_chat(src, "<font color='red'>Error: AllowUpload(): Spam prevention. Please wait [round(time_to_wait/10)] seconds.</font>")
|
||||
return 0
|
||||
fileaccess_timer = world.time + FTPDELAY */
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
|
||||
///////////
|
||||
@@ -234,14 +233,18 @@
|
||||
|
||||
if(connection != "seeker") //Invalid connection type.
|
||||
return null
|
||||
|
||||
if(byond_version < MIN_CLIENT_VERSION) // Too out of date to play at all. Unfortunately, we can't send them a message here.
|
||||
version_blocked = TRUE
|
||||
|
||||
if(byond_build < GLOB.configuration.general.minimum_client_build)
|
||||
version_blocked = TRUE
|
||||
|
||||
var/show_update_prompt = FALSE
|
||||
|
||||
if(byond_version < SUGGESTED_CLIENT_VERSION) // Update is suggested, but not required.
|
||||
show_update_prompt = TRUE
|
||||
|
||||
else if(byond_version == SUGGESTED_CLIENT_VERSION && byond_build < SUGGESTED_CLIENT_BUILD)
|
||||
show_update_prompt = TRUE
|
||||
|
||||
@@ -282,6 +285,7 @@
|
||||
CLP.process_result(login_queries[CLP.type], src)
|
||||
|
||||
QDEL_LIST_ASSOC_VAL(login_queries) // Clear out the used queries
|
||||
|
||||
else
|
||||
// Set vars here that need to be set if the DB is offline
|
||||
|
||||
@@ -304,6 +308,7 @@
|
||||
// Log alts
|
||||
if(length(related_accounts_ip))
|
||||
log_admin("[key_name(src)] Alts by IP: [jointext(related_accounts_ip, " ")]")
|
||||
|
||||
if(length(related_accounts_cid))
|
||||
log_admin("[key_name(src)] Alts by CID: [jointext(related_accounts_cid, " ")]")
|
||||
|
||||
@@ -329,6 +334,7 @@
|
||||
deadmin()
|
||||
verbs += /client/proc/readmin
|
||||
GLOB.deadmins += ckey
|
||||
|
||||
else
|
||||
on_holder_add()
|
||||
add_admin_verbs()
|
||||
@@ -361,6 +367,7 @@
|
||||
|
||||
if(prefs.toggles & PREFTOGGLE_UI_DARKMODE) // activates dark mode if its flagged. -AA07
|
||||
activate_darkmode()
|
||||
|
||||
else
|
||||
// activate_darkmode() calls the CL update button proc, so we dont want it double called
|
||||
SSchangelog.UpdatePlayerChangelogButton(src)
|
||||
@@ -430,17 +437,21 @@
|
||||
announce_leave() // Do not put this below
|
||||
SSdebugview.stop_processing(src)
|
||||
SSchangelog.startup_clients_open -= src
|
||||
|
||||
if(holder)
|
||||
holder.owner = null
|
||||
GLOB.admins -= src
|
||||
|
||||
GLOB.directory -= ckey
|
||||
GLOB.clients -= src
|
||||
SSinstancing.update_playercache() // Clear us out
|
||||
QDEL_NULL(chatOutput)
|
||||
QDEL_NULL(pai_save)
|
||||
|
||||
if(movingmob)
|
||||
movingmob.client_mobs_in_contents -= mob
|
||||
UNSETEMPTY(movingmob.client_mobs_in_contents)
|
||||
|
||||
SSambience.ambience_listening_clients -= src
|
||||
SSinput.processing -= src
|
||||
Master.UpdateTickRate()
|
||||
@@ -563,6 +574,7 @@
|
||||
qdel(query_update)
|
||||
// After the regular update
|
||||
INVOKE_ASYNC(src, /client/.proc/get_byond_account_date, FALSE) // Async to avoid other procs in the client chain being delayed by a web request
|
||||
|
||||
else
|
||||
//New player!! Need to insert all the stuff
|
||||
var/datum/db_query/query_insert = SSdbcore.NewQuery("INSERT INTO player (id, ckey, firstseen, lastseen, ip, computerid, lastadminrank) VALUES (null, :ckey, Now(), Now(), :ip, :cid, :rank)", list(
|
||||
@@ -623,24 +635,29 @@
|
||||
/client/proc/check_forum_link()
|
||||
if(!GLOB.configuration.url.forum_link_url || !prefs || prefs.fuid)
|
||||
return
|
||||
|
||||
if(GLOB.configuration.jobs.enable_exp_tracking)
|
||||
var/living_hours = get_exp_type_num(EXP_TYPE_LIVING) / 60
|
||||
if(living_hours < 20)
|
||||
return
|
||||
|
||||
to_chat(src, "<B>You have no verified forum account. <a href='?src=[UID()];link_forum_account=true'>VERIFY FORUM ACCOUNT</a></B>")
|
||||
|
||||
/client/proc/create_oauth_token()
|
||||
var/datum/db_query/query_find_token = SSdbcore.NewQuery("SELECT token FROM oauth_tokens WHERE ckey=:ckey limit 1", list(
|
||||
"ckey" = ckey
|
||||
))
|
||||
|
||||
// These queries have log_error=FALSE to avoid auth tokens being in plaintext logs
|
||||
if(!query_find_token.warn_execute(log_error=FALSE))
|
||||
qdel(query_find_token)
|
||||
return
|
||||
|
||||
if(query_find_token.NextRow())
|
||||
var/tkn = query_find_token.item[1]
|
||||
qdel(query_find_token)
|
||||
return tkn
|
||||
|
||||
qdel(query_find_token)
|
||||
|
||||
var/tokenstr = md5("[rand(0,9999)][world.time][rand(0,9999)][ckey][rand(0,9999)][address][rand(0,9999)][computer_id][rand(0,9999)]")
|
||||
@@ -649,40 +666,49 @@
|
||||
"ckey" = ckey,
|
||||
"tokenstr" = tokenstr,
|
||||
))
|
||||
|
||||
// These queries have log_error=FALSE to avoid auth tokens being in plaintext logs
|
||||
if(!query_insert_token.warn_execute(log_error=FALSE))
|
||||
if(!query_insert_token.warn_execute(log_error = FALSE))
|
||||
qdel(query_insert_token)
|
||||
return
|
||||
|
||||
qdel(query_insert_token)
|
||||
return tokenstr
|
||||
|
||||
/client/proc/link_forum_account(fromban)
|
||||
if(!GLOB.configuration.url.forum_link_url)
|
||||
return
|
||||
|
||||
if(IsGuestKey(key))
|
||||
to_chat(src, "Guest keys cannot be linked.")
|
||||
return
|
||||
|
||||
if(prefs && prefs.fuid)
|
||||
if(!fromban)
|
||||
to_chat(src, "Your forum account is already set.")
|
||||
return
|
||||
|
||||
var/datum/db_query/query_find_link = SSdbcore.NewQuery("SELECT fuid FROM player WHERE ckey=:ckey LIMIT 1", list(
|
||||
"ckey" = ckey
|
||||
))
|
||||
|
||||
if(!query_find_link.warn_execute())
|
||||
qdel(query_find_link)
|
||||
return
|
||||
|
||||
if(query_find_link.NextRow())
|
||||
if(query_find_link.item[1])
|
||||
if(!fromban)
|
||||
to_chat(src, "Your forum account is already set. ([query_find_link.item[1]])")
|
||||
qdel(query_find_link)
|
||||
return
|
||||
|
||||
qdel(query_find_link)
|
||||
var/tokenid = create_oauth_token()
|
||||
if(!tokenid)
|
||||
to_chat(src, "link_forum_account: unable to create token")
|
||||
return
|
||||
|
||||
var/url = "[GLOB.configuration.url.forum_link_url][tokenid]"
|
||||
if(fromban)
|
||||
url += "&fwd=appeal"
|
||||
@@ -690,6 +716,7 @@
|
||||
to_chat(src, "<span class='boldannounce'>If you are screenshotting this screen for your ban appeal, please blur/draw over the token in the above link.</span>")
|
||||
else
|
||||
to_chat(src, {"Now opening a window to verify your information with the forums. If the window does not load, please go to: <a href="[url]">[url]</a>"})
|
||||
|
||||
src << link(url)
|
||||
return
|
||||
|
||||
@@ -701,11 +728,14 @@
|
||||
/client/proc/check_randomizer(topic)
|
||||
set waitfor = FALSE // Yes I know this is already called from an async proc but someone may change that without thinking properly
|
||||
. = FALSE
|
||||
|
||||
if(connection != "seeker") //Invalid connection type.
|
||||
return null
|
||||
|
||||
topic = params2list(topic)
|
||||
if(!GLOB.configuration.general.enabled_cid_randomiser_buster)
|
||||
return
|
||||
|
||||
// Stash o' ckeys
|
||||
var/static/cidcheck = list()
|
||||
var/static/tokens = list()
|
||||
@@ -719,6 +749,7 @@
|
||||
var/datum/db_query/query_cidcheck = SSdbcore.NewQuery("SELECT computerid FROM player WHERE ckey=:ckey", list(
|
||||
"ckey" = ckey
|
||||
))
|
||||
|
||||
if(!query_cidcheck.warn_execute())
|
||||
qdel(query_cidcheck)
|
||||
return
|
||||
@@ -726,6 +757,7 @@
|
||||
var/lastcid = computer_id
|
||||
if(query_cidcheck.NextRow())
|
||||
lastcid = query_cidcheck.item[1]
|
||||
|
||||
qdel(query_cidcheck)
|
||||
|
||||
if(computer_id != lastcid)
|
||||
@@ -741,9 +773,10 @@
|
||||
to_chat(src, "<pre class=\"system system\">you're a huge nerd. wakka wakka doodle doop nobody's ever gonna see this, the chat system shouldn't be online by this point</pre>")
|
||||
qdel(src)
|
||||
return TRUE
|
||||
|
||||
else
|
||||
if (!topic || !topic["token"] || !tokens[ckey] || topic["token"] != tokens[ckey])
|
||||
if (!cidcheck_spoofckeys[ckey])
|
||||
if(!topic || !topic["token"] || !tokens[ckey] || topic["token"] != tokens[ckey])
|
||||
if(!cidcheck_spoofckeys[ckey])
|
||||
message_admins("<span class='adminnotice'>[key_name(src)] appears to have attempted to spoof a cid randomizer check.</span>")
|
||||
cidcheck_spoofckeys[ckey] = TRUE
|
||||
cidcheck[ckey] = computer_id
|
||||
@@ -752,6 +785,7 @@
|
||||
sleep(10) //browse is queued, we don't want them to disconnect before getting the browse() command.
|
||||
qdel(src)
|
||||
return TRUE
|
||||
|
||||
// We DO have their cached CID handy - compare it, now
|
||||
if(oldcid != computer_id)
|
||||
// Change detected, they are randomizing
|
||||
@@ -770,6 +804,7 @@
|
||||
|
||||
qdel(src)
|
||||
return TRUE
|
||||
|
||||
else
|
||||
// don't shoot, I'm innocent
|
||||
if(cidcheck_failedckeys[ckey])
|
||||
@@ -777,7 +812,8 @@
|
||||
message_admins("<span class='adminnotice'>[key_name_admin(src)] has been allowed to connect after showing they removed their cid randomizer</span>")
|
||||
SSdiscord.send2discord_simple_noadmins("**\[Info]** [key_name(src)] has been allowed to connect after showing they removed their cid randomizer.")
|
||||
cidcheck_failedckeys -= ckey
|
||||
if (cidcheck_spoofckeys[ckey])
|
||||
|
||||
if(cidcheck_spoofckeys[ckey])
|
||||
message_admins("<span class='adminnotice'>[key_name_admin(src)] has been allowed to connect after appearing to have attempted to spoof a cid randomizer check because it <i>appears</i> they aren't spoofing one this time</span>")
|
||||
cidcheck_spoofckeys -= ckey
|
||||
cidcheck -= ckey
|
||||
@@ -790,33 +826,42 @@
|
||||
"ckey" = ckey,
|
||||
"adminckey" = adminckey
|
||||
))
|
||||
|
||||
if(!query_get_notes.warn_execute())
|
||||
qdel(query_get_notes)
|
||||
return
|
||||
|
||||
if(query_get_notes.NextRow())
|
||||
qdel(query_get_notes)
|
||||
return
|
||||
|
||||
qdel(query_get_notes)
|
||||
|
||||
// Only add a note if their most recent note isn't from the randomizer blocker, either
|
||||
var/datum/db_query/query_get_note = SSdbcore.NewQuery("SELECT adminckey FROM notes WHERE ckey=:ckey ORDER BY timestamp DESC LIMIT 1", list(
|
||||
"ckey" = ckey
|
||||
))
|
||||
|
||||
if(!query_get_note.warn_execute())
|
||||
qdel(query_get_note)
|
||||
return
|
||||
|
||||
if(query_get_note.NextRow())
|
||||
if(query_get_note.item[1] == adminckey)
|
||||
qdel(query_get_note)
|
||||
return
|
||||
|
||||
qdel(query_get_note)
|
||||
add_note(ckey, "Detected as using a cid randomizer.", null, adminckey, logged = 0)
|
||||
add_note(ckey, "Detected as using a cid randomizer.", null, adminckey, logged = FALSE)
|
||||
|
||||
/client/proc/cid_check_reconnect()
|
||||
var/token = md5("[rand(0,9999)][world.time][rand(0,9999)][ckey][rand(0,9999)][address][rand(0,9999)][computer_id][rand(0,9999)]")
|
||||
. = token
|
||||
|
||||
log_adminwarn("Failed Login: [key] [computer_id] [address] - CID randomizer check")
|
||||
|
||||
var/url = winget(src, null, "url")
|
||||
|
||||
//special javascript to make them reconnect under a new window.
|
||||
src << browse("<a id='link' href='byond://[url]?token=[token]'>\
|
||||
byond://[url]?token=[token]\
|
||||
@@ -826,12 +871,12 @@
|
||||
window.location=\"byond://winset?command=.quit\"\
|
||||
</script>",
|
||||
"border=0;titlebar=0;size=1x1")
|
||||
|
||||
to_chat(src, "<a href='byond://[url]?token=[token]'>You will be automatically taken to the game, if not, click here to be taken manually</a>. Except you can't, since the chat window doesn't exist yet.")
|
||||
|
||||
//checks if a client is afk
|
||||
//3000 frames = 5 minutes
|
||||
/client/proc/is_afk(duration=3000)
|
||||
if(inactivity > duration) return inactivity
|
||||
/client/proc/is_afk(duration = 5 MINUTES)
|
||||
if(inactivity > duration)
|
||||
return inactivity
|
||||
return 0
|
||||
|
||||
//Send resources to the client.
|
||||
@@ -839,13 +884,16 @@
|
||||
// Change the way they should download resources.
|
||||
if(length(GLOB.configuration.url.rsc_urls))
|
||||
preload_rsc = pick(GLOB.configuration.url.rsc_urls)
|
||||
|
||||
else
|
||||
preload_rsc = 1 // If config.resource_urls is not set, preload like normal.
|
||||
|
||||
// Most assets are now handled through global_cache.dm
|
||||
getFiles(
|
||||
'html/search.js', // Used in various non-TGUI HTML windows for search functionality
|
||||
'html/panels.css' // Used for styling certain panels, such as in the new player panel
|
||||
)
|
||||
|
||||
spawn (10) //removing this spawn causes all clients to not get verbs.
|
||||
//Precache the client with all other assets slowly, so as to not block other browse() calls
|
||||
getFilesSlow(src, SSassets.preload, register_asset = FALSE)
|
||||
@@ -855,8 +903,10 @@
|
||||
for(var/L in GLOB.all_languages)
|
||||
var/datum/language/lang = GLOB.all_languages[L]
|
||||
var/message = "[lang.name] : [lang.type]"
|
||||
|
||||
if(lang.flags & RESTRICTED)
|
||||
message += " (RESTRICTED)"
|
||||
|
||||
to_chat(world, "[message]")
|
||||
|
||||
/client/proc/colour_transition(list/colour_to = null, time = 10) //Call this with no parameters to reset to default.
|
||||
@@ -950,10 +1000,13 @@
|
||||
/client/proc/send_ssd_warning(mob/M)
|
||||
if(!GLOB.configuration.general.ssd_warning)
|
||||
return FALSE
|
||||
|
||||
if(ssd_warning_acknowledged)
|
||||
return FALSE
|
||||
if(M && M.player_logged < SSD_WARNING_TIMER)
|
||||
|
||||
if(M?.player_logged < SSD_WARNING_TIMER)
|
||||
return FALSE
|
||||
|
||||
to_chat(src, "Are you taking this person to cryo or giving them medical treatment? If you are, <a href='byond://?src=[UID()];ssdwarning=accepted'>confirm that</a> and proceed. Interacting with SSD players in other ways is against server rules unless you've ahelped first for permission.")
|
||||
return TRUE
|
||||
|
||||
@@ -1009,13 +1062,16 @@
|
||||
var/list/lines = splittext(http["CONTENT"], "\n")
|
||||
var/list/initial_data = list()
|
||||
var/current_index = ""
|
||||
|
||||
for(var/L in lines)
|
||||
if(L == "")
|
||||
continue
|
||||
|
||||
if(!findtext(L, "\t"))
|
||||
current_index = L
|
||||
initial_data[current_index] = list()
|
||||
continue
|
||||
|
||||
initial_data[current_index] += replacetext(replacetext(L, "\t", ""), "\"", "")
|
||||
|
||||
var/list/parsed_data = list()
|
||||
@@ -1032,12 +1088,15 @@
|
||||
|
||||
// Main return is here
|
||||
return parsed_data
|
||||
|
||||
catch
|
||||
log_debug("Error parsing byond.com data for [ckey]. Please inform maintainers.")
|
||||
return null
|
||||
|
||||
else
|
||||
log_debug("Error retrieving data from byond.com for [ckey]. Invalid status code (Expected: 200 | Got: [status]).")
|
||||
return null
|
||||
|
||||
else
|
||||
log_debug("Failed to retrieve data from byond.com for [ckey]. Connection failed.")
|
||||
return null
|
||||
@@ -1056,6 +1115,7 @@
|
||||
var/datum/db_query/query_date = SSdbcore.NewQuery("SELECT byond_date, DATEDIFF(Now(), byond_date) FROM player WHERE ckey=:ckey", list(
|
||||
"ckey" = ckey
|
||||
))
|
||||
|
||||
if(!query_date.warn_execute())
|
||||
qdel(query_date)
|
||||
return
|
||||
@@ -1083,21 +1143,25 @@
|
||||
"date" = byondacc_date,
|
||||
"ckey" = ckey
|
||||
))
|
||||
|
||||
if(!query_update.warn_execute())
|
||||
qdel(query_update)
|
||||
return
|
||||
|
||||
qdel(query_update)
|
||||
|
||||
// Now retrieve the age again because BYOND doesnt have native methods for this
|
||||
var/datum/db_query/query_age = SSdbcore.NewQuery("SELECT DATEDIFF(Now(), byond_date) FROM player WHERE ckey=:ckey", list(
|
||||
"ckey" = ckey
|
||||
))
|
||||
|
||||
if(!query_age.warn_execute())
|
||||
qdel(query_age)
|
||||
return
|
||||
|
||||
while(query_age.NextRow())
|
||||
byondacc_age = max(text2num(query_age.item[1]), 0) // Ensure account isnt negative days old
|
||||
|
||||
qdel(query_age)
|
||||
|
||||
// Notify admins on new clients connecting, if the byond account age is less than a config value
|
||||
@@ -1111,7 +1175,9 @@
|
||||
if(prefs.sound & SOUND_AMBIENCE)
|
||||
if(SSambience.ambience_listening_clients[src] > world.time)
|
||||
return // If already properly set we don't want to reset the timer.
|
||||
|
||||
SSambience.ambience_listening_clients[src] = world.time + 10 SECONDS //Just wait 10 seconds before the next one aight mate? cheers.
|
||||
|
||||
else
|
||||
SSambience.ambience_listening_clients -= src
|
||||
|
||||
@@ -1124,12 +1190,11 @@
|
||||
var/output = GLOB.join_tos
|
||||
output += "<hr><p>By withdrawing your consent, you acknowledge that you will be instantaneously kicked from the server and will have to re-accept the Terms of Service. If you do not wish to withdraw your consent at this moment, feel free to close this window.</p>"
|
||||
output += "<p><a href='byond://?src=[UID()];withdraw_consent=1'>Withdraw consent</a></p>"
|
||||
src << browse(output,"window=privacy_consent;size=600x500")
|
||||
|
||||
var/datum/browser/popup = new(src, "privacy_consent", "<div align='center'>Privacy Consent</div>", 500, 400)
|
||||
|
||||
popup.set_content(output)
|
||||
popup.open(FALSE)
|
||||
return
|
||||
|
||||
|
||||
#undef LIMITER_SIZE
|
||||
#undef CURRENT_SECOND
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
// Might as well scrub out any malformed be_special list entries while we're here
|
||||
for(var/role in be_special)
|
||||
if(!(role in GLOB.special_roles))
|
||||
log_runtime(EXCEPTION("[C.key] had a malformed role entry: '[role]'. Removing!"), src)
|
||||
stack_trace("[C.key] had a malformed role entry: '[role]'. Removing!")
|
||||
be_special -= role
|
||||
|
||||
// We're saving volume_mixer here as well, so no point in keeping the timer running
|
||||
|
||||
Reference in New Issue
Block a user