Fixed top menu categories being available even if not usable (bug 3256, r=me).
Fixed top menu categories being available even if not usable (
bug 3256, r=me).
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);