示例#1
0
        private void RegisterItemIntoMetaTagSystem(ItemSpawnerEntry entry)
        {
            if (!IM.OD.ContainsKey(entry.MainObjectID))
            {
                return;
            }

            FVRObject mainObject        = IM.OD[entry.MainObjectID];
            string    pageString        = entry.EntryPath.Split('/')[0];
            string    subCategoryString = entry.EntryPath.Split('/')[1];

            ItemSpawnerV2.PageMode page = ItemSpawnerV2.PageMode.Firearms;
            if (Enum.IsDefined(typeof(ItemSpawnerV2.PageMode), pageString))
            {
                page = (ItemSpawnerV2.PageMode)Enum.Parse(typeof(ItemSpawnerV2.PageMode), pageString);
            }

            ItemSpawnerID.ESubCategory subCategory = ItemSpawnerID.ESubCategory.None;
            if (Enum.IsDefined(typeof(ItemSpawnerID.ESubCategory), subCategoryString))
            {
                subCategory = (ItemSpawnerID.ESubCategory)Enum.Parse(typeof(ItemSpawnerID.ESubCategory), subCategoryString);
            }

            IM.AddMetaTag(subCategoryString, TagType.SubCategory, entry.MainObjectID, page);

            entry.ModTags.ForEach(tag =>
                                  IM.AddMetaTag(tag, TagType.ModTag, entry.MainObjectID, page));

            RegisterItemIntoMetaTagSystem(mainObject, page);
        }
示例#2
0
        private static IEnumerator SpawnItems(ItemSpawnerV2 instance, ItemSpawnerEntry entry)
        {
            List <AnvilCallback <GameObject> > itemsToSpawn = new List <AnvilCallback <GameObject> >();

            itemsToSpawn.Add(IM.OD[entry.MainObjectID].GetGameObjectAsync());
            itemsToSpawn.AddRange(entry.SpawnWithIDs.Select(o => IM.OD[o].GetGameObjectAsync()));

            for (int i = 0; i < itemsToSpawn.Count; i++)
            {
                yield return(itemsToSpawn[i]);

                if (i == 0 && entry.UsesLargeSpawnPad)
                {
                    UnityEngine.Object.Instantiate(itemsToSpawn[i].Result, instance.SpawnPoint_Large.position, instance.SpawnPoint_Large.rotation);
                }
                else
                {
                    if (instance.m_curSmallPos >= instance.SpawnPoints_Small.Count)
                    {
                        instance.m_curSmallPos = 0;
                    }

                    UnityEngine.Object.Instantiate(itemsToSpawn[i].Result, instance.SpawnPoints_Small[instance.m_curSmallPos].position, instance.SpawnPoints_Small[instance.m_curSmallPos].rotation);

                    instance.m_curSmallPos += 1;
                }
            }
        }
示例#3
0
 public EntryNode(ItemSpawnerEntry entry = null)
 {
     if (entry == null)
     {
         this.entry = ScriptableObject.CreateInstance <ItemSpawnerEntry>();
     }
     else
     {
         this.entry = entry;
     }
 }
示例#4
0
        private static void PopulateSpawnerEntries()
        {
            foreach (KeyValuePair <ItemSpawnerV2.PageMode, List <string> > PageLists in IM.Instance.PageItemLists)
            {
                foreach (string ItemID in PageLists.Value)
                {
                    ItemSpawnerID SpawnerID = IM.Instance.SpawnerIDDic[ItemID];

                    ItemSpawnerEntry SpawnerEntry = ScriptableObject.CreateInstance <ItemSpawnerEntry>();
                    SpawnerEntry.LegacyPopulateFromID(PageLists.Key, SpawnerID, false);
                    ItemLoader.PopulateEntryPaths(SpawnerEntry, SpawnerID);
                }
            }
        }
示例#5
0
        private static bool ShouldIncludeGeneral(FVRObject item, ItemSpawnerEntry entry, Dictionary <TagType, List <string> > tagQuery)
        {
            if (tagQuery[TagType.SubCategory].Count > 0 && !tagQuery[TagType.SubCategory].Contains(entry.EntryPath.Split('/')[1]))
            {
                return(false);
            }

            if (tagQuery[TagType.Set].Count > 0 && !tagQuery[TagType.Set].Contains(item.TagSet.ToString()))
            {
                return(false);
            }

            if (tagQuery[TagType.Era].Count > 0 && !tagQuery[TagType.Era].Contains(item.TagEra.ToString()))
            {
                return(false);
            }

            if (tagQuery[TagType.ModTag].Count > 0 && !entry.ModTags.Any(o => tagQuery[TagType.ModTag].Contains(o.ToString())))
            {
                return(false);
            }

            return(true);
        }
