public bool CheckBlueprintMatchesQuery(GameObjectBlueprint blueprint, string queryLowercase)
        {
            if (blueprint == null)
            {
                return(false);
            }
            if (!string.IsNullOrEmpty(blueprint.Name) && blueprint.Name.ToLower().Contains(queryLowercase))
            {
                return(true);
            }
            bool hasParent = !string.IsNullOrEmpty(blueprint.Inherits);

            if (hasParent && blueprint.Inherits.ToLower().Contains(queryLowercase))
            {
                return(true);
            }
            GameObjectBlueprint parent;

            if (hasParent && GameObjectFactory.Factory.Blueprints.TryGetValue(blueprint.Inherits, out parent))
            {
                if (!string.IsNullOrEmpty(parent.Inherits) && parent.Inherits.ToLower().Contains(queryLowercase))
                {
                    return(true);
                }
            }
            GamePartBlueprint renderPart = blueprint.GetPart("Render");

            if (renderPart != null)
            {
                string displayName = renderPart.Parameters.ContainsKey("DisplayName") ? renderPart.Parameters["DisplayName"] : null;
                if (!string.IsNullOrEmpty(displayName))
                {
                    if (ColorUtility.StripFormatting(displayName).ToLower().Contains(queryLowercase))
                    {
                        return(true);
                    }
                }
            }
            return(false);
        }
        public IEnumerable <TileMetadata> LoadBlueprintTiles(IEnumerable <GameObjectBlueprint> blueprints)
        {
            HashSet <string> foundTiles = new HashSet <string>();

            foreach (GameObjectBlueprint blueprint in blueprints)
            {
                GamePartBlueprint renderPart = blueprint.GetPart("Render");
                if (renderPart == null)
                {
                    continue;
                }
                string detailColor     = renderPart.Parameters.ContainsKey("DetailColor") ? renderPart.Parameters["DetailColor"] : null;
                string foregroundColor = renderPart.Parameters.ContainsKey("ColorString") ? renderPart.Parameters["ColorString"] : "&y";
                string tileColor       = renderPart.Parameters.ContainsKey("TileColor") ? renderPart.Parameters["TileColor"] : null;
                if (!string.IsNullOrEmpty(tileColor))
                {
                    foregroundColor = tileColor; //Some things use TileColor attribute; it has the same structure as ColorString
                }
                if (string.IsNullOrEmpty(detailColor) || string.IsNullOrEmpty(foregroundColor) || detailColor.Length != 1)
                {
                    continue;
                }
                int idx = foregroundColor.IndexOf('&');
                if (idx >= 0 && idx + 1 < foregroundColor.Length)
                {
                    foregroundColor = foregroundColor[foregroundColor.LastIndexOf('&') + 1].ToString();
                }
                GamePartBlueprint holoPart = blueprint.GetPart("HologramMaterial");
                if (holoPart != null)
                {
                    foregroundColor = "B";
                    detailColor     = "b";
                }
                GamePartBlueprint dischargePart = blueprint.GetPart("DischargeOnStep");
                if (dischargePart != null)
                {
                    foregroundColor = "W";
                }
                if (IsPhotosynthetic)
                {
                    foregroundColor = "g";
                }
                GamePartBlueprint randomTilePart = blueprint.GetPart("RandomTile");
                if (randomTilePart == null)
                {
                    string tilePath = renderPart.Parameters.ContainsKey("Tile") ? renderPart.Parameters["Tile"] : null;
                    tilePath = tilePath != null?tilePath.ToLower() : null;

                    if (!string.IsNullOrEmpty(tilePath))
                    {
                        if (!foundTiles.Contains($"{tilePath}{detailColor}{foregroundColor}"))
                        {
                            foundTiles.Add($"{tilePath}{detailColor}{foregroundColor}");
                            string displayName   = renderPart.Parameters.ContainsKey("DisplayName") ? renderPart.Parameters["DisplayName"] : "";
                            string blueprintPath = BlueprintPath(blueprint);
                            yield return(new TileMetadata(tilePath, detailColor, foregroundColor, displayName, blueprintPath));
                        }
                    }
                }
                else //ignore Render Tile if this has RandomTile part (as the game does)
                {
                    string tileList = randomTilePart.Parameters.ContainsKey("Tiles") ? randomTilePart.Parameters["Tiles"] : null;
                    if (!string.IsNullOrEmpty(tileList))
                    {
                        string displayName   = renderPart.Parameters.ContainsKey("DisplayName") ? renderPart.Parameters["DisplayName"] : "";
                        string blueprintPath = BlueprintPath(blueprint);
                        foreach (string tile in tileList.ToLower().Split(','))
                        {
                            if (!foundTiles.Contains($"{tile}{detailColor}{foregroundColor}"))
                            {
                                foundTiles.Add($"{tile}{detailColor}{foregroundColor}");
                                yield return(new TileMetadata(tile, detailColor, foregroundColor, displayName, blueprintPath));
                            }
                        }
                    }
                }
            }
        }