using System.Collections.Generic; using System.IO; using UnityEngine; using UnityEngine.Scripting; namespace NecromancerTome { /// /// Почтовый ящик консоли - только для разработки (03.10: ассистент подбирает позу рук сам, без /// клавиатуры). Работает, лишь если есть папка %APPDATA%\7DaysToDie\NecroMailbox - у игроков её /// нет. Раз в полсекунды: команды из cmd.txt (по строке) выполняются в консоли игры, как набранные /// вручную, файл удаляется, ответ - в лог строками «[NecromancerTome] mailbox:». /// public static class NecroMailbox { public static string Dir => Path.Combine(GameIO.GetUserGameDataDir(), "NecroMailbox"); static string CmdFile => Path.Combine(Dir, "cmd.txt"); static float _next; public static void Init() { ModEvents.UnityUpdate.RegisterHandler(OnUnityUpdate); } static void OnUnityUpdate(ref ModEvents.SUnityUpdateData _data) { if (Time.unscaledTime < _next) { return; } _next = Time.unscaledTime + 0.5f; if (!File.Exists(CmdFile) || SdtdConsole.Instance == null) { return; } string[] lines; try { lines = File.ReadAllLines(CmdFile); File.Delete(CmdFile); } catch (IOException) { return; // файл ещё пишется - в следующий раз } foreach (string raw in lines) { string line = raw.Trim(); if (line.Length == 0) { continue; } Debug.Log("[NecromancerTome] mailbox: > " + line); try { List res = SdtdConsole.Instance.ExecuteSync(line, null); if (res != null) { foreach (string r in res) { Debug.Log("[NecromancerTome] mailbox: " + r); } } } catch (System.Exception ex) { Debug.LogWarning("[NecromancerTome] mailbox: ошибка - " + ex); } } } } /// necroshot [имя] - снимок экрана игры в %APPDATA%\7DaysToDie\NecroMailbox\shots\имя.png /// (как F9, только в известное место). Файл появляется в конце кадра. [Preserve] public class ConsoleCmdNecroShot : ConsoleCmdAbstract { public override string[] getCommands() => new[] { "necroshot" }; public override string getDescription() => "NecromancerTome: снимок экрана в NecroMailbox/shots/<имя>.png"; public override void Execute(List _params, CommandSenderInfo _senderInfo) { string dir = Path.Combine(NecroMailbox.Dir, "shots"); Directory.CreateDirectory(dir); string name = _params.Count > 0 ? _params[0] : System.DateTime.Now.ToString("HHmmss"); // necroshot имя N интервал - серия из N кадров (имя1..имяN) через интервал секунд (18.10: мигание, полёт духа). if (_params.Count >= 3 && int.TryParse(_params[1], out int n) && float.TryParse(_params[2], System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out float dt)) { ThreadManager.StartCoroutine(Burst(dir, name, n, dt)); SdtdConsole.Instance.Output("серия: " + n + " кадров через " + dt + " с"); return; } string path = Path.Combine(dir, name + ".png"); ScreenCapture.CaptureScreenshot(path); SdtdConsole.Instance.Output("снимок: " + path); } static System.Collections.IEnumerator Burst(string _dir, string _name, int _n, float _dt) { for (int i = 1; i <= _n; i++) { ScreenCapture.CaptureScreenshot(Path.Combine(_dir, _name + i + ".png")); yield return new WaitForSecondsRealtime(_dt); } Debug.Log("[NecromancerTome] mailbox: серия " + _name + " готова"); } } /// necrospawn - нажать «Появиться» в окне появления (18.10: ассистент сам запускает игру с сейвом /// -LoadSaveGame=true и входит в мир без мыши). То же, что кнопка: XUiC_SpawnSelectionWindow.SpawnButtonPressed. [Preserve] public class ConsoleCmdNecroSpawn : ConsoleCmdAbstract { public override string[] getCommands() => new[] { "necrospawn" }; public override string getDescription() => "NecromancerTome: нажать «Появиться» (разработка, почтовый ящик)"; public override bool AllowedInMainMenu => false; public override void Execute(List _params, CommandSenderInfo _senderInfo) { foreach (LocalPlayerUI ui in LocalPlayerUI.PlayerUIs) { XUiC_SpawnSelectionWindow w = ui?.xui?.GetWindowByType(); if (w != null && w.IsOpen) { w.SpawnButtonPressed(SpawnMethod.Invalid); SdtdConsole.Instance.Output("necrospawn: нажато «Появиться»"); return; } } SdtdConsole.Instance.Output("necrospawn: окно появления не открыто"); } } /// necroexit [quit] - выйти из мира с сохранением, как «Выход» в меню паузы (GameManager.Disconnect); с quit - /// затем закрыть игру. Нужно перед сборкой бандлов и заменой DLL (игра держит файлы). [Preserve] public class ConsoleCmdNecroExit : ConsoleCmdAbstract { public override string[] getCommands() => new[] { "necroexit" }; public override string getDescription() => "NecromancerTome: выйти из мира с сохранением [quit - и закрыть игру] (разработка)"; public override bool AllowedInMainMenu => true; public override void Execute(List _params, CommandSenderInfo _senderInfo) { bool quit = _params.Count > 0 && _params[0] == "quit"; SdtdConsole.Instance.Output("necroexit: выход" + (quit ? " и закрытие игры" : " в меню")); ThreadManager.StartCoroutine(ExitCo(quit)); } static System.Collections.IEnumerator ExitCo(bool _quit) { if (GameManager.Instance.World != null) { GameManager.Instance.Disconnect(); while (GameManager.Instance.World != null) { yield return null; } Debug.Log("[NecromancerTome] necroexit: мир сохранён и закрыт"); } if (_quit) { yield return new WaitForSecondsRealtime(2f); Debug.Log("[NecromancerTome] necroexit: закрываю игру"); Application.Quit(); } } } }