示例#6
0
        private static bool RedrawListPatch(ItemSpawnerV2 __instance)
        {
            if (__instance.PMode == ItemSpawnerV2.PageMode.MainMenu)
            {
                return(false);
            }

            //Ensure that the selected tags list contains values for every tag type
            //TODO this should be done in the place where the selected tags list is assigned, but that will require a new patch
            if (!__instance.m_selectedTags.ContainsKey(__instance.PMode))
            {
                __instance.m_selectedTags[__instance.PMode] = new Dictionary <TagType, List <string> >();
            }
            foreach (TagType tagType in Enum.GetValues(typeof(TagType)))
            {
                if (!__instance.m_selectedTags[__instance.PMode].ContainsKey(tagType))
                {
                    __instance.m_selectedTags[__instance.PMode][tagType] = new List <string>();
                }
            }

            Dictionary <FVRObject, ItemSpawnerEntry> entries = GetEntryPairsFromQuery(IM.Instance.PageItemLists[__instance.PMode], __instance.m_selectedTags[__instance.PMode]);

            __instance.WorkingItemIDs.Clear();
            __instance.WorkingItemIDs.AddRange(entries.Keys.Select(o => o.ItemID));
            __instance.WorkingItemIDs.Sort();
            __instance.m_displayedItemIds.Clear();

            //Assign values based on the display mode of the spawner
            int          numItems = __instance.WorkingItemIDs.Count;
            int          numPages = 1;
            int          entriesPerPage;
            List <Image> images;
            List <Text>  texts;

            if (__instance.LDMode == ItemSpawnerV2.ListDisplayMode.Text)
            {
                __instance.GO_List.SetActive(true);
                __instance.GO_Grid.SetActive(false);

                entriesPerPage = 22;
                images         = __instance.IM_List;
                texts          = __instance.TXT_List;
            }
            else
            {
                __instance.GO_List.SetActive(false);
                __instance.GO_Grid.SetActive(true);

                entriesPerPage = 12;
                images         = __instance.IM_Grid;
                texts          = __instance.TXT_Grid;
            }


            //If there are no items from our query, let the use know
            if (numItems == 0)
            {
                for (int l = 0; l < images.Count; l++)
                {
                    __instance.m_curListPageNum[__instance.PMode] = 0;
                    images[l].gameObject.SetActive(false);
                    texts[l].gameObject.SetActive(false);
                }
                __instance.TXT_ListPage.text    = string.Empty;
                __instance.TXT_ListShowing.text = "No Items Match All Selected Tags";
            }

            else
            {
                numPages = Mathf.Max(Mathf.CeilToInt((float)numItems / entriesPerPage), 1);

                if (__instance.m_curListPageNum[__instance.PMode] >= numPages)
                {
                    __instance.m_curListPageNum[__instance.PMode] = numPages - 1;
                }

                int startIndex         = __instance.m_curListPageNum[__instance.PMode] * entriesPerPage;
                int nextPageStartIndex = (__instance.m_curListPageNum[__instance.PMode] + 1) * entriesPerPage;
                int currentIndex       = startIndex;

                for (int m = 0; m < images.Count; m++)
                {
                    if (currentIndex >= numItems)
                    {
                        images[m].gameObject.SetActive(false);
                        texts[m].gameObject.SetActive(false);
                    }
                    else
                    {
                        ItemSpawnerEntry entry = OtherLoader.SpawnerEntriesByID[__instance.WorkingItemIDs[currentIndex]];
                        __instance.m_displayedItemIds.Add(entry.MainObjectID);
                        images[m].sprite = entry.EntryIcon;
                        images[m].gameObject.SetActive(true);
                        texts[m].text = entry.DisplayName;
                        texts[m].gameObject.SetActive(true);
                    }

                    currentIndex++;
                }

                __instance.TXT_ListShowing.text = string.Concat(new object[]
                {
                    "Showing ",
                    startIndex,
                    " - ",
                    Mathf.Min(nextPageStartIndex, numItems),
                    " of ",
                    numItems
                });
            }


            //Now perform logic for displaying page buttons
            __instance.TXT_ListPage.text = (__instance.m_curListPageNum[__instance.PMode] + 1).ToString() + " / " + numPages.ToString();
            if (__instance.m_curListPageNum[__instance.PMode] > 0)
            {
                __instance.BTN_ListPagePrev.SetActive(true);
            }
            else
            {
                __instance.BTN_ListPagePrev.SetActive(false);
            }
            if (__instance.m_curListPageNum[__instance.PMode] < numPages - 1)
            {
                __instance.BTN_ListPageNext.SetActive(true);
            }
            else
            {
                __instance.BTN_ListPageNext.SetActive(false);
            }

            return(false);
        }
