Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VV expansion: refreshing list, viewable+EDITABLE special lists, filters beta #11507

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
Open
1 change: 1 addition & 0 deletions beestation.dme
Original file line number Diff line number Diff line change
Expand Up @@ -1883,6 +1883,7 @@
#include "code\modules\admin\view_variables\topic_basic.dm"
#include "code\modules\admin\view_variables\topic_list.dm"
#include "code\modules\admin\view_variables\view_variables.dm"
#include "code\modules\admin\view_variables\vv_ghost.dm"
#include "code\modules\antagonists\eldritch.dm"
#include "code\modules\antagonists\toddsie.dm"
#include "code\modules\antagonists\_common\antag_datum.dm"
Expand Down
2 changes: 1 addition & 1 deletion code/__DEFINES/is_helpers.dm
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ GLOBAL_VAR_INIT(magic_appearance_detecting_image, new /image) // appearances are

// The filters list has the same ref type id as a filter, but isnt one and also isnt a list, so we have to check if the thing has Cut() instead
GLOBAL_VAR_INIT(refid_filter, TYPEID(filter(type="angular_blur")))
#define isfilter(thing) (!hascall(thing, "Cut") && TYPEID(thing) == GLOB.refid_filter)
#define isfilter(thing) (!islist(thing) && hascall(thing, "Cut") && TYPEID(thing) == GLOB.refid_filter)

// simple check whether or not a player is a guest using their key
#define IS_GUEST_KEY(key) (findtextEx(key, "Guest-", 1, 7))
Expand Down
37 changes: 37 additions & 0 deletions code/__DEFINES/vv.dm
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@
#define VV_HREF_TARGETREF(targetref, href_key, text) "<a href='[VV_HREF_TARGETREF_INTERNAL(targetref, href_key)]'>[text]</a>"
#define VV_HREF_TARGET_1V(target, href_key, text, varname) "<a href='[VV_HREF_TARGET_INTERNAL(target, href_key)];[VV_HK_VARNAME]=[varname]'>[text]</a>" //for stuff like basic varedits, one variable
#define VV_HREF_TARGETREF_1V(targetref, href_key, text, varname) "<a href='[VV_HREF_TARGETREF_INTERNAL(targetref, href_key)];[VV_HK_VARNAME]=[varname]'>[text]</a>"
//! Non-standard helper for special list vv. this doesn't use VV_HK_TARGET and REF because special list doesn't work in a sane sense.
#define VV_HREF_SPECIAL(special_owner, href_action, text, list_index, special_varname) "<a href='?_src_=vars;[HrefToken()];[href_action]=TRUE;special_owner=[special_owner];special_varname=[special_varname];[VV_HK_VARNAME]=[list_index]'>[text]</a>"
#define VV_HREF_SPECIAL_MENU(special_owner, href_action, special_varname) "?_src_=vars;[HrefToken()];[href_action]=TRUE;[VV_HK_DO_LIST_EDIT]=TRUE;special_owner=[special_owner];special_varname=[special_varname]"

#define GET_VV_TARGET locate(href_list[VV_HK_TARGET])
#define GET_VV_VAR_TARGET href_list[VV_HK_VARNAME]
Expand All @@ -71,6 +74,9 @@
#define VV_HK_LIST_SHUFFLE "listshuffle"
#define VV_HK_LIST_SET_LENGTH "listlen"

// I exist alone here just for special list edit. God, why.
#define VV_HK_DO_LIST_EDIT "do_vv_list_edit"

// vv_do_basic() keys
#define VV_HK_BASIC_EDIT "datumedit"
#define VV_HK_BASIC_CHANGE "datumchange"
Expand Down Expand Up @@ -179,3 +185,34 @@

/// ALWAYS render a reduced list, useful for fuckoff big datums that need to be condensed for the sake of client load
#define VV_ALWAYS_CONTRACT_LIST (1<<0)
#define VV_READ_ONLY (1<<1)


#define VV_LIST_PROTECTED (1) /// Can not vv the list. Doing vv this list is not safe.
#define VV_LIST_READ_ONLY (2) /// Can vv the list, but can not edit.
#define VV_LIST_EDITABLE (3) /// Can vv the list, and edit.

