Parent Directory | Revision Log
Revision 44 - (view) (download)
1 : | ian | 17 | /* AMX Mod X |
2 : | * Plugin Cvar and Command Menu | ||
3 : | * | ||
4 : | * by the AMX Mod X Development Team | ||
5 : | * | ||
6 : | * This file is part of AMX Mod X. | ||
7 : | * | ||
8 : | * | ||
9 : | * This program is free software; you can redistribute it and/or modify it | ||
10 : | * under the terms of the GNU General Public License as published by the | ||
11 : | * Free Software Foundation; either version 2 of the License, or (at | ||
12 : | * your option) any later version. | ||
13 : | * | ||
14 : | * This program is distributed in the hope that it will be useful, but | ||
15 : | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 : | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 : | * General Public License for more details. | ||
18 : | * | ||
19 : | * You should have received a copy of the GNU General Public License | ||
20 : | * along with this program; if not, write to the Free Software Foundation, | ||
21 : | * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
22 : | * | ||
23 : | * In addition, as a special exception, the author gives permission to | ||
24 : | * link the code of this program with the Half-Life Game Engine ("HL | ||
25 : | * Engine") and Modified Game Libraries ("MODs") developed by Valve, | ||
26 : | * L.L.C ("Valve"). You must obey the GNU General Public License in all | ||
27 : | * respects for all of the code used other than the HL Engine and MODs | ||
28 : | * from Valve. If you modify this file, you may extend this exception | ||
29 : | * to your version of the file, but you are not obligated to do so. If | ||
30 : | * you do not wish to do so, delete this exception statement from your | ||
31 : | * version. | ||
32 : | */ | ||
33 : | |||
34 : | #include <amxmodx> | ||
35 : | #include <amxmisc> | ||
36 : | |||
37 : | |||
38 : | |||
39 : | new DisabledCallback; | ||
40 : | new EnabledCallback; | ||
41 : | |||
42 : | // pcvar that the client is currently modifying | ||
43 : | new CurrentCvar[33]; | ||
44 : | |||
45 : | // Name of the cvar being modified | ||
46 : | new CurrentCvarName[33][32]; | ||
47 : | |||
48 : | // Plugin ID that the client is modifying | ||
49 : | new CurrentPlid[33]; | ||
50 : | |||
51 : | // Page that the client is currently on | ||
52 : | new CurrentPage[33]; | ||
53 : | |||
54 : | // Menu function ID that the client is in | ||
55 : | new CurrentMenuFunction[33] = { -1,... }; | ||
56 : | |||
57 : | new CurrentCommand[33][32]; | ||
58 : | ian | 44 | new cvarmenu_cmdid; |
59 : | new cmdmenu_cmdid; | ||
60 : | ian | 17 | |
61 : | new ExplicitPlugin[33]; | ||
62 : | |||
63 : | public plugin_init() | ||
64 : | { | ||
65 : | register_plugin("Plugin Menu",AMXX_VERSION_STR,"AMXX Dev Team"); | ||
66 : | |||
67 : | register_dictionary("common.txt"); | ||
68 : | register_dictionary("pausecfg.txt"); // Needed for PAUSE_COULDNT_FIND | ||
69 : | |||
70 : | ian | 44 | cvarmenu_cmdid=register_clcmd("amx_plugincvarmenu", "CvarMenuCommand", ADMIN_CVAR, " - displays the plugin cvar menu"); |
71 : | cmdmenu_cmdid=register_clcmd("amx_plugincmdmenu", "CommandMenuCommand", ADMIN_MENU, " - displays the plugin command menu"); | ||
72 : | ian | 17 | |
73 : | register_clcmd("amx_changecvar","CommandChangeCvar"); | ||
74 : | register_clcmd("amx_executecmd","CommandExecuteCommand"); | ||
75 : | |||
76 : | // Register global menu callbacks. | ||
77 : | DisabledCallback=menu_makecallback("AlwaysDisableCallback"); | ||
78 : | EnabledCallback=menu_makecallback("AlwaysEnableCallback"); | ||
79 : | } | ||
80 : | |||
81 : | // Add these menus to the amxmodmenu | ||
82 : | public plugin_cfg() | ||
83 : | { | ||
84 : | ian | 44 | set_task(0.1, "addToMenuFront"); |
85 : | } | ||
86 : | public addToMenuFront() | ||
87 : | { | ||
88 : | ian | 17 | new PluginFileName[64]; |
89 : | |||
90 : | get_plugin(-1, PluginFileName, charsmax(PluginFileName)); | ||
91 : | ian | 44 | new cvarflags; |
92 : | new cmdflags; | ||
93 : | new garbage[1]; | ||
94 : | new cmd[32]; | ||
95 : | |||
96 : | get_concmd(cmdmenu_cmdid, cmd, charsmax(cmd), cmdflags, garbage, charsmax(garbage), -1); | ||
97 : | |||
98 : | if (strcmp(cmd, "amx_plugincmdmenu") != 0) | ||
99 : | { | ||
100 : | // this should never happen, but just incase! | ||
101 : | cmdflags = ADMIN_MENU; | ||
102 : | } | ||
103 : | get_concmd(cvarmenu_cmdid, cmd, charsmax(cmd), cvarflags, garbage, charsmax(garbage), -1); | ||
104 : | |||
105 : | if (strcmp(cmd, "amx_plugincvarmenu") != 0) | ||
106 : | { | ||
107 : | // this should never happen, but just incase! | ||
108 : | cvarflags = ADMIN_CVAR; | ||
109 : | } | ||
110 : | |||
111 : | AddMenuItem("Plugin Cvars", "amx_plugincvarmenu", cvarflags, PluginFileName); | ||
112 : | AddMenuItem("Plugin Commands", "amx_plugincmdmenu", cmdflags, PluginFileName); | ||
113 : | ian | 17 | } |
114 : | |||
115 : | // Reset all fields for each client as they connect. | ||
116 : | public client_connect(id) | ||
117 : | { | ||
118 : | CurrentCvar[id]=0; | ||
119 : | CurrentPlid[id]=0; | ||
120 : | CurrentMenuFunction[id]=-1; | ||
121 : | CurrentCvarName[id][0]=0; | ||
122 : | CurrentCommand[id][0]=0; | ||
123 : | ExplicitPlugin[id]=-1; | ||
124 : | |||
125 : | } | ||
126 : | |||
127 : | /** | ||
128 : | * Creates a plugin list menu. | ||
129 : | * | ||
130 : | * @param MenuText The text to display as the title. | ||
131 : | * @param Handler The function to call when an item is selected. | ||
132 : | * @param Command The function to pass to the handler. It will be passed as "PLID Command". | ||
133 : | * @param Callback Function to call for each plugin to be listed. Displays a number next to it (how many cvars, etc.) | ||
134 : | */ | ||
135 : | stock DisplayPluginMenu(id,const MenuText[], const Handler[], const Command[], const Callback[]) | ||
136 : | { | ||
137 : | new Menu=menu_create(MenuText,Handler); | ||
138 : | |||
139 : | |||
140 : | new PluginState[32]; | ||
141 : | new PluginName[64]; | ||
142 : | new func=get_func_id(Callback); | ||
143 : | new tally; | ||
144 : | new PluginCmd[64]; | ||
145 : | new MenuText[64]; | ||
146 : | for (new i=0, max=get_pluginsnum(); | ||
147 : | i<max; | ||
148 : | i++) | ||
149 : | { | ||
150 : | if (callfunc_begin_i(func,-1)==1) | ||
151 : | { | ||
152 : | callfunc_push_int(i); // push the plid | ||
153 : | if ((tally=callfunc_end())>0) | ||
154 : | { | ||
155 : | get_plugin(i,"",0,PluginName,sizeof(PluginName)-1,"",0,"",0,PluginState,sizeof(PluginState)-1); | ||
156 : | |||
157 : | // Command syntax is: "# Function", # being plugin ID, function being public function to call. | ||
158 : | formatex(PluginCmd,sizeof(PluginCmd)-1,"%d %s",i,Command); | ||
159 : | formatex(MenuText,sizeof(MenuText)-1,"%s - %d",PluginName,tally); | ||
160 : | // If the plugin is running, add this as an activated menu item. | ||
161 : | if (strcmp(PluginState,"running",true)==0 || | ||
162 : | strcmp(PluginState,"debug", true)==0) | ||
163 : | { | ||
164 : | menu_additem(Menu,MenuText,PluginCmd,EnabledCallback); | ||
165 : | } | ||
166 : | else | ||
167 : | { | ||
168 : | menu_additem(Menu,MenuText,"",_,DisabledCallback); | ||
169 : | } | ||
170 : | } | ||
171 : | } | ||
172 : | } | ||
173 : | |||
174 : | menu_setprop(Menu,MPROP_NUMBER_COLOR,"\y"); | ||
175 : | menu_setprop(Menu,MPROP_EXIT,MEXIT_ALL); | ||
176 : | menu_display(id,Menu,0); | ||
177 : | |||
178 : | } | ||
179 : | |||
180 : | /** | ||
181 : | * Byrefs the plugin id of a target plugin (passed by argv(1)), but only if it's valid. | ||
182 : | * | ||
183 : | * @param id id of the display messages to upon failure. | ||
184 : | * @param plid Variable to byref the plugin id. | ||
185 : | * @return True on successful lookup, false on failure. | ||
186 : | */ | ||
187 : | stock bool:GetPlidForValidPlugins(id, &plid) | ||
188 : | { | ||
189 : | // If arguments have been passed, then we were given | ||
190 : | // a specific plugin to examine. | ||
191 : | if (read_argc()>1) | ||
192 : | { | ||
193 : | // Yes, we were provided a plugin. | ||
194 : | new TargetPlugin[64]; | ||
195 : | read_argv(1,TargetPlugin,sizeof(TargetPlugin)-1); | ||
196 : | |||
197 : | new BufferName[64]; | ||
198 : | new BufferFile[64]; | ||
199 : | new BufferState[64]; | ||
200 : | // Scan for the plugin ID. | ||
201 : | for (new i=0, max=get_pluginsnum(); | ||
202 : | i<max; | ||
203 : | i++) | ||
204 : | { | ||
205 : | get_plugin(i,BufferFile,sizeof(BufferFile)-1,BufferName,sizeof(BufferName)-1,"",0,"",0,BufferState,sizeof(BufferState)-1); | ||
206 : | |||
207 : | if (strcmp(BufferFile,TargetPlugin,true) != 0|| | ||
208 : | strcmp(BufferName,TargetPlugin,true) != 0) | ||
209 : | { | ||
210 : | // We have a match. | ||
211 : | |||
212 : | // Check the status of the plugin. If it's anything other than "running" or "debug" fail. | ||
213 : | if (strcmp(BufferState,"running") != 0 && | ||
214 : | strcmp(BufferState,"debug") != 0) | ||
215 : | { | ||
216 : | // TODO: ML This | ||
217 : | console_print(id,"Plugin ^"%s^" is not running.",BufferFile); | ||
218 : | // Return a failed state. | ||
219 : | return false; | ||
220 : | } | ||
221 : | plid=i; | ||
222 : | break; | ||
223 : | } | ||
224 : | } | ||
225 : | |||
226 : | // If the plugin was not found, then tell them there was an error. | ||
227 : | if (plid==-1) | ||
228 : | { | ||
229 : | console_print(id, "%L", id, "PAUSE_COULDNT_FIND", TargetPlugin); | ||
230 : | |||
231 : | // return a failure state | ||
232 : | return false; | ||
233 : | } | ||
234 : | } | ||
235 : | |||
236 : | return true; | ||
237 : | } | ||
238 : | |||
239 : | /** | ||
240 : | * Returns the number of cvars available for a plugin by plid. (Callback for the plugin menu.) | ||
241 : | * | ||
242 : | * @return number of cvars in the plugin. | ||
243 : | */ | ||
244 : | public GetNumberOfCvarsForPlid(plid) | ||
245 : | { | ||
246 : | new count=0; | ||
247 : | new CvarPlid; | ||
248 : | for (new i=0, max=get_plugins_cvarsnum(); | ||
249 : | i<max; | ||
250 : | i++) | ||
251 : | { | ||
252 : | get_plugins_cvar(i, "", 0,_, CvarPlid, _); | ||
253 : | |||
254 : | if (CvarPlid==plid) | ||
255 : | { | ||
256 : | count++; | ||
257 : | } | ||
258 : | } | ||
259 : | |||
260 : | return count; | ||
261 : | } | ||
262 : | /** | ||
263 : | * Returns the number of commands available for a plugin by plid. (Callback for the plugin menu.) | ||
264 : | * | ||
265 : | * @return Number of valid commands in the plugin. | ||
266 : | */ | ||
267 : | public GetNumberOfCmdsForPlid(plid) | ||
268 : | { | ||
269 : | new count=0; | ||
270 : | |||
271 : | for (new i=0, max=get_concmdsnum(-1,-1); | ||
272 : | i<max; | ||
273 : | i++) | ||
274 : | { | ||
275 : | if (get_concmd_plid(i,-1,-1)==plid) | ||
276 : | { | ||
277 : | count++; | ||
278 : | } | ||
279 : | } | ||
280 : | |||
281 : | return count; | ||
282 : | } | ||
283 : | |||
284 : | /** | ||
285 : | * Whether or not the client has access to modify this cvar. | ||
286 : | * | ||
287 : | * @param id The admin id. | ||
288 : | * @param Cvar The name of the cvar to be checked. | ||
289 : | * @return True if the client has access, false otherwise. | ||
290 : | */ | ||
291 : | stock bool:CanIModifyCvar(id, const Cvar[]) | ||
292 : | { | ||
293 : | new UserFlags=get_user_flags(id); | ||
294 : | // If the user has rcon access don't bother checking anything. | ||
295 : | if (UserFlags & ADMIN_RCON) | ||
296 : | { | ||
297 : | return true; | ||
298 : | } | ||
299 : | |||
300 : | // If the cvar is "sv_password" (somehow), then check access. | ||
301 : | if (equali(Cvar,"sv_password") && UserFlags & ADMIN_PASSWORD) | ||
302 : | { | ||
303 : | return true; | ||
304 : | } | ||
305 : | |||
306 : | // Check to see if the cvar is flagged as protected. | ||
307 : | if (get_cvar_flags(Cvar) & FCVAR_PROTECTED) | ||
308 : | { | ||
309 : | // non-rcon user trying to modify a protected cvar. | ||
310 : | return false; | ||
311 : | } | ||
312 : | |||
313 : | // All known checks done, they can change this cvar if they | ||
314 : | // were able to open the menu. | ||
315 : | return true; | ||
316 : | } | ||
317 : | |||
318 : | /** | ||
319 : | * Simple function to ensure that a menu item is always disabled. | ||
320 : | * | ||
321 : | * All parameters are dummy, nothing is used. | ||
322 : | */ | ||
323 : | public AlwaysDisableCallback(playerid, menuid, itemid) | ||
324 : | { | ||
325 : | return ITEM_DISABLED; | ||
326 : | } | ||
327 : | /** | ||
328 : | * Simple function to ensure that a menu item is always enabled. | ||
329 : | * | ||
330 : | * All parameters are dummy, nothing is used. | ||
331 : | */ | ||
332 : | public AlwaysEnableCallback(playerid, menuid, itemid) | ||
333 : | { | ||
334 : | return ITEM_ENABLED; | ||
335 : | } | ||
336 : | /** | ||
337 : | * Handler for the plugin menu. | ||
338 : | * | ||
339 : | * @param id The client selecting an item. | ||
340 : | * @param menu The menu handle. | ||
341 : | * @param item The item number that was selected. | ||
342 : | */ | ||
343 : | public PluginMenuSelection(id, menu, item) | ||
344 : | { | ||
345 : | if (item==MENU_EXIT) | ||
346 : | { | ||
347 : | menu_destroy(menu); | ||
348 : | } | ||
349 : | if (item<0) | ||
350 : | { | ||
351 : | return PLUGIN_HANDLED; | ||
352 : | } | ||
353 : | |||
354 : | new Command[64]; | ||
355 : | new Dummy[1]; | ||
356 : | |||
357 : | // All of the commands set for each item is the public | ||
358 : | // function that we want to call after the item is selected. | ||
359 : | // The parameters are: function(idPlayer,itemnumber) | ||
360 : | // Note the menu is destroyed BEFORE the command | ||
361 : | // gets executed. | ||
362 : | // The command retrieved is in the format: "PLID Command" | ||
363 : | menu_item_getinfo(menu, item, Dummy[0], Command, sizeof(Command)-1,Dummy,0,Dummy[0]); | ||
364 : | |||
365 : | |||
366 : | new plid=str_to_num(Command); | ||
367 : | new Function[32]; | ||
368 : | |||
369 : | for (new i=0;i<sizeof(Command)-1;i++) | ||
370 : | { | ||
371 : | if (Command[i]==' ') | ||
372 : | { | ||
373 : | // we're at the break. move up one space. | ||
374 : | i++; | ||
375 : | copy(Function,sizeof(Function)-1,Command[i]); | ||
376 : | break; | ||
377 : | } | ||
378 : | } | ||
379 : | |||
380 : | menu_destroy(menu); | ||
381 : | |||
382 : | new funcid=get_func_id(Function); | ||
383 : | if (funcid != -1 && callfunc_begin_i(funcid)==1) | ||
384 : | { | ||
385 : | CurrentPage[id]=0; | ||
386 : | CurrentPlid[id]=plid; | ||
387 : | CurrentMenuFunction[id]=funcid; | ||
388 : | callfunc_push_int(id); | ||
389 : | callfunc_push_int(plid); | ||
390 : | callfunc_push_int(0); | ||
391 : | callfunc_end(); | ||
392 : | |||
393 : | } | ||
394 : | return PLUGIN_HANDLED; | ||
395 : | } | ||
396 : | |||
397 : | /** | ||
398 : | * The command to change a cvar has been called. | ||
399 : | * | ||
400 : | * @param id The client who is changing the cvar. | ||
401 : | */ | ||
402 : | public CommandChangeCvar(id) | ||
403 : | { | ||
404 : | // All access checks are done before this command is called. | ||
405 : | // So if the client has no pcvar pointer in his array slot | ||
406 : | // then just ignore the command. | ||
407 : | if (CurrentCvar[id]==0) | ||
408 : | { | ||
409 : | return PLUGIN_CONTINUE; | ||
410 : | } | ||
411 : | |||
412 : | new Args[256]; | ||
413 : | |||
414 : | read_args(Args,sizeof(Args)-1); | ||
415 : | |||
416 : | remove_quotes(Args); | ||
417 : | |||
418 : | if (equali(Args,"!cancel",7)) | ||
419 : | { | ||
420 : | // The client didn't want to change this cvar. | ||
421 : | client_print(id,print_chat,"[AMXX] Cvar not changed."); | ||
422 : | } | ||
423 : | else | ||
424 : | { | ||
425 : | // Changed to set_cvar_* for 1.76 tests | ||
426 : | |||
427 : | new pointer=CurrentCvar[id]; | ||
428 : | set_pcvar_string(CurrentCvar[id],Args); | ||
429 : | |||
430 : | client_print(id,print_chat,"[AMXX] Cvar ^"%s^" changed to ^"%s^"",CurrentCvarName[id],Args); | ||
431 : | |||
432 : | // Copy of admincmd's global output. | ||
433 : | |||
434 : | new Name[32]; | ||
435 : | new AuthID[40]; | ||
436 : | |||
437 : | get_user_name(id,Name,sizeof(Name)-1); | ||
438 : | get_user_authid(id,AuthID,sizeof(AuthID)-1); | ||
439 : | |||
440 : | log_amx("Cmd: ^"%s<%d><%s><>^" set cvar (name ^"%s^") (value ^"%s^")", Name, get_user_userid(id), AuthID, CurrentCvarName[id], Args); | ||
441 : | |||
442 : | |||
443 : | new cvar_val[64]; | ||
444 : | new maxpl = get_maxplayers(); | ||
445 : | for (new i = 1; i <= maxpl; i++) | ||
446 : | { | ||
447 : | if (is_user_connected(i) && !is_user_bot(i)) | ||
448 : | { | ||
449 : | if (get_pcvar_flags(pointer) & FCVAR_PROTECTED || equali(Args, "rcon_password")) | ||
450 : | { | ||
451 : | formatex(cvar_val, charsmax(cvar_val), "*** %L ***", i, "PROTECTED"); | ||
452 : | } | ||
453 : | else | ||
454 : | { | ||
455 : | copy(cvar_val, charsmax(cvar_val), Args); | ||
456 : | } | ||
457 : | show_activity_id(i, id, Name, "%L", i, "SET_CVAR_TO", "", CurrentCvarName[id], cvar_val); | ||
458 : | } | ||
459 : | } | ||
460 : | console_print(id, "[AMXX] %L", id, "CVAR_CHANGED", CurrentCvarName[id], Args); | ||
461 : | |||
462 : | } | ||
463 : | |||
464 : | // Now redraw the menu for the client | ||
465 : | if (CurrentMenuFunction[id]!=-1 && callfunc_begin_i(CurrentMenuFunction[id])==1) | ||
466 : | { | ||
467 : | callfunc_push_int(id); | ||
468 : | callfunc_push_int(CurrentPlid[id]); | ||
469 : | callfunc_push_int(CurrentPage[id]); | ||
470 : | callfunc_end(); | ||
471 : | } | ||
472 : | |||
473 : | return PLUGIN_HANDLED; | ||
474 : | } | ||
475 : | |||
476 : | /** | ||
477 : | * Process a selection from the cvar menu. | ||
478 : | * | ||
479 : | * @param id The client who chose an item. | ||
480 : | * @param menu The menu handle. | ||
481 : | * @param item The item that has been selected. | ||
482 : | */ | ||
483 : | public CvarMenuSelection(id, menu, item) | ||
484 : | { | ||
485 : | |||
486 : | if (item==MENU_EXIT) | ||
487 : | { | ||
488 : | menu_destroy(menu); | ||
489 : | |||
490 : | if (ExplicitPlugin[id]==-1) | ||
491 : | { | ||
492 : | client_cmd(id,"amx_plugincvarmenu"); | ||
493 : | } | ||
494 : | return PLUGIN_HANDLED; | ||
495 : | } | ||
496 : | else if (item==MENU_BACK) | ||
497 : | { | ||
498 : | --CurrentPage[id]; | ||
499 : | client_print(id,print_chat,"MENU_BACK"); | ||
500 : | return PLUGIN_HANDLED; | ||
501 : | } | ||
502 : | else if (item==MENU_MORE) | ||
503 : | { | ||
504 : | ++CurrentPage[id]; | ||
505 : | client_print(id,print_chat,"MENU_MORE"); | ||
506 : | return PLUGIN_HANDLED; | ||
507 : | } | ||
508 : | else | ||
509 : | { | ||
510 : | new CvarName[64]; | ||
511 : | new Command[32]; | ||
512 : | new Dummy[1]; | ||
513 : | // pcvar pointer is stored in command, extract the name of the cvar from the name field. | ||
514 : | menu_item_getinfo(menu, item, Dummy[0], Command, sizeof(Command)-1,CvarName,sizeof(CvarName)-1,Dummy[0]); | ||
515 : | |||
516 : | CurrentCvar[id]=str_to_num(Command); | ||
517 : | |||
518 : | if (CurrentCvar[id]==0) // This should never happen, but just incase.. | ||
519 : | { | ||
520 : | client_print(id,print_chat,"[AMXX] There was an error extracting the cvar pointer. (Name=^"%s^")",CvarName); | ||
521 : | return PLUGIN_HANDLED; | ||
522 : | } | ||
523 : | // TODO: ML this | ||
524 : | |||
525 : | // Scan up "CvarName" and stop at the first space | ||
526 : | for (new i=0;i<sizeof(CvarName)-1;i++) | ||
527 : | { | ||
528 : | if (CvarName[i]==' ') | ||
529 : | { | ||
530 : | CvarName[i]='^0'; | ||
531 : | break; | ||
532 : | } | ||
533 : | } | ||
534 : | copy(CurrentCvarName[id],sizeof(CurrentCvarName[])-1,CvarName); | ||
535 : | client_print(id,print_chat,"[AMXX] Type in the new value for %s, or !cancel to cancel.",CvarName); | ||
536 : | client_cmd(id,"messagemode amx_changecvar"); | ||
537 : | |||
538 : | menu_destroy(menu); | ||
539 : | return PLUGIN_HANDLED; | ||
540 : | } | ||
541 : | |||
542 : | return 0; | ||
543 : | } | ||
544 : | /** | ||
545 : | * Displays the cvar menu to a client. | ||
546 : | * | ||
547 : | * @param id id of the client. | ||
548 : | * @param plid Plugin ID to display cvars from. | ||
549 : | * @param page Page of the menu to start at. | ||
550 : | */ | ||
551 : | public DisplayCvarMenu(id, plid, page) | ||
552 : | { | ||
553 : | new PluginName[32]; | ||
554 : | new MenuTitle[64]; | ||
555 : | get_plugin(plid,"",0,PluginName,sizeof(PluginName)-1,"",0,"",0,"",0); | ||
556 : | |||
557 : | formatex(MenuTitle,sizeof(MenuTitle)-1,"%s Cvars:",PluginName); | ||
558 : | |||
559 : | new Menu=menu_create(MenuTitle,"CvarMenuSelection"); | ||
560 : | |||
561 : | new Cvar[64]; | ||
562 : | new CvarPlid; | ||
563 : | new CvarText[64]; | ||
564 : | new CvarData[32]; | ||
565 : | new CvarPtr; | ||
566 : | |||
567 : | for (new i=0, max=get_plugins_cvarsnum(); | ||
568 : | i<max; | ||
569 : | i++) | ||
570 : | { | ||
571 : | get_plugins_cvar(i, Cvar, sizeof(Cvar),_, CvarPlid, CvarPtr); | ||
572 : | |||
573 : | if (CvarPlid==plid) | ||
574 : | { | ||
575 : | if (CanIModifyCvar(id,Cvar)) | ||
576 : | { | ||
577 : | get_pcvar_string(CvarPtr,CvarData,sizeof(CvarData)-1); | ||
578 : | formatex(CvarText,sizeof(CvarText)-1,"%s - %s",Cvar,CvarData); | ||
579 : | |||
580 : | // Now store the pcvar data in Cvar | ||
581 : | num_to_str(CvarPtr,Cvar,sizeof(Cvar)-1); | ||
582 : | menu_additem(Menu,CvarText,Cvar,_,EnabledCallback); | ||
583 : | } | ||
584 : | else | ||
585 : | { | ||
586 : | menu_additem(Menu,Cvar,"",_,DisabledCallback); | ||
587 : | } | ||
588 : | |||
589 : | } | ||
590 : | } | ||
591 : | |||
592 : | menu_setprop(Menu,MPROP_EXIT,MEXIT_ALL); | ||
593 : | menu_setprop(Menu,MPROP_NUMBER_COLOR,"\y"); | ||
594 : | menu_display(id,Menu,page); | ||
595 : | |||
596 : | } | ||
597 : | /** | ||
598 : | * Process the "amx_plugincvarmenu" command. | ||
599 : | * | ||
600 : | * @param id id of the client that is calling the command. | ||
601 : | * @param level Access level required by the command. | ||
602 : | * @param cid Command ID. | ||
603 : | */ | ||
604 : | public CvarMenuCommand(id, level, cid) | ||
605 : | { | ||
606 : | if (!cmd_access(id,level,cid,0)) | ||
607 : | { | ||
608 : | return PLUGIN_HANDLED; | ||
609 : | } | ||
610 : | |||
611 : | // This is which plugin to display. -1 means display all plugins in a list. | ||
612 : | new plid=-1; | ||
613 : | |||
614 : | if (GetPlidForValidPlugins(id,plid)!=true) | ||
615 : | { | ||
616 : | // If GetPlidForValidPlugins returns false then it failed to find the plugin. | ||
617 : | return PLUGIN_HANDLED; | ||
618 : | } | ||
619 : | |||
620 : | // Check if we were passed a specific plugin to display or not. | ||
621 : | if (plid==-1) | ||
622 : | { | ||
623 : | ExplicitPlugin[id]=-1; | ||
624 : | // We need to display a list of the plugins, instead of a specific plugin. | ||
625 : | DisplayPluginMenu(id,"Plugin Cvar Menu:", "PluginMenuSelection","DisplayCvarMenu","GetNumberOfCvarsForPlid"); | ||
626 : | } | ||
627 : | else | ||
628 : | { | ||
629 : | ExplicitPlugin[id]=plid; | ||
630 : | CurrentPlid[id]=plid; | ||
631 : | CurrentPage[id]=0; | ||
632 : | DisplayCvarMenu(id,plid,0); | ||
633 : | } | ||
634 : | return PLUGIN_HANDLED; | ||
635 : | } | ||
636 : | /** | ||
637 : | * Handler for the menu that displays a single command ("Execute with no params", etc). | ||
638 : | * | ||
639 : | * @param id Id of the client. | ||
640 : | * @param menu Menu handle. | ||
641 : | * @param item Item that was selected. | ||
642 : | */ | ||
643 : | public SpecificCommandHandler(id,menu,item) | ||
644 : | { | ||
645 : | // Exit was called, return to the previous menu. | ||
646 : | if (item<0) | ||
647 : | { | ||
648 : | if (CurrentMenuFunction[id]!=-1 && callfunc_begin_i(CurrentMenuFunction[id])==1) | ||
649 : | { | ||
650 : | callfunc_push_int(id); | ||
651 : | callfunc_push_int(CurrentPlid[id]); | ||
652 : | callfunc_push_int(CurrentPage[id]); | ||
653 : | callfunc_end(); | ||
654 : | } | ||
655 : | menu_destroy(menu); | ||
656 : | |||
657 : | return PLUGIN_HANDLED; | ||
658 : | } | ||
659 : | |||
660 : | new Dummy[1]; | ||
661 : | if (item==0) // "With params" | ||
662 : | { | ||
663 : | menu_item_getinfo(menu, item, Dummy[0], CurrentCommand[id], sizeof(CurrentCommand[])-1,"",0,Dummy[0]); | ||
664 : | if (CurrentCommand[id][0]==0) // This should never happen, but just incase.. | ||
665 : | { | ||
666 : | client_print(id,print_chat,"[AMXX] There was an error extracting the command name."); | ||
667 : | return PLUGIN_HANDLED; | ||
668 : | } | ||
669 : | // TODO: ML this | ||
670 : | |||
671 : | client_print(id,print_chat,"[AMXX] Type in the parameters for %s, or !cancel to cancel.",CurrentCommand[id]); | ||
672 : | client_cmd(id,"messagemode amx_executecmd"); | ||
673 : | |||
674 : | menu_destroy(menu); | ||
675 : | |||
676 : | return PLUGIN_HANDLED; // Don't return to original menu immediately! | ||
677 : | } | ||
678 : | else if (item==1) // "No params" | ||
679 : | { | ||
680 : | menu_item_getinfo(menu, item, Dummy[0], CurrentCommand[id], sizeof(CurrentCommand[])-1,"",0,Dummy[0]); | ||
681 : | if (CurrentCommand[id][0]==0) // This should never happen, but just incase.. | ||
682 : | { | ||
683 : | client_print(id,print_chat,"[AMXX] There was an error extracting the command name."); | ||
684 : | return PLUGIN_HANDLED; | ||
685 : | } | ||
686 : | // TODO: ML this | ||
687 : | |||
688 : | // Now redraw the menu for the client BEFORE the command is executed, incase | ||
689 : | // that menu brings up a menu of its own. | ||
690 : | if (CurrentMenuFunction[id]!=-1 && callfunc_begin_i(CurrentMenuFunction[id])==1) | ||
691 : | { | ||
692 : | callfunc_push_int(id); | ||
693 : | callfunc_push_int(CurrentPlid[id]); | ||
694 : | callfunc_push_int(CurrentPage[id]); | ||
695 : | callfunc_end(); | ||
696 : | } | ||
697 : | menu_destroy(menu); | ||
698 : | |||
699 : | client_cmd(id,"%s",CurrentCommand[id]); | ||
700 : | client_print(id,print_chat,"[AMXX] Command ^"%s^" executed with no parameters",CurrentCommand[id]); | ||
701 : | |||
702 : | return PLUGIN_HANDLED; | ||
703 : | } | ||
704 : | |||
705 : | // We should never get here, but just incase.. | ||
706 : | menu_destroy(menu); | ||
707 : | |||
708 : | return PLUGIN_HANDLED; | ||
709 : | } | ||
710 : | |||
711 : | /** | ||
712 : | * Generates and displays a menu to the client for a specific command. | ||
713 : | * | ||
714 : | * @param id The client to display the menu to. | ||
715 : | * @param cid The command id to display. | ||
716 : | */ | ||
717 : | stock DisplaySpecificCommand(id,cid) | ||
718 : | { | ||
719 : | new CommandName[64]; | ||
720 : | new CommandDesc[128]; | ||
721 : | new CommandTitle[256]; | ||
722 : | new CommandAccess; | ||
723 : | new Menu; | ||
724 : | |||
725 : | get_concmd(cid,CommandName,sizeof(CommandName)-1,CommandAccess, CommandDesc,sizeof(CommandDesc)-1, -1, -1); | ||
726 : | |||
727 : | if (CommandDesc[0]!='^0') | ||
728 : | { | ||
729 : | formatex(CommandTitle,sizeof(CommandTitle)-1,"%s^n%s",CommandName,CommandDesc); | ||
730 : | Menu=menu_create(CommandTitle,"SpecificCommandHandler"); | ||
731 : | } | ||
732 : | else | ||
733 : | { | ||
734 : | Menu=menu_create(CommandName,"SpecificCommandHandler"); | ||
735 : | } | ||
736 : | menu_additem(Menu,"Execute with parameters.",CommandName,_,EnabledCallback); | ||
737 : | menu_additem(Menu,"Execute with no parameters.",CommandName,_,EnabledCallback); | ||
738 : | |||
739 : | menu_setprop(Menu,MPROP_NUMBER_COLOR,"\y"); | ||
740 : | menu_display(id,Menu,0); | ||
741 : | } | ||
742 : | |||
743 : | /** | ||
744 : | * Handles the executed command (via "amx_executecmd"). | ||
745 : | * | ||
746 : | * @param id The id of the client who executed this. | ||
747 : | */ | ||
748 : | public CommandExecuteCommand(id) | ||
749 : | { | ||
750 : | // If they had no command stored, then just ignore it entirely. | ||
751 : | if (CurrentCommand[id][0]=='^0') | ||
752 : | { | ||
753 : | return PLUGIN_CONTINUE; | ||
754 : | } | ||
755 : | |||
756 : | new Args[256]; | ||
757 : | |||
758 : | read_args(Args,sizeof(Args)-1); | ||
759 : | |||
760 : | remove_quotes(Args); | ||
761 : | |||
762 : | if (equali(Args,"!cancel",7)) | ||
763 : | { | ||
764 : | // The client didn't want to execute this command. | ||
765 : | client_print(id,print_chat,"[AMXX] Command not executed."); | ||
766 : | |||
767 : | // Now redraw the menu for the client | ||
768 : | if (CurrentMenuFunction[id]!=-1 && callfunc_begin_i(CurrentMenuFunction[id])==1) | ||
769 : | { | ||
770 : | callfunc_push_int(id); | ||
771 : | callfunc_push_int(CurrentPlid[id]); | ||
772 : | callfunc_push_int(CurrentPage[id]); | ||
773 : | callfunc_end(); | ||
774 : | } | ||
775 : | |||
776 : | } | ||
777 : | else | ||
778 : | { | ||
779 : | // TODO: ML | ||
780 : | client_print(id,print_chat,"[AMXX] Command ^"%s^" executed with ^"%s^"",CurrentCommand[id],Args); | ||
781 : | |||
782 : | // Now redraw the menu for the client | ||
783 : | if (CurrentMenuFunction[id]!=-1 && callfunc_begin_i(CurrentMenuFunction[id])==1) | ||
784 : | { | ||
785 : | callfunc_push_int(id); | ||
786 : | callfunc_push_int(CurrentPlid[id]); | ||
787 : | callfunc_push_int(CurrentPage[id]); | ||
788 : | callfunc_end(); | ||
789 : | } | ||
790 : | |||
791 : | // Execute the command on the client. | ||
792 : | client_cmd(id,"%s %s",CurrentCommand[id],Args); | ||
793 : | } | ||
794 : | |||
795 : | |||
796 : | return PLUGIN_HANDLED; | ||
797 : | |||
798 : | } | ||
799 : | |||
800 : | /** | ||
801 : | * Handle a specific selection from the command menu. | ||
802 : | * | ||
803 : | * @param id id of the client who made the selection. | ||
804 : | * @param menu The menu handle. | ||
805 : | * @param item The item that was selected. | ||
806 : | */ | ||
807 : | public CommandMenuSelection(id, menu, item) | ||
808 : | { | ||
809 : | |||
810 : | if (item==MENU_EXIT) | ||
811 : | { | ||
812 : | menu_destroy(menu); | ||
813 : | |||
814 : | // If the player did not explicitly specify a plugin, return them to the | ||
815 : | // plugin selection menu. | ||
816 : | |||
817 : | if (ExplicitPlugin[id]==-1) | ||
818 : | { | ||
819 : | client_cmd(id,"amx_plugincmdmenu"); | ||
820 : | } | ||
821 : | return PLUGIN_HANDLED; | ||
822 : | } | ||
823 : | else if (item==MENU_BACK) | ||
824 : | { | ||
825 : | --CurrentPage[id]; | ||
826 : | client_print(id,print_chat,"MENU_BACK"); | ||
827 : | return PLUGIN_HANDLED; | ||
828 : | } | ||
829 : | else if (item==MENU_MORE) | ||
830 : | { | ||
831 : | ++CurrentPage[id]; | ||
832 : | client_print(id,print_chat,"MENU_MORE"); | ||
833 : | return PLUGIN_HANDLED; | ||
834 : | } | ||
835 : | else | ||
836 : | { | ||
837 : | new Command[32]; | ||
838 : | new Dummy[1]; | ||
839 : | // pcvar pointer is stored in command, extract the name of the cvar from the name field. | ||
840 : | menu_item_getinfo(menu, item, Dummy[0], Command, sizeof(Command)-1,"",0,Dummy[0]); | ||
841 : | |||
842 : | menu_destroy(menu); | ||
843 : | |||
844 : | DisplaySpecificCommand(id,str_to_num(Command)); | ||
845 : | return PLUGIN_HANDLED; | ||
846 : | } | ||
847 : | |||
848 : | return 0; | ||
849 : | } | ||
850 : | /** | ||
851 : | * This blocks "say" and "say_team" commands. | ||
852 : | * Other commands that shouldn't be displayed (eg: amxauth<stuff>) should be filtered out already. | ||
853 : | * | ||
854 : | * @param Command The command that is being checked. | ||
855 : | */ | ||
856 : | stock bool:IsDisplayableCmd(const Command[]) | ||
857 : | { | ||
858 : | // Block "say" and "say_team" | ||
859 : | if (equal(Command,"say",3)) | ||
860 : | { | ||
861 : | return false; | ||
862 : | } | ||
863 : | |||
864 : | return true; | ||
865 : | } | ||
866 : | /** | ||
867 : | * Displays a command list for the specified plugin. | ||
868 : | * | ||
869 : | * @param id Id of the client that's being displayed to. | ||
870 : | * @param plid Plugin ID of the plugin that is to be displayed. | ||
871 : | * @param page The page to start at. | ||
872 : | */ | ||
873 : | public DisplayCmdMenu(id, plid, page) | ||
874 : | { | ||
875 : | new PluginName[32]; | ||
876 : | new MenuTitle[64]; | ||
877 : | get_plugin(plid,"",0,PluginName,sizeof(PluginName)-1,"",0,"",0,"",0); | ||
878 : | |||
879 : | formatex(MenuTitle,sizeof(MenuTitle)-1,"%s Commands:",PluginName); | ||
880 : | |||
881 : | new Menu=menu_create(MenuTitle,"CommandMenuSelection"); | ||
882 : | |||
883 : | new Command[64]; | ||
884 : | new CidString[32]; | ||
885 : | new CommandAccess; | ||
886 : | new userflags=get_user_flags(id); | ||
887 : | new bool:isadmin=bool:is_user_admin(id); | ||
888 : | |||
889 : | |||
890 : | for (new i=0, max=get_concmdsnum(-1,-1); | ||
891 : | i<max; | ||
892 : | i++) | ||
893 : | { | ||
894 : | if (get_concmd_plid(i,-1,-1)==plid) | ||
895 : | { | ||
896 : | get_concmd(i,Command,sizeof(Command)-1,CommandAccess, "",0, -1, -1); | ||
897 : | |||
898 : | if (IsDisplayableCmd(Command)) | ||
899 : | { | ||
900 : | if ( userflags & CommandAccess || | ||
901 : | (CommandAccess==ADMIN_ADMIN && isadmin) || | ||
902 : | CommandAccess==ADMIN_USER || | ||
903 : | CommandAccess==ADMIN_ALL) | ||
904 : | { | ||
905 : | num_to_str(i,CidString,sizeof(CidString)-1); | ||
906 : | menu_additem(Menu,Command,CidString,0,EnabledCallback); | ||
907 : | } | ||
908 : | else | ||
909 : | { | ||
910 : | menu_additem(Menu,Command,"",0,DisabledCallback); | ||
911 : | } | ||
912 : | } | ||
913 : | } | ||
914 : | } | ||
915 : | menu_setprop(Menu,MPROP_NUMBER_COLOR,"\y"); | ||
916 : | menu_display(id,Menu,page); | ||
917 : | |||
918 : | } | ||
919 : | /** | ||
920 : | * Handles the "amx_plugincmdmenu" command. | ||
921 : | * | ||
922 : | * @param id Id of the client that's being checked. | ||
923 : | * @param level Access level of the command. | ||
924 : | * @param cid Command ID of the command that was executed. | ||
925 : | */ | ||
926 : | public CommandMenuCommand(id, level, cid) | ||
927 : | { | ||
928 : | if (!cmd_access(id,level,cid,0)) | ||
929 : | { | ||
930 : | return PLUGIN_HANDLED; | ||
931 : | } | ||
932 : | |||
933 : | // This is which plugin to display. -1 means display all plugins in a list. | ||
934 : | new plid=-1; | ||
935 : | |||
936 : | if (GetPlidForValidPlugins(id,plid)!=true) | ||
937 : | { | ||
938 : | // If GetPlidForValidPlugins returns false then it failed to find the plugin. | ||
939 : | return PLUGIN_HANDLED; | ||
940 : | } | ||
941 : | |||
942 : | // Check if we were passed a specific plugin to display or not. | ||
943 : | if (plid==-1) | ||
944 : | { | ||
945 : | // We need to display a list of the plugins, instead of a specific plugin. | ||
946 : | ExplicitPlugin[id]=-1; | ||
947 : | DisplayPluginMenu(id,"Plugin Command Menu:", "PluginMenuSelection","DisplayCmdMenu","GetNumberOfCmdsForPlid"); | ||
948 : | } | ||
949 : | else | ||
950 : | { | ||
951 : | ExplicitPlugin[id]=plid; | ||
952 : | CurrentPlid[id]=plid; | ||
953 : | CurrentPage[id]=0; | ||
954 : | DisplayCmdMenu(id,plid,0); | ||
955 : | } | ||
956 : | return PLUGIN_HANDLED; | ||
957 : | } |
Contact | ViewVC Help |
Powered by ViewVC 1.0.4 |