示例#7
0
        private static bool RedrawSimplePatch(ItemSpawnerV2 __instance)
        {
            if (__instance.PMode == ItemSpawnerV2.PageMode.MainMenu)
            {
                return(false);
            }

            ItemSpawnerData data = __instance.GetComponent <ItemSpawnerData>();

            data.VisibleEntries.Clear();

            List <EntryNode> entries = OtherLoader.SpawnerEntriesByPath[data.CurrentPath].childNodes.Where(o => o.entry.IsDisplayedInMainEntry).ToList();

            OtherLogger.Log($"Got {entries.Count} entries for path: {data.CurrentPath}", OtherLogger.LogType.General);

            entries = entries.OrderBy(o => o.entry.DisplayName).OrderBy(o => o.entry.IsModded?1:0).OrderBy(o => o.childNodes.Count > 0?0:1).ToList();

            int currPage   = data.SavedPagePositions[__instance.PMode][data.CurrentDepth];
            int startIndex = currPage * __instance.IMG_SimpleTiles.Count;

            for (int i = 0; i < __instance.IMG_SimpleTiles.Count; i++)
            {
                if (startIndex + i < entries.Count)
                {
                    ItemSpawnerEntry entry = entries[startIndex + i].entry;
                    data.VisibleEntries.Add(entry);

                    __instance.IMG_SimpleTiles[i].gameObject.SetActive(true);
                    __instance.TXT_SimpleTiles[i].gameObject.SetActive(true);
                    __instance.IMG_SimpleTiles[i].sprite = entry.EntryIcon;
                    __instance.TXT_SimpleTiles[i].text   = entry.DisplayName;
                }
                else
                {
                    __instance.IMG_SimpleTiles[i].gameObject.SetActive(false);
                    __instance.TXT_SimpleTiles[i].gameObject.SetActive(false);
                }
            }

            int numPages = (int)Math.Ceiling((double)entries.Count / __instance.IMG_SimpleTiles.Count);

            OtherLogger.Log($"There are {numPages} pages for this entry", OtherLogger.LogType.General);

            __instance.TXT_SimpleTiles_PageNumber.text = (currPage + 1) + " / " + (numPages);
            __instance.TXT_SimpleTiles_Showing.text    =
                "Showing " +
                (currPage * __instance.IMG_SimpleTiles.Count) +
                " - " +
                (currPage * __instance.IMG_SimpleTiles.Count + data.VisibleEntries.Count) +
                " Of " +
                entries.Count;


            if (currPage > 0)
            {
                __instance.GO_SimpleTiles_PrevPage.SetActive(true);
            }
            else
            {
                __instance.GO_SimpleTiles_PrevPage.SetActive(false);
            }

            if (currPage < numPages - 1)
            {
                __instance.GO_SimpleTiles_NextPage.SetActive(true);
            }
            else
            {
                __instance.GO_SimpleTiles_NextPage.SetActive(false);
            }

            return(false);
        }
