Пример #1
0
        public List<IFilteredItem> ProcessItemsAgainstItemFilterScript(IItemFilterScript itemFilterScript, IEnumerable<IItem> items)
        {
            var overallsw = Stopwatch.StartNew();

            var filteredItems = new List<IFilteredItem>();

            var sw = Stopwatch.StartNew();
            foreach (var item in items)
            {
                sw.Restart();

                var matchedBlock = itemFilterScript.ItemFilterBlocks
                                    .Where(b => !(b is ItemFilterSection))
                                    .FirstOrDefault(block => _blockItemMatcher.ItemBlockMatch(block, item));

                filteredItems.Add(new FilteredItem(item, matchedBlock));

                Debug.WriteLine("Processed Item in {0}ms", sw.ElapsedMilliseconds);
            }
            sw.Stop();

            overallsw.Stop();
            Debug.WriteLine("Total processing time: {0}ms", overallsw.ElapsedMilliseconds);
            return filteredItems;
        }
Пример #2
0
        public string TranslateItemFilterScriptToString(IItemFilterScript script)
        {
            var outputString = string.Empty;

            outputString += "# Script edited with Filtration - https://github.com/ben-wallis/Filtration" +
                            Environment.NewLine;

            if (script.ItemFilterScriptSettings.BlockGroupsEnabled)
            {
                outputString += "# EnableBlockGroups" + Environment.NewLine;
            }

            if (!string.IsNullOrEmpty(script.Description))
            {
                // ReSharper disable once LoopCanBeConvertedToQuery
                foreach (var line in new LineReader(() => new StringReader(script.Description)))
                {
                    if (!line.Contains("Script edited with Filtration"))
                    {
                        outputString += "# " + line + Environment.NewLine;
                    }
                }
            }
            outputString += Environment.NewLine;

            // ReSharper disable once LoopCanBeConvertedToQuery
            foreach (var block in script.ItemFilterBlocks)
            {
                outputString += _blockTranslator.TranslateItemFilterBlockBaseToString(block) + Environment.NewLine;

                if (Settings.Default.ExtraLineBetweenBlocks)
                {
                    outputString += Environment.NewLine;
                }
            }

            return(outputString);
        }
Пример #3
0
 public PasteBlockCommand(IItemFilterScript itemFilterScript, IItemFilterBlockBase pastedItemFilterBlock, IItemFilterBlockBase addAfterItemFilterBlock)
 {
     _itemFilterScript        = itemFilterScript;
     _pastedItemFilterBlock   = pastedItemFilterBlock;
     _addAfterItemFilterBlock = addAfterItemFilterBlock;
 }
Пример #4
0
 public AddCommentBlockCommand(IItemFilterScript itemFilterScript, IItemFilterBlockBase addAfterItemFilterBlock)
 {
     _itemFilterScript        = itemFilterScript;
     _addAfterItemFilterBlock = addAfterItemFilterBlock;
 }
Пример #5
0
 private void OnLoadScriptCommand()
 {
     _itemFilterScript = _itemFilterScriptTranslator.TranslateStringToItemFilterScript(Resources.neversinkfilter);
 }
Пример #6
0
 private void OnLoadAlternateScriptCommand()
 {
     _itemFilterScript = _itemFilterScriptTranslator.TranslateStringToItemFilterScript(Resources.muldini);
 }
Пример #7
0
 public ItemFilterBlock(IItemFilterScript parentScript) : base(parentScript)
 {
     BlockItems = new ObservableCollection <IItemFilterBlockItem> {
         ActionBlockItem
     };
 }
