summaryrefslogtreecommitdiff
path: root/builtin/common/information_formspecs.lua
blob: 8afa5bc87cbbb253e9836b2c0724fd6ee03ecea4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
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 = {}

	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 priv_name, def in pairs(core.registered_privileges) do
		privs[#privs + 1] = { priv_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)
	local admin = core.settings:get("name")

	-- If the admin ran help, put the output in the chat buffer as well to
	-- work with the server terminal
	if param == "privs" then
		core.show_formspec(name, "__builtin:help_privs",
			build_privs_formspec(name))
		if name ~= admin then
			return true
		end
	end
	if param == "" or param == "all" then
		core.show_formspec(name, "__builtin:help_cmds",
			build_chatcommands_formspec(name))
		if name ~= admin then
			return true
		end
	end

	return old_help_func(name, param)
end