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