using System.Text; using System.Text.RegularExpressions; namespace CVRManager.Services; public static class MultiInstance { const int KeepLogs = 7; static readonly Regex SingleInstanceLine = new(@"^single-instance[^\r\n]*(\r?\n|$)", RegexOptions.Multiline | RegexOptions.Compiled); public static void Prepare(string gameDir, Action log) { RemoveSingleInstanceFlag(gameDir, log); PruneMelonLoaderLogs(gameDir, log); } static void RemoveSingleInstanceFlag(string gameDir, Action log) { var boot = Path.Combine(gameDir, "ChilloutVR_Data", "boot.config"); if (!File.Exists(boot)) return; var text = File.ReadAllText(boot); var cleaned = SingleInstanceLine.Replace(text, ""); if (cleaned == text) return; File.WriteAllText(boot, cleaned, new UTF8Encoding(false)); log("Removed 'single-instance' from boot.config so more than one instance can run."); } static void PruneMelonLoaderLogs(string gameDir, Action log) { var logs = Path.Combine(gameDir, "MelonLoader", "Logs"); if (!Directory.Exists(logs)) return; var files = new DirectoryInfo(logs).GetFiles("*.log").OrderBy(f => f.LastWriteTimeUtc).ToList(); var excess = files.Count - KeepLogs; var removed = 0; foreach (var f in files) { if (removed >= excess) break; try { f.Delete(); removed++; } catch (Exception e) when (e is IOException or UnauthorizedAccessException) { } } if (removed > 0) log($"Removed {removed} old MelonLoader log(s) so a second instance does not trip MelonLoader's log cleanup."); } }