mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-07-21 04:48:18 +01:00
Updates SDQL2 to the latest TG version and adds variable protection. (#17997)
* SDQL2 update * fix that verb * cl * fix that * toworld * this is pointless * update info * siiiiick.. * vv edit update * fix that * fix editing vars * fix VV * discord protection --------- Co-authored-by: Matt Atlas <liermattia@gmail.com>
This commit is contained in:
@@ -203,7 +203,6 @@ var/list/admin_verbs_debug = list(
|
||||
/client/proc/callproc,
|
||||
/client/proc/callproc_target,
|
||||
/client/proc/toggledebuglogs,
|
||||
/client/proc/SDQL_query,
|
||||
/client/proc/SDQL2_query,
|
||||
/client/proc/Jump,
|
||||
/client/proc/jumptomob,
|
||||
@@ -384,7 +383,6 @@ var/list/admin_verbs_hideable = list(
|
||||
/client/proc/delete_random_map,
|
||||
/client/proc/enable_debug_verbs,
|
||||
/client/proc/fix_player_list,
|
||||
/client/proc/SDQL_query,
|
||||
/client/proc/SDQL2_query,
|
||||
/client/proc/cmd_admin_dress,
|
||||
/client/proc/kill_air,
|
||||
|
||||
@@ -18,6 +18,15 @@ var/list/admin_datums = list()
|
||||
|
||||
var/list/watched_processes // Processes marked to be shown in Status instead of just Processes.
|
||||
|
||||
/datum/admins/vv_edit_var(var_name, var_value)
|
||||
if(var_name == NAMEOF(src, rights))
|
||||
return FALSE
|
||||
if(var_name == NAMEOF(src, owner))
|
||||
return FALSE
|
||||
if(var_name == NAMEOF(src, original_mob))
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/datum/admins/New(initial_rank = "Temporary Admin", initial_rights = 0, ckey)
|
||||
if(!ckey)
|
||||
log_world("ERROR: Admin datum created without a ckey argument. Datum has been deleted")
|
||||
|
||||
@@ -1,497 +0,0 @@
|
||||
|
||||
//Structured Datum Query Language. Basically SQL meets BYOND objects.
|
||||
|
||||
//Note: For use in BS12, need text_starts_with proc, and to modify the action on select to use BS12's object edit command(s).
|
||||
|
||||
/client/proc/SDQL_query(query_text as message)
|
||||
set category = "Admin"
|
||||
if(!check_rights(R_DEBUG)) //Shouldn't happen... but just to be safe.
|
||||
message_admins("<span class='warning'>ERROR: Non-admin [usr.key] attempted to execute a SDQL query!</span>")
|
||||
log_admin("Non-admin [usr.key] attempted to execute a SDQL query!",level=2,ckey=key_name(usr))
|
||||
|
||||
var/list/query_list = SDQL_tokenize(query_text)
|
||||
|
||||
if(query_list.len < 2)
|
||||
if(query_list.len > 0)
|
||||
to_chat(usr, "<span class='warning'>SDQL: Too few discrete tokens in query \"[query_text]\". Please check your syntax and try again.</span>")
|
||||
return
|
||||
|
||||
if(!(lowertext(query_list[1]) in list("select", "delete", "update")))
|
||||
to_chat(usr, "<span class='warning'>SDQL: Unknown query type: \"[query_list[1]]\" in query \"[query_text]\". Please check your syntax and try again.</span>")
|
||||
return
|
||||
|
||||
var/list/types = list()
|
||||
|
||||
var/i
|
||||
for(i = 2; i <= query_list.len; i += 2)
|
||||
types += query_list[i]
|
||||
|
||||
if(i + 1 >= query_list.len || query_list[i + 1] != ",")
|
||||
break
|
||||
|
||||
i++
|
||||
|
||||
var/list/from = list()
|
||||
|
||||
if(i <= query_list.len)
|
||||
if(lowertext(query_list[i]) in list("from", "in"))
|
||||
for(i++; i <= query_list.len; i += 2)
|
||||
from += query_list[i]
|
||||
|
||||
if(i + 1 >= query_list.len || query_list[i + 1] != ",")
|
||||
break
|
||||
|
||||
i++
|
||||
|
||||
if(from.len < 1)
|
||||
from += "world"
|
||||
|
||||
var/list/set_vars = list()
|
||||
|
||||
if(lowertext(query_list[1]) == "update")
|
||||
if(i <= query_list.len && lowertext(query_list[i]) == "set")
|
||||
for(i++; i <= query_list.len; i++)
|
||||
if(i + 2 <= query_list.len && query_list[i + 1] == "=")
|
||||
set_vars += query_list[i]
|
||||
set_vars[query_list[i]] = query_list[i + 2]
|
||||
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>SDQL: Invalid set parameter in query \"[query_text]\". Please check your syntax and try again.</span>")
|
||||
return
|
||||
|
||||
i += 3
|
||||
|
||||
if(i >= query_list.len || query_list[i] != ",")
|
||||
break
|
||||
|
||||
if(set_vars.len < 1)
|
||||
to_chat(usr, "<span class='warning'>SDQL: Invalid or missing set in query \"[query_text]\". Please check your syntax and try again.</span>")
|
||||
return
|
||||
|
||||
var/list/where = list()
|
||||
|
||||
if(i <= query_list.len && lowertext(query_list[i]) == "where")
|
||||
where = query_list.Copy(i + 1)
|
||||
|
||||
var/list/from_objs = list()
|
||||
if("world" in from)
|
||||
from_objs += world
|
||||
else
|
||||
for(var/f in from)
|
||||
if(copytext(f, 1, 2) == "'" || copytext(f, 1, 2) == "\"")
|
||||
from_objs += locate(copytext(f, 2, length(f)))
|
||||
else if(copytext(f, 1, 2) != "/")
|
||||
from_objs += locate(f)
|
||||
else
|
||||
var/f2 = text2path(f)
|
||||
if(text_starts_with(f, "/mob"))
|
||||
for(var/mob/m in world)
|
||||
if(istype(m, f2))
|
||||
from_objs += m
|
||||
|
||||
else if(text_starts_with(f, "/turf/space"))
|
||||
for(var/turf/space/m in world)
|
||||
if(istype(m, f2))
|
||||
from_objs += m
|
||||
|
||||
else if(text_starts_with(f, "/turf/simulated"))
|
||||
for(var/turf/simulated/m in world)
|
||||
if(istype(m, f2))
|
||||
from_objs += m
|
||||
|
||||
else if(text_starts_with(f, "/turf/unsimulated"))
|
||||
for(var/turf/unsimulated/m in world)
|
||||
if(istype(m, f2))
|
||||
from_objs += m
|
||||
|
||||
else if(text_starts_with(f, "/turf"))
|
||||
for(var/turf/m in world)
|
||||
if(istype(m, f2))
|
||||
from_objs += m
|
||||
|
||||
else if(text_starts_with(f, "/area"))
|
||||
for(var/area/m in world)
|
||||
if(istype(m, f2))
|
||||
from_objs += m
|
||||
|
||||
else if(text_starts_with(f, "/obj/item"))
|
||||
for(var/obj/item/m in world)
|
||||
if(istype(m, f2))
|
||||
from_objs += m
|
||||
|
||||
else if(text_starts_with(f, "/obj/machinery"))
|
||||
for(var/obj/machinery/m in world)
|
||||
if(istype(m, f2))
|
||||
from_objs += m
|
||||
|
||||
else if(text_starts_with(f, "/obj"))
|
||||
for(var/obj/m in world)
|
||||
if(istype(m, f2))
|
||||
from_objs += m
|
||||
|
||||
else if(text_starts_with(f, "/atom"))
|
||||
for(var/atom/m in world)
|
||||
if(istype(m, f2))
|
||||
from_objs += m
|
||||
/*
|
||||
else
|
||||
for(var/datum/m in world)
|
||||
if(istype(m, f2))
|
||||
from_objs += m
|
||||
*/
|
||||
|
||||
var/list/objs = list()
|
||||
|
||||
for(var/from_obj in from_objs)
|
||||
if("*" in types)
|
||||
objs += from_obj:contents
|
||||
else
|
||||
for(var/f in types)
|
||||
if(copytext(f, 1, 2) == "'" || copytext(f, 1, 2) == "\"")
|
||||
objs += locate(copytext(f, 2, length(f))) in from_obj
|
||||
else if(copytext(f, 1, 2) != "/")
|
||||
objs += locate(f) in from_obj
|
||||
else
|
||||
var/f2 = text2path(f)
|
||||
if(text_starts_with(f, "/mob"))
|
||||
for(var/mob/m in from_obj)
|
||||
if(istype(m, f2))
|
||||
objs += m
|
||||
|
||||
else if(text_starts_with(f, "/turf/space"))
|
||||
for(var/turf/space/m in from_obj)
|
||||
if(istype(m, f2))
|
||||
objs += m
|
||||
|
||||
else if(text_starts_with(f, "/turf/simulated"))
|
||||
for(var/turf/simulated/m in from_obj)
|
||||
if(istype(m, f2))
|
||||
objs += m
|
||||
|
||||
else if(text_starts_with(f, "/turf/unsimulated"))
|
||||
for(var/turf/unsimulated/m in from_obj)
|
||||
if(istype(m, f2))
|
||||
objs += m
|
||||
|
||||
else if(text_starts_with(f, "/turf"))
|
||||
for(var/turf/m in from_obj)
|
||||
if(istype(m, f2))
|
||||
objs += m
|
||||
|
||||
else if(text_starts_with(f, "/area"))
|
||||
for(var/area/m in from_obj)
|
||||
if(istype(m, f2))
|
||||
objs += m
|
||||
|
||||
else if(text_starts_with(f, "/obj/item"))
|
||||
for(var/obj/item/m in from_obj)
|
||||
if(istype(m, f2))
|
||||
objs += m
|
||||
|
||||
else if(text_starts_with(f, "/obj/machinery"))
|
||||
for(var/obj/machinery/m in from_obj)
|
||||
if(istype(m, f2))
|
||||
objs += m
|
||||
|
||||
else if(text_starts_with(f, "/obj"))
|
||||
for(var/obj/m in from_obj)
|
||||
if(istype(m, f2))
|
||||
objs += m
|
||||
|
||||
else if(text_starts_with(f, "/atom"))
|
||||
for(var/atom/m in from_obj)
|
||||
if(istype(m, f2))
|
||||
objs += m
|
||||
|
||||
else
|
||||
for(var/datum/m in from_obj)
|
||||
if(istype(m, f2))
|
||||
objs += m
|
||||
|
||||
|
||||
for(var/datum/t in objs)
|
||||
var/currently_false = 0
|
||||
for(i = 1, i - 1 < where.len, i++)
|
||||
var/v = where[i++]
|
||||
var/compare_op = where[i++]
|
||||
if(!(compare_op in list("==", "=", "<>", "<", ">", "<=", ">=", "!=")))
|
||||
to_chat(usr, "<span class='warning'>SDQL: Unknown comparison operator [compare_op] in where clause following [v] in query \"[query_text]\". Please check your syntax and try again.</span>")
|
||||
return
|
||||
|
||||
var/j
|
||||
for(j = i, j <= where.len, j++)
|
||||
if(lowertext(where[j]) in list("and", "or", ";"))
|
||||
break
|
||||
|
||||
if(!currently_false)
|
||||
var/value = SDQL_text2value(t, v)
|
||||
var/result = SDQL_evaluate(t, where.Copy(i, j))
|
||||
|
||||
switch(compare_op)
|
||||
if("=", "==")
|
||||
currently_false = !(value == result)
|
||||
|
||||
if("!=", "<>")
|
||||
currently_false = !(value != result)
|
||||
|
||||
if("<")
|
||||
currently_false = !(value < result)
|
||||
|
||||
if(">")
|
||||
currently_false = !(value > result)
|
||||
|
||||
if("<=")
|
||||
currently_false = !(value <= result)
|
||||
|
||||
if(">=")
|
||||
currently_false = !(value >= result)
|
||||
|
||||
|
||||
if(j > where.len || lowertext(where[j]) == ";")
|
||||
break
|
||||
else if(lowertext(where[j]) == "or")
|
||||
if(currently_false)
|
||||
currently_false = 0
|
||||
else
|
||||
break
|
||||
|
||||
i = j
|
||||
|
||||
if(currently_false)
|
||||
objs -= t
|
||||
|
||||
|
||||
|
||||
to_chat(usr, "<span class='notice'>SQDL Query: [query_text]</span>")
|
||||
message_admins("[usr] executed SDQL query: \"[query_text]\".")
|
||||
/*
|
||||
for(var/t in types)
|
||||
to_chat(usr, "Type: [t]")
|
||||
|
||||
for(var/t in from)
|
||||
to_chat(usr, "From: [t]")
|
||||
|
||||
for(var/t in set_vars)
|
||||
to_chat(usr, "Set: [t] = [set_vars[t]]")
|
||||
|
||||
if(where.len)
|
||||
var/where_str = ""
|
||||
for(var/t in where)
|
||||
where_str += "[t] "
|
||||
|
||||
to_chat(usr, "Where: [where_str]")
|
||||
|
||||
to_chat(usr, "From objects:")
|
||||
for(var/datum/t in from_objs)
|
||||
to_chat(usr, t)
|
||||
|
||||
to_chat(usr, "Objects:")
|
||||
for(var/datum/t in objs)
|
||||
to_chat(usr, t)
|
||||
*/
|
||||
switch(lowertext(query_list[1]))
|
||||
if("delete")
|
||||
for(var/datum/t in objs)
|
||||
qdel(t)
|
||||
|
||||
if("update")
|
||||
for(var/datum/t in objs)
|
||||
objs[t] = list()
|
||||
for(var/v in set_vars)
|
||||
if(v in t.vars)
|
||||
objs[t][v] = SDQL_text2value(t, set_vars[v])
|
||||
|
||||
for(var/datum/t in objs)
|
||||
for(var/v in objs[t])
|
||||
t.vars[v] = objs[t][v]
|
||||
|
||||
if("select")
|
||||
var/text = ""
|
||||
for(var/datum/t in objs)
|
||||
if(istype(t, /atom))
|
||||
var/atom/a = t
|
||||
|
||||
if(a.x)
|
||||
text += "<a href='?src=\ref[t];SDQL_select=\ref[t]'>\ref[t]</a>: [t] at ([a.x], [a.y], [a.z])<br>"
|
||||
|
||||
else if(a.loc && a.loc.x)
|
||||
text += "<a href='?src=\ref[t];SDQL_select=\ref[t]'>\ref[t]</a>: [t] in [a.loc] at ([a.loc.x], [a.loc.y], [a.loc.z])<br>"
|
||||
|
||||
else
|
||||
text += "<a href='?src=\ref[t];SDQL_select=\ref[t]'>\ref[t]</a>: [t]<br>"
|
||||
|
||||
else
|
||||
text += "<a href='?src=\ref[t];SDQL_select=\ref[t]'>\ref[t]</a>: [t]<br>"
|
||||
|
||||
//text += "[t]<br>"
|
||||
usr << browse(text, "window=sdql_result")
|
||||
|
||||
|
||||
/client/Topic(href,href_list[],hsrc)
|
||||
if(href_list["SDQL_select"])
|
||||
debug_variables(locate(href_list["SDQL_select"]))
|
||||
|
||||
..()
|
||||
|
||||
|
||||
/proc/SDQL_evaluate(datum/object, list/equation)
|
||||
if(equation.len == 0)
|
||||
return null
|
||||
|
||||
else if(equation.len == 1)
|
||||
return SDQL_text2value(object, equation[1])
|
||||
|
||||
else if(equation[1] == "!")
|
||||
return !SDQL_evaluate(object, equation.Copy(2))
|
||||
|
||||
else if(equation[1] == "-")
|
||||
return -SDQL_evaluate(object, equation.Copy(2))
|
||||
|
||||
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>SDQL: Sorry, equations not yet supported :(</span>")
|
||||
return null
|
||||
|
||||
|
||||
/proc/SDQL_text2value(datum/object, text)
|
||||
if(text2num(text) != null)
|
||||
return text2num(text)
|
||||
else if(text == "null")
|
||||
return null
|
||||
else if(copytext(text, 1, 2) == "'" || copytext(text, 1, 2) == "\"" )
|
||||
return copytext(text, 2, length(text))
|
||||
else if(copytext(text, 1, 2) == "/")
|
||||
return text2path(text)
|
||||
else
|
||||
if(findtext(text, "."))
|
||||
var/split = findtext(text, ".")
|
||||
var/v = copytext(text, 1, split)
|
||||
|
||||
if((v in object.vars) && istype(object.vars[v], /datum))
|
||||
return SDQL_text2value(object.vars[v], copytext(text, split + 1))
|
||||
else
|
||||
return null
|
||||
|
||||
else
|
||||
if(text in object.vars)
|
||||
return object.vars[text]
|
||||
else
|
||||
return null
|
||||
|
||||
|
||||
/proc/text_starts_with(text, start)
|
||||
if(copytext(text, 1, length(start) + 1) == start)
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/proc/SDQL_tokenize(query_text)
|
||||
|
||||
var/list/whitespace = list(" ", "\n", "\t")
|
||||
var/list/single = list("(", ")", ",", "+", "-")
|
||||
var/list/multi = list(
|
||||
"=" = list("", "="),
|
||||
"<" = list("", "=", ">"),
|
||||
">" = list("", "="),
|
||||
"!" = list("", "="))
|
||||
|
||||
var/word = ""
|
||||
var/list/query_list = list()
|
||||
var/len = length(query_text)
|
||||
|
||||
for(var/i = 1, i <= len, i++)
|
||||
var/char = copytext(query_text, i, i + 1)
|
||||
|
||||
if(char in whitespace)
|
||||
if(word != "")
|
||||
query_list += word
|
||||
word = ""
|
||||
|
||||
else if(char in single)
|
||||
if(word != "")
|
||||
query_list += word
|
||||
word = ""
|
||||
|
||||
query_list += char
|
||||
|
||||
else if(char in multi)
|
||||
if(word != "")
|
||||
query_list += word
|
||||
word = ""
|
||||
|
||||
var/char2 = copytext(query_text, i + 1, i + 2)
|
||||
|
||||
if(char2 in multi[char])
|
||||
query_list += "[char][char2]"
|
||||
i++
|
||||
|
||||
else
|
||||
query_list += char
|
||||
|
||||
else if(char == "'")
|
||||
if(word != "")
|
||||
to_chat(usr, "<span class='warning'>SDQL: You have an error in your SDQL syntax, unexpected ' in query: \"<font color=gray>[query_text]</font>\" following \"<font color=gray>[word]</font>\". Please check your syntax, and try again.</span>")
|
||||
return null
|
||||
|
||||
word = "'"
|
||||
|
||||
for(i++, i <= len, i++)
|
||||
char = copytext(query_text, i, i + 1)
|
||||
|
||||
if(char == "'")
|
||||
if(copytext(query_text, i + 1, i + 2) == "'")
|
||||
word += "'"
|
||||
i++
|
||||
|
||||
else
|
||||
break
|
||||
|
||||
else
|
||||
word += char
|
||||
|
||||
if(i > len)
|
||||
to_chat(usr, "<span class='warning'>SDQL: You have an error in your SDQL syntax, unmatched ' in query: \"<font color=gray>[query_text]</font>\". Please check your syntax, and try again.</span>")
|
||||
return null
|
||||
|
||||
query_list += "[word]'"
|
||||
word = ""
|
||||
|
||||
else if(char == "\"")
|
||||
if(word != "")
|
||||
to_chat(usr, "<span class='warning'>SDQL: You have an error in your SDQL syntax, unexpected \" in query: \"<font color=gray>[query_text]</font>\" following \"<font color=gray>[word]</font>\". Please check your syntax, and try again.</span>")
|
||||
return null
|
||||
|
||||
word = "\""
|
||||
|
||||
for(i++, i <= len, i++)
|
||||
char = copytext(query_text, i, i + 1)
|
||||
|
||||
if(char == "\"")
|
||||
if(copytext(query_text, i + 1, i + 2) == "'")
|
||||
word += "\""
|
||||
i++
|
||||
|
||||
else
|
||||
break
|
||||
|
||||
else
|
||||
word += char
|
||||
|
||||
if(i > len)
|
||||
to_chat(usr, "<span class='danger'>SDQL: You have an error in your SDQL syntax, unmatched \" in query: \"<font color=gray>[query_text]</font>\". Please check your syntax, and try again.</span>")
|
||||
return null
|
||||
|
||||
query_list += "[word]\""
|
||||
word = ""
|
||||
|
||||
else
|
||||
word += char
|
||||
|
||||
if(word != "")
|
||||
query_list += word
|
||||
|
||||
return query_list
|
||||
+1016
-211
File diff suppressed because it is too large
Load Diff
@@ -1,105 +1,148 @@
|
||||
//I'm pretty sure that this is a recursive [s]descent[/s] ascent parser.
|
||||
|
||||
|
||||
|
||||
//Spec
|
||||
|
||||
//////////
|
||||
//
|
||||
// query : select_query | delete_query | update_query | call_query | explain
|
||||
// explain : 'EXPLAIN' query
|
||||
// query : select_query | delete_query | update_query | call_query | explain
|
||||
// explain : 'EXPLAIN' query
|
||||
// select_query : 'SELECT' object_selectors
|
||||
// delete_query : 'DELETE' object_selectors
|
||||
// update_query : 'UPDATE' object_selectors 'SET' assignments
|
||||
// call_query : 'CALL' variable 'ON' object_selectors // Note here: 'variable' does function calls. This simplifies parsing.
|
||||
//
|
||||
// select_query : 'SELECT' select_list [('FROM' | 'IN') from_list] ['WHERE' bool_expression]
|
||||
// delete_query : 'DELETE' select_list [('FROM' | 'IN') from_list] ['WHERE' bool_expression]
|
||||
// update_query : 'UPDATE' select_list [('FROM' | 'IN') from_list] 'SET' assignments ['WHERE' bool_expression]
|
||||
// call_query : 'CALL' call_function ['ON' select_list [('FROM' | 'IN') from_list] ['WHERE' bool_expression]]
|
||||
// select_item : '*' | object_type
|
||||
//
|
||||
// select_list : select_item [',' select_list]
|
||||
// select_item : '*' | select_function | object_type
|
||||
// select_function : count_function
|
||||
// count_function : 'COUNT' '(' '*' ')' | 'COUNT' '(' object_types ')'
|
||||
// object_selectors : select_item [('FROM' | 'IN') from_item] [modifier_list]
|
||||
// modifier_list : ('WHERE' bool_expression | 'MAP' expression) [modifier_list]
|
||||
//
|
||||
// from_list : from_item [',' from_list]
|
||||
// from_item : 'world' | object_type
|
||||
// from_item : 'world' | expression
|
||||
//
|
||||
// call_function : <function name> ['(' [arguments] ')']
|
||||
// arguments : expression [',' arguments]
|
||||
// call_function : <function name> '(' [expression_list] ')'
|
||||
//
|
||||
// object_type : <type path> | string
|
||||
// object_type : <type path>
|
||||
//
|
||||
// assignments : assignment, [',' assignments]
|
||||
// assignment : <variable name> '=' expression
|
||||
// variable : <variable name> | <variable name> '.' variable
|
||||
// assignments : assignment [',' assignments]
|
||||
// assignment : <variable name> '=' expression
|
||||
// variable : <variable name> | variable '.' variable | variable '[' <list index> ']' | '{' <ref as hex number> '}' | '(' expression ')' | call_function
|
||||
//
|
||||
// bool_expression : expression comparitor expression [bool_operator bool_expression]
|
||||
// expression : ( unary_expression | '(' expression ')' | value ) [binary_operator expression]
|
||||
// unary_expression : unary_operator ( unary_expression | value | '(' expression ')' )
|
||||
// comparitor : '=' | '==' | '!=' | '<>' | '<' | '<=' | '>' | '>='
|
||||
// value : variable | string | number | 'null'
|
||||
// unary_operator : '!' | '-' | '~'
|
||||
// binary_operator : comparitor | '+' | '-' | '/' | '*' | '&' | '|' | '^'
|
||||
// bool_operator : 'AND' | '&&' | 'OR' | '||'
|
||||
// bool_expression : expression comparator expression [bool_operator bool_expression]
|
||||
// expression : ( unary_expression | '(' expression ')' | value ) [binary_operator expression]
|
||||
// expression_list : expression [',' expression_list]
|
||||
// unary_expression : unary_operator ( unary_expression | value )
|
||||
//
|
||||
// string : ''' <some text> ''' | '"' <some text > '"'
|
||||
// number : <some digits>
|
||||
// comparator : '=' | '==' | '!=' | '<>' | '<' | '<=' | '>' | '>='
|
||||
// value : variable | string | number | 'null' | object_type | array | selectors_array
|
||||
// unary_operator : '!' | '-' | '~'
|
||||
// binary_operator : comparator | '+' | '-' | '/' | '*' | '&' | '|' | '^' | '%'
|
||||
// bool_operator : 'AND' | '&&' | 'OR' | '||'
|
||||
//
|
||||
// array : '[' expression_list ']'
|
||||
// selectors_array : '@[' object_selectors ']'
|
||||
//
|
||||
// string : ''' <some text> ''' | '"' <some text > '"'
|
||||
// number : <some digits>
|
||||
//
|
||||
//////////
|
||||
|
||||
/datum/SDQL_parser
|
||||
#define SDQL2_VALID_OPTION_TYPES list(\
|
||||
"autogc",\
|
||||
"priority",\
|
||||
"proccall",\
|
||||
"select",\
|
||||
"sequential",\
|
||||
)
|
||||
|
||||
#define SDQL2_VALID_OPTION_VALUES list(\
|
||||
"async",\
|
||||
"blocking",\
|
||||
"force_nulls",\
|
||||
"high",\
|
||||
"keep_alive" ,\
|
||||
"normal",\
|
||||
"skip_nulls",\
|
||||
"true",\
|
||||
)
|
||||
|
||||
/datum/sdql_parser
|
||||
var/query_type
|
||||
var/error = 0
|
||||
|
||||
var/list/query
|
||||
var/list/tree
|
||||
|
||||
var/list/select_functions = list("count")
|
||||
var/list/boolean_operators = list("and", "or", "&&", "||")
|
||||
var/list/unary_operators = list("!", "-", "~")
|
||||
var/list/binary_operators = list("+", "-", "/", "*", "&", "|", "^")
|
||||
var/list/comparitors = list("=", "==", "!=", "<>", "<", "<=", ">", ">=")
|
||||
var/list/binary_operators = list("+", "-", "/", "*", "&", "|", "^", "%")
|
||||
var/list/comparators = list("=", "==", "!=", "<>", "<", "<=", ">", ">=")
|
||||
|
||||
|
||||
|
||||
/datum/SDQL_parser/New(query_list)
|
||||
/datum/sdql_parser/New(query_list)
|
||||
query = query_list
|
||||
|
||||
|
||||
|
||||
/datum/SDQL_parser/proc/parse_error(error_message)
|
||||
/datum/sdql_parser/proc/parse_error(error_message)
|
||||
error = 1
|
||||
to_chat(usr, "<span class='warning'>SQDL2 Parsing Error: [error_message]</span>")
|
||||
to_chat(usr, SPAN_WARNING("SDQL2 Parsing Error: [error_message]"), confidential = TRUE)
|
||||
return query.len + 1
|
||||
|
||||
/datum/SDQL_parser/proc/parse()
|
||||
/datum/sdql_parser/proc/parse()
|
||||
tree = list()
|
||||
query(1, tree)
|
||||
query_options(1, tree)
|
||||
|
||||
if(error)
|
||||
return list()
|
||||
else
|
||||
return tree
|
||||
|
||||
/datum/SDQL_parser/proc/token(i)
|
||||
/datum/sdql_parser/proc/token(i)
|
||||
if(i <= query.len)
|
||||
return query[i]
|
||||
|
||||
else
|
||||
return null
|
||||
|
||||
/datum/SDQL_parser/proc/tokens(i, num)
|
||||
/datum/sdql_parser/proc/tokens(i, num)
|
||||
if(i + num <= query.len)
|
||||
return query.Copy(i, i + num)
|
||||
|
||||
else
|
||||
return null
|
||||
|
||||
/datum/SDQL_parser/proc/tokenl(i)
|
||||
/datum/sdql_parser/proc/tokenl(i)
|
||||
return lowertext(token(i))
|
||||
|
||||
/datum/sdql_parser/proc/query_options(i, list/node)
|
||||
var/list/options = list()
|
||||
if(tokenl(i) == "using")
|
||||
i = option_assignments(i + 1, node, options)
|
||||
query(i, node)
|
||||
if(length(options))
|
||||
node["options"] = options
|
||||
|
||||
//option_assignment: query_option '=' define
|
||||
/datum/sdql_parser/proc/option_assignment(i, list/node, list/assignment_list = list())
|
||||
var/type = tokenl(i)
|
||||
if(!(type in SDQL2_VALID_OPTION_TYPES))
|
||||
parse_error("Invalid option type: [type]")
|
||||
if(!(token(i + 1) == "="))
|
||||
parse_error("Invalid option assignment symbol: [token(i + 1)]")
|
||||
var/val = tokenl(i + 2)
|
||||
if(!(val in SDQL2_VALID_OPTION_VALUES))
|
||||
parse_error("Invalid option value: [val]")
|
||||
assignment_list[type] = val
|
||||
return (i + 3)
|
||||
|
||||
//query: select_query | delete_query | update_query
|
||||
/datum/SDQL_parser/proc/query(i, list/node)
|
||||
//option_assignments: option_assignment, [',' option_assignments]
|
||||
/datum/sdql_parser/proc/option_assignments(i, list/node, list/store)
|
||||
i = option_assignment(i, node, store)
|
||||
|
||||
if(token(i) == ",")
|
||||
i = option_assignments(i + 1, node, store)
|
||||
|
||||
return i
|
||||
|
||||
//query: select_query | delete_query | update_query
|
||||
/datum/sdql_parser/proc/query(i, list/node)
|
||||
query_type = tokenl(i)
|
||||
|
||||
switch(query_type)
|
||||
@@ -121,134 +164,98 @@
|
||||
query(i + 1, node["explain"])
|
||||
|
||||
|
||||
// select_query: 'SELECT' select_list [('FROM' | 'IN') from_list] ['WHERE' bool_expression]
|
||||
/datum/SDQL_parser/proc/select_query(i, list/node)
|
||||
// select_query: 'SELECT' object_selectors
|
||||
/datum/sdql_parser/proc/select_query(i, list/node)
|
||||
var/list/select = list()
|
||||
i = select_list(i + 1, select)
|
||||
i = object_selectors(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]
|
||||
/datum/SDQL_parser/proc/delete_query(i, list/node)
|
||||
//delete_query: 'DELETE' object_selectors
|
||||
/datum/sdql_parser/proc/delete_query(i, list/node)
|
||||
var/list/select = list()
|
||||
i = select_list(i + 1, select)
|
||||
i = object_selectors(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]
|
||||
/datum/SDQL_parser/proc/update_query(i, list/node)
|
||||
//update_query: 'UPDATE' object_selectors 'SET' assignments
|
||||
/datum/sdql_parser/proc/update_query(i, list/node)
|
||||
var/list/select = list()
|
||||
i = select_list(i + 1, select)
|
||||
i = object_selectors(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]]
|
||||
/datum/SDQL_parser/proc/call_query(i, list/node)
|
||||
//call_query: 'CALL' call_function ['ON' object_selectors]
|
||||
/datum/sdql_parser/proc/call_query(i, list/node)
|
||||
var/list/func = list()
|
||||
i = call_function(i + 1, func)
|
||||
i = variable(i + 1, func) // Yes technically does anything variable() matches but I don't care, if admins fuck up this badly then they shouldn't be allowed near SDQL.
|
||||
|
||||
node += "call"
|
||||
node["call"] = func
|
||||
|
||||
if(tokenl(i) != "on")
|
||||
return i
|
||||
return parse_error("You need to specify what to call ON.")
|
||||
|
||||
var/list/select = list()
|
||||
i = select_list(i + 1, select)
|
||||
i = object_selectors(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
|
||||
|
||||
// object_selectors: select_item [('FROM' | 'IN') from_item] [modifier_list]
|
||||
/datum/sdql_parser/proc/object_selectors(i, list/node)
|
||||
i = select_item(i, node)
|
||||
|
||||
//select_list: select_item [',' select_list]
|
||||
/datum/SDQL_parser/proc/select_list(i, list/node)
|
||||
if (tokenl(i) == "from" || tokenl(i) == "in")
|
||||
i++
|
||||
var/list/from = list()
|
||||
i = from_item(i, from)
|
||||
node[++node.len] = from
|
||||
|
||||
else
|
||||
node[++node.len] = list("world")
|
||||
|
||||
i = modifier_list(i, node)
|
||||
return i
|
||||
|
||||
// modifier_list: ('WHERE' bool_expression | 'MAP' expression) [modifier_list]
|
||||
/datum/sdql_parser/proc/modifier_list(i, list/node)
|
||||
while (TRUE)
|
||||
if (tokenl(i) == "where")
|
||||
i++
|
||||
node += "where"
|
||||
var/list/expr = list()
|
||||
i = bool_expression(i, expr)
|
||||
node[++node.len] = expr
|
||||
|
||||
else if (tokenl(i) == "map")
|
||||
i++
|
||||
node += "map"
|
||||
var/list/expr = list()
|
||||
i = expression(i, expr)
|
||||
node[++node.len] = expr
|
||||
|
||||
else
|
||||
return i
|
||||
|
||||
//select_list:select_item [',' select_list]
|
||||
/datum/sdql_parser/proc/select_list(i, list/node)
|
||||
i = select_item(i, node)
|
||||
|
||||
if(token(i) == ",")
|
||||
@@ -256,19 +263,8 @@
|
||||
|
||||
return i
|
||||
|
||||
|
||||
//from_list: from_item [',' from_list]
|
||||
/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]
|
||||
/datum/SDQL_parser/proc/assignments(i, list/node)
|
||||
//assignments: assignment, [',' assignments]
|
||||
/datum/sdql_parser/proc/assignments(i, list/node)
|
||||
i = assignment(i, node)
|
||||
|
||||
if(token(i) == ",")
|
||||
@@ -277,35 +273,61 @@
|
||||
return i
|
||||
|
||||
|
||||
//select_item: '*' | select_function | object_type
|
||||
/datum/SDQL_parser/proc/select_item(i, list/node)
|
||||
if(token(i) == "*")
|
||||
//select_item: '*' | select_function | object_type
|
||||
/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 if(token(i)[1] == "/")
|
||||
i = object_type(i, node)
|
||||
|
||||
else
|
||||
i = object_type(i, node)
|
||||
i = parse_error("Expected '*' or type path for select item")
|
||||
|
||||
return i
|
||||
|
||||
// Standardized method for handling the IN/FROM and WHERE options.
|
||||
/datum/sdql_parser/proc/selectors(i, list/node)
|
||||
while (token(i))
|
||||
var/tok = tokenl(i)
|
||||
if (tok in list("from", "in"))
|
||||
var/list/from = list()
|
||||
i = from_item(i + 1, from)
|
||||
|
||||
//from_item: 'world' | object_type
|
||||
/datum/SDQL_parser/proc/from_item(i, list/node)
|
||||
node["from"] = from
|
||||
continue
|
||||
|
||||
if (tok == "where")
|
||||
var/list/where = list()
|
||||
i = bool_expression(i + 1, where)
|
||||
|
||||
node["where"] = where
|
||||
continue
|
||||
|
||||
parse_error("Expected either FROM, IN or WHERE token, found [token(i)] instead.")
|
||||
return i + 1
|
||||
|
||||
if (!node.Find("from"))
|
||||
node["from"] = list("world")
|
||||
|
||||
return i
|
||||
|
||||
//from_item: 'world' | expression
|
||||
/datum/sdql_parser/proc/from_item(i, list/node)
|
||||
if(token(i) == "world")
|
||||
node += "world"
|
||||
i++
|
||||
|
||||
else
|
||||
i = object_type(i, node)
|
||||
i = expression(i, node)
|
||||
|
||||
return i
|
||||
|
||||
|
||||
//bool_expression: expression [bool_operator bool_expression]
|
||||
/datum/SDQL_parser/proc/bool_expression(i, list/node)
|
||||
//bool_expression: expression [bool_operator bool_expression]
|
||||
/datum/sdql_parser/proc/bool_expression(i, list/node)
|
||||
|
||||
var/list/bool = list()
|
||||
i = expression(i, bool)
|
||||
|
||||
@@ -318,15 +340,18 @@
|
||||
return i
|
||||
|
||||
|
||||
//assignment: <variable name> '=' expression
|
||||
/datum/SDQL_parser/proc/assignment(i, list/node)
|
||||
node += token(i)
|
||||
//assignment: <variable name> '=' expression
|
||||
/datum/sdql_parser/proc/assignment(i, list/node, list/assignment_list = list())
|
||||
assignment_list += token(i)
|
||||
|
||||
if(token(i + 1) == "=")
|
||||
var/varname = token(i)
|
||||
node[varname] = list()
|
||||
if(token(i + 1) == ".")
|
||||
i = assignment(i + 2, node, assignment_list)
|
||||
|
||||
i = expression(i + 2, node[varname])
|
||||
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")
|
||||
@@ -334,57 +359,97 @@
|
||||
return i
|
||||
|
||||
|
||||
//variable: <variable name> | <variable name> '.' variable
|
||||
/datum/SDQL_parser/proc/variable(i, list/node)
|
||||
//variable: <variable name> | variable '.' variable | variable '[' <list index> ']' | '{' <ref as hex number> '}' | '(' expression ')' | call_function
|
||||
/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.")
|
||||
|
||||
else if(token(i) == "(") // not a proc but an expression
|
||||
var/list/sub_expression = list()
|
||||
|
||||
i = expression(i + 1, sub_expression)
|
||||
|
||||
if(token(i) != ")")
|
||||
parse_error("Missing ) at end of expression.")
|
||||
|
||||
L[++L.len] = sub_expression
|
||||
|
||||
if(token(i + 1) == ".")
|
||||
L += "."
|
||||
i = variable(i + 2, L)
|
||||
|
||||
else if (token(i + 1) == "(") // OH BOY PROC
|
||||
var/list/arguments = list()
|
||||
i = call_function(i, null, arguments)
|
||||
L += ":"
|
||||
L[++L.len] = arguments
|
||||
|
||||
else if (token(i + 1) == "\[")
|
||||
var/list/expression = list()
|
||||
i = expression(i + 2, expression)
|
||||
if (token(i) != "]")
|
||||
parse_error("Missing ] at the end of list access.")
|
||||
|
||||
L += "\["
|
||||
L[++L.len] = expression
|
||||
i++
|
||||
|
||||
else
|
||||
i++
|
||||
|
||||
return i
|
||||
|
||||
|
||||
//object_type: <type path> | string
|
||||
/datum/SDQL_parser/proc/object_type(i, list/node)
|
||||
if(copytext(token(i), 1, 2) == "/")
|
||||
node += token(i)
|
||||
//object_type: <type path>
|
||||
/datum/sdql_parser/proc/object_type(i, list/node)
|
||||
|
||||
else
|
||||
i = string(i, node)
|
||||
if(token(i)[1] != "/")
|
||||
return parse_error("Expected type, but it didn't begin with /")
|
||||
|
||||
var/path = text2path(token(i))
|
||||
if (path == null)
|
||||
return parse_error("Nonexistent type path: [token(i)]")
|
||||
|
||||
node += path
|
||||
|
||||
return i + 1
|
||||
|
||||
|
||||
//comparitor: '=' | '==' | '!=' | '<>' | '<' | '<=' | '>' | '>='
|
||||
/datum/SDQL_parser/proc/comparitor(i, list/node)
|
||||
//comparator: '=' | '==' | '!=' | '<>' | '<' | '<=' | '>' | '>='
|
||||
/datum/sdql_parser/proc/comparator(i, list/node)
|
||||
|
||||
if(token(i) in list("=", "==", "!=", "<>", "<", "<=", ">", ">="))
|
||||
node += token(i)
|
||||
|
||||
else
|
||||
parse_error("Unknown comparitor [token(i)]")
|
||||
parse_error("Unknown comparator [token(i)]")
|
||||
|
||||
return i + 1
|
||||
|
||||
|
||||
//bool_operator: 'AND' | '&&' | 'OR' | '||'
|
||||
/datum/SDQL_parser/proc/bool_operator(i, list/node)
|
||||
//bool_operator: 'AND' | '&&' | 'OR' | '||'
|
||||
/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)]")
|
||||
parse_error("Unknown comparator [token(i)]")
|
||||
|
||||
return i + 1
|
||||
|
||||
|
||||
//string: ''' <some text> ''' | '"' <some text > '"'
|
||||
/datum/SDQL_parser/proc/string(i, list/node)
|
||||
if(copytext(token(i), 1, 2) in list("'", "\""))
|
||||
//string: ''' <some text> ''' | '"' <some text > '"'
|
||||
/datum/sdql_parser/proc/string(i, list/node)
|
||||
|
||||
if(token(i)[1] in list("'", "\""))
|
||||
node += token(i)
|
||||
|
||||
else
|
||||
@@ -392,38 +457,111 @@
|
||||
|
||||
return i + 1
|
||||
|
||||
//array: '[' expression_list ']'
|
||||
/datum/sdql_parser/proc/array(i, list/node)
|
||||
// Arrays get turned into this: list("[", list(exp_1a = exp_1b, ...), ...), "[" is to mark the next node as an array.
|
||||
if(token(i)[1] != "\[")
|
||||
parse_error("Expected an array but found '[token(i)]'")
|
||||
return i + 1
|
||||
|
||||
//call_function: <function name> ['(' [arguments] ')']
|
||||
/datum/SDQL_parser/proc/call_function(i, list/node)
|
||||
parse_error("Sorry, function calls aren't available yet")
|
||||
node += token(i) // Add the "["
|
||||
|
||||
return i
|
||||
var/list/expression_list = list()
|
||||
|
||||
i++
|
||||
if(token(i) != "]")
|
||||
var/list/temp_expression_list = list()
|
||||
var/tok
|
||||
do
|
||||
tok = token(i)
|
||||
if (tok == "," || tok == ":")
|
||||
if (temp_expression_list == null)
|
||||
parse_error("Found ',' or ':' without expression in an array.")
|
||||
return i + 1
|
||||
|
||||
expression_list[++expression_list.len] = temp_expression_list
|
||||
temp_expression_list = null
|
||||
if (tok == ":")
|
||||
temp_expression_list = list()
|
||||
i = expression(i + 1, temp_expression_list)
|
||||
expression_list[expression_list[expression_list.len]] = temp_expression_list
|
||||
temp_expression_list = null
|
||||
tok = token(i)
|
||||
if (tok != ",")
|
||||
if (tok == "]")
|
||||
break
|
||||
|
||||
parse_error("Expected ',' or ']' after array assoc value, but found '[token(i)]'")
|
||||
return i
|
||||
|
||||
|
||||
//select_function: count_function
|
||||
/datum/SDQL_parser/proc/select_function(i, list/node)
|
||||
parse_error("Sorry, function calls aren't available yet")
|
||||
i++
|
||||
continue
|
||||
|
||||
return i
|
||||
temp_expression_list = list()
|
||||
i = expression(i, temp_expression_list)
|
||||
|
||||
while(token(i) && token(i) != "]")
|
||||
|
||||
//expression: ( unary_expression | '(' expression ')' | value ) [binary_operator expression]
|
||||
/datum/SDQL_parser/proc/expression(i, list/node)
|
||||
if(token(i) in unary_operators)
|
||||
i = unary_expression(i, node)
|
||||
if (temp_expression_list)
|
||||
expression_list[++expression_list.len] = temp_expression_list
|
||||
|
||||
else if(token(i) == "(")
|
||||
var/list/expr = list()
|
||||
node[++node.len] = expression_list
|
||||
|
||||
i = expression(i + 1, expr)
|
||||
return i + 1
|
||||
|
||||
if(token(i) != ")")
|
||||
parse_error("Missing ) at end of expression.")
|
||||
//selectors_array: '@[' object_selectors ']'
|
||||
/datum/sdql_parser/proc/selectors_array(i, list/node)
|
||||
if(token(i) == "@\[")
|
||||
node += token(i++)
|
||||
if(token(i) != "]")
|
||||
var/list/select = list()
|
||||
i = object_selectors(i, select)
|
||||
node[++node.len] = select
|
||||
if(token(i) != "]")
|
||||
parse_error("Expected ']' to close selector array, but found '[token(i)]'")
|
||||
else
|
||||
parse_error("Selector array expected a selector, but found nothing")
|
||||
else
|
||||
parse_error("Expected '@\[' but found '[token(i)]'")
|
||||
|
||||
return i + 1
|
||||
|
||||
//call_function: <function name> ['(' [arguments] ')']
|
||||
/datum/sdql_parser/proc/call_function(i, list/node, list/arguments)
|
||||
if(length(tokenl(i)))
|
||||
var/procname = ""
|
||||
if(tokenl(i) == "global" && token(i + 1) == ".") // Global proc.
|
||||
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/temp_expression_list = list()
|
||||
do
|
||||
i = expression(i + 1, temp_expression_list)
|
||||
if(token(i) == ",")
|
||||
arguments[++arguments.len] = temp_expression_list
|
||||
temp_expression_list = list()
|
||||
continue
|
||||
|
||||
while(token(i) && token(i) != ")")
|
||||
|
||||
arguments[++arguments.len] = temp_expression_list // The code this is copy pasted from won't be executed when it's the last param, this fixes that.
|
||||
else
|
||||
i++
|
||||
else
|
||||
parse_error("Expected a function but found nothing")
|
||||
return i + 1
|
||||
|
||||
node[++node.len] = expr
|
||||
|
||||
//expression: ( unary_expression | value ) [binary_operator expression]
|
||||
/datum/sdql_parser/proc/expression(i, list/node)
|
||||
|
||||
if(token(i) in unary_operators)
|
||||
i = unary_expression(i, node)
|
||||
|
||||
else
|
||||
i = value(i, node)
|
||||
@@ -432,7 +570,7 @@
|
||||
i = binary_operator(i, node)
|
||||
i = expression(i, node)
|
||||
|
||||
else if(token(i) in comparitors)
|
||||
else if(token(i) in comparators)
|
||||
i = binary_operator(i, node)
|
||||
|
||||
var/list/rhs = list()
|
||||
@@ -444,8 +582,9 @@
|
||||
return i
|
||||
|
||||
|
||||
//unary_expression: unary_operator ( unary_expression | value | '(' expression ')' )
|
||||
/datum/SDQL_parser/proc/unary_expression(i, list/node)
|
||||
//unary_expression: unary_operator ( unary_expression | value )
|
||||
/datum/sdql_parser/proc/unary_expression(i, list/node)
|
||||
|
||||
if(token(i) in unary_operators)
|
||||
var/list/unary_exp = list()
|
||||
|
||||
@@ -455,19 +594,6 @@
|
||||
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
|
||||
|
||||
else
|
||||
i = value(i, unary_exp)
|
||||
|
||||
@@ -480,9 +606,10 @@
|
||||
return i
|
||||
|
||||
|
||||
//binary_operator: comparitor | '+' | '-' | '/' | '*' | '&' | '|' | '^'
|
||||
/datum/SDQL_parser/proc/binary_operator(i, list/node)
|
||||
if(token(i) in (binary_operators + comparitors))
|
||||
//binary_operator: comparator | '+' | '-' | '/' | '*' | '&' | '|' | '^' | '%'
|
||||
/datum/sdql_parser/proc/binary_operator(i, list/node)
|
||||
|
||||
if(token(i) in (binary_operators + comparators))
|
||||
node += token(i)
|
||||
|
||||
else
|
||||
@@ -491,25 +618,36 @@
|
||||
return i + 1
|
||||
|
||||
|
||||
//value: variable | string | number | 'null'
|
||||
/datum/SDQL_parser/proc/value(i, list/node)
|
||||
//value: variable | string | number | 'null' | object_type | array | selectors_array
|
||||
/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))))//3 == length("0x") + 1
|
||||
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("'", "\""))
|
||||
else if(token(i)[1] in list("'", "\""))
|
||||
i = string(i, node)
|
||||
|
||||
else if(token(i)[1] == "\[") // Start a list.
|
||||
i = array(i, node)
|
||||
|
||||
else if(copytext(token(i), 1, 3) == "@\[")//3 == length("@\[") + 1
|
||||
i = selectors_array(i, node)
|
||||
|
||||
else if(token(i)[1] == "/")
|
||||
i = object_type(i, node)
|
||||
|
||||
else
|
||||
i = variable(i, node)
|
||||
|
||||
return i
|
||||
|
||||
|
||||
|
||||
|
||||
/*EXPLAIN SELECT * WHERE 42 = 6 * 9 OR val = - 5 == 7*/
|
||||
#undef SDQL2_VALID_OPTION_TYPES
|
||||
#undef SDQL2_VALID_OPTION_VALUES
|
||||
|
||||
@@ -0,0 +1,293 @@
|
||||
// Wrappers for BYOND default procs which can't directly be called by call().
|
||||
|
||||
/proc/_abs(A)
|
||||
return abs(A)
|
||||
|
||||
/proc/_animate(atom/target, set_vars, time = 10, loop = 1, easing = LINEAR_EASING, flags = null)
|
||||
if(target)
|
||||
animate(target, appearance = set_vars, time, loop, easing, flags)
|
||||
else
|
||||
animate(appearance = set_vars, time, easing = easing, flags)
|
||||
|
||||
/proc/_arccos(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/_findtext(Haystack, Needle, Start = 1, End = 0)
|
||||
return findtext(Haystack, Needle, Start, End)
|
||||
|
||||
/proc/_findtextEx(Haystack, Needle, Start = 1, End = 0)
|
||||
return findtextEx(Haystack, Needle, Start, End)
|
||||
|
||||
/proc/_flick(Icon, Object)
|
||||
flick(Icon, Object)
|
||||
|
||||
/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/_istype(object, type)
|
||||
return istype(object, type)
|
||||
|
||||
/proc/_ispath(path, type)
|
||||
return ispath(path, type)
|
||||
|
||||
/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.
|
||||
// direct ref locate
|
||||
var/datum/D = locate(X)
|
||||
// &&'s to last value
|
||||
return istype(D) && D
|
||||
|
||||
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)
|
||||
var/datum/result
|
||||
|
||||
if(!length(arguments))
|
||||
result = new type()
|
||||
else
|
||||
result = new type(arglist(arguments))
|
||||
return result
|
||||
|
||||
/proc/_num2text(N, SigFig = 6)
|
||||
return num2text(N, SigFig)
|
||||
|
||||
/proc/_text2num(T)
|
||||
return text2num(T)
|
||||
|
||||
/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))
|
||||
|
||||
/// Allow me to explain
|
||||
/// for some reason, if pick() is passed arglist(args) directly and args contains only one list
|
||||
/// it considers it to be a list of lists
|
||||
/// this means something like _pick(list) would fail
|
||||
/// need to do this instead
|
||||
///
|
||||
/// I hate this timeline
|
||||
/proc/_pick_list(list/pick_from)
|
||||
return pick(pick_from)
|
||||
|
||||
/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/_rect_turfs(H_Radius = 0, V_Radius = 0, atom/Center)
|
||||
return RECT_TURFS(H_Radius, V_Radius, 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/_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_set(list/L, key, value)
|
||||
L[key] = value
|
||||
|
||||
/proc/_list_get(list/L, key)
|
||||
return L[key]
|
||||
|
||||
/proc/_list_numerical_add(L, key, num)
|
||||
L[key] += num
|
||||
|
||||
/proc/_list_swap(list/L, Index1, Index2)
|
||||
L.Swap(Index1, Index2)
|
||||
|
||||
/proc/_walk(ref, dir, lag)
|
||||
walk(ref, dir, lag)
|
||||
|
||||
/proc/_walk_towards(ref, trg, lag)
|
||||
walk_towards(ref, trg, lag)
|
||||
|
||||
/proc/_walk_to(ref, trg, min, lag)
|
||||
walk_to(ref, trg, min, lag)
|
||||
|
||||
/proc/_walk_away(ref, trg, max, lag)
|
||||
walk_away(ref, trg, max, lag)
|
||||
|
||||
/proc/_walk_rand(ref, lag)
|
||||
walk_rand(ref, lag)
|
||||
|
||||
/proc/_step(ref, dir)
|
||||
step(ref, dir)
|
||||
|
||||
/proc/_step_rand(ref)
|
||||
step_rand(ref)
|
||||
|
||||
/proc/_step_to(ref, trg, min)
|
||||
step_to(ref, trg, min)
|
||||
|
||||
/proc/_step_towards(ref, trg)
|
||||
step_towards(ref, trg)
|
||||
|
||||
/proc/_step_away(ref, trg, max)
|
||||
step_away(ref, trg, max)
|
||||
|
||||
/proc/_has_trait(datum/thing, trait)
|
||||
return HAS_TRAIT(thing, trait)
|
||||
|
||||
/proc/_add_trait(datum/thing, trait, source)
|
||||
ADD_TRAIT(thing, trait, source)
|
||||
|
||||
/proc/_remove_trait(datum/thing, trait, source)
|
||||
REMOVE_TRAIT(thing, trait, source)
|
||||
|
||||
/proc/_winset(player, control_id, params)
|
||||
winset(player, control_id, params)
|
||||
|
||||
/proc/_winget(player, control_id, params)
|
||||
winget(player, control_id, params)
|
||||
|
||||
/proc/_text2path(text)
|
||||
return text2path(text)
|
||||
|
||||
/proc/_turn(dir, angle)
|
||||
return turn(dir, angle)
|
||||
|
||||
/proc/_view(Dist, Center = usr)
|
||||
return view(Dist, Center)
|
||||
|
||||
/proc/_viewers(Dist, Center = usr)
|
||||
return viewers(Dist, Center)
|
||||
|
||||
/// Auxtools REALLY doesn't know how to handle filters as values;
|
||||
/// when passed as arguments to auxtools-called procs, they aren't simply treated as nulls -
|
||||
/// they don't even count towards the length of args.
|
||||
/// For example, calling some_proc([a filter], foo, bar) from auxtools
|
||||
/// is equivalent to calling some_proc(foo, bar). Thus, we can't use _animate directly on filters.
|
||||
/// Use this to perform animation steps on a filter. Consecutive steps on the same filter can be
|
||||
/// achieved by calling _animate with no target.
|
||||
/proc/_animate_filter(atom/target, filter_index, set_vars, time = 10, loop = 1, easing = LINEAR_EASING, flags = null)
|
||||
if(!istype(target))
|
||||
return
|
||||
if(!filter_index || filter_index < 1 || filter_index > length(target.filters))
|
||||
return
|
||||
animate(target.filters[filter_index], appearance = set_vars, time, loop, easing, flags)
|
||||
@@ -28,11 +28,6 @@
|
||||
|
||||
var/list/locked = list("vars", "key", "ckey", "client")
|
||||
|
||||
for(var/p in forbidden_varedit_object_types)
|
||||
if( istype(O,p) )
|
||||
to_chat(usr, "<span class='danger'>It is forbidden to edit this object's variables.</span>")
|
||||
return
|
||||
|
||||
var/list/names = list()
|
||||
for (var/V in O.vars)
|
||||
names += V
|
||||
@@ -46,7 +41,8 @@
|
||||
else
|
||||
variable = var_name
|
||||
|
||||
if(!variable) return
|
||||
if(!variable)
|
||||
return
|
||||
var/default
|
||||
var/var_value = O.vars[variable]
|
||||
var/dir
|
||||
@@ -129,9 +125,12 @@
|
||||
original_name = O:name
|
||||
|
||||
switch(class)
|
||||
|
||||
if("restore to default")
|
||||
O.vars[variable] = initial(O.vars[variable])
|
||||
var/initial_var = initial(O.vars[variable])
|
||||
if(!O.vv_edit_var(variable, initial_var))
|
||||
to_chat(usr, SPAN_WARNING("You cannot edit this variable."))
|
||||
return
|
||||
O.vars[variable] = initial_var
|
||||
if(method)
|
||||
if(istype(O, /mob))
|
||||
for(var/mob/M in mob_list)
|
||||
@@ -169,7 +168,11 @@
|
||||
|
||||
if("text")
|
||||
var/new_value = input("Enter new text:","Text",O.vars[variable]) as text|null//todo: sanitize ???
|
||||
if(new_value == null) return
|
||||
if(new_value == null)
|
||||
return
|
||||
if(!O.vv_edit_var(variable, new_value))
|
||||
to_chat(usr, SPAN_WARNING("You cannot edit this variable."))
|
||||
return
|
||||
O.vars[variable] = new_value
|
||||
|
||||
if(method)
|
||||
@@ -206,7 +209,12 @@
|
||||
if("num")
|
||||
var/new_value = input("Enter new number:","Num",\
|
||||
O.vars[variable]) as num|null
|
||||
if(new_value == null) return
|
||||
if(new_value == null)
|
||||
return
|
||||
|
||||
if(!O.vv_edit_var(variable, new_value))
|
||||
to_chat(usr, SPAN_WARNING("You cannot edit this variable."))
|
||||
return
|
||||
|
||||
if(variable=="light_range")
|
||||
O.set_light(new_value)
|
||||
@@ -266,7 +274,13 @@
|
||||
if("type")
|
||||
var/new_value
|
||||
new_value = input("Enter type:","Type",O.vars[variable]) as null|anything in typesof(/obj,/mob,/area,/turf)
|
||||
if(new_value == null) return
|
||||
if(new_value == null)
|
||||
return
|
||||
|
||||
if(!O.vv_edit_var(variable, new_value))
|
||||
to_chat(usr, SPAN_WARNING("You cannot edit this variable."))
|
||||
return
|
||||
|
||||
O.vars[variable] = new_value
|
||||
if(method)
|
||||
if(istype(O, /mob))
|
||||
@@ -301,7 +315,13 @@
|
||||
|
||||
if("file")
|
||||
var/new_value = input("Pick file:","File",O.vars[variable]) as null|file
|
||||
if(new_value == null) return
|
||||
if(new_value == null)
|
||||
return
|
||||
|
||||
if(!O.vv_edit_var(variable, new_value))
|
||||
to_chat(usr, SPAN_WARNING("You cannot edit this variable."))
|
||||
return
|
||||
|
||||
O.vars[variable] = new_value
|
||||
|
||||
if(method)
|
||||
@@ -337,7 +357,13 @@
|
||||
|
||||
if("icon")
|
||||
var/new_value = input("Pick icon:","Icon",O.vars[variable]) as null|icon
|
||||
if(new_value == null) return
|
||||
if(new_value == null)
|
||||
return
|
||||
|
||||
if(!O.vv_edit_var(variable, new_value))
|
||||
to_chat(usr, SPAN_WARNING("You cannot edit this variable."))
|
||||
return
|
||||
|
||||
O.vars[variable] = new_value
|
||||
if(method)
|
||||
if(istype(O, /mob))
|
||||
|
||||
@@ -1,10 +1,3 @@
|
||||
var/list/forbidden_varedit_object_types = list(
|
||||
/datum/admins, //Admins editing their own admin-power object? Yup, sounds like a good idea.
|
||||
/datum/controller/subsystem/statistics, //Prevents people messing with feedback gathering
|
||||
/datum/controller/subsystem/discord, //Nope.jpg
|
||||
/datum/feedback_variable //Prevents people messing with feedback gathering
|
||||
)
|
||||
|
||||
var/list/VVlocked = list("vars", "holder", "client", "virus", "viruses", "cuffed", "last_eaten", "unlock_content", "bound_x", "bound_y", "step_x", "step_y", "force_ending")
|
||||
var/list/VVicon_edit_lock = list("icon", "icon_state", "overlays", "underlays")
|
||||
var/list/VVckey_edit = list("key", "ckey")
|
||||
@@ -406,15 +399,14 @@ var/list/VVdynamic_lock = list(
|
||||
/client/proc/modify_variables(var/atom/O, var/param_var_name = null, var/autodetect_class = 0)
|
||||
if(!check_rights(R_VAREDIT|R_DEV)) return
|
||||
|
||||
for(var/p in forbidden_varedit_object_types)
|
||||
if( istype(O,p) )
|
||||
to_chat(usr, "<span class='danger'>It is forbidden to edit this object's variables.</span>")
|
||||
return
|
||||
|
||||
if(istype(O, /client) && (param_var_name == "ckey" || param_var_name == "key"))
|
||||
to_chat(usr, "<span class='danger'>You cannot edit ckeys on client objects.</span>")
|
||||
return
|
||||
|
||||
if(!O.vv_edit_var(param_var_name))
|
||||
to_chat(src, SPAN_WARNING("You cannot edit this variable."))
|
||||
return
|
||||
|
||||
var/class
|
||||
var/variable
|
||||
var/var_value
|
||||
@@ -485,7 +477,8 @@ var/list/VVdynamic_lock = list(
|
||||
names = sortList(names)
|
||||
|
||||
variable = input("Which var?","Var") as null|anything in names
|
||||
if(!variable) return
|
||||
if(!variable)
|
||||
return
|
||||
var_value = O.vars[variable]
|
||||
|
||||
if(variable in VVlocked)
|
||||
@@ -596,17 +589,35 @@ var/list/VVdynamic_lock = list(
|
||||
|
||||
if("text")
|
||||
var/var_new = input("Enter new text:","Text",O.vars[variable]) as null|text
|
||||
if(var_new==null) return
|
||||
if(var_new==null)
|
||||
return
|
||||
|
||||
if(!O.vv_edit_var(variable, var_new))
|
||||
to_chat(usr, SPAN_WARNING("You cannot edit this variable."))
|
||||
return
|
||||
|
||||
O.vars[variable] = var_new
|
||||
|
||||
if("num")
|
||||
if(variable=="light_range")
|
||||
var/var_new = input("Enter new number:","Num",O.vars[variable]) as null|num
|
||||
if(var_new == null) return
|
||||
if(var_new == null)
|
||||
return
|
||||
|
||||
if(!O.vv_edit_var(variable, var_new))
|
||||
to_chat(usr, SPAN_WARNING("You cannot edit this variable."))
|
||||
return
|
||||
|
||||
O.set_light(var_new)
|
||||
else if(variable=="stat")
|
||||
var/var_new = input("Enter new number:","Num",O.vars[variable]) as null|num
|
||||
if(var_new == null) return
|
||||
if(var_new == null)
|
||||
return
|
||||
|
||||
if(!O.vv_edit_var(variable, var_new))
|
||||
to_chat(usr, SPAN_WARNING("You cannot edit this variable."))
|
||||
return
|
||||
|
||||
if((O.vars[variable] == 2) && (var_new < 2))//Bringing the dead back to life
|
||||
dead_mob_list -= O
|
||||
living_mob_list += O
|
||||
@@ -616,7 +627,13 @@ var/list/VVdynamic_lock = list(
|
||||
O.vars[variable] = var_new
|
||||
else
|
||||
var/var_new = input("Enter new number:","Num",O.vars[variable]) as null|num
|
||||
if(var_new==null) return
|
||||
if(var_new==null)
|
||||
return
|
||||
|
||||
if(!O.vv_edit_var(variable, var_new))
|
||||
to_chat(usr, SPAN_WARNING("You cannot edit this variable."))
|
||||
return
|
||||
|
||||
O.vars[variable] = var_new
|
||||
|
||||
if("type")
|
||||
@@ -641,27 +658,56 @@ var/list/VVdynamic_lock = list(
|
||||
else
|
||||
var_new = input("Select an atom type", "Spawn Atom", matches[1]) as null|anything in matches
|
||||
|
||||
if(var_new==null) return
|
||||
if(var_new==null)
|
||||
return
|
||||
|
||||
if(!O.vv_edit_var(variable, var_new))
|
||||
to_chat(usr, SPAN_WARNING("You cannot edit this variable."))
|
||||
return
|
||||
|
||||
O.vars[variable] = var_new
|
||||
|
||||
if("reference")
|
||||
var/var_new = input("Select reference:","Reference",O.vars[variable]) as null|mob|obj|turf|area in world
|
||||
if(var_new==null) return
|
||||
if(var_new==null)
|
||||
return
|
||||
|
||||
if(!O.vv_edit_var(variable, var_new))
|
||||
to_chat(usr, SPAN_WARNING("You cannot edit this variable."))
|
||||
return
|
||||
|
||||
O.vars[variable] = var_new
|
||||
|
||||
if("mob reference")
|
||||
var/var_new = input("Select reference:","Reference",O.vars[variable]) as null|mob in world
|
||||
if(var_new==null) return
|
||||
|
||||
if(!O.vv_edit_var(variable, var_new))
|
||||
to_chat(usr, SPAN_WARNING("You cannot edit this variable."))
|
||||
return
|
||||
|
||||
O.vars[variable] = var_new
|
||||
|
||||
if("file")
|
||||
var/var_new = input("Pick file:","File",O.vars[variable]) as null|file
|
||||
if(var_new==null) return
|
||||
if(var_new==null)
|
||||
return
|
||||
|
||||
if(!O.vv_edit_var(variable, var_new))
|
||||
to_chat(usr, SPAN_WARNING("You cannot edit this variable."))
|
||||
return
|
||||
|
||||
O.vars[variable] = var_new
|
||||
|
||||
if("icon")
|
||||
var/var_new = input("Pick icon:","Icon",O.vars[variable]) as null|icon
|
||||
if(var_new==null) return
|
||||
if(var_new==null)
|
||||
return
|
||||
|
||||
if(!O.vv_edit_var(variable, var_new))
|
||||
to_chat(usr, SPAN_WARNING("You cannot edit this variable."))
|
||||
return
|
||||
|
||||
O.vars[variable] = var_new
|
||||
|
||||
if("marked datum")
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
if(!D)
|
||||
return
|
||||
|
||||
var/static/list/blacklist = list(/datum/configuration, /datum/controller/subsystem/discord)
|
||||
var/static/list/blacklist = list(/datum/configuration)
|
||||
if(is_type_in_list(D,blacklist))
|
||||
return
|
||||
|
||||
@@ -121,6 +121,8 @@
|
||||
CHECK_TICK
|
||||
if(x in view_variables_hide_vars)
|
||||
continue
|
||||
if(!D.can_vv_get(x))
|
||||
continue
|
||||
variables += x
|
||||
variables = sortList(variables)
|
||||
for(var/x in variables)
|
||||
|
||||
Reference in New Issue
Block a user