#define NAME_LENGTH 64 #define CMD_LENGTH 255 #define ARRAY_STRING_LENGTH 32 enum GroupCommands { ArrayList:groupListName, ArrayList:groupListCommand }; int g_groupList[GroupCommands]; int g_groupCount; SMCParser g_configParser; enum Places { Place_Category, Place_Item, Place_ReplaceNum }; char g_command[MAXPLAYERS+1][CMD_LENGTH]; int g_currentPlace[MAXPLAYERS+1][Places]; /** * What to put in the 'info' menu field (for PlayerList and Player_Team menus only) */ enum PlayerMethod { ClientId, /** Client id number ( 1 - Maxplayers) */ UserId, /** Client userid */ Name, /** Client Name */ SteamId, /** Client Steamid */ IpAddress, /** Client's Ip Address */ UserId2 /** Userid (not prefixed with #) */ }; enum ExecuteType { Execute_Player, Execute_Server } enum SubMenu_Type { SubMenu_Group, SubMenu_GroupPlayer, SubMenu_Player, SubMenu_MapCycle, SubMenu_List, SubMenu_OnOff } enum Item { String:Item_cmd[256], ExecuteType:Item_execute, ArrayList:Item_submenus } enum Submenu { SubMenu_Type:Submenu_type, String:Submenu_title[32], PlayerMethod:Submenu_method, Submenu_listcount, DataPack:Submenu_listdata } ArrayList g_DataArray; void BuildDynamicMenu() { int itemInput[Item]; g_DataArray = new ArrayList(sizeof(itemInput)); char executeBuffer[32]; KeyValues kvMenu = new KeyValues("Commands"); kvMenu.SetEscapeSequences(true); char file[256]; /* As a compatibility shim, we use the old file if it exists. */ BuildPath(Path_SM, file, 255, "configs/dynamicmenu/menu.ini"); if (FileExists(file)) { LogError("Warning! configs/dynamicmenu/menu.ini is now configs/adminmenu_custom.txt."); LogError("Read the 1.0.2 release notes, as the dynamicmenu folder has been removed."); } else { BuildPath(Path_SM, file, 255, "configs/adminmenu_custom.txt"); } FileToKeyValues(kvMenu, file); char name[NAME_LENGTH]; char buffer[NAME_LENGTH]; if (!kvMenu.GotoFirstSubKey()) return; char admin[30]; TopMenuObject categoryId; do { kvMenu.GetSectionName(buffer, sizeof(buffer)); kvMenu.GetString("admin", admin, sizeof(admin),"sm_admin"); if ((categoryId = hAdminMenu.FindCategory(buffer)) == INVALID_TOPMENUOBJECT) { categoryId = hAdminMenu.AddCategory(buffer, DynamicMenuCategoryHandler, admin, ADMFLAG_GENERIC, name); } char category_name[NAME_LENGTH]; strcopy(category_name, sizeof(category_name), buffer); if (!kvMenu.GotoFirstSubKey()) { return; } do { kvMenu.GetSectionName(buffer, sizeof(buffer)); kvMenu.GetString("admin", admin, sizeof(admin),""); if (admin[0] == '\0') { //No 'admin' keyvalue was found //Use the first argument of the 'cmd' string instead char temp[64]; kvMenu.GetString("cmd", temp, sizeof(temp),""); BreakString(temp, admin, sizeof(admin)); } kvMenu.GetString("cmd", itemInput[Item_cmd], sizeof(itemInput[Item_cmd])); kvMenu.GetString("execute", executeBuffer, sizeof(executeBuffer)); if (StrEqual(executeBuffer, "server")) { itemInput[Item_execute] = Execute_Server; } else //assume player type execute { itemInput[Item_execute] = Execute_Player; } /* iterate all submenus and load data into itemInput[Item_submenus] (ArrayList) */ int count = 1; char countBuffer[10] = "1"; char inputBuffer[48]; while (kvMenu.JumpToKey(countBuffer)) { int submenuInput[Submenu]; if (count == 1) { itemInput[Item_submenus] = new ArrayList(sizeof(submenuInput)); } kvMenu.GetString("type", inputBuffer, sizeof(inputBuffer)); if (strncmp(inputBuffer,"group",5)==0) { if (StrContains(inputBuffer, "player") != -1) { submenuInput[Submenu_type] = SubMenu_GroupPlayer; } else { submenuInput[Submenu_type] = SubMenu_Group; } } else if (StrEqual(inputBuffer,"mapcycle")) { submenuInput[Submenu_type] = SubMenu_MapCycle; kvMenu.GetString("path", inputBuffer, sizeof(inputBuffer),"mapcycle.txt"); submenuInput[Submenu_listdata] = new DataPack(); submenuInput[Submenu_listdata].WriteString(inputBuffer); submenuInput[Submenu_listdata].Reset(); } else if (StrContains(inputBuffer, "player") != -1) { submenuInput[Submenu_type] = SubMenu_Player; } else if (StrEqual(inputBuffer,"onoff")) { submenuInput[Submenu_type] = SubMenu_OnOff; } else //assume 'list' type { submenuInput[Submenu_type] = SubMenu_List; submenuInput[Submenu_listdata] = new DataPack(); char temp[6]; char value[64]; char text[64]; char subadm[30]; // same as "admin", cf. line 110 int i=1; bool more = true; int listcount = 0; do { Format(temp,3,"%i",i); kvMenu.GetString(temp, value, sizeof(value), ""); Format(temp,5,"%i.",i); kvMenu.GetString(temp, text, sizeof(text), value); Format(temp,5,"%i*",i); kvMenu.GetString(temp, subadm, sizeof(subadm),""); if (value[0]=='\0') { more = false; } else { listcount++; submenuInput[Submenu_listdata].WriteString(value); submenuInput[Submenu_listdata].WriteString(text); submenuInput[Submenu_listdata].WriteString(subadm); } i++; } while (more); submenuInput[Submenu_listdata].Reset(); submenuInput[Submenu_listcount] = listcount; } if ((submenuInput[Submenu_type] == SubMenu_Player) || (submenuInput[Submenu_type] == SubMenu_GroupPlayer)) { kvMenu.GetString("method", inputBuffer, sizeof(inputBuffer)); if (StrEqual(inputBuffer, "clientid")) { submenuInput[Submenu_method] = ClientId; } else if (StrEqual(inputBuffer, "steamid")) { submenuInput[Submenu_method] = SteamId; } else if (StrEqual(inputBuffer, "userid2")) { submenuInput[Submenu_method] = UserId2; } else if (StrEqual(inputBuffer, "userid")) { submenuInput[Submenu_method] = UserId; } else if (StrEqual(inputBuffer, "ip")) { submenuInput[Submenu_method] = IpAddress; } else { submenuInput[Submenu_method] = Name; } } kvMenu.GetString("title", inputBuffer, sizeof(inputBuffer)); strcopy(submenuInput[Submenu_title], sizeof(submenuInput[Submenu_title]), inputBuffer); count++; Format(countBuffer, sizeof(countBuffer), "%i", count); itemInput[Item_submenus].PushArray(submenuInput[0]); kvMenu.GoBack(); } /* Save this entire item into the global items array and add it to the menu */ int location = g_DataArray.PushArray(itemInput[0]); char locString[10]; IntToString(location, locString, sizeof(locString)); if (hAdminMenu.AddItem(buffer, DynamicMenuItemHandler, categoryId, admin, ADMFLAG_GENERIC, locString) == INVALID_TOPMENUOBJECT) { LogError("Duplicate command name \"%s\" in adminmenu_custom.txt category \"%s\"", buffer, category_name); } } while (kvMenu.GotoNextKey()); kvMenu.GoBack(); } while (kvMenu.GotoNextKey()); delete kvMenu; } void ParseConfigs() { if (!g_configParser) g_configParser = new SMCParser(); g_configParser.OnEnterSection = NewSection; g_configParser.OnKeyValue = KeyValue; g_configParser.OnLeaveSection = EndSection; delete g_groupList[groupListName]; delete g_groupList[groupListCommand]; g_groupList[groupListName] = new ArrayList(ARRAY_STRING_LENGTH); g_groupList[groupListCommand] = new ArrayList(ARRAY_STRING_LENGTH); char configPath[256]; BuildPath(Path_SM, configPath, sizeof(configPath), "configs/dynamicmenu/adminmenu_grouping.txt"); if (FileExists(configPath)) { LogError("Warning! configs/dynamicmenu/adminmenu_grouping.txt is now configs/adminmenu_grouping.txt."); LogError("Read the 1.0.2 release notes, as the dynamicmenu folder has been removed."); } else { BuildPath(Path_SM, configPath, sizeof(configPath), "configs/adminmenu_grouping.txt"); } if (!FileExists(configPath)) { LogError("Unable to locate admin menu groups file: %s", configPath); return; } int line; SMCError err = g_configParser.ParseFile(configPath, line); if (err != SMCError_Okay) { char error[256]; SMC_GetErrorString(err, error, sizeof(error)); LogError("Could not parse file (line %d, file \"%s\"):", line, configPath); LogError("Parser encountered error: %s", error); } return; } public SMCResult NewSection(SMCParser smc, const char[] name, bool opt_quotes) { } public SMCResult KeyValue(SMCParser smc, const char[] key, const char[] value, bool key_quotes, bool value_quotes) { g_groupList[groupListName].PushString(key); g_groupList[groupListCommand].PushString(value); } public SMCResult EndSection(SMCParser smc) { g_groupCount = g_groupList[groupListName].Length; } public void DynamicMenuCategoryHandler(TopMenu topmenu, TopMenuAction action, TopMenuObject object_id, int param, char[] buffer, int maxlength) { if ((action == TopMenuAction_DisplayTitle) || (action == TopMenuAction_DisplayOption)) { topmenu.GetObjName(object_id, buffer, maxlength); } } public void DynamicMenuItemHandler(TopMenu topmenu, TopMenuAction action, TopMenuObject object_id, int param, char[] buffer, int maxlength) { if (action == TopMenuAction_DisplayOption) { topmenu.GetObjName(object_id, buffer, maxlength); } else if (action == TopMenuAction_SelectOption) { char locString[10]; topmenu.GetInfoString(object_id, locString, sizeof(locString)); int location = StringToInt(locString); int output[Item]; g_DataArray.GetArray(location, output[0]); strcopy(g_command[param], sizeof(g_command[]), output[Item_cmd]); g_currentPlace[param][Place_Item] = location; g_currentPlace[param][Place_ReplaceNum] = 1; ParamCheck(param); } } public void ParamCheck(int client) { char buffer[6]; char buffer2[6]; int outputItem[Item]; int outputSubmenu[Submenu]; g_DataArray.GetArray(g_currentPlace[client][Place_Item], outputItem[0]); if (g_currentPlace[client][Place_ReplaceNum] < 1) { g_currentPlace[client][Place_ReplaceNum] = 1; } Format(buffer, 5, "#%i", g_currentPlace[client][Place_ReplaceNum]); Format(buffer2, 5, "@%i", g_currentPlace[client][Place_ReplaceNum]); if (StrContains(g_command[client], buffer) != -1 || StrContains(g_command[client], buffer2) != -1) { outputItem[Item_submenus].GetArray(g_currentPlace[client][Place_ReplaceNum] - 1, outputSubmenu[0]); Menu itemMenu = new Menu(Menu_Selection); itemMenu.ExitBackButton = true; if ((outputSubmenu[Submenu_type] == SubMenu_Group) || (outputSubmenu[Submenu_type] == SubMenu_GroupPlayer)) { char nameBuffer[ARRAY_STRING_LENGTH]; char commandBuffer[ARRAY_STRING_LENGTH]; for (int i = 0; i= maxlen) { /* Null terminate for safety */ output[maxlen-1] = 0; return false; } if (FindCharInString(quotechars, input[i]) != -1 || input[i] == '\\') { /* This char needs escaping */ output[count] = '\\'; count++; if (count >= maxlen) { /* Null terminate for safety */ output[maxlen-1] = 0; return false; } } } output[count] = 0; return true; } stock bool UnQuoteString(char[] input, char[] output, int maxlen, char[] quotechars) { int count = 1; int len = strlen(input); output[0] = input[0]; for (int i=1; i= maxlen) { /* Null terminate for safety */ output[maxlen-1] = 0; return false; } } output[count] = 0; return true; }