plugins/adminmenu/dynamicmenu.sp
author David Anderson <dvander@alliedmods.net>
Sat May 17 05:12:52 2008 +0000 (2008-05-17)
changeset 2056 f1fcde46ac7c
parent 1984 15e02f0df87c
child 2078 6e641c6f4f97
permissions -rw-r--r--
added amb1119 - sm_revote command
     1 
     2 #define NAME_LENGTH 32
     3 #define CMD_LENGTH 255
     4 
     5 #define ARRAY_STRING_LENGTH 32
     6 
     7 enum GroupCommands
     8 {
     9 	Handle:groupListName,
    10 	Handle:groupListCommand	
    11 };
    12 
    13 new g_groupList[GroupCommands];
    14 new g_groupCount;
    15 
    16 new Handle:g_configParser = INVALID_HANDLE;
    17 
    18 enum Places
    19 {
    20 	Place_Category,
    21 	Place_Item,
    22 	Place_ReplaceNum	
    23 };
    24 
    25 new String:g_command[MAXPLAYERS+1][CMD_LENGTH];
    26 new g_currentPlace[MAXPLAYERS+1][Places];
    27 
    28 /**
    29  * What to put in the 'info' menu field (for PlayerList and Player_Team menus only)
    30  */
    31 enum PlayerMethod
    32 {		
    33 	ClientId,				/** Client id number ( 1 - Maxplayers) */
    34 	UserId,					/** Client userid */
    35 	Name,					/** Client Name */
    36 	SteamId,				/** Client Steamid */
    37 	IpAddress,				/** Client's Ip Address */
    38 	UserId2					/** Userid (not prefixed with #) */
    39 };
    40 
    41 enum ExecuteType
    42 {
    43 	Execute_Player,
    44 	Execute_Server
    45 }
    46 
    47 enum SubMenu_Type
    48 {
    49 	SubMenu_Group,
    50 	SubMenu_GroupPlayer,
    51 	SubMenu_Player,
    52 	SubMenu_MapCycle,
    53 	SubMenu_List,
    54 	SubMenu_OnOff	
    55 }
    56 
    57 enum Item
    58 {
    59 	String:Item_cmd[256],
    60 	ExecuteType:Item_execute,
    61 	Handle:Item_submenus
    62 }
    63 
    64 enum Submenu
    65 {
    66 	SubMenu_Type:Submenu_type,
    67 	String:Submenu_title[32],
    68 	PlayerMethod:Submenu_method,
    69 	Submenu_listcount,
    70 	Handle:Submenu_listdata
    71 }
    72 
    73 new Handle:g_DataArray;
    74 
    75 BuildDynamicMenu()
    76 {
    77 	new itemInput[Item];
    78 	g_DataArray = CreateArray(sizeof(itemInput));
    79 	
    80 	new String:executeBuffer[32];
    81 	
    82 	new Handle:kvMenu;
    83 	kvMenu = CreateKeyValues("Commands");
    84 	new String:file[256];
    85 	BuildPath(Path_SM, file, 255, "configs/dynamicmenu/menu.ini");
    86 	FileToKeyValues(kvMenu, file);
    87 	
    88 	new String:name[NAME_LENGTH];
    89 	new String:buffer[NAME_LENGTH];
    90 	
    91 	KvSetEscapeSequences(kvMenu, true);
    92 		
    93 	if (!KvGotoFirstSubKey(kvMenu))
    94 	{
    95 		return;
    96 	}
    97 	
    98 	decl String:admin[30];
    99 	
   100 	new TopMenuObject:categoryId;
   101 	
   102 	do
   103 	{		
   104 		KvGetSectionName(kvMenu, buffer, sizeof(buffer));
   105 
   106 		KvGetString(kvMenu, "admin", admin, sizeof(admin),"sm_admin");
   107 				
   108 		if ((categoryId =FindTopMenuCategory(hAdminMenu, buffer)) == INVALID_TOPMENUOBJECT)
   109 		{
   110 			categoryId = AddToTopMenu(hAdminMenu,
   111 							buffer,
   112 							TopMenuObject_Category,
   113 							DynamicMenuCategoryHandler,
   114 							INVALID_TOPMENUOBJECT,
   115 							admin,
   116 							ADMFLAG_GENERIC,
   117 							name);
   118 
   119 		}
   120 		
   121 		if (!KvGotoFirstSubKey(kvMenu))
   122 		{
   123 			return;
   124 		}
   125 		
   126 		do
   127 		{		
   128 			KvGetSectionName(kvMenu, buffer, sizeof(buffer));
   129 			
   130 			KvGetString(kvMenu, "admin", admin, sizeof(admin),"");
   131 			
   132 			if (admin[0] == '\0')
   133 			{
   134 				//No 'admin' keyvalue was found
   135 				//Use the first argument of the 'cmd' string instead
   136 				
   137 				decl String:temp[64];
   138 				KvGetString(kvMenu, "cmd", temp, sizeof(temp),"");
   139 				
   140 				BreakString(temp, admin, sizeof(admin));
   141 			}
   142 			
   143 			
   144 			KvGetString(kvMenu, "cmd", itemInput[Item_cmd], sizeof(itemInput[Item_cmd]));	
   145 			KvGetString(kvMenu, "execute", executeBuffer, sizeof(executeBuffer));
   146 			
   147 			if (StrEqual(executeBuffer, "server"))
   148 			{
   149 				itemInput[Item_execute] = Execute_Server;
   150 			}
   151 			else //assume player type execute
   152 			{
   153 				itemInput[Item_execute] = Execute_Player;
   154 			}
   155   							
   156   			/* iterate all submenus and load data into itemInput[Item_submenus] (adt array handle) */
   157   			
   158   			new count = 1;
   159   			decl String:countBuffer[10] = "1";
   160   			
   161   			decl String:inputBuffer[32];
   162   			
   163   			while (KvJumpToKey(kvMenu, countBuffer))
   164   			{
   165 	  			new submenuInput[Submenu];
   166 	  			
   167 	  			if (count == 1)
   168 	  			{
   169 		  			itemInput[Item_submenus] = CreateArray(sizeof(submenuInput));	
   170 	  			}
   171 	  			
   172 	  			KvGetString(kvMenu, "type", inputBuffer, sizeof(inputBuffer));
   173 	  			
   174 	  			if (strncmp(inputBuffer,"group",5)==0)
   175 				{	
   176 					if (StrContains(inputBuffer, "player") != -1)
   177 					{			
   178 						submenuInput[Submenu_type] = SubMenu_GroupPlayer;
   179 					}
   180 					else
   181 					{
   182 						submenuInput[Submenu_type] = SubMenu_Group;
   183 					}
   184 				}			
   185 				else if (StrEqual(inputBuffer,"mapcycle"))
   186 				{
   187 					submenuInput[Submenu_type] = SubMenu_MapCycle;
   188 					
   189 					KvGetString(kvMenu, "path", inputBuffer, sizeof(inputBuffer),"mapcycle.txt");
   190 					
   191 					submenuInput[Submenu_listdata] = CreateDataPack();
   192 					WritePackString(submenuInput[Submenu_listdata], inputBuffer);
   193 					ResetPack(submenuInput[Submenu_listdata]);
   194 				}
   195 				else if (StrContains(inputBuffer, "player") != -1)
   196 				{			
   197 					submenuInput[Submenu_type] = SubMenu_Player;
   198 				}
   199 				else if (StrEqual(inputBuffer,"onoff"))
   200 				{
   201 					submenuInput[Submenu_type] = SubMenu_OnOff;
   202 				}		
   203 				else //assume 'list' type
   204 				{
   205 					submenuInput[Submenu_type] = SubMenu_List;
   206 					
   207 					submenuInput[Submenu_listdata] = CreateDataPack();
   208 					
   209 					new String:temp[6];
   210 					new String:value[64];
   211 					new String:text[64];
   212 					new i=1;
   213 					new bool:more = true;
   214 					
   215 					new listcount = 0;
   216 								
   217 					do
   218 					{
   219 						Format(temp,3,"%i",i);
   220 						KvGetString(kvMenu, temp, value, sizeof(value), "");
   221 						
   222 						Format(temp,5,"%i.",i);
   223 						KvGetString(kvMenu, temp, text, sizeof(text), value);
   224 						
   225 						Format(temp,5,"%i*",i);
   226 						KvGetString(kvMenu, temp, admin, sizeof(admin),"");	
   227 						
   228 						if (value[0]=='\0')
   229 						{
   230 							more = false;
   231 						}
   232 						else
   233 						{
   234 							listcount++;
   235 							WritePackString(submenuInput[Submenu_listdata], value);
   236 							WritePackString(submenuInput[Submenu_listdata], text);
   237 							WritePackString(submenuInput[Submenu_listdata], admin);
   238 						}
   239 						
   240 						i++;
   241 										
   242 					} while (more);
   243 					
   244 					ResetPack(submenuInput[Submenu_listdata]);
   245 					submenuInput[Submenu_listcount] = listcount;
   246 				}
   247 				
   248 				if ((submenuInput[Submenu_type] == SubMenu_Player) || (submenuInput[Submenu_type] == SubMenu_GroupPlayer))
   249 				{
   250 					KvGetString(kvMenu, "method", inputBuffer, sizeof(inputBuffer));
   251 					
   252 					if (StrEqual(inputBuffer, "clientid"))
   253 					{
   254 						submenuInput[Submenu_method] = ClientId;
   255 					}
   256 					else if (StrEqual(inputBuffer, "steamid"))
   257 					{
   258 						submenuInput[Submenu_method] = SteamId;
   259 					}
   260 					else if (StrEqual(inputBuffer, "userid2"))
   261 					{
   262 						submenuInput[Submenu_method] = UserId2;
   263 					}
   264 					else if (StrEqual(inputBuffer, "userid"))
   265 					{
   266 						submenuInput[Submenu_method] = UserId;
   267 					}
   268 					else if (StrEqual(inputBuffer, "ip"))
   269 					{
   270 						submenuInput[Submenu_method] = IpAddress;
   271 					}
   272 					else
   273 					{
   274 						submenuInput[Submenu_method] = Name;
   275 					}					
   276 					
   277 				}
   278 				
   279 				KvGetString(kvMenu, "title", inputBuffer, sizeof(inputBuffer));
   280 				strcopy(submenuInput[Submenu_title], sizeof(submenuInput[Submenu_title]), inputBuffer);
   281 	  			
   282 	  			count++;
   283 	  			Format(countBuffer, sizeof(countBuffer), "%i", count);
   284 	  			
   285 	  			PushArrayArray(itemInput[Item_submenus], submenuInput[0]);
   286 	  		
   287 	  			KvGoBack(kvMenu);	
   288   			}
   289   			
   290   			/* Save this entire item into the global items array and add it to the menu */
   291   			
   292   			new location = PushArrayArray(g_DataArray, itemInput[0]);
   293 			
   294 			decl String:locString[10];
   295 			IntToString(location, locString, sizeof(locString));
   296 
   297 			AddToTopMenu(hAdminMenu,
   298 							buffer,
   299 							TopMenuObject_Item,
   300 							DynamicMenuItemHandler,
   301   							categoryId,
   302   							admin,
   303   							ADMFLAG_GENERIC,
   304   							locString);			
   305 		
   306 		} while (KvGotoNextKey(kvMenu));
   307 		
   308 		KvGoBack(kvMenu);
   309 		
   310 	} while (KvGotoNextKey(kvMenu));
   311 	
   312 	CloseHandle(kvMenu);
   313 }
   314 
   315 ParseConfigs()
   316 {
   317 	if (g_configParser == INVALID_HANDLE)
   318 	{
   319 		g_configParser = SMC_CreateParser();
   320 	}
   321 	
   322 	SMC_SetReaders(g_configParser, NewSection, KeyValue, EndSection);
   323 	
   324 	if (g_groupList[groupListName] != INVALID_HANDLE)
   325 	{
   326 		CloseHandle(g_groupList[groupListName]);
   327 	}
   328 	
   329 	if (g_groupList[groupListCommand] != INVALID_HANDLE)
   330 	{
   331 		CloseHandle(g_groupList[groupListCommand]);
   332 	}
   333 	
   334 	g_groupList[groupListName] = CreateArray(ARRAY_STRING_LENGTH);
   335 	g_groupList[groupListCommand] = CreateArray(ARRAY_STRING_LENGTH);
   336 	
   337 	decl String:configPath[256];
   338 	BuildPath(Path_SM, configPath, sizeof(configPath), "configs/dynamicmenu/adminmenu_grouping.txt");
   339 	
   340 	if (!FileExists(configPath))
   341 	{
   342 		LogError("Unable to locate admin menu groups file: %s", configPath);
   343 			
   344 		return;		
   345 	}
   346 	
   347 	new line;
   348 	new SMCError:err = SMC_ParseFile(g_configParser, configPath, line);
   349 	if (err != SMCError_Okay)
   350 	{
   351 		decl String:error[256];
   352 		SMC_GetErrorString(err, error, sizeof(error));
   353 		LogError("Could not parse file (line %d, file \"%s\"):", line, configPath);
   354 		LogError("Parser encountered error: %s", error);
   355 	}
   356 	
   357 	return;
   358 }
   359 
   360 public SMCResult:NewSection(Handle:smc, const String:name[], bool:opt_quotes)
   361 {
   362 
   363 }
   364 
   365 public SMCResult:KeyValue(Handle:smc, const String:key[], const String:value[], bool:key_quotes, bool:value_quotes)
   366 {
   367 	PushArrayString(g_groupList[groupListName], key);
   368 	PushArrayString(g_groupList[groupListCommand], value);
   369 }
   370 
   371 public SMCResult:EndSection(Handle:smc)
   372 {
   373 	g_groupCount = GetArraySize(g_groupList[groupListName]);
   374 }
   375 
   376 public DynamicMenuCategoryHandler(Handle:topmenu, 
   377 						TopMenuAction:action,
   378 						TopMenuObject:object_id,
   379 						param,
   380 						String:buffer[],
   381 						maxlength)
   382 {
   383 	if ((action == TopMenuAction_DisplayTitle) || (action == TopMenuAction_DisplayOption))
   384 	{
   385 		GetTopMenuObjName(topmenu, object_id, buffer, maxlength);
   386 	}
   387 }
   388 
   389 public DynamicMenuItemHandler(Handle:topmenu, 
   390 					  TopMenuAction:action,
   391 					  TopMenuObject:object_id,
   392 					  param,
   393 					  String:buffer[],
   394 					  maxlength)
   395 {
   396 	if (action == TopMenuAction_DisplayOption)
   397 	{
   398 		GetTopMenuObjName(topmenu, object_id, buffer, maxlength);
   399 	}
   400 	else if (action == TopMenuAction_SelectOption)
   401 	{	
   402 		new String:locString[10];
   403 		GetTopMenuInfoString(topmenu, object_id, locString, sizeof(locString));
   404 		
   405 		new location = StringToInt(locString);
   406 		
   407 		new output[Item];
   408 		GetArrayArray(g_DataArray, location, output[0]);
   409 		
   410 		strcopy(g_command[param], sizeof(g_command[]), output[Item_cmd]);
   411 					
   412 		g_currentPlace[param][Place_Item] = location;
   413 		
   414 		ParamCheck(param);
   415 	}
   416 }
   417 
   418 public ParamCheck(client)
   419 {
   420 	new String:buffer[6];
   421 	new String:buffer2[6];
   422 	
   423 	new outputItem[Item];
   424 	new outputSubmenu[Submenu];
   425 	
   426 	GetArrayArray(g_DataArray, g_currentPlace[client][Place_Item], outputItem[0]);
   427 		
   428 	if (g_currentPlace[client][Place_ReplaceNum] < 1)
   429 	{
   430 		g_currentPlace[client][Place_ReplaceNum] = 1;
   431 	}
   432 	
   433 	Format(buffer, 5, "#%i", g_currentPlace[client][Place_ReplaceNum]);
   434 	Format(buffer2, 5, "@%i", g_currentPlace[client][Place_ReplaceNum]);
   435 	
   436 	if (StrContains(g_command[client], buffer) != -1 || StrContains(g_command[client], buffer2) != -1)
   437 	{
   438 		GetArrayArray(outputItem[Item_submenus], g_currentPlace[client][Place_ReplaceNum] - 1, outputSubmenu[0]);
   439 		
   440 		new Handle:itemMenu = CreateMenu(Menu_Selection);
   441 			
   442 		if ((outputSubmenu[Submenu_type] == SubMenu_Group) || (outputSubmenu[Submenu_type] == SubMenu_GroupPlayer))
   443 		{	
   444 			decl String:nameBuffer[ARRAY_STRING_LENGTH];
   445 			decl String:commandBuffer[ARRAY_STRING_LENGTH];
   446 		
   447 			for (new i = 0; i<g_groupCount; i++)
   448 			{			
   449 				GetArrayString(g_groupList[groupListName], i, nameBuffer, sizeof(nameBuffer));
   450 				GetArrayString(g_groupList[groupListCommand], i, commandBuffer, sizeof(commandBuffer));
   451 				AddMenuItem(itemMenu, commandBuffer, nameBuffer);
   452 			}
   453 		}
   454 		
   455 		if (outputSubmenu[Submenu_type] == SubMenu_MapCycle)
   456 		{	
   457 			decl String:path[200];
   458 			ReadPackString(outputSubmenu[Submenu_listdata], path, sizeof(path));
   459 			ResetPack(outputSubmenu[Submenu_listdata]);
   460 		
   461 			new Handle:file = OpenFile(path, "rt");
   462 			new String:readData[128];
   463 			
   464 			if(file != INVALID_HANDLE)
   465 			{
   466 				while(!IsEndOfFile(file) && ReadFileLine(file, readData, sizeof(readData)))
   467 				{
   468 					TrimString(readData);
   469 					
   470 					if (IsMapValid(readData))
   471 					{
   472 						AddMenuItem(itemMenu, readData, readData);
   473 					}
   474 				}
   475 			}
   476 		}
   477 		else if ((outputSubmenu[Submenu_type] == SubMenu_Player) || (outputSubmenu[Submenu_type] == SubMenu_GroupPlayer))
   478 		{
   479 			new PlayerMethod:playermethod = outputSubmenu[Submenu_method];
   480 		
   481 			new String:nameBuffer[32];
   482 			new String:infoBuffer[32];
   483 			new String:temp[4];
   484 			
   485 			//loop through players. Add name as text and name/userid/steamid as info
   486 			for (new i=1; i<=g_maxPlayers; i++)
   487 			{
   488 				if (IsClientInGame(i))
   489 				{			
   490 					GetClientName(i, nameBuffer, 31);
   491 					
   492 					switch (playermethod)
   493 					{
   494 						case UserId:
   495 						{
   496 							new userid = GetClientUserId(i);
   497 							Format(infoBuffer, sizeof(infoBuffer), "#%i", userid);
   498 							AddMenuItem(itemMenu, infoBuffer, nameBuffer);	
   499 						}
   500 						case UserId2:
   501 						{
   502 							new userid = GetClientUserId(i);
   503 							Format(infoBuffer, sizeof(infoBuffer), "%i", userid);
   504 							AddMenuItem(itemMenu, infoBuffer, nameBuffer);							
   505 						}
   506 						case SteamId:
   507 						{
   508 							GetClientAuthString(i, infoBuffer, sizeof(infoBuffer));
   509 							AddMenuItem(itemMenu, infoBuffer, nameBuffer);							
   510 						}	
   511 						case IpAddress:
   512 						{
   513 							GetClientIP(i, infoBuffer, sizeof(infoBuffer));
   514 							AddMenuItem(itemMenu, infoBuffer, nameBuffer);							
   515 						}
   516 						case Name:
   517 						{
   518 							AddMenuItem(itemMenu, nameBuffer, nameBuffer);
   519 						}	
   520 						default: //assume client id
   521 						{
   522 							Format(temp,3,"%i",i);
   523 							AddMenuItem(itemMenu, temp, nameBuffer);						
   524 						}								
   525 					}
   526 				}
   527 			}
   528 		}
   529 		else if (outputSubmenu[Submenu_type] == SubMenu_OnOff)
   530 		{
   531 			AddMenuItem(itemMenu, "1", "On");
   532 			AddMenuItem(itemMenu, "0", "Off");
   533 		}		
   534 		else
   535 		{
   536 			new String:value[64];
   537 			new String:text[64];
   538 					
   539 			new String:admin[NAME_LENGTH];
   540 			
   541 			for (new i=0; i<outputSubmenu[Submenu_listcount]; i++)
   542 			{
   543 				ReadPackString(outputSubmenu[Submenu_listdata], value, sizeof(value));
   544 				ReadPackString(outputSubmenu[Submenu_listdata], text, sizeof(text));
   545 				ReadPackString(outputSubmenu[Submenu_listdata], admin, sizeof(admin));
   546 				
   547 				if (CheckCommandAccess(client, admin, 0))
   548 				{
   549 					AddMenuItem(itemMenu, value, text);
   550 				}
   551 			}
   552 			
   553 			ResetPack(outputSubmenu[Submenu_listdata]);	
   554 		}
   555 		
   556 		SetMenuTitle(itemMenu, outputSubmenu[Submenu_title]);
   557 		
   558 		DisplayMenu(itemMenu, client, MENU_TIME_FOREVER);
   559 	}
   560 	else
   561 	{	
   562 		//nothing else need to be done. Run teh command.
   563 		
   564 		DisplayTopMenu(hAdminMenu, client, TopMenuPosition_LastCategory);
   565 		
   566 		if (outputItem[Item_execute] == Execute_Player) // assume 'player' type execute option
   567 		{
   568 			FakeClientCommand(client, g_command[client]);
   569 		}
   570 		else // assume 'server' type execute option
   571 		{
   572 			InsertServerCommand(g_command[client]);
   573 			ServerExecute();
   574 		}
   575 
   576 		g_command[client][0] = '\0';
   577 		g_currentPlace[client][Place_ReplaceNum] = 1;
   578 	}
   579 }
   580 
   581 public Menu_Selection(Handle:menu, MenuAction:action, param1, param2)
   582 {
   583 	if (action == MenuAction_End)
   584 	{
   585 		CloseHandle(menu);
   586 	}
   587 	
   588 	if (action == MenuAction_Select)
   589 	{
   590 		new String:info[NAME_LENGTH];
   591  
   592 		/* Get item info */
   593 		new bool:found = GetMenuItem(menu, param2, info, sizeof(info));
   594 		
   595 		if (!found)
   596 		{
   597 			return;
   598 		}
   599 		
   600 		new String:buffer[6];
   601 		new String:infobuffer[NAME_LENGTH+2];
   602 		Format(infobuffer, sizeof(infobuffer), "\"%s\"", info);
   603 		
   604 		Format(buffer, 5, "#%i", g_currentPlace[param1][Place_ReplaceNum]);
   605 		ReplaceString(g_command[param1], sizeof(g_command[]), buffer, infobuffer);
   606 		//replace #num with the selected option (quoted)
   607 		
   608 		Format(buffer, 5, "@%i", g_currentPlace[param1][Place_ReplaceNum]);
   609 		ReplaceString(g_command[param1], sizeof(g_command[]), buffer, info);
   610 		//replace @num with the selected option (unquoted)
   611 		
   612 		// Increment the parameter counter.
   613 		g_currentPlace[param1][Place_ReplaceNum]++;
   614 		
   615 		ParamCheck(param1);
   616 	}
   617 	
   618 	if (action == MenuAction_Cancel && param2 == MenuCancel_Exit)
   619 	{
   620 		//client exited we should go back to submenu i think
   621 		DisplayTopMenu(hAdminMenu, param1, TopMenuPosition_LastCategory);
   622 	}
   623 }