/// A list of all the special byond lists that need to be handled different by vv.
/// manually adding var name is recommanded.
GLOBAL_LIST_INIT(vv_special_lists, list(
// /datum
"vars" = VV_LIST_READ_ONLY, // This is meant to be read-only
// /atom
"overlays" = VV_LIST_EDITABLE,
"underlays" = VV_LIST_EDITABLE,
"vis_contents" = VV_LIST_EDITABLE,
"vis_locs" = VV_LIST_READ_ONLY,
"contents" = VV_LIST_EDITABLE,
"locs" = VV_LIST_READ_ONLY,
"verbs" = VV_LIST_READ_ONLY, // I don't believe anyone in live server
"filters" = VV_LIST_PROTECTED, // This is not good to change in vv, yet.
// /client
"bounds" = VV_LIST_PROTECTED, // DM document says it's read-only. Better not to edit this.
"images" = VV_LIST_EDITABLE,
"screen" = VV_LIST_EDITABLE,
))
// NOTE: this is highly attached to how /datum/vv_ghost works.

#ifndef DEBUG
GLOBAL_PROTECT(vv_special_lists) // changing this in live server is a bad idea
#endif
16 changes: 0 additions & 16 deletions code/_globalvars/lists/admin.dm
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,3 @@
GLOBAL_LIST_INIT_TYPED(smite_list, /datum/smite, init_smites())

GLOBAL_VAR_INIT(admin_notice, "") // Admin notice that all clients see when joining the server

// A list of all the special byond lists that need to be handled different by vv
GLOBAL_LIST_INIT(vv_special_lists, init_special_list_names())

/proc/init_special_list_names()
var/list/output = list()
var/obj/sacrifice = new
for(var/varname in sacrifice.vars)
var/value = sacrifice.vars[varname]
if(!islist(value))
if(!isdatum(value) && hascall(value, "Cut"))
output += varname
continue
if(isnull(locate(REF(value))))
output += varname
return output
66 changes: 48 additions & 18 deletions code/modules/admin/view_variables/debug_variables.dm
Original file line number Diff line number Diff line change
@@ -1,17 +1,32 @@
#define VV_HTML_ENCODE(thing) ( sanitize ? html_encode(thing) : thing )
/// Get displayed variable in VV variable list
/proc/debug_variable(name, value, level, datum/owner, sanitize = TRUE, display_flags = NONE) //if D is a list, name will be index, and value will be assoc value.
// variables to store values
var/index
var/list/owner_list
var/datum/vv_ghost/vv_spectre

// checks if a thing is /list, or /vv_ghost to deliver a special list, and then reassign name/value
if(owner)
if(islist(owner))
var/index = name
var/list/owner_list = owner
if(istype(owner, /datum/vv_ghost))
vv_spectre = owner
if(islist(owner) || vv_spectre)
index = name
owner_list = vv_spectre?.special_ref || owner
if (value)
name = owner_list[name] //name is really the index until this line
else
value = owner_list[name]
. = "<li style='backgroundColor:white'>([VV_HREF_TARGET_1V(owner_list, VV_HK_LIST_EDIT, "E", index)]) ([VV_HREF_TARGET_1V(owner_list, VV_HK_LIST_CHANGE, "C", index)]) ([VV_HREF_TARGET_1V(owner_list, VV_HK_LIST_REMOVE, "-", index)]) "
else
. = "<li style='backgroundColor:white'>([VV_HREF_TARGET_1V(owner, VV_HK_BASIC_EDIT, "E", name)]) ([VV_HREF_TARGET_1V(owner, VV_HK_BASIC_CHANGE, "C", name)]) ([VV_HREF_TARGET_1V(owner, VV_HK_BASIC_MASSEDIT, "M", name)]) "

// Builds text for single letter actions
if(CHECK_BITFIELD(display_flags, VV_READ_ONLY))
. = "<li style='backgroundColor:white'>(READ ONLY) "
else if(vv_spectre)
. = "<li style='backgroundColor:white'>([VV_HREF_SPECIAL(vv_spectre.special_owner, VV_HK_LIST_EDIT, "E", index, vv_spectre.special_varname)]) ([VV_HREF_SPECIAL(vv_spectre.special_owner, VV_HK_LIST_CHANGE, "C", index, vv_spectre.special_varname)]) ([VV_HREF_SPECIAL(vv_spectre.special_owner, VV_HK_LIST_REMOVE, "-", index, vv_spectre.special_varname)]) "
else if(owner_list)
. = "<li style='backgroundColor:white'>([VV_HREF_TARGET_1V(owner_list, VV_HK_LIST_EDIT, "E", index)]) ([VV_HREF_TARGET_1V(owner_list, VV_HK_LIST_CHANGE, "C", index)]) ([VV_HREF_TARGET_1V(owner_list, VV_HK_LIST_REMOVE, "-", index)]) "
else if(owner)
. = "<li style='backgroundColor:white'>([VV_HREF_TARGET_1V(owner, VV_HK_BASIC_EDIT, "E", name)]) ([VV_HREF_TARGET_1V(owner, VV_HK_BASIC_CHANGE, "C", name)]) ([VV_HREF_TARGET_1V(owner, VV_HK_BASIC_MASSEDIT, "M", name)]) "
else
. = "<li>"