示例#8
0
        private static bool RedrawDetailsCanvasPatch(ItemSpawnerV2 __instance)
        {
            OtherLogger.Log("Selected ID: " + __instance.m_selectedID, OtherLogger.LogType.General);

            //If there is no spawner entry for the selected ID, set everything to blank
            if (!OtherLoader.SpawnerEntriesByID.ContainsKey(__instance.m_selectedID))
            {
                return(true);
            }


            else
            {
                ItemSpawnerEntry entry = OtherLoader.SpawnerEntriesByID[__instance.m_selectedID];
                ItemSpawnerData  data  = __instance.GetComponent <ItemSpawnerData>();

                OtherLogger.Log("We found an entry for it!", OtherLogger.LogType.General);

                //First, fill activate some of the detail and populate it with info
                for (int l = 0; l < __instance.IM_FavButtons.Count; l++)
                {
                    __instance.IM_FavButtons[l].gameObject.SetActive(true);
                }

                __instance.IM_Detail.gameObject.SetActive(true);
                __instance.IM_Detail.sprite = entry.EntryIcon;
                __instance.TXT_Title.text   = entry.DisplayName;
                __instance.BTN_SpawnSelectedObject.SetActive(true);
                __instance.TXT_Detail.text = __instance.GetDetailText(__instance.m_selectedID);



                //Now get all the secondary entries
                List <ItemSpawnerEntry> secondaryEntries = new List <ItemSpawnerEntry>();
                for (int m = 0; m < entry.SecondaryObjectIDs.Count; m++)
                {
                    if (!OtherLoader.SpawnerEntriesByID.ContainsKey(entry.SecondaryObjectIDs[m]))
                    {
                        OtherLogger.LogWarning($"Secondary ID for ({entry.MainObjectID}) was not in entry dictionary! It will not appear! Secondary ID ({entry.SecondaryObjectIDs[m]})");
                        continue;
                    }

                    ItemSpawnerEntry secondary = OtherLoader.SpawnerEntriesByID[entry.SecondaryObjectIDs[m]];
                    if (!secondary.IsReward || GM.Rewards.RewardUnlocks.Rewards.Contains(secondary.MainObjectID))
                    {
                        secondaryEntries.Add(secondary);
                    }
                }


                //Now we create the secondaries page
                //Start by drawing the tiles
                data.VisibleSecondaryEntries.Clear();
                int startIndex = __instance.m_selectedIDRelatedPage * __instance.IM_DetailRelated.Count;
                for (int i = 0; i < __instance.IM_DetailRelated.Count; i++)
                {
                    if (startIndex + i < secondaryEntries.Count)
                    {
                        ItemSpawnerEntry secondaryEntry = secondaryEntries[startIndex + i];
                        data.VisibleSecondaryEntries.Add(secondaryEntry);

                        __instance.IM_DetailRelated[i].gameObject.SetActive(true);
                        __instance.IM_DetailRelated[i].sprite = secondaryEntry.EntryIcon;
                    }
                    else
                    {
                        __instance.IM_DetailRelated[i].gameObject.SetActive(false);
                    }
                }

                //Now handle the page selectors
                int numPages = (int)Math.Ceiling((double)secondaryEntries.Count / __instance.IM_DetailRelated.Count);
                __instance.TXT_DetailsRelatedPageNum.gameObject.SetActive(true);
                __instance.TXT_DetailsRelatedPageNum.text = (__instance.m_selectedIDRelatedPage + 1).ToString() + " / " + numPages.ToString();

                if (__instance.m_selectedIDRelatedPage > 0)
                {
                    __instance.BTN_DetailsRelatedPrevPage.SetActive(true);
                }
                else
                {
                    __instance.BTN_DetailsRelatedPrevPage.SetActive(false);
                }

                if (__instance.m_selectedIDRelatedPage < numPages - 1)
                {
                    __instance.BTN_DetailsRelatedNextPage.SetActive(true);
                }
                else
                {
                    __instance.BTN_DetailsRelatedNextPage.SetActive(false);
                }



                //Setup the tutorials panel
                for (int i = 0; i < __instance.BTNS_DetailTutorial.Count; i++)
                {
                    if (i < entry.TutorialBlockIDs.Count)
                    {
                        if (IM.TutorialBlockDic.ContainsKey(entry.TutorialBlockIDs[i]))
                        {
                            __instance.BTNS_DetailTutorial[i].gameObject.SetActive(true);
                            __instance.BTNS_DetailTutorial[i].text = IM.TutorialBlockDic[entry.TutorialBlockIDs[i]].Title;
                        }
                        else
                        {
                            __instance.BTNS_DetailTutorial[i].gameObject.SetActive(false);
                        }
                    }
                    else
                    {
                        __instance.BTNS_DetailTutorial[i].gameObject.SetActive(false);
                    }
                }



                //Setup the favorites icons
                for (int i = 0; i < __instance.IM_FavButtons.Count; i++)
                {
                    if (ManagerSingleton <IM> .Instance.ItemMetaDic.ContainsKey(__instance.m_selectedID) && ManagerSingleton <IM> .Instance.ItemMetaDic[__instance.m_selectedID].ContainsKey(TagType.Favorites) && ManagerSingleton <IM> .Instance.ItemMetaDic[__instance.m_selectedID][TagType.Favorites].Contains(__instance.FaveTags[i]))
                    {
                        __instance.IM_FavButtons[i].sprite = __instance.IM_FavButton_Faved[i];
                    }
                    else
                    {
                        __instance.IM_FavButtons[i].sprite = __instance.IM_FavButton_UnFaved[i];
                    }
                }
            }


            return(false);
        }
