diff --git a/citadel.dme b/citadel.dme index d4c30f09945e..02790c791cea 100644 --- a/citadel.dme +++ b/citadel.dme @@ -26,7 +26,6 @@ #include "code\__DEFINES\_lists.dm" #include "code\__DEFINES\_planes+layers.dm" #include "code\__DEFINES\_profile.dm" -#include "code\__DEFINES\_protect.dm" #include "code\__DEFINES\_tick.dm" #include "code\__DEFINES\ability.dm" #include "code\__DEFINES\access.dm" @@ -112,6 +111,7 @@ #include "code\__DEFINES\_flags\turf_flags.dm" #include "code\__DEFINES\admin\admin.dm" #include "code\__DEFINES\admin\bans.dm" +#include "code\__DEFINES\admin\introspection.dm" #include "code\__DEFINES\admin\keybindings.dm" #include "code\__DEFINES\assets\medical.dm" #include "code\__DEFINES\atmospherics\atmos.dm" @@ -2000,6 +2000,7 @@ #include "code\modules\admin\news.dm" #include "code\modules\admin\player_notes.dm" #include "code\modules\admin\player_panel.dm" +#include "code\modules\admin\reference_tracking.dm" #include "code\modules\admin\topic.dm" #include "code\modules\admin\ToRban.dm" #include "code\modules\admin\ban\ban_system.dm" @@ -2008,7 +2009,19 @@ #include "code\modules\admin\callproc\callproc.dm" #include "code\modules\admin\DB ban\functions.dm" #include "code\modules\admin\functions\modify_traits.dm" +#include "code\modules\admin\introspection\context.dm" +#include "code\modules\admin\introspection\delete.dm" +#include "code\modules\admin\introspection\internal.dm" #include "code\modules\admin\permissionverbs\permissionedit.dm" +#include "code\modules\admin\introspection\external.dm" +#include "code\modules\admin\introspection\input.dm" +#include "code\modules\admin\introspection\marking.dm" +#include "code\modules\admin\introspection\modify_datum.dm" +#include "code\modules\admin\introspection\modify_list.dm" +#include "code\modules\admin\introspection\proccall.dm" +#include "code\modules\admin\introspection\render.dm" +#include "code\modules\admin\introspection\ui.dm" +#include "code\modules\admin\introspection\verbs.dm" #include "code\modules\admin\secrets\admin_secrets\admin_logs.dm" #include "code\modules\admin\secrets\admin_secrets\alter_narsie.dm" #include "code\modules\admin\secrets\admin_secrets\bombing_list.dm" @@ -2093,7 +2106,6 @@ #include "code\modules\admin\view_variables\mark_datum.dm" #include "code\modules\admin\view_variables\mass_edit_variables.dm" #include "code\modules\admin\view_variables\modify_variables.dm" -#include "code\modules\admin\view_variables\reference_tracking.dm" #include "code\modules\admin\view_variables\topic.dm" #include "code\modules\admin\view_variables\topic_basic.dm" #include "code\modules\admin\view_variables\topic_list.dm" diff --git a/code/__DEFINES/_protect.dm b/code/__DEFINES/_protect.dm deleted file mode 100644 index c865bd363ed6..000000000000 --- a/code/__DEFINES/_protect.dm +++ /dev/null @@ -1,13 +0,0 @@ -#define GENERAL_PROTECT_DATUM(Path)\ -##Path/can_vv_get(var_name){\ - return FALSE;\ -}\ -##Path/vv_edit_var(var_name, var_value){\ - return FALSE;\ -}\ -##Path/CanProcCall(procname){\ - return FALSE;\ -}\ -##Path/can_vv_mark(){\ - return FALSE;\ -} diff --git a/code/__DEFINES/admin/bans.dm b/code/__DEFINES/admin/bans.dm index 77acce3eade4..5b7abea2e4ad 100644 --- a/code/__DEFINES/admin/bans.dm +++ b/code/__DEFINES/admin/bans.dm @@ -1,3 +1,6 @@ +//* This file is explicitly licensed under the MIT license. *// +//* Copyright (c) 2023 Citadel Station developers. *// + //? roleban types /// full server ban - currently just a shim to go to legacy isbanned, eventually just will go to server_ban.dm #define BAN_ROLE_SERVER "server" diff --git a/code/__DEFINES/admin/introspection.dm b/code/__DEFINES/admin/introspection.dm new file mode 100644 index 000000000000..7beef047ae2d --- /dev/null +++ b/code/__DEFINES/admin/introspection.dm @@ -0,0 +1,58 @@ +//* This file is explicitly licensed under the MIT license. *// +//* Copyright (c) 2023 Citadel Station developers. *// + +//* configuration + +/// this is used on all introspect client verb paths +/// use this to hook it into your admin system +#define VV_VERB_DECLARE(PATH, NAME) + +//* general + +/// when seen, we know to treat as global scope +#define VV_GLOBAL_SCOPE /datum/vv_global +/// max marks +#define VV_MAX_MARKS 50 + +//* return values for vv_edit_var + +/// forbid +#define VV_EDIT_REJECT 0 +/// perform after (default) +#define VV_EDIT_NORMAL 1 +/// allow, but handle in proc (don't actually modify) +#define VV_EDIT_HANDLED 2 + +//* return values for vv_call_proc + +/// forbid +#define VV_CALL_REJECT 0 +/// perform after (default) +#define VV_CALL_NORMAL 1 +/// allow, but handle in proc (doesn't do the normal proccall) +#define VV_CALL_HANDLED 2 +/// allow, but hint that we modified the args for them +#define VV_CALL_MUTATED 3 + +//* helpers + +/// prevent a datum from being written to +#define VV_LOCK_DATUM(path) \ +##path/can_vv_call(datum/vv_context/actor, proc_name, raw_call) { return FALSE; } \ +##path/vv_edit_var(datum/vv_context/actor, var_name, var_value, mass_edit, raw_edit) { return VV_EDIT_REJECT; } \ +##path/can_vv_delete(datum/vv_context/actor) { return FALSE; } + +/// prevent a datum from being read or written to +#define VV_FORBID_DATUM(path) \ +##path/can_vv_call(datum/vv_context/actor, proc_name, raw_call) { return FALSE; } \ +##path/vv_edit_var(datum/vv_context/actor, var_name, var_value, mass_edit, raw_edit) { return VV_EDIT_REJECT; } \ +##path/vv_get_var(datum/vv_context/actor, var_name, raw_read) { return "!vv-forbidden!"; } \ +##path/vv_var_query(datum/vv_context/actor) { return null; } \ +##path/can_vv_mark(datum/vv_context/actor) { return FALSE; } \ +##path/can_vv_bind(datum/vv_context/actor) { return FALSE; } \ +##path/can_vv_delete(datum/vv_context/actor) { return FALSE; } + +//* ui constants + +#define VV_MARK_DIRECT "N" +#define VV_MARK_BINDING "B" diff --git a/code/__DEFINES/vv.dm b/code/__DEFINES/vv.dm index c911c5e2b3ed..e7953ef664b5 100644 --- a/code/__DEFINES/vv.dm +++ b/code/__DEFINES/vv.dm @@ -1,3 +1,5 @@ + + #define VV_NUM "Number" #define VV_TEXT "Text" #define VV_MESSAGE "Mutiline Text" diff --git a/code/modules/admin/holder2.dm b/code/modules/admin/holder2.dm index 57ac0ef0e9f0..37679c9fc847 100644 --- a/code/modules/admin/holder2.dm +++ b/code/modules/admin/holder2.dm @@ -20,6 +20,9 @@ GLOBAL_PROTECT(href_token) var/datum/filter_editor/filteriffic + /// vv context + var/datum/vv_context/introspection = new + /datum/admins/New(initial_rank = "Temporary Admin", initial_rights = 0, ckey) if(!ckey) log_world("Admin datum created without a ckey argument. Datum has been deleted") @@ -41,6 +44,7 @@ GLOBAL_PROTECT(href_token) owner.holder = src owner.add_admin_verbs() //TODO GLOB.admins |= C + introspection?.active = C /datum/admins/proc/disassociate() if(owner) @@ -48,6 +52,7 @@ GLOBAL_PROTECT(href_token) owner.remove_admin_verbs() owner.deadmin_holder = owner.holder owner.holder = null + introspection?.active = null /datum/admins/proc/reassociate() if(owner) @@ -55,6 +60,7 @@ GLOBAL_PROTECT(href_token) owner.holder = src owner.deadmin_holder = null owner.add_admin_verbs() + introspection?.active = owner /* checks if usr is an admin with at least ONE of the flags in rights_required. (Note, they don't need all the flags) diff --git a/code/modules/admin/introspection/README.md b/code/modules/admin/introspection/README.md new file mode 100644 index 000000000000..cad014495150 --- /dev/null +++ b/code/modules/admin/introspection/README.md @@ -0,0 +1,14 @@ +# Introspection Module + +A fully functional, self-contained module for performing debugging and manipulation actions on the game. + +Contains the following: +- View / Edit Variables +- Function Calling +- Arbitrary Datum Marking & Retrieval +- "Backreferencing" system for contextual marking + +Limitations / Caveats: +- The entire system is namespaced on /datum, and /datum/vv_context. The system will not work without a /datum/vv_context set up. This makes it slightly fragile when doing low level debugging, when there's no assuredness of /datum/vv_context being bound / hooked correctly. +- Backreferences are **not** to be treated as a security measure. They can be freely forged via href, and are there for convenience purposes rather than security purposes. +- **Deletions** are specifically forbidden to be hooked, unlike everything else. Hooking VV deletes implies special behavior for VV, which we want to avoid because it leads to weird code practices. The only place this is changed is globally on /datum/vv_context, which is where you put codebase specific handling for things like /turfs. diff --git a/code/modules/admin/introspection/context.dm b/code/modules/admin/introspection/context.dm new file mode 100644 index 000000000000..8fb9a755cc94 --- /dev/null +++ b/code/modules/admin/introspection/context.dm @@ -0,0 +1,43 @@ +VV_LOCK_DATUM(/datum/vv_context) + +/** + * context object for vv users + * + * holds data like markings/whatnot + */ +/datum/vv_context + /// ckey + var/ckey + /// active client - keep this up to date; this should always be the client of that ckey! + var/client/active + #warn hook active + /// active marks + var/list/datum/vv_mark/marks = list() + +/datum/vv_context/proc/log_action(msg) + #warn impl + +/** + * @params + * * msg - message + * * reference - thing edited, whether it may be a datum or a list + */ +/datum/vv_context/proc/log_edit(msg, datum/reference) + #warn impl + +/** + * @params + * * target - datum being called; world for world, VV_GLOBAL_SCOPE for global + * * procname - proc name + * * params - list of params + */ +/datum/vv_context/proc/log_proccall(target, procname, list/params) + #warn impl + +/** + * @params + * * msg - message + * * reference - thing edited, whether it may be a datum or a list + */ +/datum/vv_context/proc/send_chat(msg, datum/reference) + #warn impl diff --git a/code/modules/admin/introspection/delete.dm b/code/modules/admin/introspection/delete.dm new file mode 100644 index 000000000000..7e830e392863 --- /dev/null +++ b/code/modules/admin/introspection/delete.dm @@ -0,0 +1,11 @@ +/** + * attempt to delete something + * + * @params + * * target - target datum + */ +/datum/vv_context/proc/delete_entity(datum/target) + if(!istype(target)) + send_chat("cannot delete - not a datum", target) + return FALSE + #warn impl diff --git a/code/modules/admin/introspection/external.dm b/code/modules/admin/introspection/external.dm new file mode 100644 index 000000000000..6f413d70b12b --- /dev/null +++ b/code/modules/admin/introspection/external.dm @@ -0,0 +1,111 @@ +//* This file is explicitly licensed under the MIT license. *// +//* Copyright (c) 2023 Citadel Station developers. *// + +/** + * called to get list of variables + * + * @params + * * actor - actor + * * raw_query - query requested was raw, do not inject helper / wrapper vars + * + * @return list, or null to forbid + */ +/datum/proc/vv_var_query(datum/vv_context/actor) + return vars + + +/** + * called to handle a var edit + * + * @params + * * actor - actor + * * var_name - variable name + * * var_value - variable value + * * mass_edit - mass edit op? this is set to iteration, so you can check == 1 if needed + * * raw_edit - edit requested was raw, do not do automatic handling + */ +/datum/proc/vv_edit_var(datum/vv_context/actor, var_name, var_value, mass_edit, raw_edit) + #warn overrides + return VV_EDIT_NORMAL + +/** + * called to read a variable + * + * @params + * * actor - actor + * * var_name - variable name + * * raw_read - read requested was raw, do not do automatic handling + * + * @return variable value + */ +/datum/proc/vv_get_var(datum/vv_context/actor, var_name, raw_read) + #warn overrides + #warn redo? + return vars[var_name] + +/** + * checks if we can be marked as a datum; this means someone is trying to grab a reference to us + * + * @params + * * actor - actor + */ +/datum/proc/can_vv_mark(datum/vv_context/actor) + #warn overrides + return TRUE + +/** + * checks if we can make a bind-mark to a variable name on us + * + * bound marks follows the variable, and not the thing marked + * + * @params + * * actor - actor + * * var_name - variable name + */ +/datum/proc/can_vv_bind(datum/vv_context/actor, var_name) + return TRUE + +/** + * can call a proc of a given name + * + * @params + * * actor - actor + * * proc_name - proc name + * * raw_call - call requested was raw, do ont do automatic handling + */ +/datum/proc/can_vv_call(datum/vv_context/actor, proc_name, raw_call) + return TRUE + +/** + * can call a proc of a given name with the given params + * + * @params + * * actor - actor + * * proc_name - proc name + * * proc_args - proc args, you can edit or parse this list at your own peril + * * raw_call - call requested was raw, do not do automatic handling + */ +/datum/proc/vv_call_proc(datum/vv_context/actor, proc_name, list/proc_args, raw_call) + return can_vv_call(actor, proc_name, raw_call)? VV_CALL_NORMAL : VV_CALL_REJECT + +/** + * allow vv deletes? + * + * @params + * * actor - actor + */ +/datum/proc/can_vv_delete(datum/vv_context/actor) + return TRUE + +/** + * return a list of dropdown options + * + * this does not include the base dropdowns for callproc, delete, etc + * + * @params + * * actor - actor + * + * @return list(key = name) + */ +/datum/proc/vv_dropdown(datum/vv_context/actor) + return list() diff --git a/code/modules/admin/introspection/input.dm b/code/modules/admin/introspection/input.dm new file mode 100644 index 000000000000..6720ad1ed381 --- /dev/null +++ b/code/modules/admin/introspection/input.dm @@ -0,0 +1,32 @@ +//* This file is explicitly licensed under the MIT license. *// +//* Copyright (c) 2023 Citadel Station developers. *// + +/** + * Given a specific variable name and value, intuit what datatype it should be + * + * @params + * * key - variable name, or index if source is list + * * value - variable value + * * source - (optional) datum / list that we're currently scanning variables of + */ +/proc/vv_detect_datatype(key, value, source) + #warn impl + +/** + * Request an arbitrary value. + * + * @params + * * user - who to ask + * * datatypes - (optional) list of allowed datatypes, or a single datatype. defaults to all datatype. if it's a single datatype, this datatype is forced. + * * default_datatype - (optional) default datatype to use + * * var_name - variable name + * * add_datatypes - (optional) forcefully add these datatypes to datatypes list. + * * remove_datatypes - (optional) forcefully remove these datatypes from datatypes list. overrides add_datatypes. + */ +/proc/vv_request_datatype(client/user, list/datatypes, default_datatype, var_name, list/add_datatypes, list/remove_datatypes) + var/list/retval = list( + "type" = null, + "value" = null, + ) + #warn impl + return retval diff --git a/code/modules/admin/introspection/internal.dm b/code/modules/admin/introspection/internal.dm new file mode 100644 index 000000000000..a98dcdb17bfa --- /dev/null +++ b/code/modules/admin/introspection/internal.dm @@ -0,0 +1,4 @@ +/** + * sentinel value for global scope + */ +/datum/vv_global diff --git a/code/modules/admin/introspection/marking.dm b/code/modules/admin/introspection/marking.dm new file mode 100644 index 000000000000..f2ae7e0ee278 --- /dev/null +++ b/code/modules/admin/introspection/marking.dm @@ -0,0 +1,45 @@ +//* This file is explicitly licensed under the MIT license. *// +//* Copyright (c) 2023 Citadel Station developers. *// + +/** + * essentially a softcode pointer + * + * these intentionally do not use weakrefs right now, and *will* block garbage collection! + */ +/datum/vv_mark + /// type - used for UI + var/type_enum + +/** + * get the bound object + */ +/datum/vv_mark/proc/resolve() + CRASH("?") + +/datum/vv_mark/direct + /// target datum + var/datum/target + +/datum/vv_mark/direct/resolve() + return target + +/datum/vv_mark/binding + /// target datum + var/datum/target + /// target var name + var/var_name + +/datum/vv_mark/binding/resolve() + return target?.vars[var_name] + +/** + * mark a datum + */ +/datum/vv_context/proc/mark_datum(datum/D) + +/** + * perform a binding mark on a datum + */ +/datum/vv_context/proc/bind_datum(datum/D, var_name) + +#warn impl all diff --git a/code/modules/admin/introspection/modify_datum.dm b/code/modules/admin/introspection/modify_datum.dm new file mode 100644 index 000000000000..e09597820166 --- /dev/null +++ b/code/modules/admin/introspection/modify_datum.dm @@ -0,0 +1,2 @@ +//* This file is explicitly licensed under the MIT license. *// +//* Copyright (c) 2023 Citadel Station developers. *// diff --git a/code/modules/admin/introspection/modify_list.dm b/code/modules/admin/introspection/modify_list.dm new file mode 100644 index 000000000000..e09597820166 --- /dev/null +++ b/code/modules/admin/introspection/modify_list.dm @@ -0,0 +1,2 @@ +//* This file is explicitly licensed under the MIT license. *// +//* Copyright (c) 2023 Citadel Station developers. *// diff --git a/code/modules/admin/introspection/proccall.dm b/code/modules/admin/introspection/proccall.dm new file mode 100644 index 000000000000..e09597820166 --- /dev/null +++ b/code/modules/admin/introspection/proccall.dm @@ -0,0 +1,2 @@ +//* This file is explicitly licensed under the MIT license. *// +//* Copyright (c) 2023 Citadel Station developers. *// diff --git a/code/modules/admin/introspection/render.dm b/code/modules/admin/introspection/render.dm new file mode 100644 index 000000000000..e09597820166 --- /dev/null +++ b/code/modules/admin/introspection/render.dm @@ -0,0 +1,2 @@ +//* This file is explicitly licensed under the MIT license. *// +//* Copyright (c) 2023 Citadel Station developers. *// diff --git a/code/modules/admin/introspection/ui.dm b/code/modules/admin/introspection/ui.dm new file mode 100644 index 000000000000..e09597820166 --- /dev/null +++ b/code/modules/admin/introspection/ui.dm @@ -0,0 +1,2 @@ +//* This file is explicitly licensed under the MIT license. *// +//* Copyright (c) 2023 Citadel Station developers. *// diff --git a/code/modules/admin/introspection/verbs.dm b/code/modules/admin/introspection/verbs.dm new file mode 100644 index 000000000000..8921b0110eda --- /dev/null +++ b/code/modules/admin/introspection/verbs.dm @@ -0,0 +1,42 @@ +//* This file is explicitly licensed under the MIT license. *// +//* Copyright (c) 2023 Citadel Station developers. *// + +VV_VERB_DECLARE(/client/proc/introspect_vv_rightclick, "View Variables") +/client/proc/introspect_vv_rightclick(datum/D in world) + set category = "Debug" + set name = "View Variables" + introspect_vv(D) + +/client/proc/introspect_vv(datum/D) + +VV_VERB_DECLARE(/client/proc/introspect_call_rightclick, "Atom Proccall") +/client/proc/introspect_call_rightclick(datum/D in world) + set category = "Debug" + set name = "Atom Proccall" + introspect_call(D) + +VV_VERB_DECLARE(/client/proc/introspect_call_advanced, "Advanced Proccall") +/client/proc/introspect_call_advanced() + set category = "Debug" + set name = "Advanced Proccall" + introspect_call() + +/client/proc/introspect_call(datum/D) + +VV_VERB_DECLARE(/client/proc/introspect_delete_rightclick, "Delete Entity") +/client/proc/introspect_delete_rightclick(datum/D in world) + set category = "Debug" + set name = "Delete Entity" + introspect_delete(D) + +/client/proc/introspect_delete(datum/D) + +VV_VERB_DECLARE(/client/proc/introspect_mark_rightclick, "Mark Entity") +/client/proc/introspect_mark_rightclick(datum/D in world) + set category = "Debug" + set name = "Mark Entity" + introspect_mark(D) + +/client/proc/introspect_mark(datum/D) + +#warn impl all diff --git a/code/modules/admin/view_variables/reference_tracking.dm b/code/modules/admin/reference_tracking.dm similarity index 100% rename from code/modules/admin/view_variables/reference_tracking.dm rename to code/modules/admin/reference_tracking.dm diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index 23dc06cc8aeb..bb341c648a12 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -223,6 +223,8 @@ if(is_localhost() && CONFIG_GET(flag/enable_localhost_rank)) holder = new /datum/admins("!localhost!", ALL, ckey) holder.owner = src + if(istype(holder.introspection)) + holder.introspection.active = src GLOB.admins |= src //admins |= src // this makes them not have admin. what the fuck?? // holder.associate(ckey) @@ -306,6 +308,8 @@ if(holder) add_admin_verbs() admin_memo_show() + if(istype(holder.introspection)) + holder.introspection.active = src // to_chat(src, get_message_output("memo")) // adminGreet() @@ -379,6 +383,8 @@ SSserver_maint.UpdateHubStatus() if(holder) holder.owner = null + if(istype(holder.introspection)) + holder.introspection.active = null GLOB.admins -= src //delete them on the managed one too active_mousedown_item = null