summaryrefslogtreecommitdiffstats
path: root/MCServer/Plugins/InfoReg.lua
blob: 1cf68dbed8684f127f3f20eab06a8eb8b2dbc765 (plain) (blame)
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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171

-- InfoReg.lua

-- Implements registration functions that process g_PluginInfo





--- Lists all the subcommands that the player has permissions for
local function ListSubcommands(a_Player, a_Subcommands, a_CmdString)
	a_Player:SendMessage("The " .. a_CmdString .. " command requires another verb:");
	local Verbs = {};
	for cmd, info in pairs(a_Subcommands) do
		if (a_Player:HasPermission(info.Permission or "")) then
			table.insert(Verbs, a_CmdString .. " " .. cmd);
		end
	end
	table.sort(Verbs);
	for idx, verb in ipairs(Verbs) do
		a_Player:SendMessage(verb);
	end
end





--- This is a generic command callback used for handling multicommands' parent commands
-- For example, if there are "/gal save" and "/gal load" commands, this callback handles the "/gal" command
local function MultiCommandHandler(a_Split, a_Player, a_CmdString, a_CmdInfo, a_Level)
	local Verb = a_Split[a_Level + 1];
	if (Verb == nil) then
		-- No verb was specified. If there is a handler for the upper level command, call it:
		if (a_CmdInfo.Handler ~= nil) then
			return a_CmdInfo.Handler(a_Split, a_Player);
		end
		-- Let the player know they need to give a subcommand:
		ListSubcommands(a_Player, a_CmdInfo.Subcommands, a_CmdString);
		return true;
	end
	
	-- A verb was specified, look it up in the subcommands table:
	local Subcommand = a_CmdInfo.Subcommands[Verb];
	if (Subcommand == nil) then
		if (a_Level > 1) then
			-- This is a true subcommand, display the message and make MCS think the command was handled
			-- Otherwise we get weird behavior: for "/cmd verb" we get "unknown command /cmd" although "/cmd" is valid
			a_Player:SendMessage("The " .. a_CmdString .. " command doesn't support verb " .. Verb);
			return true;
		end
		-- This is a top-level command, let MCS handle the unknown message
		return false;
	end
	
	-- Check the permission:
	if not(a_Player:HasPermission(Subcommand.Permission or "")) then
		a_Player:SendMessage("You don't have permission to execute this command");
		return true;
	end
	
	-- Check if the handler is valid:
	if (Subcommand.Handler == nil) then
		if (Subcommand.Subcommands == nil) then
			LOG("Cannot find handler for command " .. a_CmdString .. " " .. Verb);
			return false;
		end
		ListSubcommands(a_Player, Subcommand.Subcommands, a_CmdString .. " " .. Verb);
		return true;
	end
	
	-- Execute:
	return Subcommand.Handler(a_Split, a_Player);
end





--- Registers all commands specified in the g_PluginInfo.Commands
function RegisterPluginInfoCommands()
	-- A sub-function that registers all subcommands of a single command, using the command's Subcommands table
	-- The a_Prefix param already contains the space after the previous command
	-- a_Level is the depth of the subcommands being registered, with 1 being the top level command
	local function RegisterSubcommands(a_Prefix, a_Subcommands, a_Level)
		assert(a_Subcommands ~= nil);
		
		-- A table that will hold aliases to subcommands temporarily, during subcommand iteration
		local AliasTable = {}
		
		-- Iterate through the subcommands, register them, and accumulate aliases:
		for cmd, info in pairs(a_Subcommands) do
			local CmdName = a_Prefix .. cmd;
			local Handler = info.Handler;
			-- Provide a special handler for multicommands:
			if (info.Subcommands ~= nil) then
				Handler = function(a_Split, a_Player)
					return MultiCommandHandler(a_Split, a_Player, CmdName, info, a_Level);
				end
			end
			
			if (Handler == nil) then
				LOGWARNING(g_PluginInfo.Name .. ": Invalid handler for command " .. CmdName .. ", command will not be registered.");
			else
				local HelpString;
				if (info.HelpString ~= nil) then
					HelpString = " - " .. info.HelpString;
				else
					HelpString = "";
				end
				cPluginManager.BindCommand(CmdName, info.Permission or "", Handler, HelpString);
				-- Register all aliases for the command:
				if (info.Alias ~= nil) then
					if (type(info.Alias) == "string") then
						info.Alias = {info.Alias};
					end
					for idx, alias in ipairs(info.Alias) do
						cPluginManager.BindCommand(a_Prefix .. alias, info.Permission or "", Handler, HelpString);
						-- Also copy the alias's info table as a separate subcommand,
						-- so that MultiCommandHandler() handles it properly. Need to off-load into a separate table
						-- than the one we're currently iterating and join after the iterating.
						AliasTable[alias] = info
					end
				end
			end  -- else (if Handler == nil)
			
			-- Recursively register any subcommands:
			if (info.Subcommands ~= nil) then
				RegisterSubcommands(a_Prefix .. cmd .. " ", info.Subcommands, a_Level + 1);
			end
		end  -- for cmd, info - a_Subcommands[]
		
		-- Add the subcommand aliases that were off-loaded during registration:
		for alias, info in pairs(AliasTable) do
			a_Subcommands[alias] = info
		end
		AliasTable = {}
	end
	
	-- Loop through all commands in the plugin info, register each:
	RegisterSubcommands("", g_PluginInfo.Commands, 1);
end





--- Registers all console commands specified in the g_PluginInfo.ConsoleCommands
function RegisterPluginInfoConsoleCommands()
	-- A sub-function that registers all subcommands of a single command, using the command's Subcommands table
	-- The a_Prefix param already contains the space after the previous command
	local function RegisterSubcommands(a_Prefix, a_Subcommands)
		assert(a_Subcommands ~= nil);
		
		for cmd, info in pairs(a_Subcommands) do
			local CmdName = a_Prefix .. cmd;
			cPluginManager.BindConsoleCommand(cmd, info.Handler, info.HelpString or "");
			-- Recursively register any subcommands:
			if (info.Subcommands ~= nil) then
				RegisterSubcommands(a_Prefix .. cmd .. " ", info.Subcommands);
			end
		end
	end
	
	-- Loop through all commands in the plugin info, register each:
	RegisterSubcommands("", g_PluginInfo.ConsoleCommands);
end