示例#9
0
        /// <summary>
        /// Pop
        /// </summary>
        /// <param name="Page"></param>
        /// <param name="ID"></param>
        public static void PopulateEntryPaths(ItemSpawnerEntry entry, ItemSpawnerID spawnerID = null)
        {
            string[] pathSegments = entry.EntryPath.Split('/');
            string   currentPath  = "";

            for (int i = 0; i < pathSegments.Length; i++)
            {
                //If we are at the full path length for this entry, we can just assign the entry
                if (i == pathSegments.Length - 1)
                {
                    EntryNode previousNode = OtherLoader.SpawnerEntriesByPath[currentPath];
                    currentPath += (i == 0 ? "" : "/") + pathSegments[i];

                    //If there is already an node at this path, we should just update it. Otherwise, add it as a new node
                    EntryNode node;
                    if (OtherLoader.SpawnerEntriesByPath.ContainsKey(currentPath))
                    {
                        node       = OtherLoader.SpawnerEntriesByPath[currentPath];
                        node.entry = entry;
                    }
                    else
                    {
                        node = new EntryNode(entry);
                        OtherLoader.SpawnerEntriesByPath[currentPath] = node;
                        previousNode.childNodes.Add(node);
                    }
                }


                //If we are at the page level, just check to see if we need to add a page node
                else if (i == 0)
                {
                    currentPath += (i == 0 ? "" : "/") + pathSegments[i];

                    if (!OtherLoader.SpawnerEntriesByPath.ContainsKey(currentPath))
                    {
                        EntryNode pageNode = new EntryNode();
                        pageNode.entry.EntryPath = currentPath;
                        OtherLoader.SpawnerEntriesByPath[currentPath] = pageNode;
                    }
                }

                //If these are just custom categories of any depth, just add the ones that aren't already loaded
                else
                {
                    EntryNode previousNode = OtherLoader.SpawnerEntriesByPath[currentPath];
                    currentPath += (i == 0 ? "" : "/") + pathSegments[i];

                    if (!OtherLoader.SpawnerEntriesByPath.ContainsKey(currentPath))
                    {
                        EntryNode node = new EntryNode();
                        node.entry.EntryPath = currentPath;
                        node.entry.IsDisplayedInMainEntry = true;

                        //Now this section below is for legacy support
                        if (spawnerID != null)
                        {
                            //If this is meatfortress category, do that
                            if (i == 1 && spawnerID.Category == ItemSpawnerID.EItemCategory.MeatFortress)
                            {
                                node.entry.EntryIcon   = IM.CDefInfo[ItemSpawnerID.EItemCategory.MeatFortress].Sprite;
                                node.entry.DisplayName = IM.CDefInfo[ItemSpawnerID.EItemCategory.MeatFortress].DisplayName;
                            }

                            //If this is a modded main category, do that
                            else if (i == 1 && !Enum.IsDefined(typeof(ItemSpawnerID.EItemCategory), spawnerID.Category))
                            {
                                if (IM.CDefInfo.ContainsKey(spawnerID.Category))
                                {
                                    node.entry.EntryIcon   = IM.CDefInfo[spawnerID.Category].Sprite;
                                    node.entry.DisplayName = IM.CDefInfo[spawnerID.Category].DisplayName;
                                }
                            }

                            //If this is a subcategory (modded or not), do that
                            else if (IM.CDefSubInfo.ContainsKey(spawnerID.SubCategory))
                            {
                                node.entry.EntryIcon   = IM.CDefSubInfo[spawnerID.SubCategory].Sprite;
                                node.entry.DisplayName = IM.CDefSubInfo[spawnerID.SubCategory].DisplayName;
                            }

                            node.entry.IsModded = IM.OD[spawnerID.MainObject.ItemID].IsModContent;
                        }

                        previousNode.childNodes.Add(node);
                        OtherLoader.SpawnerEntriesByPath[currentPath] = node;
                    }
                }
            }
        }