Expand Down Expand Up @@ -57,9 +72,9 @@
var/image/image = value
return "<a href='?_src_=vars;[HrefToken()];Vars=[REF(value)]'>[image.type] (<span class='value'>[get_appearance_vv_summary_name(image)]</span>) [REF(value)]</a>"

if(isfilter(value))
var/datum/filter_value = value
return "/filter (<span class='value'>[filter_value.type] [REF(filter_value)]</span>)"
var/isfilter = isfilter(value)
if(isfilter && !isdatum(owner) && !isappearance(owner)) // each filter in atom.filters
return "/[value] (<span class='value'>[value:type]</span>)"

if(isfile(value))
return "<span class='value'>'[value]'</span>"
Expand All @@ -68,17 +83,32 @@
var/datum/datum_value = value
return datum_value.debug_variable_value(name, level, owner, sanitize, display_flags)

if(islist(value) || (name in GLOB.vv_special_lists)) // Some special lists arent detectable as a list through istype
// list debug
var/special_list_level = (istext(name) && isdatum(owner)) ? GLOB.vv_special_lists[name] : null
if(islist(value) || special_list_level) // Some special lists arent detectable as a list through istype
var/list/list_value = value
var/list/items = list()

// This is becuse some lists either dont count as lists or a locate on their ref will return null
var/link_vars = "Vars=[REF(value)]"
if(name in GLOB.vv_special_lists)
link_vars = "Vars=[REF(owner)];special_varname=[name]"
// Saves a list name format
var/list_name
if(isnull(special_list_level))
list_name = "list"
else if(isfilter)
list_name = "[value]"
else
list_name = "special_list"

if (!(display_flags & VV_ALWAYS_CONTRACT_LIST) && list_value.len > 0 && list_value.len <= (IS_NORMAL_LIST(list_value) ? VV_NORMAL_LIST_NO_EXPAND_THRESHOLD : VV_SPECIAL_LIST_NO_EXPAND_THRESHOLD))
for (var/i in 1 to list_value.len)
// checks if a list is safe to open. Some special list does very weird thing
var/is_unsafe_list = (special_list_level == VV_LIST_PROTECTED) || isappearance(owner)
// This is becuse some lists either dont count as lists or a locate on their ref will return null
var/link_vars = is_unsafe_list ? null : (special_list_level ? "special_owner=[REF(owner)];special_varname=[name]" : "Vars=[REF(value)]")
// do not make a href hyperlink to open a list if it's not safe. filters aren't recommended to open
var/a_open = is_unsafe_list ? null : "<a href='?_src_=vars;[HrefToken()];[link_vars]'>"
var/a_close = is_unsafe_list ? null : "</a>"

// Checks if it's too big to open, so it's gonna be folded, or not. If is_unsafe_list, it's always unfolded.
if (!(display_flags & VV_ALWAYS_CONTRACT_LIST) && length(list_value) > 0 && length(list_value) <= (IS_NORMAL_LIST(list_value) ? VV_NORMAL_LIST_NO_EXPAND_THRESHOLD : VV_SPECIAL_LIST_NO_EXPAND_THRESHOLD) || is_unsafe_list)
for (var/i in 1 to length(list_value))
var/key = list_value[i]
var/val
if (IS_NORMAL_LIST(list_value) && !isnum(key))
Expand All @@ -89,9 +119,9 @@

items += debug_variable(key, val, level + 1, sanitize = sanitize)

return "<a href='?_src_=vars;[HrefToken()];[link_vars]'>/list ([list_value.len])</a><ul>[items.Join()]</ul>"
return "[a_open]/[list_name] ([length(list_value)])[a_close]<ul>[items.Join()]</ul>"
else
return "<a href='?_src_=vars;[HrefToken()];[link_vars]'>/list ([list_value.len])</a>"
return "[a_open]/[list_name] ([length(list_value)])[a_close]"

if(name in GLOB.bitfields)
var/list/flags = list()
Expand Down
44 changes: 28 additions & 16 deletions code/modules/admin/view_variables/topic.dm
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,36 @@
if( (usr.client != src) || !src.holder || !holder.CheckAdminHref(href, href_list))
return
var/target = GET_VV_TARGET
var/vv_refresh_target /// If this var has a reference, vv window will be auto-refreshed

