using System.Diagnostics; using BrassAndSigil.Server.Models; using BrassAndSigil.Server.Services; using Spectre.Console; using Spectre.Console.Cli; namespace BrassAndSigil.Server.Commands; public sealed class CheckCommand : AsyncCommand { public override async Task ExecuteAsync(CommandContext context, BaseCommandSettings settings) { var config = ServerConfig.Load(settings.ConfigPath); AnsiConsole.MarkupLine("[bold]Checking server install...[/]"); var ok = true; // 1. Java available? var javaVersion = await TryRunForOutputAsync(config.JavaPath, "-version"); if (javaVersion is not null) AnsiConsole.MarkupLine($" [green]✓[/] Java reachable: {javaVersion.Split('\n')[0].Trim().EscapeMarkup()}"); else { AnsiConsole.MarkupLine($" [red]✗[/] Java not found at '{config.JavaPath}'"); ok = false; } // 2. Server dir var serverDir = Path.GetFullPath(config.ServerDir); if (Directory.Exists(serverDir)) AnsiConsole.MarkupLine($" [green]✓[/] Server dir exists: {serverDir}"); else { AnsiConsole.MarkupLine($" [yellow]?[/] Server dir missing -- run [yellow]install[/] first"); ok = false; } // 3. EULA var eulaPath = Path.Combine(serverDir, "eula.txt"); if (File.Exists(eulaPath) && File.ReadAllText(eulaPath).Contains("eula=true")) AnsiConsole.MarkupLine(" [green]✓[/] EULA accepted"); else { AnsiConsole.MarkupLine(" [yellow]?[/] EULA not accepted (re-run [yellow]install --accept-eula[/])"); ok = false; } // 4. NeoForge run script var runScript = Path.Combine(serverDir, OperatingSystem.IsWindows() ? "run.bat" : "run.sh"); if (File.Exists(runScript)) AnsiConsole.MarkupLine($" [green]✓[/] Loader start script: {Path.GetFileName(runScript)}"); else AnsiConsole.MarkupLine($" [yellow]?[/] No {Path.GetFileName(runScript)} -- install the NeoForge server first"); // 5. Manifest reachable try { using var http = new HttpClient { Timeout = TimeSpan.FromSeconds(10) }; var resp = await http.GetAsync(config.ManifestUrl); if (resp.IsSuccessStatusCode) AnsiConsole.MarkupLine($" [green]✓[/] Manifest reachable: {config.ManifestUrl}"); else { AnsiConsole.MarkupLine($" [red]✗[/] Manifest HTTP {(int)resp.StatusCode}: {config.ManifestUrl}"); ok = false; } } catch (Exception ex) { AnsiConsole.MarkupLine($" [red]✗[/] Manifest fetch error: {ex.Message.EscapeMarkup()}"); ok = false; } // 6. Pack version on disk var packVer = Path.Combine(serverDir, "pack-version.json"); if (File.Exists(packVer)) AnsiConsole.MarkupLine($" [green]✓[/] Pack synced: {File.ReadAllText(packVer).Replace("\n", " ").Replace("\r", "").Trim().EscapeMarkup()}"); else AnsiConsole.MarkupLine(" [yellow]?[/] Pack not synced yet (run [yellow]sync[/])"); AnsiConsole.MarkupLine(""); AnsiConsole.MarkupLine(ok ? "[green]All required checks passed.[/]" : "[yellow]Some checks failed; see above.[/]"); return ok ? 0 : 1; } private static async Task TryRunForOutputAsync(string fileName, string args) { try { var p = Process.Start(new ProcessStartInfo { FileName = fileName, Arguments = args, RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, CreateNoWindow = true, }); if (p is null) return null; var output = await p.StandardError.ReadToEndAsync() + await p.StandardOutput.ReadToEndAsync(); await p.WaitForExitAsync(); return output; } catch { return null; } } }