From 69bf964241666428e8d1663164a443654f51d53a Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Sat, 20 Jul 2019 18:22:32 +0200 Subject: [PATCH] Add /help formspec for commands and privileges (#8385) * Trigger for 'all' as well * Add description textarea, double-click to copy --- builtin/common/chatcommands.lua | 7 -- builtin/common/information_formspecs.lua | 145 +++++++++++++++++++++++ builtin/game/init.lua | 1 + 3 files changed, 146 insertions(+), 7 deletions(-) create mode 100644 builtin/common/information_formspecs.lua diff --git a/builtin/common/chatcommands.lua b/builtin/common/chatcommands.lua index 52edda659..71204657c 100644 --- a/builtin/common/chatcommands.lua +++ b/builtin/common/chatcommands.lua @@ -77,13 +77,6 @@ local function do_help_cmd(name, param) end table.sort(cmds) return true, gettext("Available commands:").."\n"..table.concat(cmds, "\n") - elseif INIT == "game" and param == "privs" then - local privs = {} - for priv, def in pairs(core.registered_privileges) do - privs[#privs + 1] = priv .. ": " .. def.description - end - table.sort(privs) - return true, "Available privileges:\n"..table.concat(privs, "\n") else local cmd = param local def = core.registered_chatcommands[cmd] diff --git a/builtin/common/information_formspecs.lua b/builtin/common/information_formspecs.lua new file mode 100644 index 000000000..4e893f7aa --- /dev/null +++ b/builtin/common/information_formspecs.lua @@ -0,0 +1,145 @@ +local COLOR_BLUE = "#7AF" +local COLOR_GREEN = "#7F7" +local COLOR_GRAY = "#BBB" + +local LIST_FORMSPEC = [[ + size[13,6.5] + label[0,-0.1;%s] + tablecolumns[color;tree;text;text] + table[0,0.5;12.8,5.5;list;%s;0] + button_exit[5,6;3,1;quit;%s] + ]] + +local LIST_FORMSPEC_DESCRIPTION = [[ + size[13,7.5] + label[0,-0.1;%s] + tablecolumns[color;tree;text;text] + table[0,0.5;12.8,4.8;list;%s;%i] + box[0,5.5;12.8,1.5;#000] + textarea[0.3,5.5;13.05,1.9;;;%s] + button_exit[5,7;3,1;quit;%s] + ]] + +local formspec_escape = core.formspec_escape +local check_player_privs = core.check_player_privs + + +-- CHAT COMMANDS FORMSPEC + +local mod_cmds = {} + +local function load_mod_command_tree() + mod_cmds = {} + + local check_player_privs = core.check_player_privs + for name, def in pairs(core.registered_chatcommands) do + mod_cmds[def.mod_origin] = mod_cmds[def.mod_origin] or {} + local cmds = mod_cmds[def.mod_origin] + + -- Could be simplified, but avoid the priv checks whenever possible + cmds[#cmds + 1] = { name, def } + end + local sorted_mod_cmds = {} + for modname, cmds in pairs(mod_cmds) do + table.sort(cmds, function(a, b) return a[1] < b[1] end) + sorted_mod_cmds[#sorted_mod_cmds + 1] = { modname, cmds } + end + table.sort(sorted_mod_cmds, function(a, b) return a[1] < b[1] end) + mod_cmds = sorted_mod_cmds +end + +core.after(0, load_mod_command_tree) + +local function build_chatcommands_formspec(name, sel, copy) + local rows = {} + rows[1] = "#FFF,0,Command,Parameters" + + local description = "For more information, click on any entry in the list.\n" .. + "Double-click to copy the entry to the chat history." + + for i, data in ipairs(mod_cmds) do + rows[#rows + 1] = COLOR_BLUE .. ",0," .. formspec_escape(data[1]) .. "," + for j, cmds in ipairs(data[2]) do + local has_priv = check_player_privs(name, cmds[2].privs) + rows[#rows + 1] = ("%s,1,%s,%s"):format( + has_priv and COLOR_GREEN or COLOR_GRAY, + cmds[1], formspec_escape(cmds[2].params)) + if sel == #rows then + description = cmds[2].description + if copy then + core.chat_send_player(name, ("Command: %s %s"):format( + core.colorize("#0FF", "/" .. cmds[1]), cmds[2].params)) + end + end + end + end + + return LIST_FORMSPEC_DESCRIPTION:format( + "Available commands: (see also: /help )", + table.concat(rows, ","), sel or 0, + description, "Close" + ) +end + + +-- PRIVILEGES FORMSPEC + +local function build_privs_formspec(name) + local privs = {} + for name, def in pairs(core.registered_privileges) do + privs[#privs + 1] = { name, def } + end + table.sort(privs, function(a, b) return a[1] < b[1] end) + + local rows = {} + rows[1] = "#FFF,0,Privilege,Description" + + local player_privs = core.get_player_privs(name) + for i, data in ipairs(privs) do + rows[#rows + 1] = ("%s,0,%s,%s"):format( + player_privs[data[1]] and COLOR_GREEN or COLOR_GRAY, + data[1], formspec_escape(data[2].description)) + end + + return LIST_FORMSPEC:format( + "Available privileges:", + table.concat(rows, ","), + "Close" + ) +end + + +-- DETAILED CHAT COMMAND INFORMATION + +core.register_on_player_receive_fields(function(player, formname, fields) + if formname ~= "__builtin:help_cmds" or fields.quit then + return + end + + local event = minetest.explode_table_event(fields.list) + if event.type ~= "INV" then + local name = player:get_player_name() + core.show_formspec(name, "__builtin:help_cmds", + build_chatcommands_formspec(name, event.row, event.type == "DCL")) + end +end) + + +local help_command = core.registered_chatcommands["help"] +local old_help_func = help_command.func + +help_command.func = function(name, param) + if param == "privs" then + core.show_formspec(name, "__builtin:help_privs", + build_privs_formspec(name)) + return + end + if param == "" or param == "all" then + core.show_formspec(name, "__builtin:help_cmds", + build_chatcommands_formspec(name)) + return + end + + old_help_func(name, param) +end + diff --git a/builtin/game/init.lua b/builtin/game/init.lua index ab1503dee..04f0732e5 100644 --- a/builtin/game/init.lua +++ b/builtin/game/init.lua @@ -25,6 +25,7 @@ dofile(gamepath.."privileges.lua") dofile(gamepath.."auth.lua") dofile(commonpath .. "chatcommands.lua") dofile(gamepath.."chatcommands.lua") +dofile(commonpath .. "information_formspecs.lua") dofile(gamepath.."static_spawn.lua") dofile(gamepath.."detached_inventory.lua") assert(loadfile(gamepath.."falling.lua"))(builtin_shared)