Updates some admin stuff (#15297)

* Fixes camera view

* Unique CID tracking notes

* Ban tracking

* Note round IDs

* Karma viewing

* Minor tweak

* Manual ban job bans

* More tweaks

* Farie tweaks

* Connection result field

* Orange watchlist names

* Autopopulate tickbox
This commit is contained in:
AffectedArc07
2021-01-16 21:38:45 +00:00
committed by GitHub
parent 787b2ad39a
commit adb9b58f8e
24 changed files with 462 additions and 49 deletions
+10 -3
View File
@@ -3,6 +3,8 @@
if(!key || !address || !computer_id)
log_adminwarn("Failed Login (invalid data): [key] [address]-[computer_id]")
// The nested ternaries are needed here
INVOKE_ASYNC(GLOBAL_PROC, .proc/log_connection, (ckey(key) || ""), (address || ""), (computer_id || ""), CONNECTION_TYPE_DROPPED_INVALID)
return list("reason"="invalid login data", "desc"="Error: Could not check ban status, please try again. Error message: Your computer provided invalid or blank information to the server on connection (BYOND Username, IP, and Computer ID). Provided information for reference: Username: '[key]' IP: '[address]' Computer ID: '[computer_id]'. If you continue to get this error, please restart byond or contact byond support.")
if(type == "world")
@@ -10,6 +12,7 @@
if(text2num(computer_id) == 2147483647) //this cid causes stickybans to go haywire
log_adminwarn("Failed Login (invalid cid): [key] [address]-[computer_id]")
INVOKE_ASYNC(GLOBAL_PROC, .proc/log_connection, ckey(key), address, computer_id, CONNECTION_TYPE_DROPPED_INVALID)
return list("reason"="invalid login data", "desc"="Error: Could not check ban status, Please try again. Error message: Your computer provided an invalid Computer ID.")
var/admin = 0
@@ -28,6 +31,7 @@
if(!GLOB.guests_allowed && IsGuestKey(key))
log_adminwarn("Failed Login: [key] [computer_id] [address] - Guests not allowed")
// message_admins("<span class='notice'>Failed Login: [key] - Guests not allowed</span>")
INVOKE_ASYNC(GLOBAL_PROC, .proc/log_connection, ckey(key), address, computer_id, CONNECTION_TYPE_DROPPED_BANNED)
return list("reason"="guest", "desc"="\nReason: Guests not allowed. Please sign in with a BYOND account.")
//check if the IP address is a known proxy/vpn, and the user is not whitelisted
@@ -36,6 +40,7 @@
var/mistakemessage = ""
if(config.banappeals)
mistakemessage = "\nIf you have to use one, request whitelisting at: [config.banappeals]"
INVOKE_ASYNC(GLOBAL_PROC, .proc/log_connection, ckey(key), address, computer_id, CONNECTION_TYPE_DROPPED_IPINTEL)
return list("reason"="using proxy or vpn", "desc"="\nReason: Proxies/VPNs are not allowed here. [mistakemessage]")
@@ -72,7 +77,7 @@
sql_query_params["cid"] = computer_id
var/datum/db_query/query = SSdbcore.NewQuery({"
SELECT ckey, ip, computerid, a_ckey, reason, expiration_time, duration, bantime, bantype FROM [format_table_name("ban")]
SELECT ckey, ip, computerid, a_ckey, reason, expiration_time, duration, bantime, bantype, ban_round_id FROM [format_table_name("ban")]
WHERE (ckey=:ckeytext [ipquery] [cidquery]) AND (bantype = 'PERMABAN' OR bantype = 'ADMIN_PERMABAN'
OR ((bantype = 'TEMPBAN' OR bantype = 'ADMIN_TEMPBAN') AND expiration_time > Now())) AND isnull(unbanned)"}, sql_query_params)
@@ -91,6 +96,7 @@
var/duration = query.item[7]
var/bantime = query.item[8]
var/bantype = query.item[9]
var/ban_round_id = query.item[10]
if(bantype == "ADMIN_PERMABAN" || bantype == "ADMIN_TEMPBAN")
//admin bans MUST match on ckey to prevent cid-spoofing attacks
// as well as dynamic ip abuse
@@ -114,11 +120,12 @@
appealmessage = " You may appeal it at <a href='[config.banappeals]'>[config.banappeals]</a>."
expires = " This ban does not expire automatically and must be appealed.[appealmessage]"
var/desc = "\nReason: You, or another user of this computer or connection ([pckey]) is banned from playing here. The ban reason is:\n[reason]\nThis ban was applied by [ackey] on [bantime].[expires]"
var/desc = "\nReason: You, or another user of this computer or connection ([pckey]) is banned from playing here. The ban reason is:\n[reason]\nThis ban was applied by [ackey] on [bantime][ban_round_id ? " (Round [ban_round_id])" : ""].[expires]"
. = list("reason"="[bantype]", "desc"="[desc]")
log_adminwarn("Failed Login: [key] [computer_id] [address] - Banned [.["reason"]]")
INVOKE_ASYNC(GLOBAL_PROC, .proc/log_connection, ckey(key), address, computer_id, CONNECTION_TYPE_DROPPED_BANNED)
qdel(query)
return .
qdel(query)
@@ -135,5 +142,5 @@
return null
else
log_adminwarn("Failed Login: [key] [computer_id] [address] - Banned [.["message"]]")
INVOKE_ASYNC(GLOBAL_PROC, .proc/log_connection, ckey(key), address, computer_id, CONNECTION_TYPE_DROPPED_BANNED)
return .
+1
View File
@@ -126,6 +126,7 @@ GLOBAL_VAR_INIT(nologevent, 0)
body += "<A href='?_src_=holder;jobban2=[M.UID()];dbbanaddckey=[M.ckey]'>Jobban</A> | "
body += "<A href='?_src_=holder;appearanceban=[M.UID()];dbbanaddckey=[M.ckey]'>Appearance Ban</A> | "
body += "<A href='?_src_=holder;shownoteckey=[M.ckey]'>Notes</A> | "
body += "<A href='?_src_=holder;viewkarma=[M.ckey]'>View Karma</A> | "
if(config.forum_playerinfo_url)
body += "<A href='?_src_=holder;webtools=[M.ckey]'>WebInfo</A> | "
if(M.client)
+13
View File
@@ -42,6 +42,19 @@ GLOBAL_DATUM_INIT(jobban_regex, /regex, regex("(\[\\S]+) - (\[^#]+\[^# ])(?: ##
else
return 0
/proc/jobban_isbanned_ckey(ckey, rank)
if(!ckey || !rank)
return null
if(config.guest_jobban && guest_jobbans(rank))
if(IsGuestKey(ckey))
return "Guest Job-ban"
if(GLOB.jobban_assoclist[ckey])
return GLOB.jobban_assoclist[ckey][rank]
return null
/proc/jobban_loadbanfile()
if(config.ban_legacy_system)
var/savefile/S=new("data/job_full.ban")
+113
View File
@@ -0,0 +1,113 @@
//////////////////////////////////////////////////////////////////////////////////////
// This file houses all the code for cookie datum serialization and deserialization
//
// If you are going to modify ANYTHING in here, please test it THOROUGHLY
// The serialization and deserialization here is so complicated that you WILL break something here
// PLEASE test things properly if you modify this file. -aa07
//
//////////////////////////////////////////////////////////////////////////////////////
// Everything in this file is intentionally NOT autodocumented. PLEASE keep it that way.
// All these defines are integral to the workings and mesh together with the database.
// DO NOT EDIT THESE UNDER ANY CIRCUMSTANCES EVER
#define COOKIERECORD_FIRST_INFRACTION "First cookie match: "
#define COOKIERECORD_LAST_INFRACTION "Last cookie match: "
#define COOKIERECORD_TOTAL_INFRACTIONS "Total cookie matches: "
#define COOKIERECORD_MATCHED_CKEYS "Matched ckeys: "
#define COOKIERECORD_MATCHED_IPS "Matched IPs: "
#define COOKIERECORD_MATCHED_CIDS "Matched CIDS: "
#define COOKIERECORD_PSUEDO_CKEY "ALICE-COOKIE_RECORD"
/datum/cookie_record
var/cookie_holder_ckey
var/first_infraction_date
var/last_infraction_date
var/infraction_count
var/list/matched_ckeys = list()
var/list/matched_ips = list()
var/list/matched_cids = list()
// Some of these params can be null, others CAN NOT
/datum/cookie_record/New(holder_ckey, matched_ckey, matched_ip, matched_cid)
// Right off the bat
cookie_holder_ckey = holder_ckey
var/has_note = FALSE
var/raw_text = ""
// Now lets see if we have a note logging the infraction in the past
var/datum/db_query/check_existing_note = SSdbcore.NewQuery("SELECT notetext FROM [format_table_name("notes")] WHERE ckey=:ckey AND adminckey=:ackey", list(
"ckey" = cookie_holder_ckey,
"ackey" = COOKIERECORD_PSUEDO_CKEY
))
if(!check_existing_note.warn_execute())
qdel(check_existing_note)
return
if(check_existing_note.NextRow())
has_note = TRUE
raw_text = check_existing_note.item[1]
qdel(check_existing_note)
if(has_note)
deserialize_and_load(raw_text)
infraction_count++
else
// Sane defaults
first_infraction_date = SQLtime()
infraction_count = 1
last_infraction_date = SQLtime()
matched_ckeys |= matched_ckey
matched_ips |= matched_ip
matched_cids |= matched_cid
serialize_and_save(has_note)
/*
Expected output below. These are parsed from raw_text by splitting by <br>
[1] COOKIERECORD_FIRST_INFRACTION
[2] COOKIERECORD_LAST_INFRACTION
[3] COOKIERECORD_TOTAL_INFRACTIONS
[4] COOKIERECORD_MATCHED_CKEYS
[5] COOKIERECORD_MATCHED_IPS
[6] COOKIERECORD_MATCHED_CIDS
*/
/datum/cookie_record/proc/deserialize_and_load(raw_text)
var/list/lines = splittext(raw_text, "<br>")
// Text
first_infraction_date = splittext(lines[1], COOKIERECORD_FIRST_INFRACTION)[2]
last_infraction_date = splittext(lines[2], COOKIERECORD_LAST_INFRACTION)[2]
// Number
infraction_count = text2num(splittext(lines[3], COOKIERECORD_TOTAL_INFRACTIONS)[2]) // Make sure its a number
// Lists
matched_ckeys = splittext(splittext(lines[4], COOKIERECORD_MATCHED_CKEYS)[2], ",")
matched_ips = splittext(splittext(lines[5], COOKIERECORD_MATCHED_IPS)[2], ",")
matched_cids = splittext(splittext(lines[6], COOKIERECORD_MATCHED_CIDS)[2], ",")
/datum/cookie_record/proc/serialize_and_save(has_note)
var/serialized_text
var/list/serialized_list = list()
serialized_list.len = 6 // Make it 6 off the bat
serialized_list[1] = "[COOKIERECORD_FIRST_INFRACTION][first_infraction_date]"
serialized_list[2] = "[COOKIERECORD_LAST_INFRACTION][last_infraction_date]"
serialized_list[3] = "[COOKIERECORD_TOTAL_INFRACTIONS][infraction_count]"
serialized_list[4] = "[COOKIERECORD_MATCHED_CKEYS][matched_ckeys.Join(",")]"
serialized_list[5] = "[COOKIERECORD_MATCHED_IPS][matched_ips.Join(",")]"
serialized_list[6] = "[COOKIERECORD_MATCHED_CIDS][matched_cids.Join(",")]"
serialized_text = serialized_list.Join("<br>")
if(has_note) // They have a note. Update.
var/datum/db_query/update_existing_note = SSdbcore.NewQuery("UPDATE [format_table_name("notes")] SET notetext=:nt, timestamp=NOW(), round_id=:rid WHERE ckey=:ckey AND adminckey=:ackey", list(
"nt" = serialized_text,
"rid" = GLOB.round_id,
"ckey" = cookie_holder_ckey,
"ackey" = COOKIERECORD_PSUEDO_CKEY
))
if(!update_existing_note.warn_execute())
qdel(update_existing_note)
return
qdel(update_existing_note)
else // They dont have a note. Insert.
add_note(cookie_holder_ckey, serialized_text, adminckey = COOKIERECORD_PSUEDO_CKEY, logged = FALSE, checkrights = FALSE, automated = TRUE)
+12 -7
View File
@@ -146,8 +146,8 @@
qdel(adm_query)
var/datum/db_query/query_insert = SSdbcore.NewQuery({"
INSERT INTO [format_table_name("ban")] (`id`,`bantime`,`serverip`,`bantype`,`reason`,`job`,`duration`,`rounds`,`expiration_time`,`ckey`,`computerid`,`ip`,`a_ckey`,`a_computerid`,`a_ip`,`who`,`adminwho`,`edits`,`unbanned`,`unbanned_datetime`,`unbanned_ckey`,`unbanned_computerid`,`unbanned_ip`)
VALUES (null, Now(), :serverip, :bantype_str, :reason, :job, :duration, :rounds, Now() + INTERVAL :duration MINUTE, :ckey, :computerid, :ip, :a_ckey, :a_computerid, :a_ip, :who, :adminwho, '', null, null, null, null, null)
INSERT INTO [format_table_name("ban")] (`id`,`bantime`,`serverip`,`bantype`,`reason`,`job`,`duration`,`rounds`,`expiration_time`,`ckey`,`computerid`,`ip`,`a_ckey`,`a_computerid`,`a_ip`,`who`,`adminwho`,`edits`,`unbanned`,`unbanned_datetime`,`unbanned_ckey`,`unbanned_computerid`,`unbanned_ip`,`ban_round_id`,`unbanned_round_id`)
VALUES (null, Now(), :serverip, :bantype_str, :reason, :job, :duration, :rounds, Now() + INTERVAL :duration MINUTE, :ckey, :computerid, :ip, :a_ckey, :a_computerid, :a_ip, :who, :adminwho, '', null, null, null, null, null, :roundid, null)
"}, list(
// Get ready for parameters
"serverip" = serverip,
@@ -163,7 +163,8 @@
"a_computerid" = a_computerid,
"a_ip" = a_ip,
"who" = who,
"adminwho" = adminwho
"adminwho" = adminwho,
"roundid" = GLOB.round_id
))
if(!query_insert.warn_execute())
qdel(query_insert)
@@ -399,10 +400,11 @@
var/unban_computerid = src.owner:computer_id
var/unban_ip = src.owner:address
var/datum/db_query/query_update = SSdbcore.NewQuery("UPDATE [format_table_name("ban")] SET unbanned = 1, unbanned_datetime = Now(), unbanned_ckey=:unban_ckey, unbanned_computerid=:unban_computerid, unbanned_ip=:unban_ip WHERE id=:id", list(
var/datum/db_query/query_update = SSdbcore.NewQuery("UPDATE [format_table_name("ban")] SET unbanned = 1, unbanned_datetime = Now(), unbanned_ckey=:unban_ckey, unbanned_computerid=:unban_computerid, unbanned_ip=:unban_ip, unbanned_round_id=:roundid WHERE id=:id", list(
"unban_ckey" = unban_ckey,
"unban_computerid" = unban_computerid,
"unban_ip" = unban_ip,
"roundid" = GLOB.round_id,
"id" = id
))
if(!query_update.warn_execute())
@@ -477,6 +479,7 @@
output += "<option value='[j]'>[j]</option>"
output += "</select></td></tr></table>"
output += "<b>Reason:<br></b><textarea name='dbbanreason' cols='50'></textarea><br>"
output += "<input type='checkbox' value='1' name='autopopulate' checked='1'>&nbsp;Auto populate CID & IP for online players<br>"
output += "<input type='submit' value='Add ban'>"
output += "</form>"
@@ -582,7 +585,7 @@
var/datum/db_query/select_query = SSdbcore.NewQuery({"
SELECT id, bantime, bantype, reason, job, duration, expiration_time, ckey, a_ckey, unbanned, unbanned_ckey, unbanned_datetime, edits, ip, computerid
SELECT id, bantime, bantype, reason, job, duration, expiration_time, ckey, a_ckey, unbanned, unbanned_ckey, unbanned_datetime, edits, ip, computerid, ban_round_id, unbanned_round_id
FROM [format_table_name("ban")] WHERE 1 [playersearch] [adminsearch] [ipsearch] [cidsearch] [bantypesearch] ORDER BY bantime DESC LIMIT 100"}, sql_params)
if(!select_query.warn_execute())
@@ -605,6 +608,8 @@
var/edits = select_query.item[13]
var/ip = select_query.item[14]
var/cid = select_query.item[15]
var/ban_round_id = select_query.item[16]
var/unban_round_id = select_query.item[17]
var/lcolor = blcolor
var/dcolor = bdcolor
@@ -632,7 +637,7 @@
output += "<tr bgcolor='[dcolor]'>"
output += "<td align='center'>[typedesc]</td>"
output += "<td align='center'><b>[ckey]</b></td>"
output += "<td align='center'>[bantime]</td>"
output += "<td align='center'>[bantime][ban_round_id ? " (Round [ban_round_id])" : ""]</td>"
output += "<td align='center'><b>[ackey]</b></td>"
output += "<td align='center'>[(unbanned) ? "" : "<b><a href=\"byond://?src=[UID()];dbbanedit=unban;dbbanid=[banid]\">Unban</a></b>"]</td>"
output += "</tr>"
@@ -652,7 +657,7 @@
output += "</tr>"
if(unbanned)
output += "<tr bgcolor='[dcolor]'>"
output += "<td align='center' colspan='5' bgcolor=''><b>UNBANNED by admin [unbanckey] on [unbantime]</b></td>"
output += "<td align='center' colspan='5' bgcolor=''><b>UNBANNED by admin [unbanckey] on [unbantime][unban_round_id ? " (Round [unban_round_id])" : ""]</b></td>"
output += "</tr>"
output += "<tr>"
output += "<td colspan='5' bgcolor='white'>&nbsp</td>"
+21 -9
View File
@@ -1,5 +1,5 @@
// Do not attemtp to remove the blank string from the server arg. It will break DB saving.
/proc/add_note(target_ckey, notetext, timestamp, adminckey, logged = 1, server = "", checkrights = 1)
/proc/add_note(target_ckey, notetext, timestamp, adminckey, logged = 1, server = "", checkrights = 1, show_after = TRUE, automated = FALSE)
if(checkrights && !check_rights(R_ADMIN|R_MOD))
return
if(!SSdbcore.IsConnected())
@@ -57,15 +57,20 @@
if(config && config.server_name)
server = config.server_name
// Force cast this to 1/0 incase someone tries to feed bad data
automated = !!automated
var/datum/db_query/query_noteadd = SSdbcore.NewQuery({"
INSERT INTO [format_table_name("notes")] (ckey, timestamp, notetext, adminckey, server, crew_playtime)
VALUES (:targetckey, NOW(), :notetext, :adminkey, :server, :crewnum)
INSERT INTO [format_table_name("notes")] (ckey, timestamp, notetext, adminckey, server, crew_playtime, round_id, automated)
VALUES (:targetckey, NOW(), :notetext, :adminkey, :server, :crewnum, :roundid, :automated)
"}, list(
"targetckey" = target_ckey,
"notetext" = notetext,
"adminkey" = adminckey,
"server" = server,
"crewnum" = crew_number
"crewnum" = crew_number,
"roundid" = GLOB.round_id,
"automated" = automated
))
if(!query_noteadd.warn_execute())
qdel(query_noteadd)
@@ -74,7 +79,8 @@
if(logged)
log_admin("[usr ? key_name(usr) : adminckey] has added a note to [target_ckey]: [notetext]")
message_admins("[usr ? key_name_admin(usr) : adminckey] has added a note to [target_ckey]:<br>[notetext]")
show_note(target_ckey)
if(show_after)
show_note(target_ckey)
/proc/remove_note(note_id)
if(!check_rights(R_ADMIN|R_MOD))
@@ -124,7 +130,7 @@
return
note_id = text2num(note_id)
var/target_ckey
var/datum/db_query/query_find_note_edit = SSdbcore.NewQuery("SELECT ckey, notetext, adminckey FROM [format_table_name("notes")] WHERE id=:note_id", list(
var/datum/db_query/query_find_note_edit = SSdbcore.NewQuery("SELECT ckey, notetext, adminckey, automated FROM [format_table_name("notes")] WHERE id=:note_id", list(
"note_id" = note_id
))
if(!query_find_note_edit.warn_execute())
@@ -134,6 +140,10 @@
target_ckey = query_find_note_edit.item[1]
var/old_note = query_find_note_edit.item[2]
var/adminckey = query_find_note_edit.item[3]
var/automated = query_find_note_edit.item[4]
if(automated)
to_chat(usr, "<span class='notice'>That note is generated automatically. You can't edit it.</span>")
return
var/new_note = input("Input new note", "New Note", "[old_note]") as message|null
if(!new_note)
return
@@ -171,7 +181,7 @@
if(target_ckey)
var/target_sql_ckey = ckey(target_ckey)
var/datum/db_query/query_get_notes = SSdbcore.NewQuery({"
SELECT id, timestamp, notetext, adminckey, last_editor, server, crew_playtime
SELECT id, timestamp, notetext, adminckey, last_editor, server, crew_playtime, round_id, automated
FROM [format_table_name("notes")] WHERE ckey=:targetkey ORDER BY timestamp"}, list(
"targetkey" = target_sql_ckey
))
@@ -190,14 +200,16 @@
var/last_editor = query_get_notes.item[5]
var/server = query_get_notes.item[6]
var/mins = text2num(query_get_notes.item[7])
output += "<b>[timestamp] | [server] | [adminckey]"
var/round_id = text2num(query_get_notes.item[8])
var/automated = text2num(query_get_notes.item[9]) // 0/1 bool stored in table
output += "<b>[timestamp][round_id ? " (Round [round_id])" : ""] | [server] | [adminckey]"
if(mins)
var/playstring = get_exp_format(mins)
output += " | [playstring] as Crew"
output += "</b>"
if(!linkless)
output += " <a href='?_src_=holder;removenote=[id]'>\[Remove Note\]</a> <a href='?_src_=holder;editnote=[id]'>\[Edit Note\]</a>"
output += " <a href='?_src_=holder;removenote=[id]'>\[Remove Note\]</a> [automated ? "\[Automated Note\]" : "<a href='?_src_=holder;editnote=[id]'>\[Edit Note\]</a>"]"
if(last_editor)
output += " <font size='2'>Last edit by [last_editor] <a href='?_src_=holder;noteedits=[id]'>(Click here to see edit log)</a></font>"
output += "<br>[notetext]<hr style='background:#000000; border:0; height:1px'>"
+127 -6
View File
@@ -108,6 +108,10 @@
var/banjob = href_list["dbbanaddjob"]
var/banreason = href_list["dbbanreason"]
var/job_ban = FALSE
var/multi_job = FALSE
var/list/jobs_to_ban = list()
banckey = ckey(banckey)
switch(bantype)
@@ -127,10 +131,12 @@
to_chat(usr, "<span class='warning'>Not enough parameters (Requires ckey, reason and job)</span>")
return
banduration = null
job_ban = TRUE
if(BANTYPE_JOB_TEMP)
if(!banckey || !banreason || !banjob || !banduration)
to_chat(usr, "<span class='warning'>Not enough parameters (Requires ckey, reason and job)</span>")
return
job_ban = TRUE
if(BANTYPE_APPEARANCE)
if(!banckey || !banreason)
to_chat(usr, "<span class='warning'>Not enough parameters (Requires ckey and reason)</span>")
@@ -151,11 +157,11 @@
var/mob/playermob
for(var/mob/M in GLOB.player_list)
if(M.ckey == banckey)
playermob = M
break
if("autopopulate" in href_list)
for(var/mob/M in GLOB.player_list)
if(M.ckey == banckey)
playermob = M
break
banreason = "(MANUAL BAN) "+banreason
@@ -167,7 +173,68 @@
else
message_admins("Ban process: A mob matching [playermob.ckey] was found at location [playermob.x], [playermob.y], [playermob.z]. Custom IP and computer id fields replaced with the IP and computer id from the located mob")
DB_ban_record(bantype, playermob, banduration, banreason, banjob, null, banckey, banip, bancid )
if(job_ban)
if(banjob in list("commanddept","securitydept","engineeringdept","medicaldept","sciencedept","supportdept","nonhumandept"))
multi_job = TRUE
switch(banjob)
if("commanddept")
for(var/jobPos in GLOB.command_positions)
if(!jobPos) continue
var/datum/job/temp = SSjobs.GetJob(jobPos)
if(!temp) continue
jobs_to_ban += temp.title
if("securitydept")
for(var/jobPos in GLOB.security_positions)
if(!jobPos) continue
var/datum/job/temp = SSjobs.GetJob(jobPos)
if(!temp) continue
jobs_to_ban += temp.title
if("engineeringdept")
for(var/jobPos in GLOB.engineering_positions)
if(!jobPos) continue
var/datum/job/temp = SSjobs.GetJob(jobPos)
if(!temp) continue
jobs_to_ban += temp.title
if("medicaldept")
for(var/jobPos in GLOB.medical_positions)
if(!jobPos) continue
var/datum/job/temp = SSjobs.GetJob(jobPos)
if(!temp) continue
jobs_to_ban += temp.title
if("sciencedept")
for(var/jobPos in GLOB.science_positions)
if(!jobPos) continue
var/datum/job/temp = SSjobs.GetJob(jobPos)
if(!temp) continue
jobs_to_ban += temp.title
if("supportdept")
for(var/jobPos in GLOB.support_positions)
if(!jobPos) continue
var/datum/job/temp = SSjobs.GetJob(jobPos)
if(!temp) continue
jobs_to_ban += temp.title
if("nonhumandept")
jobs_to_ban += "pAI"
for(var/jobPos in GLOB.nonhuman_positions)
if(!jobPos) continue
var/datum/job/temp = SSjobs.GetJob(jobPos)
if(!temp) continue
jobs_to_ban += temp.title
// If the job ban is for multiple jobs in one group (IE: Command), iterate through jobs and ban each individually
if(multi_job)
//Create a list of unbanned jobs within joblist
var/list/notbannedlist = list()
for(var/job in jobs_to_ban)
if(!jobban_isbanned_ckey(banckey, job))
notbannedlist += job
for(var/job in notbannedlist)
DB_ban_record(bantype, playermob, banduration, banreason, job, null, banckey, banip, bancid)
// Otherwise, do it normally
else
DB_ban_record(bantype, playermob, banduration, banreason, banjob, null, banckey, banip, bancid)
else if(href_list["editrights"])
@@ -3423,7 +3490,61 @@
log_sql("[usr.key] | [response]")
else if(answer == "no")
log_sql("[usr.key] | Reported no server hang. Please investigate")
else if(href_list["suppresscidwarning"])
if(!check_rights(R_ADMIN))
return
add_note(href_list["suppresscidwarning"], CIDWARNING_SUPPRESSED_NOTETEXT, show_after = FALSE)
else if(href_list["viewkarma"])
if(!check_rights(R_ADMIN))
return
var/target_ckey = href_list["viewkarma"]
var/total_karma = 0
var/spent_karma = 0
var/unlocked_jobs = ""
var/unlocked_species = ""
// Get their totals
var/datum/db_query/query_get_totals = SSdbcore.NewQuery("SELECT karma, karmaspent FROM [format_table_name("karmatotals")] WHERE byondkey=:ckey", list(
"ckey" = target_ckey
))
if(!query_get_totals.warn_execute())
qdel(query_get_totals)
return
// Even if there aint a row, we can still assume the defaults of 0 above
if(query_get_totals.NextRow())
total_karma = query_get_totals.item[1]
spent_karma = query_get_totals.item[2]
qdel(query_get_totals)
// Now get their unlocks
var/datum/db_query/query_get_unlocks = SSdbcore.NewQuery("SELECT job, species FROM [format_table_name("whitelist")] WHERE ckey=:ckey", list(
"ckey" = target_ckey
))
if(!query_get_unlocks.warn_execute())
qdel(query_get_unlocks)
return
if(query_get_unlocks.NextRow())
unlocked_jobs = query_get_unlocks.item[1]
unlocked_species = query_get_unlocks.item[2]
qdel(query_get_unlocks)
// Pack it into a dat
var/dat = {"
<ul>
<li>Total Karma: [total_karma]</li>
<li>Spent Karma: [spent_karma]</li>
<li>Available Karma: [total_karma - spent_karma]</li>
<li>Unlocked Jobs: [unlocked_jobs]</li>
<li>Unlocked Species: [unlocked_species]</li>
</ul>
"}
var/datum/browser/popup = new(usr, "view_karma", "Karma stats for [target_ckey]", 600, 300)
popup.set_content(dat)
popup.open(FALSE)
/client/proc/create_eventmob_for(var/mob/living/carbon/human/H, var/killthem = 0)
if(!check_rights(R_EVENT))
+7 -12
View File
@@ -22,15 +22,6 @@
GLOBAL_VAR_INIT(camera_range_display_status, 0)
GLOBAL_VAR_INIT(intercom_range_display_status, 0)
/obj/effect/debugging/camera_range
icon = 'icons/480x480.dmi'
icon_state = "25percent"
/obj/effect/debugging/camera_range/New()
. = ..()
src.pixel_x = -224
src.pixel_y = -224
/obj/effect/debugging/mapfix_marker
name = "map fix marker"
icon = 'icons/mob/screen_gen.dmi'
@@ -56,12 +47,16 @@ GLOBAL_VAR_INIT(intercom_range_display_status, 0)
else
GLOB.camera_range_display_status = 1
for(var/obj/effect/debugging/camera_range/C in world)
qdel(C)
for(var/obj/effect/debugging/marker/M in world)
qdel(M)
if(GLOB.camera_range_display_status)
for(var/obj/machinery/camera/C in GLOB.cameranet.cameras)
new/obj/effect/debugging/camera_range(C.loc)
for(var/turf/T in orange(7, C))
var/obj/effect/debugging/marker/F = new/obj/effect/debugging/marker(T)
if(!(F in view(7, C.loc)))
qdel(F)
SSblackbox.record_feedback("tally", "admin_verb", 1, "Camera Range Display") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/sec_camera_report()
+6
View File
@@ -41,6 +41,9 @@
return
log_admin("[key_name(usr)] has added [target_ckey] to the watchlist - Reason: [reason]")
message_admins("[key_name_admin(usr)] has added [target_ckey] to the watchlist - Reason: [reason]", 1)
if(GLOB.directory[target_ckey])
var/client/C = GLOB.directory[target_ckey]
C.watchlisted = TRUE // Mark them ingame now
if(browse)
watchlist_show(target_ckey)
@@ -56,6 +59,9 @@
qdel(query_watchdel)
log_admin("[key_name(usr)] has removed [target_ckey] from the watchlist")
message_admins("[key_name_admin(usr)] has removed [target_ckey] from the watchlist", 1)
if(GLOB.directory[target_ckey])
var/client/C = GLOB.directory[target_ckey]
C.watchlisted = FALSE // Mark them ingame now
if(browse)
watchlist_show()