diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index bc3def4bc5..78c5ceba85 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -826,3 +826,7 @@ var/global/BSACooldown = 0 "Admin login: [key_name(src)]") if(string) message_admins("[string]") + + +/datum/admins/SDQL_update() + return FALSE //No. \ No newline at end of file diff --git a/code/modules/admin/admin_ranks.dm b/code/modules/admin/admin_ranks.dm index 5b4f92335c..ac24f3bde2 100644 --- a/code/modules/admin/admin_ranks.dm +++ b/code/modules/admin/admin_ranks.dm @@ -6,6 +6,9 @@ var/list/admin_ranks = list() //list of all admin_rank datums var/list/adds var/list/subs +/datum/admin_rank/SDQL_update() + return FALSE //Nice try trivialadmin! + /datum/admin_rank/New(init_name, init_rights, list/init_adds, list/init_subs) name = init_name switch(name) diff --git a/code/modules/admin/sql_message_system.dm b/code/modules/admin/sql_message_system.dm index 0a11abba05..037f69d281 100644 --- a/code/modules/admin/sql_message_system.dm +++ b/code/modules/admin/sql_message_system.dm @@ -154,7 +154,7 @@ message_admins("[key_name_admin(usr)] has toggled [target_ckey]'s [type] made by [admin_ckey] to [secret ? "not secret" : "secret"]") browse_messages(target_ckey = target_ckey) -/proc/browse_messages(type, target_ckey, index, linkless = 0) +/proc/browse_messages(type, target_ckey, index, linkless = 0, filter) if(!dbcon.IsConnected()) usr << "Failed to establish database connection." return @@ -176,7 +176,11 @@ output += "\[Add memo\]" else if(type == "watchlist entry") output += "

Watchlist entries

" - output += "\[Add watchlist entry\]" + output += "\[Add watchlist entry\]" + if(filter) + output += "|\[Unfilter clients\]" + else + output += "|\[Filter offline clients\]" output += ruler var/DBQuery/query_get_type_messages = dbcon.NewQuery("SELECT id, targetckey, adminckey, text, timestamp, server, lasteditor FROM [format_table_name("messages")] WHERE type = '[type]'") if(!query_get_type_messages.Execute()) @@ -186,6 +190,8 @@ while(query_get_type_messages.NextRow()) var/id = query_get_type_messages.item[1] var/t_ckey = query_get_type_messages.item[2] + if(type == "watchlist entry" && filter && !(t_ckey in directory)) + continue var/admin_ckey = query_get_type_messages.item[3] var/text = query_get_type_messages.item[4] var/timestamp = query_get_type_messages.item[5] @@ -229,13 +235,20 @@ data += " \[Delete\]" if(type == "note") data += " [secret ? "\[Secret\]" : "\[Not secret\]"]" - data += " \[Edit\]" + if(type == "message sent") + data += " Message has been sent" + if(editor_ckey) + data += "|" + else + data += " \[Edit\]" if(editor_ckey) data += " Last edit by [editor_ckey] (Click here to see edit log)" data += "
[text]
" switch(type) if("message") messagedata += data + if("message sent") + messagedata += data if("watchlist entry") watchdata += data if("note") @@ -303,7 +316,7 @@ proc/get_message_output(type, target_ckey) log_game("SQL ERROR obtaining id, adminckey, text, timestamp, lasteditor from messages table. Error : \[[err]\]\n") return while(query_get_message_output.NextRow()) - var/id = query_get_message_output.item[1] + var/message_id = query_get_message_output.item[1] var/admin_ckey = query_get_message_output.item[2] var/text = query_get_message_output.item[3] var/timestamp = query_get_message_output.item[4] @@ -311,15 +324,19 @@ proc/get_message_output(type, target_ckey) switch(type) if("message") output += "Admin message left by [admin_ckey] on [timestamp]" - output += "
[text]" - delete_message(id, 0) + output += "
[text]
" + var/DBQuery/query_message_read = dbcon.NewQuery("UPDATE [format_table_name("messages")] SET type = 'message sent' WHERE id = [message_id]") + if(!query_message_read.Execute()) + var/err = query_message_read.ErrorMsg() + log_game("SQL ERROR updating message type. Error : \[[err]\]\n") + return if("watchlist entry") message_admins("Notice: [key_name_admin(target_ckey)] is on the watchlist and has just connected - Reason: [text]") send2admindiscord("Watchlist", "[key_name(target_ckey)] is on the watchlist and has just connected - Reason: [text]") if("memo") output += "Memo by [admin_ckey] on [timestamp]" if(editor_ckey) - output += "
Last edit by [editor_ckey] (Click here to see edit log)" + output += "
Last edit by [editor_ckey] (Click here to see edit log)" output += "
[text]