Пример #8
0
        // This method converts a string into a ItemFilterBlock. This is used for pasting ItemFilterBlocks
        // and reading ItemFilterScripts from a file.
        public IItemFilterBlock TranslateStringToItemFilterBlock(string inputString, IItemFilterScript parentItemFilterScript, string originalString = "", bool initialiseBlockGroupHierarchyBuilder = false)
        {
            if (initialiseBlockGroupHierarchyBuilder)
            {
                _blockGroupHierarchyBuilder.Initialise(parentItemFilterScript.ItemFilterBlockGroups.First());
            }

            _masterComponentCollection = parentItemFilterScript.ItemFilterScriptSettings.ThemeComponentCollection;
            var block         = new ItemFilterBlock(parentItemFilterScript);
            var showHideFound = false;

            block.OriginalText = originalString;

            foreach (var line in new LineReader(() => new StringReader(inputString)))
            {
                if (line.StartsWith(@"#"))
                {
                    if (!showHideFound)
                    {
                        block.Description = line.TrimStart('#').TrimStart(' ');
                    }
                    else
                    {
                        if (block.BlockItems.Count > 1)
                        {
                            block.BlockItems.Last().Comment += Environment.NewLine + line.TrimStart('#');
                        }
                        else
                        {
                            block.ActionBlockItem.Comment += Environment.NewLine + line.TrimStart('#');
                        }
                    }
                    continue;
                }

                var fullLine           = line.Trim();
                var trimmedLine        = fullLine;
                var blockComment       = "";
                var themeComponentType = -1;
                if (trimmedLine.IndexOf('#') > 0)
                {
                    blockComment = trimmedLine.Substring(trimmedLine.IndexOf('#') + 1);
                    trimmedLine  = trimmedLine.Substring(0, trimmedLine.IndexOf('#')).Trim();
                }
                var spaceOrEndOfLinePos = trimmedLine.IndexOf(" ", StringComparison.Ordinal) > 0 ? trimmedLine.IndexOf(" ", StringComparison.Ordinal) : trimmedLine.Length;

                var lineOption = trimmedLine.Substring(0, spaceOrEndOfLinePos);
                switch (lineOption)
                {
                case "Show":
                case "Hide":
                case "ShowDisabled":
                case "HideDisabled":
                {
                    showHideFound = true;
                    block.Action  = lineOption.StartsWith("Show") ? BlockAction.Show : BlockAction.Hide;
                    block.Enabled = !lineOption.EndsWith("Disabled");

                    // If block groups are enabled for this script, the comment after Show/Hide is parsed as a block
                    // group hierarchy, if block groups are disabled it is preserved as a simple text comment.
                    if (parentItemFilterScript.ItemFilterScriptSettings.BlockGroupsEnabled)
                    {
                        AddBlockGroupToBlock(block, fullLine);
                    }
                    else
                    {
                        block.ActionBlockItem.Comment = GetTextAfterFirstComment(fullLine);
                    }
                    break;
                }

                case "ItemLevel":
                {
                    AddNumericFilterPredicateItemToBlockItems <ItemLevelBlockItem>(block, trimmedLine);
                    break;
                }

                case "DropLevel":
                {
                    AddNumericFilterPredicateItemToBlockItems <DropLevelBlockItem>(block, trimmedLine);
                    break;
                }

                case "Quality":
                {
                    AddNumericFilterPredicateItemToBlockItems <QualityBlockItem>(block, trimmedLine);
                    break;
                }

                case "Rarity":
                {
                    RemoveExistingBlockItemsOfType <RarityBlockItem>(block);

                    var blockItemValue = new RarityBlockItem();
                    var result         = Regex.Match(trimmedLine, @"^\w+\s+([><!=]{0,2})\s*(\w+)$");
                    if (result.Groups.Count == 3)
                    {
                        blockItemValue.FilterPredicate.PredicateOperator =
                            EnumHelper.GetEnumValueFromDescription <FilterPredicateOperator>(string.IsNullOrEmpty(result.Groups[1].Value) ? "=" : result.Groups[1].Value);
                        blockItemValue.FilterPredicate.PredicateOperand =
                            (int)EnumHelper.GetEnumValueFromDescription <ItemRarity>(result.Groups[2].Value);
                    }

                    block.BlockItems.Add(blockItemValue);
                    break;
                }

                case "Class":
                {
                    AddStringListItemToBlockItems <ClassBlockItem>(block, trimmedLine);
                    break;
                }

                case "BaseType":
                {
                    AddStringListItemToBlockItems <BaseTypeBlockItem>(block, trimmedLine);
                    break;
                }

                case "Prophecy":
                {
                    AddStringListItemToBlockItems <ProphecyBlockItem>(block, trimmedLine);
                    break;
                }

                case "Corrupted":
                {
                    AddBooleanItemToBlockItems <CorruptedBlockItem>(block, trimmedLine);
                    break;
                }

                case "Identified":
                {
                    AddBooleanItemToBlockItems <IdentifiedBlockItem>(block, trimmedLine);
                    break;
                }

                case "ElderItem":
                {
                    AddBooleanItemToBlockItems <ElderItemBlockItem>(block, trimmedLine);
                    break;
                }

                case "ShaperItem":
                {
                    AddBooleanItemToBlockItems <ShaperItemBlockItem>(block, trimmedLine);
                    break;
                }

                case "ShapedMap":
                {
                    AddBooleanItemToBlockItems <ShapedMapBlockItem>(block, trimmedLine);
                    break;
                }

                case "Sockets":
                {
                    AddNumericFilterPredicateItemToBlockItems <SocketsBlockItem>(block, trimmedLine);
                    break;
                }

                case "LinkedSockets":
                {
                    AddNumericFilterPredicateItemToBlockItems <LinkedSocketsBlockItem>(block, trimmedLine);
                    break;
                }

                case "Width":
                {
                    AddNumericFilterPredicateItemToBlockItems <WidthBlockItem>(block, trimmedLine);
                    break;
                }

                case "Height":
                {
                    AddNumericFilterPredicateItemToBlockItems <HeightBlockItem>(block, trimmedLine);
                    break;
                }

                case "SocketGroup":
                {
                    AddStringListItemToBlockItems <SocketGroupBlockItem>(block, trimmedLine);
                    break;
                }

                case "SetTextColor":
                {
                    // Only ever use the last SetTextColor item encountered as multiples aren't valid.
                    RemoveExistingBlockItemsOfType <TextColorBlockItem>(block);

                    var result = Regex.Matches(trimmedLine, @"([\w\s]*)");

                    var blockItem = new TextColorBlockItem {
                        Color = GetColorFromString(result[0].Groups[1].Value)
                    };
                    block.BlockItems.Add(blockItem);
                    themeComponentType = (int)ThemeComponentType.TextColor;
                    break;
                }

                case "SetBackgroundColor":
                {
                    // Only ever use the last SetBackgroundColor item encountered as multiples aren't valid.
                    RemoveExistingBlockItemsOfType <BackgroundColorBlockItem>(block);

                    var result = Regex.Matches(trimmedLine, @"([\w\s]*)");

                    var blockItem = new BackgroundColorBlockItem {
                        Color = GetColorFromString(result[0].Groups[1].Value)
                    };
                    block.BlockItems.Add(blockItem);
                    themeComponentType = (int)ThemeComponentType.BackgroundColor;
                    break;
                }

                case "SetBorderColor":
                {
                    // Only ever use the last SetBorderColor item encountered as multiples aren't valid.
                    RemoveExistingBlockItemsOfType <BorderColorBlockItem>(block);

                    var result = Regex.Matches(trimmedLine, @"([\w\s]*)");

                    var blockItem = new BorderColorBlockItem {
                        Color = GetColorFromString(result[0].Groups[1].Value)
                    };
                    block.BlockItems.Add(blockItem);
                    themeComponentType = (int)ThemeComponentType.BorderColor;
                    break;
                }

                case "SetFontSize":
                {
                    // Only ever use the last SetFontSize item encountered as multiples aren't valid.
                    RemoveExistingBlockItemsOfType <FontSizeBlockItem>(block);

                    var match = Regex.Matches(trimmedLine, @"(\s+(\d+)\s*)");
                    if (match.Count > 0)
                    {
                        var blockItem = new FontSizeBlockItem(Convert.ToInt16(match[0].Groups[2].Value));
                        block.BlockItems.Add(blockItem);
                        themeComponentType = (int)ThemeComponentType.FontSize;
                    }
                    break;
                }

                case "PlayAlertSound":
                case "PlayAlertSoundPositional":
                {
                    // Only ever use the last PlayAlertSound item encountered as multiples aren't valid.
                    RemoveExistingBlockItemsOfType <SoundBlockItem>(block);
                    RemoveExistingBlockItemsOfType <PositionalSoundBlockItem>(block);
                    RemoveExistingBlockItemsOfType <CustomSoundBlockItem>(block);

                    var match = Regex.Match(trimmedLine, @"\S+\s+(\S+)\s?(\d+)?");

                    if (match.Success)
                    {
                        string firstValue = match.Groups[1].Value;

                        var secondValue = match.Groups[2].Success ? Convert.ToInt16(match.Groups[2].Value) : 79;

                        if (lineOption == "PlayAlertSound")
                        {
                            var blockItemValue = new SoundBlockItem
                            {
                                Value       = firstValue,
                                SecondValue = secondValue
                            };
                            block.BlockItems.Add(blockItemValue);
                        }
                        else
                        {
                            var blockItemValue = new PositionalSoundBlockItem
                            {
                                Value       = firstValue,
                                SecondValue = secondValue
                            };
                            block.BlockItems.Add(blockItemValue);
                        }
                        themeComponentType = (int)ThemeComponentType.AlertSound;
                    }
                    break;
                }

                case "GemLevel":
                {
                    AddNumericFilterPredicateItemToBlockItems <GemLevelBlockItem>(block, trimmedLine);
                    break;
                }

                case "StackSize":
                {
                    AddNumericFilterPredicateItemToBlockItems <StackSizeBlockItem>(block, trimmedLine);
                    break;
                }

                case "HasExplicitMod":
                {
                    AddStringListItemToBlockItems <HasExplicitModBlockItem>(block, trimmedLine);
                    break;
                }

                case "ElderMap":
                {
                    AddBooleanItemToBlockItems <ElderMapBlockItem>(block, trimmedLine);
                    break;
                }

                case "DisableDropSound":
                {
                    // Only ever use the last DisableDropSound item encountered as multiples aren't valid.
                    RemoveExistingBlockItemsOfType <DisableDropSoundBlockItem>(block);

                    AddNilItemToBlockItems <DisableDropSoundBlockItem>(block, trimmedLine);
                    break;
                }

                case "MinimapIcon":
                {
                    // Only ever use the last Icon item encountered as multiples aren't valid.
                    RemoveExistingBlockItemsOfType <MapIconBlockItem>(block);

                    // TODO: Get size, color, shape values programmatically
                    var match = Regex.Match(trimmedLine,
                                            @"\S+\s+(0|1|2)\s+(Red|Green|Blue|Brown|White|Yellow)\s+(Circle|Diamond|Hexagon|Square|Star|Triangle)\s*([#]?)(.*)",
                                            RegexOptions.IgnoreCase);

                    if (match.Success)
                    {
                        var blockItemValue = new MapIconBlockItem
                        {
                            Size  = (IconSize)short.Parse(match.Groups[1].Value),
                            Color = EnumHelper.GetEnumValueFromDescription <IconColor>(match.Groups[2].Value),
                            Shape = EnumHelper.GetEnumValueFromDescription <IconShape>(match.Groups[3].Value)
                        };

                        block.BlockItems.Add(blockItemValue);
                        themeComponentType = (int)ThemeComponentType.Icon;
                    }
                    break;
                }

                case "PlayEffect":
                {
                    // Only ever use the last BeamColor item encountered as multiples aren't valid.
                    RemoveExistingBlockItemsOfType <PlayEffectBlockItem>(block);

                    // TODO: Get colors programmatically
                    var match = Regex.Match(trimmedLine, @"\S+\s+(Red|Green|Blue|Brown|White|Yellow)\s*(Temp)?", RegexOptions.IgnoreCase);

                    if (match.Success)
                    {
                        var blockItemValue = new PlayEffectBlockItem
                        {
                            Color     = EnumHelper.GetEnumValueFromDescription <EffectColor>(match.Groups[1].Value),
                            Temporary = match.Groups[2].Value.Trim().ToLower() == "temp"
                        };
                        block.BlockItems.Add(blockItemValue);
                        themeComponentType = (int)ThemeComponentType.Effect;
                    }
                    break;
                }

                case "CustomAlertSound":
                {
                    // Only ever use the last CustomSoundBlockItem item encountered as multiples aren't valid.
                    RemoveExistingBlockItemsOfType <CustomSoundBlockItem>(block);
                    RemoveExistingBlockItemsOfType <SoundBlockItem>(block);
                    RemoveExistingBlockItemsOfType <PositionalSoundBlockItem>(block);

                    var match = Regex.Match(trimmedLine, @"\S+\s+""([^\*\<\>\?|]+)""");

                    if (match.Success)
                    {
                        var blockItemValue = new CustomSoundBlockItem
                        {
                            Value = match.Groups[1].Value
                        };
                        block.BlockItems.Add(blockItemValue);
                        themeComponentType = (int)ThemeComponentType.CustomSound;
                    }
                    break;
                }

                case "MapTier":
                {
                    AddNumericFilterPredicateItemToBlockItems <MapTierBlockItem>(block, trimmedLine);
                    break;
                }
                }

                if (!string.IsNullOrWhiteSpace(blockComment) && block.BlockItems.Count > 1)
                {
                    if (!(block.BlockItems.Last() is IBlockItemWithTheme blockItemWithTheme))
                    {
                        block.BlockItems.Last().Comment = blockComment;
                    }
                    else
                    {
                        switch ((ThemeComponentType)themeComponentType)
                        {
                        case ThemeComponentType.AlertSound:
                        {
                            ThemeComponent themeComponent;
                            if (blockItemWithTheme is SoundBlockItem item)
                            {
                                themeComponent = _masterComponentCollection.AddComponent(ThemeComponentType.AlertSound, blockComment.Trim(),
                                                                                         item.Value, item.SecondValue);
                            }
                            else
                            {
                                themeComponent = _masterComponentCollection.AddComponent(ThemeComponentType.AlertSound, blockComment.Trim(),
                                                                                         ((PositionalSoundBlockItem)blockItemWithTheme).Value, ((PositionalSoundBlockItem)blockItemWithTheme).SecondValue);
                            }
                            blockItemWithTheme.ThemeComponent = themeComponent;
                            break;
                        }

                        case ThemeComponentType.BackgroundColor:
                        {
                            ThemeComponent themeComponent = _masterComponentCollection.AddComponent(ThemeComponentType.BackgroundColor,
                                                                                                    blockComment.Trim(), ((BackgroundColorBlockItem)blockItemWithTheme).Color);
                            blockItemWithTheme.ThemeComponent = themeComponent;
                            break;
                        }

                        case ThemeComponentType.BorderColor:
                        {
                            ThemeComponent themeComponent = _masterComponentCollection.AddComponent(ThemeComponentType.BorderColor,
                                                                                                    blockComment.Trim(), ((BorderColorBlockItem)blockItemWithTheme).Color);
                            blockItemWithTheme.ThemeComponent = themeComponent;
                            break;
                        }

                        case ThemeComponentType.CustomSound:
                        {
                            ThemeComponent themeComponent = _masterComponentCollection.AddComponent(ThemeComponentType.CustomSound,
                                                                                                    blockComment.Trim(), ((CustomSoundBlockItem)blockItemWithTheme).Value);
                            blockItemWithTheme.ThemeComponent = themeComponent;
                            break;
                        }

                        case ThemeComponentType.Effect:
                        {
                            ThemeComponent themeComponent = _masterComponentCollection.AddComponent(ThemeComponentType.Effect,
                                                                                                    blockComment.Trim(), ((EffectColorBlockItem)blockItemWithTheme).Color, ((EffectColorBlockItem)blockItemWithTheme).Temporary);
                            blockItemWithTheme.ThemeComponent = themeComponent;
                            break;
                        }

                        case ThemeComponentType.FontSize:
                        {
                            ThemeComponent themeComponent = _masterComponentCollection.AddComponent(ThemeComponentType.FontSize,
                                                                                                    blockComment.Trim(), ((FontSizeBlockItem)blockItemWithTheme).Value);
                            blockItemWithTheme.ThemeComponent = themeComponent;
                            break;
                        }

                        case ThemeComponentType.Icon:
                        {
                            ThemeComponent themeComponent = _masterComponentCollection.AddComponent(ThemeComponentType.Icon, blockComment.Trim(),
                                                                                                    ((IconBlockItem)blockItemWithTheme).Size, ((IconBlockItem)blockItemWithTheme).Color, ((IconBlockItem)blockItemWithTheme).Shape);
                            blockItemWithTheme.ThemeComponent = themeComponent;
                            break;
                        }

                        case ThemeComponentType.TextColor:
                        {
                            ThemeComponent themeComponent = _masterComponentCollection.AddComponent(ThemeComponentType.TextColor,
                                                                                                    blockComment.Trim(), ((TextColorBlockItem)blockItemWithTheme).Color);
                            blockItemWithTheme.ThemeComponent = themeComponent;
                            break;
                        }
                        }
                    }
                }
            }
Пример #9
0
 protected ItemFilterBlockBase(IItemFilterScript parentScript)
 {
     CommandManager = parentScript.CommandManager;
     ParentScript   = parentScript;
 }
Пример #10
0
 public ItemFilterCommentBlock(IItemFilterScript parentScript) : base(parentScript)
 {
 }
Пример #11
0
 private void OnLoadAlternateScriptCommand()
 {
     _itemFilterScript = _itemFilterScriptTranslator.TranslateStringToItemFilterScript(Resources.muldini);
 }
Пример #12
0
 private void OnLoadScriptCommand()
 {
     _itemFilterScript = _itemFilterScriptTranslator.TranslateStringToItemFilterScript(Resources.neversinkfilter);
 }
Пример #13
0
 public SetScriptDescriptionCommand(IItemFilterScript itemFilterScript, string newDescription)
 {
     _itemFilterScript = itemFilterScript;
     _newDescription = newDescription;
 }
Пример #14
0
        public IReadOnlyDictionary <IItem, IItemFilterBlock> ProcessItemsAgainstItemFilterScript(IItemFilterScript itemFilterScript, IEnumerable <IItem> items)
        {
            var overallsw = Stopwatch.StartNew();

            var matchedItemBlockPairs = new Dictionary <IItem, IItemFilterBlock>();

            var sw = Stopwatch.StartNew();

            foreach (var item in items)
            {
                sw.Restart();

                var matchedBlock = itemFilterScript.ItemFilterBlocks
                                   .Where(b => !(b is ItemFilterSection))
                                   .FirstOrDefault(block => _blockItemMatcher.ItemBlockMatch(block, item));

                matchedItemBlockPairs.Add(item, matchedBlock);

                Debug.WriteLine("Processed Item in {0}ms", sw.ElapsedMilliseconds);
            }
            sw.Stop();

            overallsw.Stop();
            Debug.WriteLine("Total processing time: {0}ms", overallsw.ElapsedMilliseconds);
            return(matchedItemBlockPairs);
        }
Пример #15
0
 public RemoveBlockCommand(IItemFilterScript itemFilterScript, IItemFilterBlockBase itemFilterBlockBase)
 {
     _itemFilterScript       = itemFilterScript;
     _removedItemFilterBlock = itemFilterBlockBase;
 }
Пример #16
0
        // Converts a string into an ItemFilterCommentBlock maintaining newlines and spaces but removing # characters
        public IItemFilterCommentBlock TranslateStringToItemFilterCommentBlock(string inputString, IItemFilterScript parentItemFilterScript, string originalString = "")
        {
            var itemFilterCommentBlock = new ItemFilterCommentBlock(parentItemFilterScript)
            {
                OriginalText = originalString
            };

            foreach (var line in new LineReader(() => new StringReader(inputString)))
            {
                var trimmedLine = line.TrimStart(' ').TrimStart('#');
                itemFilterCommentBlock.Comment += trimmedLine + Environment.NewLine;
            }

            itemFilterCommentBlock.Comment = itemFilterCommentBlock.Comment.TrimEnd('\r', '\n');

            itemFilterCommentBlock.IsEdited = false;
            return(itemFilterCommentBlock);
        }
Пример #17
0
 public MoveBlocksToBottomCommand(IItemFilterScript itemFilterScript, List <int> sourceIndexes)
 {
     _itemFilterScript = itemFilterScript;
     _sourceIndexes    = sourceIndexes;
     _sourceIndexes.Sort();
 }
Пример #18
0
 public PasteBlocksCommand(IItemFilterScript itemFilterScript, List <IItemFilterBlockBase> pastedItemFilterBlocks, IItemFilterBlockBase addAfterItemFilterBlock)
 {
     _itemFilterScript        = itemFilterScript;
     _pastedItemFilterBlocks  = pastedItemFilterBlocks;
     _addAfterItemFilterBlock = addAfterItemFilterBlock;
 }
 public MoveBlockToBottomCommand(IItemFilterScript itemFilterScript, IItemFilterBlockBase blockToMove)
 {
     _itemFilterScript = itemFilterScript;
     _blockToMove      = blockToMove;
 }
Пример #20
0
 public void InitialiseForMasterTheme(IItemFilterScript script)
 {
     Components             = script.ThemeComponents;
     IsMasterThemeForScript = script;
     _filenameIsFake        = true;
 }
Пример #21
0
        // This method converts a string into a ItemFilterBlock. This is used for pasting ItemFilterBlocks
        // and reading ItemFilterScripts from a file.
        public IItemFilterBlock TranslateStringToItemFilterBlock(string inputString, IItemFilterScript parentItemFilterScript, bool initialiseBlockGroupHierarchyBuilder = false)
        {
            if (initialiseBlockGroupHierarchyBuilder)
            {
                _blockGroupHierarchyBuilder.Initialise(parentItemFilterScript.ItemFilterBlockGroups.First());
            }

            _masterComponentCollection = parentItemFilterScript.ItemFilterScriptSettings.ThemeComponentCollection;
            var block         = new ItemFilterBlock(parentItemFilterScript);
            var showHideFound = false;

            foreach (var line in new LineReader(() => new StringReader(inputString)))
            {
                if (line.StartsWith(@"#") && !showHideFound)
                {
                    block.Description = line.TrimStart('#').TrimStart(' ');
                    continue;
                }

                var trimmedLine         = line.Trim();
                var spaceOrEndOfLinePos = trimmedLine.IndexOf(" ", StringComparison.Ordinal) > 0 ? trimmedLine.IndexOf(" ", StringComparison.Ordinal) : trimmedLine.Length;

                var lineOption = trimmedLine.Substring(0, spaceOrEndOfLinePos);
                switch (lineOption)
                {
                case "Show":
                case "Hide":
                case "ShowDisabled":
                case "HideDisabled":
                {
                    showHideFound = true;
                    block.Action  = lineOption.StartsWith("Show") ? BlockAction.Show : BlockAction.Hide;
                    block.Enabled = !lineOption.EndsWith("Disabled");

                    // If block groups are enabled for this script, the comment after Show/Hide is parsed as a block
                    // group hierarchy, if block groups are disabled it is preserved as a simple text comment.
                    if (parentItemFilterScript.ItemFilterScriptSettings.BlockGroupsEnabled)
                    {
                        AddBlockGroupToBlock(block, trimmedLine);
                    }
                    else
                    {
                        block.ActionBlockItem.Comment = GetTextAfterFirstComment(trimmedLine);
                    }
                    break;
                }

                case "ItemLevel":
                {
                    AddNumericFilterPredicateItemToBlockItems <ItemLevelBlockItem>(block, trimmedLine);
                    break;
                }

                case "DropLevel":
                {
                    AddNumericFilterPredicateItemToBlockItems <DropLevelBlockItem>(block, trimmedLine);
                    break;
                }

                case "Quality":
                {
                    AddNumericFilterPredicateItemToBlockItems <QualityBlockItem>(block, trimmedLine);
                    break;
                }

                case "Rarity":
                {
                    RemoveExistingBlockItemsOfType <RarityBlockItem>(block);

                    var blockItemValue = new RarityBlockItem();
                    var result         = Regex.Match(trimmedLine, @"^\w+\s+([><!=]{0,2})\s*(\w+)$");
                    if (result.Groups.Count == 3)
                    {
                        blockItemValue.FilterPredicate.PredicateOperator =
                            EnumHelper.GetEnumValueFromDescription <FilterPredicateOperator>(string.IsNullOrEmpty(result.Groups[1].Value) ? "=" : result.Groups[1].Value);
                        blockItemValue.FilterPredicate.PredicateOperand =
                            (int)EnumHelper.GetEnumValueFromDescription <ItemRarity>(result.Groups[2].Value);
                    }

                    block.BlockItems.Add(blockItemValue);
                    break;
                }

                case "Class":
                {
                    AddStringListItemToBlockItems <ClassBlockItem>(block, trimmedLine);
                    break;
                }

                case "BaseType":
                {
                    AddStringListItemToBlockItems <BaseTypeBlockItem>(block, trimmedLine);
                    break;
                }

                case "Corrupted":
                {
                    AddBooleanItemToBlockItems <CorruptedBlockItem>(block, trimmedLine);
                    break;
                }

                case "Identified":
                {
                    AddBooleanItemToBlockItems <IdentifiedBlockItem>(block, trimmedLine);
                    break;
                }

                case "ElderItem":
                {
                    AddBooleanItemToBlockItems <ElderItemBlockItem>(block, trimmedLine);
                    break;
                }

                case "ShaperItem":
                {
                    AddBooleanItemToBlockItems <ShaperItemBlockItem>(block, trimmedLine);
                    break;
                }

                case "ShapedMap":
                {
                    AddBooleanItemToBlockItems <ShapedMapBlockItem>(block, trimmedLine);
                    break;
                }

                case "Sockets":
                {
                    AddNumericFilterPredicateItemToBlockItems <SocketsBlockItem>(block, trimmedLine);
                    break;
                }

                case "LinkedSockets":
                {
                    AddNumericFilterPredicateItemToBlockItems <LinkedSocketsBlockItem>(block, trimmedLine);
                    break;
                }

                case "Width":
                {
                    AddNumericFilterPredicateItemToBlockItems <WidthBlockItem>(block, trimmedLine);
                    break;
                }

                case "Height":
                {
                    AddNumericFilterPredicateItemToBlockItems <HeightBlockItem>(block, trimmedLine);
                    break;
                }

                case "SocketGroup":
                {
                    AddStringListItemToBlockItems <SocketGroupBlockItem>(block, trimmedLine);
                    break;
                }

                case "SetTextColor":
                {
                    // Only ever use the last SetTextColor item encountered as multiples aren't valid.
                    RemoveExistingBlockItemsOfType <TextColorBlockItem>(block);

                    AddColorItemToBlockItems <TextColorBlockItem>(block, trimmedLine);
                    break;
                }

                case "SetBackgroundColor":
                {
                    // Only ever use the last SetBackgroundColor item encountered as multiples aren't valid.
                    RemoveExistingBlockItemsOfType <BackgroundColorBlockItem>(block);

                    AddColorItemToBlockItems <BackgroundColorBlockItem>(block, trimmedLine);
                    break;
                }

                case "SetBorderColor":
                {
                    // Only ever use the last SetBorderColor item encountered as multiples aren't valid.
                    RemoveExistingBlockItemsOfType <BorderColorBlockItem>(block);

                    AddColorItemToBlockItems <BorderColorBlockItem>(block, trimmedLine);
                    break;
                }

                case "SetFontSize":
                {
                    // Only ever use the last SetFontSize item encountered as multiples aren't valid.
                    RemoveExistingBlockItemsOfType <FontSizeBlockItem>(block);

                    var match = Regex.Match(trimmedLine, @"\s+(\d+)");
                    if (match.Success)
                    {
                        var blockItemValue = new FontSizeBlockItem(Convert.ToInt16(match.Value));
                        block.BlockItems.Add(blockItemValue);
                    }
                    break;
                }

                case "PlayAlertSound":
                case "PlayAlertSoundPositional":
                {
                    // Only ever use the last PlayAlertSound item encountered as multiples aren't valid.
                    RemoveExistingBlockItemsOfType <SoundBlockItem>(block);
                    RemoveExistingBlockItemsOfType <PositionalSoundBlockItem>(block);

                    var match = Regex.Match(trimmedLine, @"\S+\s+(\S+)\s?(\d+)?");

                    if (match.Success)
                    {
                        string firstValue = match.Groups[1].Value;
                        int    secondValue;

                        if (match.Groups[2].Success)
                        {
                            secondValue = Convert.ToInt16(match.Groups[2].Value);
                        }
                        else
                        {
                            secondValue = 79;
                        }

                        if (lineOption == "PlayAlertSound")
                        {
                            var blockItemValue = new SoundBlockItem
                            {
                                Value       = firstValue,
                                SecondValue = secondValue
                            };
                            block.BlockItems.Add(blockItemValue);
                        }
                        else
                        {
                            var blockItemValue = new PositionalSoundBlockItem
                            {
                                Value       = firstValue,
                                SecondValue = secondValue
                            };
                            block.BlockItems.Add(blockItemValue);
                        }
                    }
                    break;
                }
                }
            }

            return(block);
        }