diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm
index 28ec3383ae..c55662e86f 100644
--- a/code/__DEFINES/is_helpers.dm
+++ b/code/__DEFINES/is_helpers.dm
@@ -1,3 +1,6 @@
+/// Checks if something is a BYOND object datatype rather than a primitive, or whatever's closest to one.
+#define is_object_datatype(object) (object && !ispath(object) && !istext(object) && !isnum(object))
+
// simple is_type and similar inline helpers
#define in_range(source, user) (get_dist(source, user) <= 1 && (get_step(source, 0)?:z) == (get_step(user, 0)?:z))
diff --git a/code/modules/admin/verbs/SDQL2/SDQL_2.dm b/code/modules/admin/verbs/SDQL2/SDQL_2.dm
index df54df5c7d..bff431a6c7 100644
--- a/code/modules/admin/verbs/SDQL2/SDQL_2.dm
+++ b/code/modules/admin/verbs/SDQL2/SDQL_2.dm
@@ -346,7 +346,7 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
//print the key
if(islist(key))
recursive_list_print(output, key, datum_handler, atom_handler)
- else if(is_proper_datum(key) && (datum_handler || (isatom(key) && atom_handler)))
+ else if(is_object_datatype(key) && (datum_handler || (isatom(key) && atom_handler)))
if(isatom(key) && atom_handler)
output += atom_handler.Invoke(key)
else
@@ -360,7 +360,7 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
var/value = input[key]
if(islist(value))
recursive_list_print(output, value, datum_handler, atom_handler)
- else if(is_proper_datum(value) && (datum_handler || (isatom(value) && atom_handler)))
+ else if(is_object_datatype(value) && (datum_handler || (isatom(value) && atom_handler)))
if(isatom(value) && atom_handler)
output += atom_handler.Invoke(value)
else
@@ -498,7 +498,7 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
if(length(select_text))
var/text = islist(select_text)? select_text.Join() : select_text
var/static/result_offset = 0
- showmob << browse(text, "window=SDQL-result-[result_offset++]")
+ showmob << browse(text, "window=SDQL-result-[result_offset++];size=800x1200")
show_next_to_key = null
if(qdel_on_finish)
qdel(src)
@@ -646,7 +646,7 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
switch(query_tree[1])
if("call")
for(var/i in found)
- if(!is_proper_datum(i))
+ if(!is_object_datatype(i))
continue
world.SDQL_var(i, query_tree["call"][1], null, i, superuser, src)
obj_count_finished++
@@ -664,7 +664,10 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
var/list/text_list = list()
var/print_nulls = !(options & SDQL2_OPTION_SELECT_OUTPUT_SKIP_NULLS)
obj_count_finished = select_refs
+ var/n = 0
for(var/i in found)
+ if(++n == 20000)
+ text_list += "
TRUNCATED - 20000 OBJECT LIMIT HIT"
SDQL_print(i, text_list, print_nulls)
select_refs[REF(i)] = TRUE
SDQL2_TICK_CHECK
@@ -675,7 +678,7 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
if("set" in query_tree)
var/list/set_list = query_tree["set"]
for(var/d in found)
- if(!is_proper_datum(d))
+ if(!is_object_datatype(d))
continue
SDQL_internal_vv(d, set_list)
obj_count_finished++
@@ -685,47 +688,72 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
obj_count_finished = length(obj_count_finished)
state = SDQL2_STATE_SWITCHING
-/datum/SDQL2_query/proc/SDQL_print(object, list/text_list, print_nulls = TRUE)
- if(is_proper_datum(object))
- text_list += "[REF(object)] : [object]"
- if(istype(object, /atom))
- var/atom/A = object
- var/turf/T = A.loc
- var/area/a
- if(istype(T))
- text_list += " at [T] [ADMIN_COORDJMP(T)]"
- a = T.loc
- else
- var/turf/final = get_turf(T) //Recursive, hopefully?
- if(istype(final))
- text_list += " at [final] [ADMIN_COORDJMP(final)]"
- a = final.loc
+/**
+ * Recursively prints out an object to text list for SDQL2 output to admins, with VV links and all.
+ * Recursion limit: 50
+ * Limit imposed by callers should be around 10000 objects
+ * Seriously, if you hit those limits, you're doing something wrong.
+ */
+/datum/SDQL2_query/proc/SDQL_print(datum/object, list/text_list, print_nulls = TRUE, recursion = 1, linebreak = TRUE)
+ if(recursion > 50)
+ text_list += "
RECURSION LIMIT REACHED.
"
+ return
+ if(is_object_datatype(object))
+ if(!islist(object))
+ text_list += "[object.type] [REF(object)]: [object]"
+ if(istype(object, /atom))
+ if(istype(object, /turf))
+ var/turf/T = object
+ text_list += " [ADMIN_COORDJMP(T)] at [T.loc]"
else
- text_list += " at nonexistant location"
- if(a)
- text_list += " in area [a]"
- if(T.loc != a)
- text_list += " inside [T]"
- text_list += "
"
- else if(islist(object))
- var/list/L = object
- var/first = TRUE
- text_list += "\["
- for (var/x in L)
- if (!first)
- text_list += ", "
- first = FALSE
- SDQL_print(x, text_list)
- if (!isnull(x) && !isnum(x) && L[x] != null)
- text_list += " -> "
- SDQL_print(L[L[x]], text_list)
- text_list += "]
"
+ var/atom/A = object
+ var/atom/container = A.loc
+ if(isturf(container))
+ text_list += " in [container] [ADMIN_COORDJMP(container)] at [container.loc]"
+ else if(container)
+ var/turf/T = get_turf(container)
+ var/cref = REF(container)
+ text_list += " in [container]([cref])"
+ if(T)
+ text_list += " on [T] [ADMIN_COORDJMP(T)] at[T.loc]"
+ else
+ text_list += " in nullspace"
+ else // lists are snowflake and get special treatment.
+ text_list += "/list [REF(object)] \[
"
+ var/list/L = object
+ if(length(L))
+ for(var/key in object)
+ if(islist(key))
+ text_list += ""
+ SDQL_print(key, text_list, TRUE, recursion + 1, FALSE)
+ text_list += ""
+ else
+ SDQL_print(key, text_list, TRUE, recursion, FALSE)
+ if(IS_VALID_ASSOC_KEY(key) && !isnull(L[key]))
+ var/value = L[key]
+ text_list += " --> "
+ if(islist(value))
+ text_list += ""
+ SDQL_print(value, text_list, TRUE, recursion + 1, FALSE)
+ text_list += ""
+ else
+ SDQL_print(value, text_list, TRUE, recursion, FALSE)
+ text_list += "
"
+ text_list += "\]"
+ if(linebreak)
+ text_list += "
"
else
if(isnull(object))
if(print_nulls)
- text_list += "NULL
"
+ text_list += "NULL"
+ else if(istext(object))
+ text_list += "\"[object]\""
+ else if(isnum(object) || ispath(object))
+ text_list += "[object]"
else
- text_list += "[object]
"
+ text_list += "UNKNOWN: [object]"
+ if(linebreak)
+ text_list += "
"
/datum/SDQL2_query/CanProcCall()
if(!allow_admin_interact)
@@ -957,7 +985,7 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
var/static/list/exclude = list("usr", "src", "marked", "global")
var/long = start < expression.len
var/datum/D
- if(is_proper_datum(object))
+ if(is_object_datatype(object))
D = object
if (object == world && (!long || expression[start + 1] == ".") && !(expression[start] in exclude)) //3 == length("SS") + 1
@@ -1161,9 +1189,6 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
query_list += word
return query_list
-/proc/is_proper_datum(thing)
- return istype(thing, /datum) || istype(thing, /client)
-
/obj/effect/statclick/SDQL2_delete/Click()
var/datum/SDQL2_query/Q = target
Q.delete_click()
diff --git a/code/modules/admin/view_variables/debug_variables.dm b/code/modules/admin/view_variables/debug_variables.dm
index 5116cd5cd6..ab9f4a534c 100644
--- a/code/modules/admin/view_variables/debug_variables.dm
+++ b/code/modules/admin/view_variables/debug_variables.dm
@@ -16,11 +16,19 @@
header = "
"
var/item
+ var/name_part = VV_HTML_ENCODE(name)
+ if(level > 0 || islist(D)) //handling keys in assoc lists
+ if(istype(name,/datum))
+ name_part = "[VV_HTML_ENCODE(name)] [REF(name)]"
+ else if(islist(name))
+ var/list/L = name
+ name_part = " /list ([length(L)]) [REF(name)]"
+
if (isnull(value))
- item = "[VV_HTML_ENCODE(name)] = null"
+ item = "[name_part] = null"
else if (istext(value))
- item = "[VV_HTML_ENCODE(name)] = \"[VV_HTML_ENCODE(value)]\""
+ item = "[name_part] = \"[VV_HTML_ENCODE(value)]\""
else if (isicon(value))
#ifdef VARSICON
@@ -28,33 +36,31 @@
var/rnd = rand(1,10000)
var/rname = "tmp[REF(I)][rnd].png"
usr << browse_rsc(I, rname)
- item = "[VV_HTML_ENCODE(name)] = ([value])
"
+ item = "[name_part] = ([value])
"
#else
- item = "[VV_HTML_ENCODE(name)] = /icon ([value])"
+ item = "[name_part] = /icon ([value])"
#endif
else if (isfile(value))
- item = "[VV_HTML_ENCODE(name)] = '[value]'"
+ item = "[name_part] = '[value]'"
- else if(istype(value, /matrix)) // Needs to be before datum
+ else if(istype(value,/matrix)) // Needs to be before datum
var/matrix/M = value
- item = {"[VV_HTML_ENCODE(name)] =
-
- | |
-
- | [M.a] | [M.d] | 0 |
- | [M.b] | [M.e] | 0 |
- | [M.c] | [M.f] | 1 |
- |
- |
-
"} //TODO link to modify_transform wrapper for all matrices
-
+ item = {"[name_part] =
+ | |
+
+
+ | [M.a] | [M.d] | 0 |
+ | [M.b] | [M.e] | 0 |
+ | [M.c] | [M.f] | 1 |
+
+ | |
"} //TODO link to modify_transform wrapper for all matrices
else if (istype(value, /datum))
var/datum/DV = value
if ("[DV]" != "[DV.type]") //if the thing as a name var, lets use it.
- item = "[VV_HTML_ENCODE(name)] [REF(value)] = [DV] [DV.type]"
+ item = "[name_part] = [DV] [DV.type] [REF(value)]"
else
- item = "[VV_HTML_ENCODE(name)] [REF(value)] = [DV.type]"
+ item = "[name_part] = [DV.type] [REF(value)]"
else if (islist(value))
var/list/L = value
@@ -72,19 +78,19 @@
items += debug_variable(key, val, level + 1, sanitize = sanitize)
- item = "[VV_HTML_ENCODE(name)] = /list ([L.len])"
+ item = "[name_part] = /list ([L.len])"
else
- item = "[VV_HTML_ENCODE(name)] = /list ([L.len])"
+ item = "[name_part] = /list ([L.len])"
else if (name in GLOB.bitfields)
var/list/flags = list()
for (var/i in GLOB.bitfields[name])
if (value & GLOB.bitfields[name][i])
flags += i
- item = "[VV_HTML_ENCODE(name)] = [VV_HTML_ENCODE(jointext(flags, ", "))]"
+ item = "[name_part] = [VV_HTML_ENCODE(jointext(flags, ", "))]"
else
- item = "[VV_HTML_ENCODE(name)] = [VV_HTML_ENCODE(value)]"
+ item = "[name_part] = [VV_HTML_ENCODE(value)]"
return "[header][item]"
-#undef VV_HTML_ENCODE
+#undef VV_HTML_ENCODE
\ No newline at end of file