" return output @@ -368,4 +385,4 @@ this proc can take several minutes to execute fully if converting and cause DD t world << "Deleting NOTESFILE" fdel(NOTESFILE) world << "Finished mass note conversion, remember to turn off AUTOCONVERT_NOTES"*/ -#undef NOTESFILE \ No newline at end of file +#undef NOTESFILE diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 00f7dd2e7e..200ec20df6 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -1131,6 +1131,9 @@ else if(href_list["showwatch"]) browse_messages("watchlist entry") + else if(href_list["showwatchfilter"]) + browse_messages("watchlist entry", filter = 1) + else if(href_list["showmessageckey"]) var/target = href_list["showmessageckey"] browse_messages(target_ckey = target) @@ -1744,12 +1747,42 @@ H << "Your prayers have been answered!! You received the best cookie!" H << 'sound/effects/pray_chaplain.ogg' + else if(href_list["adminsmite"]) + if(!check_rights(R_ADMIN|R_FUN)) + return + + var/mob/living/carbon/human/H = locate(href_list["adminsmite"]) in mob_list + if(!H || !istype(H)) + return + + var/list/punishment_list = list(ADMIN_PUNISHMENT_LIGHTNING, ADMIN_PUNISHMENT_BRAINDAMAGE, ADMIN_PUNISHMENT_GIB) + + var/punishment = input("Choose a punishment", "DIVINE SMITING") as null|anything in punishment_list + + if(QDELETED(H) || !punishment) + return + + switch(punishment) + if(ADMIN_PUNISHMENT_LIGHTNING) + var/turf/T = get_step(get_step(H, NORTH), NORTH) + T.Beam(H, icon_state="lightning[rand(1,12)]", time = 5) + H.adjustFireLoss(75) + H.electrocution_animation(40) + H << "The gods have punished you for your sins!" + if(ADMIN_PUNISHMENT_BRAINDAMAGE) + H.adjustBrainLoss(75) + if(ADMIN_PUNISHMENT_GIB) + H.gib(FALSE) + + message_admins("[key_name_admin(usr)] punished [key_name_admin(H)] with [punishment].") + log_admin("[key_name(usr)] punished [key_name(H)] with [punishment].") + else if(href_list["BlueSpaceArtillery"]) - var/mob/living/M = locate(href_list["BlueSpaceArtillery"]) + var/mob/living/M = locate(href_list["BlueSpaceArtillery"]) in mob_list usr.client.bluespace_artillery(M) else if(href_list["CentcommReply"]) - var/mob/living/carbon/human/H = locate(href_list["CentcommReply"]) + var/mob/living/carbon/human/H = locate(href_list["CentcommReply"]) in mob_list if(!istype(H)) usr << "This can only be used on instances of type /mob/living/carbon/human" return diff --git a/code/modules/admin/verbs/SDQL2/SDQL_2.dm b/code/modules/admin/verbs/SDQL2/SDQL_2.dm index aaead53f54..5d935439a8 100644 --- a/code/modules/admin/verbs/SDQL2/SDQL_2.dm +++ b/code/modules/admin/verbs/SDQL2/SDQL_2.dm @@ -18,11 +18,22 @@ */ +/datum/proc/SDQL_update(const/var_name, new_value) + vars[var_name] = new_value + return TRUE + /client/proc/SDQL2_query(query_text as message) set category = "Debug" if(!check_rights(R_DEBUG)) //Shouldn't happen... but just to be safe. message_admins("ERROR: Non-admin [key_name(usr, usr.client)] attempted to execute a SDQL query!") log_admin("Non-admin [usr.ckey]([usr]) attempted to execute a SDQL query!") + return FALSE + + var/query_log = "executed SDQL query: \"[query_text]\"." + message_admins("[key_name_admin(usr)] [query_log]") + query_log = "[usr.ckey]([usr]) [query_log]" + log_game(query_log) + NOTICE(query_log) if(!query_text || length(query_text) < 1) return @@ -39,119 +50,122 @@ if(!querys || querys.len < 1) return + try - var/query_log = "executed SDQL query: \"[query_text]\"." - message_admins("[key_name_admin(usr)] [query_log]") - query_log = "[usr.ckey]([usr]) [query_log]" - log_game(query_log) - NOTICE(query_log) + for(var/list/query_tree in querys) + var/list/from_objs = list() + var/list/select_types = list() - - for(var/list/query_tree in querys) - var/list/from_objs = list() - var/list/select_types = list() - - switch(query_tree[1]) - if("explain") - SDQL_testout(query_tree["explain"]) - return - - if("call") - if("on" in query_tree) - select_types = query_tree["on"] - else + switch(query_tree[1]) + if("explain") + SDQL_testout(query_tree["explain"]) return - if("select", "delete", "update") - select_types = query_tree[query_tree[1]] + if("call") + if("on" in query_tree) + select_types = query_tree["on"] + else + return - from_objs = SDQL_from_objs(query_tree["from"]) + if("select", "delete", "update") + select_types = query_tree[query_tree[1]] - var/list/objs = list() + from_objs = SDQL_from_objs(query_tree["from"]) - for(var/type in select_types) - var/char = copytext(type, 1, 2) + var/list/objs = list() - if(char == "/" || char == "*") - for(var/from in from_objs) - objs += SDQL_get_all(type, from) - CHECK_TICK + for(var/type in select_types) + var/char = copytext(type, 1, 2) - else if(char == "'" || char == "\"") - objs += locate(copytext(type, 2, length(type))) - - if("where" in query_tree) - var/objs_temp = objs - objs = list() - for(var/datum/d in objs_temp) - if(SDQL_expression(d, query_tree["where"])) - objs += d - CHECK_TICK - - switch(query_tree[1]) - if("call") - var/list/call_list = query_tree["call"] - var/list/args_list = query_tree["args"] - - for(var/datum/d in objs) - for(var/v in call_list) - SDQL_callproc(d, v, args_list) + if(char == "/" || char == "*") + for(var/from in from_objs) + objs += SDQL_get_all(type, from) CHECK_TICK - if("delete") - for(var/datum/d in objs) - qdel(d) + else if(char == "'" || char == "\"") + objs += locate(copytext(type, 2, length(type))) + + if("where" in query_tree) + var/objs_temp = objs + objs = list() + for(var/datum/d in objs_temp) + if(SDQL_expression(d, query_tree["where"])) + objs += d CHECK_TICK - if("select") - var/text = "" - for(var/datum/t in objs) - text += "\ref[t]" - if(istype(t, /atom)) - var/atom/a = t + switch(query_tree[1]) + if("call") + var/list/call_list = query_tree["call"] + var/list/args_list = query_tree["args"] - if(a.x) - text += ": [t] at ([a.x], [a.y], [a.z])
" + for(var/datum/d in objs) + var/list/new_args = list() + for(var/a in args_list) + new_args += SDQL_expression(d,a) + for(var/v in call_list) + if(copytext(v,1,8) == "global.") + v = "/proc/[copytext(v,8)]" + SDQL_callproc_global(v,new_args) + else + SDQL_callproc(d, v, new_args) + CHECK_TICK - else if(a.loc && a.loc.x) - text += ": [t] in [a.loc] at ([a.loc.x], [a.loc.y], [a.loc.z])
" + if("delete") + for(var/datum/d in objs) + qdel(d) + CHECK_TICK + + if("select") + var/text = "" + for(var/datum/t in objs) + text += "\ref[t]" + if(istype(t, /atom)) + var/atom/a = t + + if(a.x) + text += ": [t] at ([a.x], [a.y], [a.z])
" + + else if(a.loc && a.loc.x) + text += ": [t] in [a.loc] at ([a.loc.x], [a.loc.y], [a.loc.z])
" + + else + text += ": [t]
" else text += ": [t]
" - - else - text += ": [t]
" - CHECK_TICK - - usr << browse(text, "window=SDQL-result") - - if("update") - if("set" in query_tree) - var/list/set_list = query_tree["set"] - for(var/datum/d in objs) - var/list/vals = list() - for(var/v in set_list) - if(v in d.vars) - vals += v - vals[v] = SDQL_expression(d, set_list[v]) - - if(isturf(d)) - for(var/v in vals) - if(v == "x" || v == "y" || v == "z") - continue - - d.vars[v] = vals[v] - - else - for(var/v in vals) - d.vars[v] = vals[v] CHECK_TICK + usr << browse(text, "window=SDQL-result") + if("update") + if("set" in query_tree) + var/list/set_list = query_tree["set"] + for(var/datum/d in objs) + for(var/list/sets in set_list) + var/datum/temp = d + var/i = 0 + for(var/v in sets) + if(++i == sets.len) + temp.SDQL_update(v, SDQL_expression(d, set_list[sets])) + break + if(temp.vars.Find(v) && (istype(temp.vars[v], /datum))) + temp = temp.vars[v] + else + break + CHECK_TICK + catch(var/exception/e) + usr << "A runtime error has occured in your SDQL2-query." + usr << "\[NAME\][e.name]" + usr << "\[FILE\][e.file]" + usr << "\[LINE\][e.line]" + +/proc/SDQL_callproc_global(procname,args_list) + set waitfor = FALSE + call(procname)(arglist(args_list)) /proc/SDQL_callproc(thing, procname, args_list) - set waitfor = 0 + set waitfor = FALSE if(hascall(thing, procname)) call(thing, procname)(arglist(args_list)) @@ -248,7 +262,7 @@ type = text2path(type) var/typecache = typecacheof(type) - + if(ispath(type, /mob)) for(var/mob/d in location) if(typecache[d.type]) @@ -382,6 +396,12 @@ else if(copytext(expression[i], 1, 2) in list("'", "\"")) val = copytext(expression[i], 2, length(expression[i])) + else if(expression[i] == "\[") + var/list/expressions_list = expression[++i] + var/list/val2 = list() + for(var/list/expression_list in expressions_list) + val2[++val2.len] = SDQL_expression(object, expression_list) + val = val2 else val = SDQL_var(object, expression, i) i = expression.len @@ -389,22 +409,40 @@ return list("val" = val, "i" = i) /proc/SDQL_var(datum/object, list/expression, start = 1) - + var/v if(expression[start] in object.vars) - - if(start < expression.len && expression[start + 1] == ".") - return SDQL_var(object.vars[expression[start]], expression[start + 2]) - - else - return object.vars[expression[start]] - + v = object.vars[expression[start]] + else if(expression[start] == "{" && start < expression.len) + if(lowertext(copytext(expression[start + 1], 1, 3)) != "0x") + usr << "Invalid pointer syntax: [expression[start + 1]]" + return null + v = locate("\[[expression[start + 1]]]") + if(!v) + usr << "Invalid pointer: [expression[start + 1]]" + return null + start++ else - return null + switch(expression[start]) + if("usr") + v = usr + if("src") + v = object + if("marked") + if(usr.client && usr.client.holder && usr.client.holder.marked_datum) + v = usr.client.holder.marked_datum + else + return null + else + return null + if(start < expression.len && expression[start + 1] == ".") + return SDQL_var(v, expression[start + 2]) + else + return v /proc/SDQL2_tokenize(query_text) var/list/whitespace = list(" ", "\n", "\t") - var/list/single = list("(", ")", ",", "+", "-", ".", ";") + var/list/single = list("(", ")", ",", "+", "-", ".", ";", "{", "}", "\[", "]") var/list/multi = list( "=" = list("", "="), "<" = list("", "=", ">"), diff --git a/code/modules/admin/verbs/SDQL2/SDQL_2_parser.dm b/code/modules/admin/verbs/SDQL2/SDQL_2_parser.dm index 3dbe45235a..591e824312 100644 --- a/code/modules/admin/verbs/SDQL2/SDQL_2_parser.dm +++ b/code/modules/admin/verbs/SDQL2/SDQL_2_parser.dm @@ -57,13 +57,9 @@ var/list/binary_operators = list("+", "-", "/", "*", "&", "|", "^") var/list/comparitors = list("=", "==", "!=", "<>", "<", "<=", ">", ">=") - - /datum/SDQL_parser/New(query_list) query = query_list - - /datum/SDQL_parser/proc/parse_error(error_message) error = 1 usr << "SQDL2 Parsing Error: [error_message]" @@ -96,448 +92,354 @@ return lowertext(token(i)) - -/datum/SDQL_parser/proc - //query: select_query | delete_query | update_query - query(i, list/node) - query_type = tokenl(i) - - switch(query_type) - if("select") - select_query(i, node) - - if("delete") - delete_query(i, node) - - if("update") - update_query(i, node) - - if("call") - call_query(i, node) - - if("explain") - node += "explain" - node["explain"] = list() - query(i + 1, node["explain"]) +/datum/SDQL_parser/proc/query(i, list/node) + query_type = tokenl(i) + switch(query_type) + if("select") + select_query(i, node) + if("delete") + delete_query(i, node) + if("update") + update_query(i, node) + if("call") + call_query(i, node) + if("explain") + node += "explain" + node["explain"] = list() + query(i + 1, node["explain"]) // select_query: 'SELECT' select_list [('FROM' | 'IN') from_list] ['WHERE' bool_expression] - select_query(i, list/node) - var/list/select = list() - i = select_list(i + 1, select) - - node += "select" - node["select"] = select - - var/list/from = list() - if(tokenl(i) in list("from", "in")) - i = from_list(i + 1, from) - else - from += "world" - - node += "from" - node["from"] = from - - if(tokenl(i) == "where") - var/list/where = list() - i = bool_expression(i + 1, where) - - node += "where" - node["where"] = where - - return i - +/datum/SDQL_parser/proc/select_query(i, list/node) + var/list/select = list() + i = select_list(i + 1, select) + node += "select" + node["select"] = select + var/list/from = list() + if(tokenl(i) in list("from", "in")) + i = from_list(i + 1, from) + else + from += "world" + node += "from" + node["from"] = from + if(tokenl(i) == "where") + var/list/where = list() + i = bool_expression(i + 1, where) + node += "where" + node["where"] = where + return i //delete_query: 'DELETE' select_list [('FROM' | 'IN') from_list] ['WHERE' bool_expression] - delete_query(i, list/node) - var/list/select = list() - i = select_list(i + 1, select) - - node += "delete" - node["delete"] = select - - var/list/from = list() - if(tokenl(i) in list("from", "in")) - i = from_list(i + 1, from) - else - from += "world" - - node += "from" - node["from"] = from - - if(tokenl(i) == "where") - var/list/where = list() - i = bool_expression(i + 1, where) - - node += "where" - node["where"] = where - - return i - +/datum/SDQL_parser/proc/delete_query(i, list/node) + var/list/select = list() + i = select_list(i + 1, select) + node += "delete" + node["delete"] = select + var/list/from = list() + if(tokenl(i) in list("from", "in")) + i = from_list(i + 1, from) + else + from += "world" + node += "from" + node["from"] = from + if(tokenl(i) == "where") + var/list/where = list() + i = bool_expression(i + 1, where) + node += "where" + node["where"] = where + return i //update_query: 'UPDATE' select_list [('FROM' | 'IN') from_list] 'SET' assignments ['WHERE' bool_expression] - update_query(i, list/node) - var/list/select = list() - i = select_list(i + 1, select) - - node += "update" - node["update"] = select - - var/list/from = list() - if(tokenl(i) in list("from", "in")) - i = from_list(i + 1, from) - else - from += "world" - - node += "from" - node["from"] = from - - if(tokenl(i) != "set") - i = parse_error("UPDATE has misplaced SET") - - var/list/set_assignments = list() - i = assignments(i + 1, set_assignments) - - node += "set" - node["set"] = set_assignments - - if(tokenl(i) == "where") - var/list/where = list() - i = bool_expression(i + 1, where) - - node += "where" - node["where"] = where - - return i - +/datum/SDQL_parser/proc/update_query(i, list/node) + var/list/select = list() + i = select_list(i + 1, select) + node += "update" + node["update"] = select + var/list/from = list() + if(tokenl(i) in list("from", "in")) + i = from_list(i + 1, from) + else + from += "world" + node += "from" + node["from"] = from + if(tokenl(i) != "set") + i = parse_error("UPDATE has misplaced SET") + var/list/set_assignments = list() + i = assignments(i + 1, set_assignments) + node += "set" + node["set"] = set_assignments + if(tokenl(i) == "where") + var/list/where = list() + i = bool_expression(i + 1, where) + node += "where" + node["where"] = where + return i //call_query: 'CALL' call_function ['ON' select_list [('FROM' | 'IN') from_list] ['WHERE' bool_expression]] - call_query(i, list/node) - var/list/func = list() - var/list/arguments = list() - i = call_function(i + 1, func, arguments) - - node += "call" - node["call"] = func - node["args"] = arguments - - if(tokenl(i) != "on") - return i - - var/list/select = list() - i = select_list(i + 1, select) - - node += "on" - node["on"] = select - - var/list/from = list() - if(tokenl(i) in list("from", "in")) - i = from_list(i + 1, from) - else - from += "world" - - node += "from" - node["from"] = from - - if(tokenl(i) == "where") - var/list/where = list() - i = bool_expression(i + 1, where) - - node += "where" - node["where"] = where - +/datum/SDQL_parser/proc/call_query(i, list/node) + var/list/func = list() + var/list/arguments = list() + i = call_function(i + 1, func, arguments) + node += "call" + node["call"] = func + node["args"] = arguments + if(tokenl(i) != "on") return i - + var/list/select = list() + i = select_list(i + 1, select) + node += "on" + node["on"] = select + var/list/from = list() + if(tokenl(i) in list("from", "in")) + i = from_list(i + 1, from) + else + from += "world" + node += "from" + node["from"] = from + if(tokenl(i) == "where") + var/list/where = list() + i = bool_expression(i + 1, where) + node += "where" + node["where"] = where + return i //select_list: select_item [',' select_list] - select_list(i, list/node) - i = select_item(i, node) - - if(token(i) == ",") - i = select_list(i + 1, node) - - return i - +/datum/SDQL_parser/proc/select_list(i, list/node) + i = select_item(i, node) + if(token(i) == ",") + i = select_list(i + 1, node) + return i //from_list: from_item [',' from_list] - from_list(i, list/node) - i = from_item(i, node) - - if(token(i) == ",") - i = from_list(i + 1, node) - - return i - +/datum/SDQL_parser/proc/from_list(i, list/node) + i = from_item(i, node) + if(token(i) == ",") + i = from_list(i + 1, node) + return i //assignments: assignment, [',' assignments] - assignments(i, list/node) - i = assignment(i, node) - - if(token(i) == ",") - i = assignments(i + 1, node) - - return i - +/datum/SDQL_parser/proc/assignments(i, list/node) + i = assignment(i, node) + if(token(i) == ",") + i = assignments(i + 1, node) + return i //select_item: '*' | select_function | object_type - select_item(i, list/node) - - if(token(i) == "*") - node += "*" - i++ - - else if(tokenl(i) in select_functions) - i = select_function(i, node) - - else - i = object_type(i, node) - - return i - +/datum/SDQL_parser/proc/select_item(i, list/node) + if(token(i) == "*") + node += "*" + i++ + else if(tokenl(i) in select_functions) + i = select_function(i, node) + else + i = object_type(i, node) + return i //from_item: 'world' | object_type - from_item(i, list/node) - - if(token(i) == "world") - node += "world" - i++ - - else - i = object_type(i, node) - - return i - +/datum/SDQL_parser/proc/from_item(i, list/node) + if(token(i) == "world") + node += "world" + i++ + else + i = object_type(i, node) + return i //bool_expression: expression [bool_operator bool_expression] - bool_expression(i, list/node) - - var/list/bool = list() - i = expression(i, bool) - - node[++node.len] = bool - - if(tokenl(i) in boolean_operators) - i = bool_operator(i, node) - i = bool_expression(i, node) - - return i - +/datum/SDQL_parser/proc/bool_expression(i, list/node) + var/list/bool = list() + i = expression(i, bool) + node[++node.len] = bool + if(tokenl(i) in boolean_operators) + i = bool_operator(i, node) + i = bool_expression(i, node) + return i //assignment: '=' expression - assignment(i, list/node) - - node += token(i) - - if(token(i + 1) == "=") - var/varname = token(i) - node[varname] = list() - - i = expression(i + 2, node[varname]) - - else - parse_error("Assignment expected, but no = found") - - return i - +/datum/SDQL_parser/proc/assignment(var/i, var/list/node, var/list/assignment_list = list()) + assignment_list += token(i) + if(token(i + 1) == ".") + i = assignment(i + 2, node, assignment_list) + else if(token(i + 1) == "=") + var/exp_list = list() + node[assignment_list] = exp_list + i = expression(i + 2, exp_list) + else + parse_error("Assignment expected, but no = found") + return i //variable: | '.' variable - variable(i, list/node) - var/list/L = list(token(i)) - node[++node.len] = L - - if(token(i + 1) == ".") - L += "." - i = variable(i + 2, L) - - else - i++ - - return i +/datum/SDQL_parser/proc/variable(i, list/node) + var/list/L = list(token(i)) + node[++node.len] = L + if(token(i) == "{") + L += token(i+1) + i += 2 + if(token(i) != "}") + parse_error("Missing } at end of pointer.") + if(token(i + 1) == ".") + L += "." + i = variable(i + 2, L) + else + i++ + return i +//array: '[' expression, expression, ... ']' +/datum/SDQL_parser/proc/array(i, list/node) + if(copytext(token(i), 1, 2) != "\[") + parse_error("Expected an array but found '[token(i)]'") + return i + 1 + node += token(i) + var/list/expression_list = list() + if(token(i + 1) != "]") + var/list/temp_expression_list = list() + do + i = expression(i + 1, temp_expression_list) + if(token(i) == ",") + expression_list[++expression_list.len] = temp_expression_list + temp_expression_list = list() + while(token(i) && token(i) != "]") + expression_list[++expression_list.len] = temp_expression_list + else + i++ + node[++node.len] = expression_list + return i + 1 //object_type: | string - object_type(i, list/node) - - if(copytext(token(i), 1, 2) == "/") - node += token(i) - - else - i = string(i, node) - - return i + 1 - +/datum/SDQL_parser/proc/object_type(i, list/node) + if(copytext(token(i), 1, 2) == "/") + node += token(i) + else + i = string(i, node) + return i + 1 //comparitor: '=' | '==' | '!=' | '<>' | '<' | '<=' | '>' | '>=' - comparitor(i, list/node) - - if(token(i) in list("=", "==", "!=", "<>", "<", "<=", ">", ">=")) - node += token(i) - - else - parse_error("Unknown comparitor [token(i)]") - - return i + 1 - +/datum/SDQL_parser/proc/comparitor(i, list/node) + if(token(i) in list("=", "==", "!=", "<>", "<", "<=", ">", ">=")) + node += token(i) + else + parse_error("Unknown comparitor [token(i)]") + return i + 1 //bool_operator: 'AND' | '&&' | 'OR' | '||' - bool_operator(i, list/node) - - if(tokenl(i) in list("and", "or", "&&", "||")) - node += token(i) - - else - parse_error("Unknown comparitor [token(i)]") - - return i + 1 - +/datum/SDQL_parser/proc/bool_operator(i, list/node) + if(tokenl(i) in list("and", "or", "&&", "||")) + node += token(i) + else + parse_error("Unknown comparitor [token(i)]") + return i + 1 //string: ''' ''' | '"' '"' - string(i, list/node) - - if(copytext(token(i), 1, 2) in list("'", "\"")) - node += copytext(token(i),2,-1) - - else - parse_error("Expected string but found '[token(i)]'") - - return i + 1 - +/datum/SDQL_parser/proc/string(i, list/node) + if(copytext(token(i), 1, 2) in list("'", "\"")) + node += copytext(token(i),2,-1) + else + parse_error("Expected string but found '[token(i)]'") + return i + 1 //call_function: ['(' [arguments] ')'] - call_function(i, list/node, list/arguments) - if(length(tokenl(i))) - node += token(i++) - if(token(i) != "(") - parse_error("Expected ( but found '[token(i)]'") - else if(token(i + 1) != ")") - do - i = expression(i + 1, arguments) - if(token(i) == ",") - continue - while(token(i) && token(i) != ")") - else - i++ +/datum/SDQL_parser/proc/call_function(i, list/node, list/arguments) + if(length(tokenl(i))) + var/procname = "" + if(token(i) == "global" && token(i+1) == ".") + i += 2 + procname = "global." + node += procname + token(i++) + if(token(i) != "(") + parse_error("Expected ( but found '[token(i)]'") + else if(token(i + 1) != ")") + var/list/expression_list_temp = list() + do + i = expression(i + 1, expression_list_temp) + if(token(i) == ",") + arguments[++arguments.len] = expression_list_temp + expression_list_temp = list() + continue + while(token(i) && token(i) != ")") + arguments[++arguments.len] = expression_list_temp else - parse_error("Expected a function but found nothing") - return i + 1 - + i++ + else + parse_error("Expected a function but found nothing") + return i + 1 //select_function: count_function - select_function(i, list/node) - - parse_error("Sorry, function calls aren't available yet") - - return i - +/datum/SDQL_parser/proc/select_function(i, list/node) + parse_error("Sorry, function calls aren't available yet") + return i //expression: ( unary_expression | '(' expression ')' | value ) [binary_operator expression] - expression(i, list/node) - - if(token(i) in unary_operators) - i = unary_expression(i, node) - - else if(token(i) == "(") - var/list/expr = list() - - i = expression(i + 1, expr) - - if(token(i) != ")") - parse_error("Missing ) at end of expression.") - - else - i++ - - node[++node.len] = expr - +/datum/SDQL_parser/proc/expression(i, list/node) + if(token(i) in unary_operators) + i = unary_expression(i, node) + else if(token(i) == "(") + var/list/expr = list() + i = expression(i + 1, expr) + if(token(i) != ")") + parse_error("Missing ) at end of expression.") else - i = value(i, node) - - if(token(i) in binary_operators) - i = binary_operator(i, node) - i = expression(i, node) - - else if(token(i) in comparitors) - i = binary_operator(i, node) - - var/list/rhs = list() - i = expression(i, rhs) - - node[++node.len] = rhs - - - return i - + i++ + node[++node.len] = expr + else + i = value(i, node) + if(token(i) in binary_operators) + i = binary_operator(i, node) + i = expression(i, node) + else if(token(i) in comparitors) + i = binary_operator(i, node) + var/list/rhs = list() + i = expression(i, rhs) + node[++node.len] = rhs + return i //unary_expression: unary_operator ( unary_expression | value | '(' expression ')' ) - unary_expression(i, list/node) - +/datum/SDQL_parser/proc/unary_expression(i, list/node) + if(token(i) in unary_operators) + var/list/unary_exp = list() + unary_exp += token(i) + i++ if(token(i) in unary_operators) - var/list/unary_exp = list() - - unary_exp += token(i) - i++ - - if(token(i) in unary_operators) - i = unary_expression(i, unary_exp) - - else if(token(i) == "(") - var/list/expr = list() - - i = expression(i + 1, expr) - - if(token(i) != ")") - parse_error("Missing ) at end of expression.") - - else - i++ - - unary_exp[++unary_exp.len] = expr - + i = unary_expression(i, unary_exp) + else if(token(i) == "(") + var/list/expr = list() + i = expression(i + 1, expr) + if(token(i) != ")") + parse_error("Missing ) at end of expression.") else - i = value(i, unary_exp) - - node[++node.len] = unary_exp - - + i++ + unary_exp[++unary_exp.len] = expr else - parse_error("Expected unary operator but found '[token(i)]'") - - return i - + i = value(i, unary_exp) + node[++node.len] = unary_exp + else + parse_error("Expected unary operator but found '[token(i)]'") + return i //binary_operator: comparitor | '+' | '-' | '/' | '*' | '&' | '|' | '^' - binary_operator(i, list/node) - - if(token(i) in (binary_operators + comparitors)) - node += token(i) - - else - parse_error("Unknown binary operator [token(i)]") - - return i + 1 - +/datum/SDQL_parser/proc/binary_operator(i, list/node) + if(token(i) in (binary_operators + comparitors)) + node += token(i) + else + parse_error("Unknown binary operator [token(i)]") + return i + 1 //value: variable | string | number | 'null' - value(i, list/node) +/datum/SDQL_parser/proc/value(i, list/node) + if(token(i) == "null") + node += "null" + i++ + else if(lowertext(copytext(token(i),1,3)) == "0x" && isnum(hex2num(copytext(token(i),3)))) + node += hex2num(copytext(token(i),3)) + i++ + else if(isnum(text2num(token(i)))) + node += text2num(token(i)) + i++ + else if(copytext(token(i), 1, 2) in list("'", "\"")) + i = string(i, node) + else if(copytext(token(i), 1, 2) == "\[") // Start a list. + i = array(i, node) + else + i = variable(i, node) + return i - if(token(i) == "null") - node += "null" - i++ - - else if(isnum(text2num(token(i)))) - node += text2num(token(i)) - i++ - - else if(copytext(token(i), 1, 2) in list("'", "\"")) - i = string(i, node) - - else - i = variable(i, node) - - return i - - - - -/*EXPLAIN SELECT * WHERE 42 = 6 * 9 OR val = - 5 == 7*/ \ No newline at end of file +/*EXPLAIN SELECT * WHERE 42 = 6 * 9 OR val = - 5 == 7*/ diff --git a/code/modules/admin/verbs/SDQL2/SDQL_2_wrappers.dm b/code/modules/admin/verbs/SDQL2/SDQL_2_wrappers.dm new file mode 100644 index 0000000000..286e3a890f --- /dev/null +++ b/code/modules/admin/verbs/SDQL2/SDQL_2_wrappers.dm @@ -0,0 +1,174 @@ +// Wrappers for BYOND default procs which can't directly be called by call(). + +/proc/_abs(A) + return abs(A) + +/*/proc/_animate(atom/A, set_vars, time = 10, loop = 1, easing = LINEAR_EASING, flags = null) + animate(A, set_vars, time, loop, easing, flags) + Borked. If anyone wants to fix this be my guest.*/ + +/proc/_acrccos(A) + return arccos(A) + +/proc/_arcsin(A) + return arcsin(A) + +/proc/_ascii2text(A) + return ascii2text(A) + +/proc/_block(Start, End) + return block(Start, End) + +/proc/_ckey(Key) + return ckey(Key) + +/proc/_ckeyEx(Key) + return ckeyEx(Key) + +/proc/_copytext(T, Start = 1, End = 0) + return copytext(T, Start, End) + +/proc/_cos(X) + return cos(X) + +/proc/_get_dir(Loc1, Loc2) + return get_dir(Loc1, Loc2) + +/proc/_get_dist(Loc1, Loc2) + return get_dist(Loc1, Loc2) + +/proc/_get_step(Ref, Dir) + return get_step(Ref, Dir) + +/proc/_hearers(Depth = world.view, Center = usr) + return hearers(Depth, Center) + +/proc/_image(icon, loc, icon_state, layer, dir) + return image(icon, loc, icon_state, layer, dir) + +/proc/_length(E) + return length(E) + +/proc/_link(thing, url) + thing << link(url) + +/proc/_locate(X, Y, Z) + if (isnull(Y)) // Assuming that it's only a single-argument call. + return locate(X) + + return locate(X, Y, Z) + +/proc/_log(X, Y) + return log(X, Y) + +/proc/_lowertext(T) + return lowertext(T) + +/proc/_matrix(a, b, c, d, e, f) + return matrix(a, b, c, d, e, f) + +/proc/_max(...) + return max(arglist(args)) + +/proc/_md5(T) + return md5(T) + +/proc/_min(...) + return min(arglist(args)) + +/proc/_new(type, arguments) + return new type (arglist(arguments)) + +/proc/_num2text(N, SigFig = 6) + return num2text(N, SigFig) + +/proc/_ohearers(Dist, Center = usr) + return ohearers(Dist, Center) + +/proc/_orange(Dist, Center = usr) + return orange(Dist, Center) + +/proc/_output(thing, msg, control) + thing << output(msg, control) + +/proc/_oview(Dist, Center = usr) + return oview(Dist, Center) + +/proc/_oviewers(Dist, Center = usr) + return oviewers(Dist, Center) + +/proc/_params2list(Params) + return params2list(Params) + +/proc/_pick(...) + return pick(arglist(args)) + +/proc/_prob(P) + return prob(P) + +/proc/_rand(L = 0, H = 1) + return rand(L, H) + +/proc/_range(Dist, Center = usr) + return range(Dist, Center) + +/proc/_regex(pattern, flags) + return regex(pattern, flags) + +/proc/_REGEX_QUOTE(text) + return REGEX_QUOTE(text) + +/proc/_REGEX_QUOTE_REPLACEMENT(text) + return REGEX_QUOTE_REPLACEMENT(text) + +/proc/_replacetext(Haystack, Needle, Replacement, Start = 1,End = 0) + return replacetext(Haystack, Needle, Replacement, Start, End) + +/proc/_replacetextEx(Haystack, Needle, Replacement, Start = 1,End = 0) + return replacetextEx(Haystack, Needle, Replacement, Start, End) + +/proc/_rgb(R, G, B) + return rgb(R, G, B) + +/proc/_rgba(R, G, B, A) + return rgb(R, G, B, A) + +/proc/_roll(dice) + return roll(dice) + +/proc/_round(A, B = 1) + return round(A, B) + +/proc/_sin(X) + return sin(X) + +/proc/_step(Ref, Dir, Speed = 0) + return step(Ref, Dir, Speed) + +/proc/_list_add(list/L, ...) + if (args.len < 2) + return + L += args.Copy(2) + +/proc/_list_copy(list/L, Start = 1, End = 0) + return L.Copy(Start, End) + +/proc/_list_cut(list/L, Start = 1, End = 0) + L.Cut(Start, End) + +/proc/_list_find(list/L, Elem, Start = 1, End = 0) + return L.Find(Elem, Start, End) + +/proc/_list_insert(list/L, Index, Item) + return L.Insert(Index, Item) + +/proc/_list_join(list/L, Glue, Start = 0, End = 1) + return L.Join(Glue, Start, End) + +/proc/_list_remove(list/L, ...) + if (args.len < 2) + return + L -= args.Copy(2) + +/proc/_list_swap(list/L, Index1, Index2) + L.Swap(Index1, Index2) diff --git a/code/modules/admin/verbs/adminhelp.dm b/code/modules/admin/verbs/adminhelp.dm index e08919d9fc..0572aa3347 100644 --- a/code/modules/admin/verbs/adminhelp.dm +++ b/code/modules/admin/verbs/adminhelp.dm @@ -86,7 +86,7 @@ if(T.admin == "N/A") usr << "Due to the fact your Adminhelp had no assigned admin, admins have been pinged." message_admins("[src.ckey] has bumped their adminhelp #[T.ID], still no assigned admin!") - msg = "ADMINHELP: [key_name(src)] (?) (PP) (VV) (SM) (TP) (FLW) (R) (REJT): [T.msg]" + msg = "HELP: [key_name(src)] [ADMIN_QUE(mob)] [ADMIN_PP(mob)] [ADMIN_VV(mob)] [ADMIN_SM(mob)] [ADMIN_FLW(mob)] [ADMIN_TP(mob)] (REJT) (IC) (R): [msg]" for(var/client/X in admins) if(X.prefs.toggles & SOUND_ADMINHELP) X << 'sound/effects/adminhelp.ogg' diff --git a/code/modules/admin/verbs/pray.dm b/code/modules/admin/verbs/pray.dm index dd3ee471e9..b8593ff877 100644 --- a/code/modules/admin/verbs/pray.dm +++ b/code/modules/admin/verbs/pray.dm @@ -33,10 +33,7 @@ prayer_type = "CULTIST PRAYER" deity = "Nar-Sie" - msg = "\icon[cross] \ - [prayer_type][deity ? " (to [deity])" : ""]: \ - [ADMIN_FULLMONTY(src)] [ADMIN_SC(src)]: \ - [msg]" + msg = "\icon[cross][prayer_type][deity ? " (to [deity])" : ""]: [ADMIN_FULLMONTY(src)] [ADMIN_SC(src)] [ADMIN_SMITE(src)]: [msg]" for(var/client/C in admins) if(C.prefs.chat_toggles & CHAT_PRAYER) diff --git a/tgstation.dme b/tgstation.dme index 4fb22b301f..cf9c735941 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -997,6 +997,7 @@ #include "code\modules\admin\verbs\tripAI.dm" #include "code\modules\admin\verbs\SDQL2\SDQL_2.dm" #include "code\modules\admin\verbs\SDQL2\SDQL_2_parser.dm" +#include "code\modules\admin\verbs\SDQL2\SDQL_2_wrappers.dm" #include "code\modules\assembly\assembly.dm" #include "code\modules\assembly\bomb.dm" #include "code\modules\assembly\doorcontrol.dm"