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