Fixed top menu categories being available even if not usable (bug 3256, r=me).
authorDavid Anderson <dvander@alliedmods.net>
Wed Jan 07 02:08:14 2009 -0500 (2009-01-07)
changeset 25103b2349600557
parent 2509 ede1aff4bf1c
child 2511 17c67f8aa861
Fixed top menu categories being available even if not usable (bug 3256, r=me).
extensions/topmenus/TopMenu.cpp
extensions/topmenus/TopMenu.h
     1.1 --- a/extensions/topmenus/TopMenu.cpp	Fri Jan 02 00:31:23 2009 -0600
     1.2 +++ b/extensions/topmenus/TopMenu.cpp	Wed Jan 07 02:08:14 2009 -0500
     1.3 @@ -248,6 +248,7 @@
     1.4  		cat->serial = 1;
     1.5  
     1.6  		/* Add it, then update our serial change number. */
     1.7 +		obj->cat_id = m_Categories.size();
     1.8  		m_Categories.push_back(cat);
     1.9  		m_SerialNo++;
    1.10  
    1.11 @@ -257,6 +258,7 @@
    1.12  	else if (obj->type == TopMenuObject_Item)
    1.13  	{
    1.14  		/* Update the category, mark it as needing changes */
    1.15 +		obj->cat_id = 0;
    1.16  		parent_cat->obj_list.push_back(obj);
    1.17  		parent_cat->reorder = true;
    1.18  		parent_cat->serial++;
    1.19 @@ -407,6 +409,12 @@
    1.20  
    1.21  	UpdateClientRoot(client, pPlayer);
    1.22  
    1.23 +	/* This is unfortunate but it's the best solution. */
    1.24 +	for (size_t i = 0; i < m_Categories.size(); i++)
    1.25 +	{
    1.26 +		UpdateClientCategory(client, i, true);
    1.27 +	}
    1.28 +
    1.29  	topmenu_player_t *pClient = &m_clients[client];
    1.30  	if (pClient->root == NULL)
    1.31  	{
    1.32 @@ -443,8 +451,7 @@
    1.33  	UpdateClientCategory(client, category);
    1.34  
    1.35  	topmenu_player_t *pClient = &m_clients[client];
    1.36 -	if (category >= pClient->cat_count
    1.37 -		|| pClient->cats[category].menu == NULL)
    1.38 +	if (category >= pClient->cat_count || pClient->cats[category].menu == NULL)
    1.39  	{
    1.40  		return false;
    1.41  	}
    1.42 @@ -488,18 +495,16 @@
    1.43  	if (obj->type == TopMenuObject_Category)
    1.44  	{
    1.45  		/* If it's a category, the user wants to view it.. */
    1.46 -		for (size_t i = 0; i < m_Categories.size(); i++)
    1.47 +		assert(obj->cat_id < m_Categories.size());
    1.48 +		assert(m_Categories[obj->cat_id]->obj == obj);
    1.49 +		pClient->last_root_pos = item_on_page;
    1.50 +		if (!DisplayCategory(client, obj->cat_id, MENU_TIME_FOREVER, false))
    1.51  		{
    1.52 -			if (m_Categories[i]->obj == obj)
    1.53 -			{
    1.54 -				pClient->last_root_pos = item_on_page;
    1.55 -				if (!DisplayCategory(client, (unsigned int)i, MENU_TIME_FOREVER, false))
    1.56 -				{
    1.57 -					/* If we can't display the category, re-display the root menu */
    1.58 -					DisplayMenu(client, MENU_TIME_FOREVER, TopMenuPosition_LastRoot);
    1.59 -				}
    1.60 -				break;
    1.61 -			}
    1.62 +			/* If we can't display the category, re-display the root menu.
    1.63 +			 * This code should be dead as of bug 3256, which disables categories 
    1.64 +			 * that cannot be displayed.
    1.65 +			 */
    1.66 +			DisplayMenu(client, MENU_TIME_FOREVER, TopMenuPosition_LastRoot);
    1.67  		}
    1.68  	}
    1.69  	else
    1.70 @@ -535,6 +540,19 @@
    1.71  
    1.72  	obj = *pObject;
    1.73  
    1.74 +	/* If the category has nothing to display, disable it. */
    1.75 +	if (obj->type == TopMenuObject_Category)
    1.76 +	{
    1.77 +		assert(obj->cat_id < m_Categories.size());
    1.78 +		assert(m_Categories[obj->cat_id]->obj == obj);
    1.79 +		topmenu_player_t *pClient = &m_clients[client];
    1.80 +		if (obj->cat_id >= pClient->cat_count || pClient->cats[obj->cat_id].menu == NULL)
    1.81 +		{
    1.82 +			style = ITEMDRAW_IGNORE;
    1.83 +			return;
    1.84 +		}
    1.85 +	}
    1.86 +
    1.87  	style = obj->callbacks->OnTopMenuDrawOption(this, client, obj->object_id);
    1.88  	if (style != ITEMDRAW_DEFAULT)
    1.89  	{
    1.90 @@ -701,13 +719,18 @@
    1.91  	pClient->last_root_pos = 0;
    1.92  }
    1.93  
    1.94 -void TopMenu::UpdateClientCategory(int client, unsigned int category)
    1.95 +void TopMenu::UpdateClientCategory(int client, unsigned int category, bool bSkipRootCheck)
    1.96  {
    1.97 +	bool has_access = false;
    1.98 +
    1.99  	/* Update the client's root menu just in case it needs it.  This 
   1.100  	 * will validate that we have both a valid client and a valid
   1.101  	 * category structure for that client.
   1.102  	 */
   1.103 -	UpdateClientRoot(client);
   1.104 +	if (!bSkipRootCheck)
   1.105 +	{
   1.106 +		UpdateClientRoot(client);
   1.107 +	}
   1.108  
   1.109  	/* Now it's guaranteed that our category tables will be usable */
   1.110  	topmenu_player_t *pClient = &m_clients[client];
   1.111 @@ -744,6 +767,13 @@
   1.112  	for (size_t i = 0; i < cat->sorted.size(); i++)
   1.113  	{
   1.114  		cat_menu->AppendItem(cat->sorted[i]->name, ItemDrawInfo(""));
   1.115 +		if (!has_access && adminsys->CheckAccess(client,
   1.116 +												 cat->sorted[i]->cmdname,
   1.117 +												 cat->sorted[i]->flags,
   1.118 +												 false))
   1.119 +		{
   1.120 +			has_access = true;
   1.121 +		}
   1.122  	}
   1.123  
   1.124  	/* Now handle unsorted items */
   1.125 @@ -761,20 +791,39 @@
   1.126  				item->name,
   1.127  				sizeof(item->name));
   1.128  			item->obj_index = (unsigned int)i;
   1.129 +			if (!has_access && adminsys->CheckAccess(client, obj->cmdname, obj->flags, false))
   1.130 +			{
   1.131 +				has_access = true;
   1.132 +			}
   1.133  		}
   1.134  
   1.135 -		/* Sort the names */
   1.136 -		qsort(item_list, cat->unsorted.size(), sizeof(obj_by_name_t), _SortObjectNamesDescending);
   1.137 +		if (has_access)
   1.138 +		{
   1.139 +			/* Sort the names */
   1.140 +			qsort(item_list,
   1.141 +				cat->unsorted.size(),
   1.142 +				sizeof(obj_by_name_t),
   1.143 +				_SortObjectNamesDescending);
   1.144  
   1.145 -		/* Add to the menu */
   1.146 -		for (size_t i = 0; i < cat->unsorted.size(); i++)
   1.147 -		{
   1.148 -			cat_menu->AppendItem(cat->unsorted[item_list[i].obj_index]->name, ItemDrawInfo(""));
   1.149 +			/* Add to the menu */
   1.150 +			for (size_t i = 0; i < cat->unsorted.size(); i++)
   1.151 +			{
   1.152 +				cat_menu->AppendItem(cat->unsorted[item_list[i].obj_index]->name, ItemDrawInfo(""));
   1.153 +			}
   1.154  		}
   1.155  
   1.156  		delete [] item_list;
   1.157  	}
   1.158  
   1.159 +	/* If the player has access to no items, don't draw a menu. */
   1.160 +	if (!has_access)
   1.161 +	{
   1.162 +		cat_menu->Destroy();
   1.163 +		player_cat->menu = NULL;
   1.164 +		player_cat->serial = cat->serial;
   1.165 +		return;
   1.166 +	}
   1.167 +
   1.168  	/* Set the menu's title */
   1.169  	char renderbuf[128];
   1.170  	cat->obj->callbacks->OnTopMenuDisplayTitle(this, 
     2.1 --- a/extensions/topmenus/TopMenu.h	Fri Jan 02 00:31:23 2009 -0600
     2.2 +++ b/extensions/topmenus/TopMenu.h	Wed Jan 07 02:08:14 2009 -0500
     2.3 @@ -71,6 +71,7 @@
     2.4  	TopMenuObjectType type;				/** Object Type */
     2.5  	bool is_free;						/** Free or not? */
     2.6  	char info[255];						/** Info string */
     2.7 +	unsigned int cat_id;				/** Set if a category */
     2.8  };
     2.9  
    2.10  struct topmenu_category_t
    2.11 @@ -157,7 +158,7 @@
    2.12  	bool DisplayCategory(int client, unsigned int category, unsigned int hold_time, bool last_position);
    2.13  	void CreatePlayers(int max_clients);
    2.14  	void UpdateClientRoot(int client, IGamePlayer *pGamePlayer=NULL);
    2.15 -	void UpdateClientCategory(int client, unsigned int category);
    2.16 +	void UpdateClientCategory(int client, unsigned int category, bool bSkipRootCheck=false);
    2.17  	void TearDownClient(topmenu_player_t *player);
    2.18  private:
    2.19  	void OnClientConnected(int client);