using System; using System.Diagnostics; using System.IO; using System.Text.Json; using System.Windows.Forms; namespace NosClientLauncherGui { public class LaunchConfig { public string ClientExePath { get; set; } = @"C:\\NosClient\\NostaleClientX.exe"; public string WorkingDirectory { get; set; } = @"C:\\NosClient"; public string ServerIp { get; set; } = "127.0.0.1"; public int ServerPort { get; set; } = 4001; public string Arguments { get; set; } = ""; } public partial class Form1 : Form { private const string ConfigFile = "launcher.config.json"; private const string LogFile = "launcher.log"; private TextBox txtExe = new() { Left = 20, Top = 30, Width = 500 }; private Button btnBrowse = new() { Left = 530, Top = 28, Width = 90, Text = "Browse" }; private TextBox txtWorkDir = new() { Left = 20, Top = 85, Width = 600 }; private TextBox txtIp = new() { Left = 20, Top = 140, Width = 250 }; private NumericUpDown numPort = new() { Left = 280, Top = 140, Width = 120, Minimum = 1, Maximum = 65535, Value = 4001 }; private TextBox txtArgs = new() { Left = 20, Top = 195, Width = 600 }; private Button btnSave = new() { Left = 20, Top = 245, Width = 120, Text = "Save" }; private Button btnLaunch = new() { Left = 150, Top = 245, Width = 120, Text = "Launch" }; private TextBox txtLog = new() { Left = 20, Top = 295, Width = 600, Height = 180, Multiline = true, ScrollBars = ScrollBars.Vertical, ReadOnly = true }; public Form1() { InitializeComponent(); Text = "Nos Client Launcher"; Width = 670; Height = 560; FormBorderStyle = FormBorderStyle.FixedDialog; MaximizeBox = false; Controls.Clear(); Controls.Add(new Label { Left = 20, Top = 10, Text = "Client EXE" }); Controls.Add(txtExe); Controls.Add(btnBrowse); Controls.Add(new Label { Left = 20, Top = 65, Text = "Working Directory" }); Controls.Add(txtWorkDir); Controls.Add(new Label { Left = 20, Top = 120, Text = "Server IP" }); Controls.Add(txtIp); Controls.Add(new Label { Left = 280, Top = 120, Text = "Port" }); Controls.Add(numPort); Controls.Add(new Label { Left = 20, Top = 175, Text = "Arguments (optional)" }); Controls.Add(txtArgs); Controls.Add(btnSave); Controls.Add(btnLaunch); Controls.Add(txtLog); btnBrowse.Click += (_, _) => BrowseExe(); btnSave.Click += (_, _) => SaveConfig(); btnLaunch.Click += (_, _) => LaunchClient(); LoadConfig(); } private void BrowseExe() { using var ofd = new OpenFileDialog { Filter = "Executable (*.exe)|*.exe", Title = "Select NosTale Client EXE" }; if (ofd.ShowDialog() == DialogResult.OK) { txtExe.Text = ofd.FileName; if (string.IsNullOrWhiteSpace(txtWorkDir.Text)) txtWorkDir.Text = Path.GetDirectoryName(ofd.FileName) ?? ""; } } private void LoadConfig() { try { LaunchConfig cfg; if (!File.Exists(ConfigFile)) { cfg = new LaunchConfig(); File.WriteAllText(ConfigFile, JsonSerializer.Serialize(cfg, new JsonSerializerOptions { WriteIndented = true })); } else { cfg = JsonSerializer.Deserialize(File.ReadAllText(ConfigFile)) ?? new LaunchConfig(); } txtExe.Text = cfg.ClientExePath; txtWorkDir.Text = cfg.WorkingDirectory; txtIp.Text = cfg.ServerIp; numPort.Value = cfg.ServerPort; txtArgs.Text = cfg.Arguments; AppendLog("Config loaded."); } catch (Exception ex) { AppendLog("LoadConfig ERROR: " + ex.Message); } } private void SaveConfig() { try { var cfg = ReadUi(); File.WriteAllText(ConfigFile, JsonSerializer.Serialize(cfg, new JsonSerializerOptions { WriteIndented = true })); AppendLog("Config saved."); } catch (Exception ex) { AppendLog("SaveConfig ERROR: " + ex.Message); } } private void LaunchClient() { try { var cfg = ReadUi(); if (!File.Exists(cfg.ClientExePath)) { MessageBox.Show("Client EXE nicht gefunden.", "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } SaveConfig(); var psi = new ProcessStartInfo { FileName = cfg.ClientExePath, WorkingDirectory = cfg.WorkingDirectory, Arguments = cfg.Arguments, UseShellExecute = false }; psi.Environment["NOSTALE_SERVER_IP"] = cfg.ServerIp; psi.Environment["NOSTALE_SERVER_PORT"] = cfg.ServerPort.ToString(); var p = Process.Start(psi); AppendLog(p != null ? $"Client gestartet. PID={p.Id} | Target={cfg.ServerIp}:{cfg.ServerPort}" : "Process.Start returned null."); } catch (Exception ex) { AppendLog("Launch ERROR: " + ex); } } private LaunchConfig ReadUi() { return new LaunchConfig { ClientExePath = txtExe.Text.Trim(), WorkingDirectory = txtWorkDir.Text.Trim(), ServerIp = txtIp.Text.Trim(), ServerPort = (int)numPort.Value, Arguments = txtArgs.Text.Trim() }; } private void AppendLog(string line) { var msg = $"[{DateTime.Now:HH:mm:ss}] {line}"; txtLog.AppendText(msg + Environment.NewLine); File.AppendAllText(LogFile, $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] {line}{Environment.NewLine}"); } } }