vv_do_basic(target, href_list, href)
if(istype(target, /datum))
var/datum/D = target
D.vv_do_topic(href_list)
// for non-standard special list
if(href_list["special_owner"])
var/special_owner = locate(href_list["special_owner"])
if(!isdatum(special_owner))
return
if(GET_VV_VAR_TARGET || href_list[VV_HK_DO_LIST_EDIT]) // if href_list["targetvar"] exists, we do vv_edit to list. if not, it's just viewing.
vv_do_list(special_owner:vars[href_list["special_varname"]], href_list)
GLOB.vv_ghost.mark_special(href_list["special_owner"], href_list["special_varname"])
vv_refresh_target = GLOB.vv_ghost
// for standard /list
else if(islist(target))
vv_do_list(target, href_list)
if(href_list["Vars"])
var/datum/vars_target = locate(href_list["Vars"])
if(href_list["special_varname"]) // Some special vars can't be located even if you have their ref, you have to use this instead
vars_target = vars_target.vars[href_list["special_varname"]]
debug_variables(vars_target)
GLOB.vv_ghost.mark_list_ref(target)
vv_refresh_target = GLOB.vv_ghost
// for standard /datum
else if(istype(target, /datum))
var/datum/D = target
D.vv_do_topic(href_list)

// if there is no `href_list["target"]`, we check `href_list["Vars"]` to see if we want see it
if(!target && !vv_refresh_target)
vv_refresh_target = locate(href_list["Vars"])
// "Vars" means we want to view-variables this thing.

if(vv_refresh_target)
debug_variables(vv_refresh_target)
return

//Stuff below aren't in dropdowns/etc.

Expand Down Expand Up @@ -122,11 +141,4 @@
log_admin(log_msg)
admin_ticket_log(L, "<font color='blue'>[log_msg]</font>")
vv_update_display(L, Text, "[newamt]")


//Finally, refresh if something modified the list.
if(href_list["datumrefresh"])
var/datum/DAT = locate(href_list["datumrefresh"])
if(istype(DAT, /datum) || istype(DAT, /client) || islist(DAT))
debug_variables(DAT)


2 changes: 1 addition & 1 deletion code/modules/admin/view_variables/topic_basic.dm
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
if(!target)
to_chat(usr, "<span class='warning'>The object you tried to expose to [C] no longer exists (nulled or hard-deled)</span>")
return
message_admins("[key_name_admin(usr)] Showed [key_name_admin(C)] a <a href='?_src_=vars;datumrefresh=[REF(target)]'>VV window</a>")
message_admins("[key_name_admin(usr)] Showed [key_name_admin(C)] a <a href='?_src_=vars;Vars=[REF(target)]'>VV window</a>")
log_admin("Admin [key_name(usr)] Showed [key_name(C)] a VV window of a [target]")
to_chat(C, "[holder.fakekey ? "an Administrator" : "[usr.client.key]"] has granted you access to view a View Variables window")
C.debug_variables(target)
Expand Down
10 changes: 10 additions & 0 deletions code/modules/admin/view_variables/topic_list.dm
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,16 @@
/client/proc/vv_do_list(list/target, href_list)
var/target_index = text2num(GET_VV_VAR_TARGET)
if(check_rights(R_VAREDIT))
if(href_list["special_varname"])
var/special_list_level = GLOB.vv_special_lists[href_list["special_varname"]]
if(special_list_level == VV_LIST_EDITABLE)
log_world("### vv_do_list() called: [src] attempted to edit a special list ([href_list["special_varname"]]) Security-level:[special_list_level](allowed)")
log_admin("[key_name(src)] attempted to edit a special list ([href_list["special_varname"]]) Security-level:[special_list_level](allowed)")
else // fuck you exploiters
log_world("### vv_do_list() called: [src] attempted to edit a special list ([href_list["special_varname"]]), but denied due to the Security-level:[special_list_level]")
log_admin("[key_name(src)] attempted to edit a special list ([href_list["special_varname"]]), but denied due to the Security-level:[special_list_level]")
message_admins("[key_name_admin(src)] attempted to edit a special list ([href_list["special_varname"]]), but denied due to the Security-level:[special_list_level]. Bonk this guy.")
return
if(target_index)
if(href_list[VV_HK_LIST_EDIT])
mod_list(target, null, "list", "contents", target_index, autodetect_class = TRUE)
Expand Down
Loading
Loading