Files
CapySR/gui/ServerHost.cs
T
2026-10-17 20:42:15 -07:00

101 lines
3.2 KiB
C#

using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CapyLauncher
{
public class ServerHost
{
Process process;
bool stopping;
public event Action<string> Line;
public event Action<int, bool> Exited;
public string Root { get; }
public string Exe { get; }
public bool Running => process != null && !process.HasExited;
public int Id => process?.Id ?? 0;
public ServerHost(string launcherDir)
{
Root = FindRoot(launcherDir) ?? launcherDir;
Exe = new[]
{
Path.Combine(launcherDir, "capysr.exe"),
Path.Combine(Root, "capysr.exe"),
Path.Combine(Root, "build", "bin", "capysr.exe"),
}.FirstOrDefault(File.Exists);
}
static string FindRoot(string dir)
{
for (int depth = 0; depth < 5 && dir != null; depth++)
{
if (File.Exists(Path.Combine(dir, "config", "config.json")))
return dir;
dir = Path.GetDirectoryName(dir);
}
return null;
}
public Process[] Strangers() =>
Process.GetProcessesByName("capysr").Where(p => p.Id != Id).ToArray();
public void Start()
{
var info = new ProcessStartInfo(Exe)
{
WorkingDirectory = Root,
UseShellExecute = false,
CreateNoWindow = true,
RedirectStandardInput = true,
RedirectStandardOutput = true,
RedirectStandardError = true,
StandardOutputEncoding = Encoding.UTF8,
StandardErrorEncoding = Encoding.UTF8,
};
info.EnvironmentVariables["NO_COLOR"] = "1";
var started = new Process { StartInfo = info, EnableRaisingEvents = true };
started.OutputDataReceived += (s, e) => { if (e.Data != null) Line?.Invoke(e.Data); };
started.ErrorDataReceived += (s, e) => { if (e.Data != null) Line?.Invoke(e.Data); };
started.Exited += (s, e) =>
{
started.WaitForExit();
bool asked = stopping;
stopping = false;
Exited?.Invoke(started.ExitCode, asked);
};
stopping = false;
started.Start();
started.BeginOutputReadLine();
started.BeginErrorReadLine();
process = started;
}
public async Task StopAsync()
{
Process running = process;
if (running == null || running.HasExited)
return;
stopping = true;
try
{
running.StandardInput.WriteLine("stop");
running.StandardInput.Flush();
}
catch (Exception) { }
bool exited = await Task.Run(() => running.WaitForExit(8000));
if (!exited)
{
try { running.Kill(); } catch (Exception) { }
await Task.Run(() => running.WaitForExit(3000));
}
}
}
}