mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-15 12:43:13 +00:00
Removes a very large amount of world loops. Adds a macro to painlessly generate a global list, and the needed code to modify the list when an object is made or deleted automatically. Cleans up some commented out code.
498 lines
12 KiB
Plaintext
498 lines
12 KiB
Plaintext
|
|
//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("<font color='red'>ERROR: Non-admin [usr.key] attempted to execute a SDQL query!</font>")
|
|
log_admin("Non-admin [usr.key] attempted to execute a SDQL query!")
|
|
|
|
var/list/query_list = SDQL_tokenize(query_text)
|
|
|
|
if(query_list.len < 2)
|
|
if(query_list.len > 0)
|
|
usr << "<font color='red'>SDQL: Too few discrete tokens in query \"[query_text]\". Please check your syntax and try again.</font>"
|
|
return
|
|
|
|
if(!(lowertext(query_list[1]) in list("select", "delete", "update")))
|
|
usr << "<font color='red'>SDQL: Unknown query type: \"[query_list[1]]\" in query \"[query_text]\". Please check your syntax and try again.</font>"
|
|
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
|
|
usr << "<font color='red'>SDQL: Invalid set parameter in query \"[query_text]\". Please check your syntax and try again.</font>"
|
|
return
|
|
|
|
i += 3
|
|
|
|
if(i >= query_list.len || query_list[i] != ",")
|
|
break
|
|
|
|
if(set_vars.len < 1)
|
|
usr << "<font color='red'>SDQL: Invalid or missing set in query \"[query_text]\". Please check your syntax and try again.</font>"
|
|
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 mob_list)
|
|
if(istype(m, f2))
|
|
from_objs += m
|
|
|
|
else if(text_starts_with(f, "/turf/space"))
|
|
for(var/turf/space/m in turfs)
|
|
if(istype(m, f2))
|
|
from_objs += m
|
|
|
|
else if(text_starts_with(f, "/turf/simulated"))
|
|
for(var/turf/simulated/m in turfs)
|
|
if(istype(m, f2))
|
|
from_objs += m
|
|
|
|
else if(text_starts_with(f, "/turf/unsimulated"))
|
|
for(var/turf/unsimulated/m in turfs)
|
|
if(istype(m, f2))
|
|
from_objs += m
|
|
|
|
else if(text_starts_with(f, "/turf"))
|
|
for(var/turf/m in turfs)
|
|
if(istype(m, f2))
|
|
from_objs += m
|
|
|
|
else if(text_starts_with(f, "/area"))
|
|
for(var/area/m in all_areas)
|
|
if(istype(m, f2))
|
|
from_objs += m
|
|
|
|
else if(text_starts_with(f, "/obj/item"))
|
|
for(var/obj/item/m in all_items)
|
|
if(istype(m, f2))
|
|
from_objs += m
|
|
|
|
else if(text_starts_with(f, "/obj/machinery"))
|
|
for(var/obj/machinery/m in machines)
|
|
if(istype(m, f2))
|
|
from_objs += m
|
|
|
|
else if(text_starts_with(f, "/obj"))
|
|
for(var/obj/m in all_objs)
|
|
if(istype(m, f2))
|
|
from_objs += m
|
|
|
|
else if(text_starts_with(f, "/atom"))
|
|
for(var/atom/m in all_atoms)
|
|
if(istype(m, f2))
|
|
from_objs += m
|
|
/*
|
|
else
|
|
for(var/datum/m in nope)
|
|
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("==", "=", "<>", "<", ">", "<=", ">=", "!=")))
|
|
usr << "<font color='red'>SDQL: Unknown comparison operator [compare_op] in where clause following [v] in query \"[query_text]\". Please check your syntax and try again.</font>"
|
|
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
|
|
|
|
|
|
|
|
usr << "<font color='blue'>SQDL Query: [query_text]</font>"
|
|
message_admins("[usr] executed SDQL query: \"[query_text]\".")
|
|
/*
|
|
for(var/t in types)
|
|
usr << "Type: [t]"
|
|
|
|
for(var/t in from)
|
|
usr << "From: [t]"
|
|
|
|
for(var/t in set_vars)
|
|
usr << "Set: [t] = [set_vars[t]]"
|
|
|
|
if(where.len)
|
|
var/where_str = ""
|
|
for(var/t in where)
|
|
where_str += "[t] "
|
|
|
|
usr << "Where: [where_str]"
|
|
|
|
usr << "From objects:"
|
|
for(var/datum/t in from_objs)
|
|
usr << t
|
|
|
|
usr << "Objects:"
|
|
for(var/datum/t in objs)
|
|
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
|
|
usr << "<font color='red'>SDQL: Sorry, equations not yet supported :(</font>"
|
|
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 != "")
|
|
usr << "<font color='red'>SDQL: You have an error in your SDQL syntax, unexpected ' in query:</font> \"<font color=gray>[query_text]</font>\" following \"<font color=gray>[word]</font>\". Please check your syntax, and try again."
|
|
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)
|
|
usr << "<font color='red'>SDQL: You have an error in your SDQL syntax, unmatched ' in query: </font>\"<font color=gray>[query_text]</font>\". Please check your syntax, and try again."
|
|
return null
|
|
|
|
query_list += "[word]'"
|
|
word = ""
|
|
|
|
else if(char == "\"")
|
|
if(word != "")
|
|
usr << "<font color='red'>SDQL: You have an error in your SDQL syntax, unexpected \" in query: </font>\"<font color=gray>[query_text]</font>\" following \"<font color=gray>[word]</font>\". Please check your syntax, and try again."
|
|
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)
|
|
usr << "<font color='red'>SDQL: You have an error in your SDQL syntax, unmatched \" in query: </font>\"<font color=gray>[query_text]</font>\". Please check your syntax, and try again."
|
|
return null
|
|
|
|
query_list += "[word]\""
|
|
word = ""
|
|
|
|
else
|
|
word += char
|
|
|
|
if(word != "")
|
|
query_list += word
|
|
|
|
return query_list
|