示例#10
0
        private void LoadSpawnerIDs(UnityEngine.Object[] allAssets)
        {
            foreach (ItemSpawnerID id in allAssets)
            {
                OtherLogger.Log("Adding Itemspawner ID! Category: " + id.Category + ", SubCategory: " + id.SubCategory, OtherLogger.LogType.Loading);

                //Try to set the main object of this ID as a secondary if the main is null (so that it gets tagged properly)
                if (id.MainObject == null && id.Secondaries.Length > 0)
                {
                    id.MainObject = id.Secondaries.Select(o => o.MainObject).FirstOrDefault(o => o != null);
                    if (id.MainObject == null)
                    {
                        OtherLogger.Log("Could not select a secondary object for ItemSpawnerID, it will not appear in spawner: Display Name: " + id.DisplayName, OtherLogger.LogType.Loading);
                    }
                    else
                    {
                        id.ItemID = id.MainObject.ItemID;
                    }
                }


                if (id.MainObject != null)
                {
                    if (id.UnlockCost == 0)
                    {
                        id.UnlockCost = id.MainObject.CreditCost;
                    }

                    IM.RegisterItemIntoMetaTagSystem(id);
                    if (!id.IsDisplayedInMainEntry)
                    {
                        HideItemFromCategories(id);
                    }
                }


                if (IM.CD.ContainsKey(id.Category) && IM.SCD.ContainsKey(id.SubCategory))
                {
                    IM.CD[id.Category].Add(id);
                    IM.SCD[id.SubCategory].Add(id);

                    if (!ManagerSingleton <IM> .Instance.SpawnerIDDic.ContainsKey(id.ItemID))
                    {
                        ManagerSingleton <IM> .Instance.SpawnerIDDic[id.ItemID] = id;

                        //Now we will try to convert this SpawnerID into a spawner entry
                        ItemSpawnerEntry SpawnerEntry = ScriptableObject.CreateInstance <ItemSpawnerEntry>();

                        //If the category is defined, we can try to add it based on what page it was given
                        if (Enum.IsDefined(typeof(ItemSpawnerID.EItemCategory), id.Category))
                        {
                            //TODO this should be done without having to loop through potentially all spawner entries, I bet this could become expensive
                            bool added = false;
                            foreach (KeyValuePair <ItemSpawnerV2.PageMode, List <string> > pageItems in IM.Instance.PageItemLists)
                            {
                                if (pageItems.Value.Contains(id.ItemID))
                                {
                                    OtherLogger.Log("Adding SpawnerID to spawner entry tree", OtherLogger.LogType.Loading);
                                    SpawnerEntry.LegacyPopulateFromID(pageItems.Key, id, true);
                                    PopulateEntryPaths(SpawnerEntry, id);
                                    added = true;

                                    break;
                                }
                            }

                            if (added)
                            {
                                continue;
                            }

                            //If we make it to this point, we failed to add the entry to the tree structure, but should still populate the entries data
                            OtherLogger.Log("ItemSpawnerID could not be converted for new spawner because of metadata issues! ItemID: " + id.ItemID, OtherLogger.LogType.Loading);
                            SpawnerEntry.LegacyPopulateFromID(ItemSpawnerV2.PageMode.Firearms, id, true);
                        }

                        //Otherwise, all custom category items go under the firearms page
                        else
                        {
                            OtherLogger.Log("Adding SpawnerID to spawner entry tree under custom category", OtherLogger.LogType.Loading);
                            SpawnerEntry.LegacyPopulateFromID(ItemSpawnerV2.PageMode.Firearms, id, true);
                            PopulateEntryPaths(SpawnerEntry, id);
                        }
                    }
                }

                else
                {
                    OtherLogger.LogError("ItemSpawnerID could not be added, because either the main category or subcategory were not loaded! Item will not appear in the itemspawner! Item Display Name: " + id.DisplayName);
                }
            }
        }