public void ReadConfigEcf(string contentPath, string activeScenario, string blockMappingFile, IModApi modApi)
        {
            ContentPath         = contentPath;
            ScenarioContentPath = string.IsNullOrEmpty(activeScenario) ? null : Path.Combine(contentPath, "Scenarios", activeScenario, "Content");

            Log($"EmpyrionScripting ReadConfigEcf: ContentPath:{contentPath} Scenario:{activeScenario} -> {ScenarioContentPath}", LogLevel.Message);

            var timer = Stopwatch.StartNew();

            ReadBlockMappingFile(blockMappingFile, modApi);
            ReadEcfFiles();
            MergeEcfFiles();
            BuildIdAndNameAccess();
            FlatEcfConfigData();
            CalcBlockRessources();
            timer.Stop();

            if (EmpyrionScripting.Configuration?.Current?.LogLevel == LogLevel.Debug)
            {
                BlockIdMapping.ForEach(B => Log($"ReadBlockMappingFile: '{B.Key}' -> {B.Value}]", LogLevel.Debug));
                Templates_Ecf.Blocks.ForEach(B => Log($"Templates_Ecf.Blocks: '{B.Name}[{B.Values?.FirstOrDefault(A => A.Key == "Id").Value}] '{B.Values?.FirstOrDefault(A => A.Key == "Name").Value}'", LogLevel.Debug));
                BlocksConfig_Ecf.Blocks.ForEach(B => Log($"BlocksConfig_Ecf.Blocks: '{B.Name}[{B.Values?.FirstOrDefault(A => A.Key == "Id").Value}] '{B.Values?.FirstOrDefault(A => A.Key == "Name").Value}'", LogLevel.Debug));
                ItemsConfig_Ecf.Blocks.ForEach(B => Log($"ItemsConfig_Ecf.Blocks: '{B.Name}[{B.Values?.FirstOrDefault(A => A.Key == "Id").Value}] '{B.Values?.FirstOrDefault(A => A.Key == "Name").Value}'", LogLevel.Debug));
                Configuration_Ecf.Blocks.ForEach(B => Log($"Configuration_Ecf.Blocks: '{B.Name}[{B.Values?.FirstOrDefault(A => A.Key == "Id").Value}] '{B.Values?.FirstOrDefault(A => A.Key == "Name").Value}'", LogLevel.Debug));
                Flat_Config_Ecf.Blocks.ForEach(B => Log($"Flat_Config_Ecf.Blocks: '{B.Name}[{B.Values?.FirstOrDefault(A => A.Key == "Id").Value}] '{B.Values?.FirstOrDefault(A => A.Key == "Name").Value}'", LogLevel.Debug));
                FlatConfigBlockById.ForEach(B => Log($"FlatConfigBlockById: '{B.Key}' -> {B.Value?.Values?.FirstOrDefault(A => A.Key == "Name").Value}]", LogLevel.Debug));
                FlatConfigBlockByName.ForEach(B => Log($"FlatConfigBlockByName: '{B.Key}' -> {B.Value?.Values?.FirstOrDefault(A => A.Key == "Name").Value}]", LogLevel.Debug));
                ResourcesForBlockById.ForEach(B => Log($"ResourcesForBlockById: [{B.Key}] {(EmpyrionScripting.ConfigEcfAccess.FlatConfigBlockById.TryGetValue(B.Key, out var data) ? data.Values["Name"] : "")} -> {B.Value.Aggregate("", (r, i) => $"{r}\n{i.Value}: [{i.Key}] {(EmpyrionScripting.ConfigEcfAccess.FlatConfigBlockById.TryGetValue(i.Key, out var data) ? data.Values["Name"] : "")}")}", LogLevel.Message));
                ParentBlockName.ForEach(B => Log($"ParentBlockName: {B.Key} -> {B.Value}", LogLevel.Debug));
            }

            Log($"EmpyrionScripting Configuration_Ecf: #{Configuration_Ecf?.Blocks?.Count} BlockById: #{ConfigBlockById?.Count} BlockByName: #{ConfigBlockByName?.Count} ParentBlockNames: #{ParentBlockName.Count} BlockIdMapping:[{BlockIdMapping?.Count}] {blockMappingFile} takes:{timer.Elapsed}", LogLevel.Message);
        }
        private void GenerateParentBlockList()
        {
            FlatConfigBlockByName
            .Where(B => B.Value?.Values?.ContainsKey("ChildBlocks") == true)
            .ForEach(B => B.Value.Values["ChildBlocks"].ToString()
                     .Split(',').Select(N => N.Trim())
                     .ForEach(N => { if (!ParentBlockName.ContainsKey(N))
                                     {
                                         ParentBlockName.Add(N, B.Key);
                                     }
                              })
                     );

            FlatConfigBlockByName
            .Where(B => B.Value?.Values?.ContainsKey("ParentBlocks") == true)
            .ForEach(B => B.Value.Values["ParentBlocks"].ToString()
                     .Split(',').Select(N => N.Trim())
                     .ForEach(N => {
                if (!B.Value.Values.TryGetValue("Name", out var name) ||
                    !FlatConfigBlockByName.TryGetValue(N, out var parentBlock) ||
                    !parentBlock.Values.TryGetValue("AllowPlacingAt", out var placeableAt))
                {
                    return;
                }

                placeableAt.ToString().Split(',').Select(N => N.Trim())
                .ForEach(P => { if (!ParentBlockName.ContainsKey(P + name.ToString()))
                                {
                                    ParentBlockName.Add(P + name.ToString(), N);
                                }
                         });
            })
                     );
        }
        private void ScanTemplates(EcfBlock templateRootBlock, Dictionary <int, double> ressList, double multiplyer)
        {
            var templateName = templateRootBlock.Attr.FirstOrDefault(A => A.Name == "Name")?.Value.ToString();

            bool.TryParse(templateRootBlock.Attr.FirstOrDefault(A => A.Name == "BaseItem")?.Value.ToString(), out var isBaseItem);

            templateRootBlock.Childs?
            .FirstOrDefault(C => C.Key == "Child Inputs").Value?.Attr?
            .ForEach(C => {
                if (C.Name.ToString() == templateName)
                {
                    return;
                }

                if (!isBaseItem && FlatConfigTemplatesByName.TryGetValue(C.Name, out var recipe))
                {
                    bool.TryParse(recipe.Attr.FirstOrDefault(A => A.Name == "BaseItem")?.Value.ToString(), out var isSubBaseItem);
                    if (!isSubBaseItem)
                    {
                        var recipeMultiplyer = multiplyer * (int)C.Value;
                        if (recipe.Values.TryGetValue("OutputCount", out var outputCount))
                        {
                            recipeMultiplyer /= (int)outputCount;
                        }
                        ScanTemplates(recipe, ressList, recipeMultiplyer);
                        return;
                    }
                }

                if (!FlatConfigBlockByName.TryGetValue(C.Name, out var ressource))
                {
                    return;
                }
                if (!ressource.Values.TryGetValue("Id", out var ressId))
                {
                    return;
                }

                if (ressList.TryGetValue((int)ressId, out var count))
                {
                    ressList[(int)ressId] = count + multiplyer * (int)C.Value;
                }
                else
                {
                    ressList.Add((int)ressId, multiplyer * (int)C.Value);
                }
            });
        }