From ada32447dc6f377deabe72cddc5d0925895b36f4 Mon Sep 17 00:00:00 2001
From: NovaBot <154629622+NovaBot13@users.noreply.github.com>
Date: Mon, 22 Apr 2024 01:42:41 -0400
Subject: [PATCH] [MIRROR] Allows vv investigate /appearance + better checking
image (#2128)
* Allows vv investigate /appearance + better checking image (#82670)
* Allows vv investigate /appearance + better checking image
---------
Co-authored-by: EvilDragonfiend <87972842+EvilDragonfiend@users.noreply.github.com>
---
code/__DEFINES/vv.dm | 2 +
.../debug_variable_appearance.dm | 236 ++++++++++++++++++
.../admin/view_variables/debug_variables.dm | 9 +-
.../admin/view_variables/view_variables.dm | 47 +++-
code/modules/unit_tests/unit_test.dm | 2 +
tgstation.dme | 1 +
6 files changed, 287 insertions(+), 10 deletions(-)
create mode 100644 code/modules/admin/view_variables/debug_variable_appearance.dm
diff --git a/code/__DEFINES/vv.dm b/code/__DEFINES/vv.dm
index a83ef71ddc6..90bd77c0423 100644
--- a/code/__DEFINES/vv.dm
+++ b/code/__DEFINES/vv.dm
@@ -54,6 +54,8 @@
//Helpers for vv_get_dropdown()
#define VV_DROPDOWN_OPTION(href_key, name) . += ""
+//Same with VV_DROPDOWN_OPTION, but global proc doesn't have src
+#define VV_DROPDOWN_OPTION_APPEARANCE(thing, href_key, name) . += ""
// VV HREF KEYS
#define VV_HK_TARGET "target"
diff --git a/code/modules/admin/view_variables/debug_variable_appearance.dm b/code/modules/admin/view_variables/debug_variable_appearance.dm
new file mode 100644
index 00000000000..0d7bbb4b61c
--- /dev/null
+++ b/code/modules/admin/view_variables/debug_variable_appearance.dm
@@ -0,0 +1,236 @@
+/* < OH MY GOD. Can't you just make "/image/proc/foo()" instead of making these? >
+ * /appearance is a hardcoded byond type, and it is very internal type.
+ * Its type is actually /image, but it isn't truly /image. We defined it as "/appearance"
+ * new procs to /image will only work to actual /image references, but...
+ * /appearance references are not capable of executing procs, because these are not real /image
+ * This is why these global procs exist. Welcome to the curse.
+ */
+#define ADD_UNUSED_VAR(varlist, thing, varname) if(NAMEOF(##thing, ##varname)) ##varlist += #varname
+#define RESULT_VARIABLE_NOT_FOUND "_switch_result_variable_not_found"
+
+/// An alias datum that allows us to access and view the variables of an appearance by keeping certain known, yet undocumented, variables that we can access and read in a datum for debugging purposes.
+/// Kindly do not use this outside of a debugging context.
+/image/appearance
+ parent_type = /atom/movable // This is necessary to access the variables on compile-time.
+
+ // var/override // Sad point. We can't steal byond internal variable name
+#ifdef OPENDREAM
+ // opendream doens't support mouse_drop_zone yet. Remove this once OD supports it.
+ var/mouse_drop_zone
+#endif
+
+/image/appearance/New(loc, ...)
+ . = ..()
+ CRASH("something tried to use '/image/appearance', but this isn't actual type we use. Do not fucking do this.")
+
+/// Makes a var list of /appearance type actually uses. This will be only called once.
+/proc/build_virtual_appearance_vars()
+ var/list/used_variables = list("vis_flags") // manual listing.
+ . = used_variables
+ var/list/unused_var_names = list()
+
+ var/image/appearance/nameof_reference // We don't copy vars from this.
+ pass(nameof_reference) // compiler complains unused variable
+ ADD_UNUSED_VAR(unused_var_names, nameof_reference, appearance) // it only does self-reference
+ ADD_UNUSED_VAR(unused_var_names, nameof_reference, x) // xyz are always 0
+ ADD_UNUSED_VAR(unused_var_names, nameof_reference, y)
+ ADD_UNUSED_VAR(unused_var_names, nameof_reference, z)
+ ADD_UNUSED_VAR(unused_var_names, nameof_reference, weak_reference) // it's not a good idea to make a weak_ref on this, and this won't have it
+ ADD_UNUSED_VAR(unused_var_names, nameof_reference, vars) // inherited from /image, but /appearance hasn't this
+
+ // Even if these vars are essential for image, these only exists in an actual type
+ ADD_UNUSED_VAR(unused_var_names, nameof_reference, filter_data)
+ ADD_UNUSED_VAR(unused_var_names, nameof_reference, realized_overlays)
+ ADD_UNUSED_VAR(unused_var_names, nameof_reference, realized_underlays)
+
+ // we have no reason to show these, right?
+ ADD_UNUSED_VAR(unused_var_names, nameof_reference, _active_timers)
+ ADD_UNUSED_VAR(unused_var_names, nameof_reference, _datum_components)
+ ADD_UNUSED_VAR(unused_var_names, nameof_reference, _listen_lookup)
+ ADD_UNUSED_VAR(unused_var_names, nameof_reference, _signal_procs)
+ ADD_UNUSED_VAR(unused_var_names, nameof_reference, __auxtools_weakref_id)
+ ADD_UNUSED_VAR(unused_var_names, nameof_reference, _status_traits)
+ ADD_UNUSED_VAR(unused_var_names, nameof_reference, cooldowns)
+ ADD_UNUSED_VAR(unused_var_names, nameof_reference, datum_flags)
+ ADD_UNUSED_VAR(unused_var_names, nameof_reference, verbs)
+ ADD_UNUSED_VAR(unused_var_names, nameof_reference, gc_destroyed)
+ ADD_UNUSED_VAR(unused_var_names, nameof_reference, harddel_deets_dumped)
+ ADD_UNUSED_VAR(unused_var_names, nameof_reference, open_uis)
+ ADD_UNUSED_VAR(unused_var_names, nameof_reference, tgui_shared_states)
+
+ var/image/dummy_image = image(null, null) // actual type we'll copy variable names
+ for(var/each in dummy_image.vars) // try to inherit var list from /image
+ if(each in unused_var_names)
+ continue
+ used_variables += each
+ del(dummy_image)
+ dummy_image = null
+
+ return used_variables
+
+/// debug_variable() proc but made for /appearance type specifically
+/proc/debug_variable_appearance(var_name, appearance)
+ var/value
+ try
+ value = locate_appearance_variable(var_name, appearance)
+ catch
+ return "