public Dictionary<string, EngineConfigEntry> GetEngineConfigOptions(SpringPaths paths, string engine)
        {
            Trace.TraceInformation("Extracting configuration from Spring located in {0}", paths.GetEngineFolderByVersion(engine));
            var sb = new StringBuilder();
            var p = new Process();
            p.StartInfo.CreateNoWindow = true;
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.Arguments += string.Format("--list-config-vars");
            p.StartInfo.EnvironmentVariables["SPRING_DATADIR"] = paths.WritableDirectory;
            p.StartInfo.EnvironmentVariables.Remove("SPRING_ISOLATED");
            p.StartInfo.FileName = paths.GetSpringExecutablePath(engine);
            p.StartInfo.WorkingDirectory = Path.GetDirectoryName(paths.GetSpringExecutablePath(engine));
            p.StartInfo.RedirectStandardOutput = true;
            p.OutputDataReceived += (sender, args) => sb.AppendLine(args.Data);
            p.Start();
            p.BeginOutputReadLine();
            p.WaitForExit(3000);
            sb.AppendLine(); //append terminator

            var text = sb.ToString();
            int whereIsTable = text.IndexOf('{');
            text = text.Substring(whereIsTable); // skip empty line or other info (if exist). Compatibility with Spring 94+
            var data = JsonConvert.DeserializeObject<Dictionary<string, EngineConfigEntry>>(text);
            return data;
        }
        private void LaunchChobby(SpringPaths paths, string internalName, string engineVersion)
        {
            var process = new Process { StartInfo = { CreateNoWindow = true, UseShellExecute = false } };

            paths.SetDefaultEnvVars(process.StartInfo, engineVersion);

            process.StartInfo.FileName = paths.GetSpringExecutablePath(engineVersion);
            process.StartInfo.WorkingDirectory = Path.GetDirectoryName(paths.GetSpringExecutablePath(engineVersion));
            process.StartInfo.Arguments = $"--menu \"{internalName}\"";

            process.Start();
        }
        public string Start(SpringPaths paths, TestCase test, Benchmark benchmark) {
            LogLines = new StringBuilder();

            //paths.SetEnginePath(paths.GetEngineFolderByVersion(test.Engine));

            var optirun = Environment.GetEnvironmentVariable("OPTIRUN");
            
            process = new Process();
            process.StartInfo.CreateNoWindow = true;
            List<string> arg = new List<string>();

            if (string.IsNullOrEmpty(optirun)) {
                process.StartInfo.FileName = paths.GetSpringExecutablePath(test.Engine);
            }
            else {
                Trace.TraceInformation("Using optirun {0} to start the game (OPTIRUN env var defined)", optirun);
                process.StartInfo.FileName = optirun;
                arg.Add(string.Format("\"{0}\"", ( paths.GetSpringExecutablePath(test.Engine))));
            }



            process.StartInfo.WorkingDirectory = Path.GetDirectoryName(paths.GetSpringExecutablePath(test.Engine));

            arg.Add(string.Format("--config \"{0}\"", Path.Combine(test.Config.ConfigPath, "springsettings.cfg")));
            if (test.BenchmarkArg > 0) arg.Add("--benchmark " + test.BenchmarkArg);


            var dataDirList = new List<string>()
            {
                test.Config.ConfigPath,
                Directory.GetParent(benchmark.BenchmarkPath).Parent.FullName,
                paths.WritableDirectory,
            };
            dataDirList.AddRange(paths.DataDirectories);
            dataDirList.Add(Path.GetDirectoryName(paths.GetSpringExecutablePath(test.Engine)));

            if (Environment.OSVersion.Platform == PlatformID.Unix) dataDirList = dataDirList.Distinct().Select(x => x.Replace(" ", "\\ ")).ToList();
            else dataDirList = dataDirList.Distinct().ToList();

            var datadirs = string.Join(Environment.OSVersion.Platform == PlatformID.Unix ? ":" : ";", dataDirList);

            process.StartInfo.EnvironmentVariables["SPRING_DATADIR"] = datadirs;
            process.StartInfo.EnvironmentVariables["SPRING_ISOLATED"] = test.Config.ConfigPath;
            process.StartInfo.EnvironmentVariables["SPRING_WRITEDIR"] = test.Config.ConfigPath;

            var scriptPath = Path.GetTempFileName();
            File.WriteAllText(scriptPath, test.StartScript.GetScriptForTestCase(test, benchmark));
            arg.Add(string.Format("\"{0}\"", scriptPath));

            
            process.StartInfo.Arguments = string.Join(" ", arg);
            process.StartInfo.UseShellExecute = false;
            process.StartInfo.RedirectStandardOutput = true;
            process.StartInfo.RedirectStandardError = true;

            process.ErrorDataReceived += (sender, args) =>
                {
                    LogLines.AppendLine(args.Data);
                    LineAdded(args.Data);
                };
            process.OutputDataReceived += (sender, args) =>
                {
                    LogLines.AppendLine(args.Data);
                    LineAdded(args.Data);
                };
            process.EnableRaisingEvents = true;

            try {
                process.Start();
                process.BeginOutputReadLine();
                process.BeginErrorReadLine();

                process.WaitForExit();
            } catch (Exception ex) {
                Trace.TraceError("Error waiting for process: {0}", ex);
            }
            var lines = LogLines.ToString();

            File.Delete(scriptPath);

            return lines;
        }
        private async Task LaunchChobby(SpringPaths paths, string internalName, string engineVersion, int loopbackPort)
        {
            process = new Process { StartInfo = { CreateNoWindow = true, UseShellExecute = false } };

            paths.SetDefaultEnvVars(process.StartInfo, engineVersion);
            var widgetFolder = Path.Combine(paths.WritableDirectory);//, "LuaMenu", "Widgets");
            if (!Directory.Exists(widgetFolder)) Directory.CreateDirectory(widgetFolder);
            File.WriteAllText(Path.Combine(widgetFolder, "chobby_wrapper_port.txt"), loopbackPort.ToString());

            process.StartInfo.FileName = paths.GetSpringExecutablePath(engineVersion);
            process.StartInfo.WorkingDirectory = Path.GetDirectoryName(paths.GetSpringExecutablePath(engineVersion));
            process.StartInfo.Arguments = $"--menu \"{internalName}\"";


            var tcs = new TaskCompletionSource<bool>();
            process.Exited += (sender, args) => tcs.TrySetResult(true);
            process.EnableRaisingEvents = true;
            process.Start();

            await tcs.Task;
        }