Add /help formspec for commands and privileges (#8385)
authorSmallJoker <SmallJoker@users.noreply.github.com>
Sat, 20 Jul 2019 16:22:32 +0000 (18:22 +0200)
committerGitHub <noreply@github.com>
Sat, 20 Jul 2019 16:22:32 +0000 (18:22 +0200)
* Trigger for 'all' as well
* Add description textarea, double-click to copy

builtin/common/chatcommands.lua
builtin/common/information_formspecs.lua [new file with mode: 0644]
builtin/game/init.lua

index 52edda659baab0a89ede36a09b6c45faf6877641..71204657c976e09535f1417caed0c0c7ebea8296 100644 (file)
@@ -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 (file)
index 0000000..4e893f7
--- /dev/null
@@ -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 <cmd>)",
+                       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
+
index ab1503dee411436c9105fb4edec16431844c9300..04f0732e566b8d7f94ce9d5fe1670f13656bb002 100644 (file)
@@ -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)