From ec438e84ca3f2405afab6875efeae0b5ba224f42 Mon Sep 17 00:00:00 2001 From: Nick Date: Thu, 6 Jul 2023 20:13:19 -0400 Subject: [PATCH 01/17] Create log socket class --- Winch/Logging/LogMessage.cs | 16 +++++++++++ Winch/Logging/LogSocket.cs | 57 +++++++++++++++++++++++++++++++++++++ Winch/Logging/Logger.cs | 17 ++++++++++- 3 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 Winch/Logging/LogMessage.cs create mode 100644 Winch/Logging/LogSocket.cs diff --git a/Winch/Logging/LogMessage.cs b/Winch/Logging/LogMessage.cs new file mode 100644 index 00000000..4e3909ca --- /dev/null +++ b/Winch/Logging/LogMessage.cs @@ -0,0 +1,16 @@ +using Newtonsoft.Json; + +namespace Winch.Logging +{ + public class LogMessage + { + [JsonProperty("source")] + public string Source { get; set; } + + [JsonProperty("level")] + public string Level { get; set; } + + [JsonProperty("message")] + public string Message { get; set; } + } +} diff --git a/Winch/Logging/LogSocket.cs b/Winch/Logging/LogSocket.cs new file mode 100644 index 00000000..5cfdbc1c --- /dev/null +++ b/Winch/Logging/LogSocket.cs @@ -0,0 +1,57 @@ +using Newtonsoft.Json; +using System; +using System.Net; +using System.Net.Sockets; +using System.Text; +using System.Threading; + +namespace Winch.Logging +{ + public class LogSocket + { + private Socket _socket; + private readonly int _port; + private readonly Logger _logger; + private const string IP = "127.0.0.1"; + + public LogSocket(Logger logger, int port) + { + _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + _port = port; + _logger = logger; + } + + public void WriteToSocket(LogMessage logMessage) + { + if (_socket == null) + { + return; + } + + if (!_socket.Connected) + { + var endPoint = new IPEndPoint(IPAddress.Parse(IP), _port); try + { + _socket?.Connect(endPoint); + } + catch (Exception ex) + { + _socket = null; + _logger.Error($"Could not connect to console at {IP}:{_port} - {ex}"); + } + } + + try + { + _socket?.Send(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(logMessage))); + } + catch (SocketException) { } + } + + public void Close() + { + Thread.Sleep(TimeSpan.FromSeconds(1)); + _socket?.Close(); + } + } +} diff --git a/Winch/Logging/Logger.cs b/Winch/Logging/Logger.cs index 9df58772..5d5ce6a4 100644 --- a/Winch/Logging/Logger.cs +++ b/Winch/Logging/Logger.cs @@ -20,6 +20,8 @@ public class Logger private bool _writeLogs; private LogLevel? _minLogLevel; + private LogSocket? _logSocket; + public Logger() { _writeLogs = WinchConfig.GetProperty("WriteLogsToFile", true); @@ -30,7 +32,13 @@ public Logger() _log = new LogFile(); _latestLog = new LogFile("latest.log"); - CleanupLogs(); + var portStr = WinchConfig.GetProperty("LogPort", string.Empty); + if (!string.IsNullOrEmpty(portStr) && int.TryParse(portStr, out var port)) + { + _logSocket = new LogSocket(this, port); + } + + CleanupLogs(); } private static void CleanupLogs() @@ -63,6 +71,13 @@ private void Log(LogLevel level, string message) private void Log(LogLevel level, string message, string source) { + _logSocket?.WriteToSocket(new LogMessage() + { + Level = level.ToString(), + Message = message, + Source = source + }); + if (!_writeLogs) return; if (level < _minLogLevel) From bd7150813e10f8787e76fb7a7a928875f6a25027 Mon Sep 17 00:00:00 2001 From: Nick Date: Tue, 26 Dec 2023 14:44:07 -0500 Subject: [PATCH 02/17] Create WinchConsole program, move relevant shared files to WinchCommon project --- Winch.sln | 12 ++ Winch/Core/WinchCore.cs | 23 ++- Winch/Logging/LogSocket.cs | 6 +- Winch/Logging/Logger.cs | 9 +- Winch/Winch.csproj | 20 +-- Winch/mod_meta.json | 2 +- .../Config/DefaultConfig.json | 0 {Winch => WinchCommon}/Config/JSONConfig.cs | 0 {Winch => WinchCommon}/Config/ModConfig.cs | 9 +- {Winch => WinchCommon}/Config/WinchConfig.cs | 16 +- WinchCommon/Constants.cs | 12 ++ WinchCommon/LogLevel.cs | 6 + {Winch => WinchCommon}/Logging/LogMessage.cs | 3 +- .../Properties/Resources.Designer.cs | 7 +- .../Properties/Resources.resx | 0 WinchCommon/WinchCommon.csproj | 33 ++++ WinchConsole/LogSocketListener.cs | 154 ++++++++++++++++++ WinchConsole/Program.cs | 31 ++++ WinchConsole/WinchConsole.csproj | 24 +++ 19 files changed, 325 insertions(+), 42 deletions(-) rename {Winch => WinchCommon}/Config/DefaultConfig.json (100%) rename {Winch => WinchCommon}/Config/JSONConfig.cs (100%) rename {Winch => WinchCommon}/Config/ModConfig.cs (85%) rename {Winch => WinchCommon}/Config/WinchConfig.cs (64%) create mode 100644 WinchCommon/Constants.cs create mode 100644 WinchCommon/LogLevel.cs rename {Winch => WinchCommon}/Logging/LogMessage.cs (81%) rename {Winch => WinchCommon}/Properties/Resources.Designer.cs (92%) rename {Winch => WinchCommon}/Properties/Resources.resx (100%) create mode 100644 WinchCommon/WinchCommon.csproj create mode 100644 WinchConsole/LogSocketListener.cs create mode 100644 WinchConsole/Program.cs create mode 100644 WinchConsole/WinchConsole.csproj diff --git a/Winch.sln b/Winch.sln index 5696d732..4ceb150f 100644 --- a/Winch.sln +++ b/Winch.sln @@ -11,6 +11,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DisasterButton", "Winch.Exa EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ExampleItems", "Winch.Examples\ExampleItems\ExampleItems.csproj", "{C112288E-E993-44F3-B7B0-FB4BD37F18EA}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WinchConsole", "WinchConsole\WinchConsole.csproj", "{D5CFABA9-FA58-474F-A394-E197BDF38FDD}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WinchCommon", "WinchCommon\WinchCommon.csproj", "{EF5F69E6-FD4D-4314-B187-A89D00BF9355}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -33,6 +37,14 @@ Global {C112288E-E993-44F3-B7B0-FB4BD37F18EA}.Debug|Any CPU.Build.0 = Debug|Any CPU {C112288E-E993-44F3-B7B0-FB4BD37F18EA}.Release|Any CPU.ActiveCfg = Release|Any CPU {C112288E-E993-44F3-B7B0-FB4BD37F18EA}.Release|Any CPU.Build.0 = Release|Any CPU + {D5CFABA9-FA58-474F-A394-E197BDF38FDD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D5CFABA9-FA58-474F-A394-E197BDF38FDD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D5CFABA9-FA58-474F-A394-E197BDF38FDD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D5CFABA9-FA58-474F-A394-E197BDF38FDD}.Release|Any CPU.Build.0 = Release|Any CPU + {EF5F69E6-FD4D-4314-B187-A89D00BF9355}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EF5F69E6-FD4D-4314-B187-A89D00BF9355}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EF5F69E6-FD4D-4314-B187-A89D00BF9355}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EF5F69E6-FD4D-4314-B187-A89D00BF9355}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Winch/Core/WinchCore.cs b/Winch/Core/WinchCore.cs index 6ba1d549..bd069c1c 100644 --- a/Winch/Core/WinchCore.cs +++ b/Winch/Core/WinchCore.cs @@ -2,17 +2,15 @@ using Newtonsoft.Json; using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Reflection; -using System.Text.RegularExpressions; -using UnityEngine.Profiling.Memory.Experimental; -using Winch.Config; using Winch.Logging; using Winch.Util; namespace Winch.Core { - public class WinchCore + public class WinchCore { public static Logger Log = new Logger(); @@ -22,6 +20,18 @@ public class WinchCore public static void Main() { + Log.Info("Starting console"); + try + { + Process.Start(Path.Combine(WinchInstallLocation, "WinchConsole.exe")); + } + catch (Exception e) + { + Log.Error($"Could not start console : {e}"); + } + + AppDomain.CurrentDomain.ProcessExit += new EventHandler(OnProcessExit); + try { string metaPath = Path.Combine(WinchInstallLocation, "mod_meta.json"); @@ -67,5 +77,10 @@ public static void Main() Log.Debug("Harmony Patching complete."); } + + public static void OnProcessExit(object sender, EventArgs e) + { + Log.Debug("DREDGE application exited"); + } } } diff --git a/Winch/Logging/LogSocket.cs b/Winch/Logging/LogSocket.cs index 5cfdbc1c..33f68d53 100644 --- a/Winch/Logging/LogSocket.cs +++ b/Winch/Logging/LogSocket.cs @@ -12,7 +12,6 @@ public class LogSocket private Socket _socket; private readonly int _port; private readonly Logger _logger; - private const string IP = "127.0.0.1"; public LogSocket(Logger logger, int port) { @@ -30,14 +29,15 @@ public void WriteToSocket(LogMessage logMessage) if (!_socket.Connected) { - var endPoint = new IPEndPoint(IPAddress.Parse(IP), _port); try + var endPoint = new IPEndPoint(IPAddress.Parse(Constants.IP), _port); + try { _socket?.Connect(endPoint); } catch (Exception ex) { _socket = null; - _logger.Error($"Could not connect to console at {IP}:{_port} - {ex}"); + _logger.Error($"Could not connect to console at {Constants.IP}:{_port} - {ex}"); } } diff --git a/Winch/Logging/Logger.cs b/Winch/Logging/Logger.cs index 5d5ce6a4..30713d9d 100644 --- a/Winch/Logging/Logger.cs +++ b/Winch/Logging/Logger.cs @@ -7,12 +7,7 @@ namespace Winch.Logging { - enum LogLevel - { - UNITY = 0, DEBUG = 1, INFO = 2, WARN = 3, ERROR = 4 - } - - public class Logger + public class Logger { private LogFile? _log; private LogFile? _latestLog; @@ -73,7 +68,7 @@ private void Log(LogLevel level, string message, string source) { _logSocket?.WriteToSocket(new LogMessage() { - Level = level.ToString(), + Level = level, Message = message, Source = source }); diff --git a/Winch/Winch.csproj b/Winch/Winch.csproj index f6c5d406..c9749d35 100644 --- a/Winch/Winch.csproj +++ b/Winch/Winch.csproj @@ -16,21 +16,6 @@ - - - True - True - Resources.resx - - - - - - ResXFileCodeGenerator - Resources.Designer.cs - - - PreserveNewest @@ -49,4 +34,9 @@ + + + + + diff --git a/Winch/mod_meta.json b/Winch/mod_meta.json index 3366cd4e..7cd7f35c 100644 --- a/Winch/mod_meta.json +++ b/Winch/mod_meta.json @@ -2,5 +2,5 @@ "Name": "Winch", "Author": "Hacktix", "ModGUID": "hacktix.winch", - "Version": "0.3.0" + "Version": "0.4.0" } diff --git a/Winch/Config/DefaultConfig.json b/WinchCommon/Config/DefaultConfig.json similarity index 100% rename from Winch/Config/DefaultConfig.json rename to WinchCommon/Config/DefaultConfig.json diff --git a/Winch/Config/JSONConfig.cs b/WinchCommon/Config/JSONConfig.cs similarity index 100% rename from Winch/Config/JSONConfig.cs rename to WinchCommon/Config/JSONConfig.cs diff --git a/Winch/Config/ModConfig.cs b/WinchCommon/Config/ModConfig.cs similarity index 85% rename from Winch/Config/ModConfig.cs rename to WinchCommon/Config/ModConfig.cs index 3e28557f..5b05ef20 100644 --- a/Winch/Config/ModConfig.cs +++ b/WinchCommon/Config/ModConfig.cs @@ -1,11 +1,8 @@ -using System.Collections.Generic; -using System.IO; -using System.Reflection; -using Winch.Core; +using System.Reflection; namespace Winch.Config { - public class ModConfig : JSONConfig + public class ModConfig : JSONConfig { private static Dictionary DefaultConfigs = new Dictionary(); private static Dictionary Instances = new Dictionary(); @@ -18,7 +15,7 @@ private static string GetDefaultConfig(string modName) { if(!DefaultConfigs.ContainsKey(modName)) { - WinchCore.Log.Error($"No 'DefaultConfig' attribute found in mod_meta.json for {modName}!"); + //WinchCore.Log.Error($"No 'DefaultConfig' attribute found in mod_meta.json for {modName}!"); throw new KeyNotFoundException($"No 'DefaultConfig' attribute found in mod_meta.json for {modName}!"); } return DefaultConfigs[modName]; diff --git a/Winch/Config/WinchConfig.cs b/WinchCommon/Config/WinchConfig.cs similarity index 64% rename from Winch/Config/WinchConfig.cs rename to WinchCommon/Config/WinchConfig.cs index 912cdc9f..ef16ddc0 100644 --- a/Winch/Config/WinchConfig.cs +++ b/WinchCommon/Config/WinchConfig.cs @@ -7,7 +7,7 @@ public class WinchConfig : JSONConfig { private static readonly string WinchConfigPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "WinchConfig.json"); - private WinchConfig() : base(WinchConfigPath, Properties.Resources.DefaultConfig) { } + private WinchConfig() : base(WinchConfigPath, WinchCommon.Properties.Resources.DefaultConfig) { } private static WinchConfig? _instance; public static WinchConfig Instance @@ -22,7 +22,19 @@ public static WinchConfig Instance public static new T? GetProperty(string key, T defaultValue) { - return ((JSONConfig)Instance).GetProperty(key, defaultValue); + try + { + return ((JSONConfig)Instance).GetProperty(key, defaultValue); + } + catch + { + return defaultValue; + } } + + public static new void SetProperty(string key, T value) + { + ((JSONConfig)Instance).SetProperty(key, value); + } } } diff --git a/WinchCommon/Constants.cs b/WinchCommon/Constants.cs new file mode 100644 index 00000000..61f7263d --- /dev/null +++ b/WinchCommon/Constants.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Winch; + +public static class Constants +{ + public const string IP = "127.0.0.1"; +} diff --git a/WinchCommon/LogLevel.cs b/WinchCommon/LogLevel.cs new file mode 100644 index 00000000..ac20e5f8 --- /dev/null +++ b/WinchCommon/LogLevel.cs @@ -0,0 +1,6 @@ +namespace Winch; + +public enum LogLevel +{ + UNITY = 0, DEBUG = 1, INFO = 2, WARN = 3, ERROR = 4 +} diff --git a/Winch/Logging/LogMessage.cs b/WinchCommon/Logging/LogMessage.cs similarity index 81% rename from Winch/Logging/LogMessage.cs rename to WinchCommon/Logging/LogMessage.cs index 4e3909ca..42098df3 100644 --- a/Winch/Logging/LogMessage.cs +++ b/WinchCommon/Logging/LogMessage.cs @@ -1,4 +1,5 @@ using Newtonsoft.Json; +using WinchCommon; namespace Winch.Logging { @@ -8,7 +9,7 @@ public class LogMessage public string Source { get; set; } [JsonProperty("level")] - public string Level { get; set; } + public LogLevel Level { get; set; } [JsonProperty("message")] public string Message { get; set; } diff --git a/Winch/Properties/Resources.Designer.cs b/WinchCommon/Properties/Resources.Designer.cs similarity index 92% rename from Winch/Properties/Resources.Designer.cs rename to WinchCommon/Properties/Resources.Designer.cs index 0349a657..e3f866b0 100644 --- a/Winch/Properties/Resources.Designer.cs +++ b/WinchCommon/Properties/Resources.Designer.cs @@ -8,7 +8,7 @@ // //------------------------------------------------------------------------------ -namespace Winch.Properties { +namespace WinchCommon.Properties { using System; @@ -39,7 +39,7 @@ internal Resources() { internal static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Winch.Properties.Resources", typeof(Resources).Assembly); + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("WinchCommon.Properties.Resources", typeof(Resources).Assembly); resourceMan = temp; } return resourceMan; @@ -66,7 +66,8 @@ internal Resources() { /// "LogLevel": "DEBUG", /// "LogsFolder": "Logs", /// "DetailedLogSources": false, - /// "EnableDeveloperConsole": true + /// "EnableDeveloperConsole": true, + /// "MaxLogFiles": 10 ///}. /// internal static string DefaultConfig { diff --git a/Winch/Properties/Resources.resx b/WinchCommon/Properties/Resources.resx similarity index 100% rename from Winch/Properties/Resources.resx rename to WinchCommon/Properties/Resources.resx diff --git a/WinchCommon/WinchCommon.csproj b/WinchCommon/WinchCommon.csproj new file mode 100644 index 00000000..0feb137a --- /dev/null +++ b/WinchCommon/WinchCommon.csproj @@ -0,0 +1,33 @@ + + + + net48 + enable + enable + 11 + + + + + + + + + + + + + Resources.resx + True + True + + + + + + Resources.Designer.cs + ResXFileCodeGenerator + + + + diff --git a/WinchConsole/LogSocketListener.cs b/WinchConsole/LogSocketListener.cs new file mode 100644 index 00000000..cd8495b9 --- /dev/null +++ b/WinchConsole/LogSocketListener.cs @@ -0,0 +1,154 @@ +using Newtonsoft.Json; +using System; +using System.Net; +using System.Net.Sockets; +using System.Text; +using System.Threading.Tasks; +using Winch.Config; +using Winch.Logging; + +namespace Winch +{ + public class LogSocketListener + { + private const string Separator = "\n--------------------------------"; + private const int BufferSize = 262144; + private static int _port; + private static TcpListener _server; + private bool _hasReceivedFatalMessage; + + public LogSocketListener() + { + + } + + public void Init() + { + var listener = new TcpListener(IPAddress.Loopback, 0); + listener.Start(); + _port = ((IPEndPoint)listener.LocalEndpoint).Port; + WriteByType(LogLevel.INFO, $"Found available port {_port}"); + listener.Stop(); + + WinchConfig.SetProperty("LogPort", $"{_port}"); + + SetupSocketListener(); + } + + private void SetupSocketListener() + { + WriteByType(LogLevel.INFO, $"Setting up socket listener {_port}"); + try + { + ListenToSocket(); + } + catch (SocketException ex) + { + WriteByType(LogLevel.ERROR, $"Error in socket listener: {ex.SocketErrorCode} - {ex}"); + } + catch (Exception ex) + { + WriteByType(LogLevel.ERROR, $"Error while listening: {ex}"); + } + finally + { + _server?.Stop(); + } + } + + private void ListenToSocket() + { + var localAddress = IPAddress.Parse(Constants.IP); + + _server = new TcpListener(localAddress, _port); + _server.Start(); + WriteByType(LogLevel.INFO, $"Connected to local {localAddress}:{_port}"); + + var bytes = new byte[BufferSize]; + + while (true) + { + var client = _server.AcceptTcpClient(); + + WriteByType(LogLevel.INFO, "Console connected to socket!"); + + var stream = client.GetStream(); + + int i; + + while ((i = stream.Read(bytes, 0, bytes.Length)) != 0) + { + ProcessMessage(bytes, i); + } + + WriteByType(LogLevel.INFO, "Closing client!"); + client.Close(); + } + } + + private void ProcessMessage(byte[] bytes, int count) + { + var message = Encoding.UTF8.GetString(bytes, 0, count); + + ProcessJson(message); + + // OWML would split messages into multiple jsons but that bugs out here + // when we get a message that has a json object in it or just new lines generally + // weird + + /* + var jsons = message.Split('\n'); + + foreach (var json in jsons) + { + if (string.IsNullOrWhiteSpace(json)) + { + return; + } + + ProcessJson(json); + } + */ + } + + private void ProcessJson(string json) + { + LogMessage data; + try + { + data = JsonConvert.DeserializeObject(json) ?? throw new NullReferenceException(); + } + catch (Exception ex) + { + WriteByType(LogLevel.WARN, $"Failed to process following message:{Separator}\n{json}{Separator}"); + WriteByType(LogLevel.WARN, $"Reason: {ex}"); + return; + } + + var nameTypePrefix = $"[{data.Source}] : "; + + var messageData = data.Message; + messageData = messageData.Replace("\n", $"\n{new string(' ', nameTypePrefix.Length)}"); + + WriteByType(data.Level, $"{nameTypePrefix}{messageData}"); + } + + public static void WriteByType(LogLevel type, string line) + { + if (string.IsNullOrEmpty(line)) + { + return; + } + + Console.ForegroundColor = type switch + { + LogLevel.ERROR => ConsoleColor.Red, + LogLevel.WARN => ConsoleColor.Yellow, + LogLevel.DEBUG => ConsoleColor.DarkGray, + _ => ConsoleColor.White + }; + + Console.WriteLine(line); + } + } +} diff --git a/WinchConsole/Program.cs b/WinchConsole/Program.cs new file mode 100644 index 00000000..24f4ca74 --- /dev/null +++ b/WinchConsole/Program.cs @@ -0,0 +1,31 @@ +using System; +using System.Diagnostics; +using System.Linq; +using Winch; + +namespace WinchConsole +{ + internal class Program + { + static void Main(string[] args) + { + Console.WriteLine("Loading Winch console!"); + + // Only allow one console to be open at a time + var currentProcess = Process.GetCurrentProcess(); + var duplicates = Process.GetProcessesByName(currentProcess.ProcessName); + + // Let the existing console handle logs + // For example, loading with the manager loads the game then it gets relaunched via Steam opening two consoles + // However only the first console shows text + if (duplicates.Length > 1) + { + currentProcess.Kill(); + } + else + { + new LogSocketListener().Init(); + } + } + } +} \ No newline at end of file diff --git a/WinchConsole/WinchConsole.csproj b/WinchConsole/WinchConsole.csproj new file mode 100644 index 00000000..6e9f9d82 --- /dev/null +++ b/WinchConsole/WinchConsole.csproj @@ -0,0 +1,24 @@ + + + + Exe + net48 + 11 + + + + + + + + + False + False + + + + + + + + From c5b698cf1f641dbe1d43463cb7554aa82f2db4dd Mon Sep 17 00:00:00 2001 From: Nick Date: Tue, 26 Dec 2023 15:14:01 -0500 Subject: [PATCH 03/17] Fix console requiring a restart, added EnableLogConsole winchconfig option --- Winch/Core/WinchCore.cs | 20 +------ Winch/Logging/Logger.cs | 83 +++++++++++++++++++-------- WinchCommon/Config/DefaultConfig.json | 3 +- WinchConsole/LogSocketListener.cs | 20 +++---- WinchConsole/Program.cs | 2 +- 5 files changed, 69 insertions(+), 59 deletions(-) diff --git a/Winch/Core/WinchCore.cs b/Winch/Core/WinchCore.cs index bd069c1c..51687df2 100644 --- a/Winch/Core/WinchCore.cs +++ b/Winch/Core/WinchCore.cs @@ -2,7 +2,6 @@ using Newtonsoft.Json; using System; using System.Collections.Generic; -using System.Diagnostics; using System.IO; using System.Reflection; using Winch.Logging; @@ -16,22 +15,10 @@ public class WinchCore public static Dictionary WinchModConfig = new(); - public static string WinchInstallLocation = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + public static string WinchInstallLocation => Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); public static void Main() { - Log.Info("Starting console"); - try - { - Process.Start(Path.Combine(WinchInstallLocation, "WinchConsole.exe")); - } - catch (Exception e) - { - Log.Error($"Could not start console : {e}"); - } - - AppDomain.CurrentDomain.ProcessExit += new EventHandler(OnProcessExit); - try { string metaPath = Path.Combine(WinchInstallLocation, "mod_meta.json"); @@ -77,10 +64,5 @@ public static void Main() Log.Debug("Harmony Patching complete."); } - - public static void OnProcessExit(object sender, EventArgs e) - { - Log.Debug("DREDGE application exited"); - } } } diff --git a/Winch/Logging/Logger.cs b/Winch/Logging/Logger.cs index 30713d9d..3a6512b7 100644 --- a/Winch/Logging/Logger.cs +++ b/Winch/Logging/Logger.cs @@ -2,8 +2,11 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; +using System.Net.Sockets; +using System.Net; using System.Text.RegularExpressions; using Winch.Config; +using Winch.Core; namespace Winch.Logging { @@ -12,28 +15,54 @@ public class Logger private LogFile? _log; private LogFile? _latestLog; - private bool _writeLogs; + private bool _writeLogsToFile; + private bool _writeLogsToConsole; private LogLevel? _minLogLevel; private LogSocket? _logSocket; + public string LogConsoleExe => Path.Combine(WinchCore.WinchInstallLocation, "WinchConsole.exe"); + public Logger() { - _writeLogs = WinchConfig.GetProperty("WriteLogsToFile", true); - if (!_writeLogs) - return; + _writeLogsToFile = WinchConfig.GetProperty("WriteLogsToFile", true); + if (_writeLogsToFile) + { + _minLogLevel = (LogLevel)Enum.Parse(typeof(LogLevel), WinchConfig.GetProperty("LogLevel", "DEBUG")); + _log = new LogFile(); + _latestLog = new LogFile("latest.log"); + CleanupLogs(); + } - _minLogLevel = (LogLevel)Enum.Parse(typeof(LogLevel), WinchConfig.GetProperty("LogLevel", "DEBUG")); - _log = new LogFile(); - _latestLog = new LogFile("latest.log"); + _writeLogsToConsole = WinchConfig.GetProperty("EnableLogConsole", true); - var portStr = WinchConfig.GetProperty("LogPort", string.Empty); - if (!string.IsNullOrEmpty(portStr) && int.TryParse(portStr, out var port)) + if (_writeLogsToConsole) { - _logSocket = new LogSocket(this, port); + // Find an avialable port for the logs + var listener = new TcpListener(IPAddress.Loopback, 0); + listener.Start(); + var port = ((IPEndPoint)listener.LocalEndpoint).Port; + listener.Stop(); + + // Console exe will get the port from the WinchConfig file + WinchConfig.SetProperty("LogPort", $"{port}"); + + Info($"Writing logs to port {port}"); + + try + { + Info($"Starting console at path {LogConsoleExe}"); + Process.Start(LogConsoleExe); + + _logSocket = new LogSocket(this, port); + } + catch (Exception e) + { + Error($"Could not start console : {e}"); + } } - CleanupLogs(); + Info($"Writing logs to file: {_writeLogsToFile}. Writing logs to console: {_writeLogsToConsole}."); } private static void CleanupLogs() @@ -66,21 +95,25 @@ private void Log(LogLevel level, string message) private void Log(LogLevel level, string message, string source) { - _logSocket?.WriteToSocket(new LogMessage() + if (level < _minLogLevel) + return; + + if (_writeLogsToConsole) { - Level = level, - Message = message, - Source = source - }); - - if (!_writeLogs) - return; - if (level < _minLogLevel) - return; - - string logMessage = $"[{GetLogTimestamp()}] [{source}] [{level}] : {message}"; - _log?.Write(logMessage); - _latestLog?.Write(logMessage); + _logSocket?.WriteToSocket(new LogMessage() + { + Level = level, + Message = message, + Source = source + }); + } + + if (_writeLogsToFile) + { + string logMessage = $"[{GetLogTimestamp()}] [{source}] [{level}] : {message}"; + _log?.Write(logMessage); + _latestLog?.Write(logMessage); + } } private string GetLogTimestamp() diff --git a/WinchCommon/Config/DefaultConfig.json b/WinchCommon/Config/DefaultConfig.json index f56e1971..7a732993 100644 --- a/WinchCommon/Config/DefaultConfig.json +++ b/WinchCommon/Config/DefaultConfig.json @@ -4,5 +4,6 @@ "LogsFolder": "Logs", "DetailedLogSources": false, "EnableDeveloperConsole": true, - "MaxLogFiles": 10 + "MaxLogFiles": 10, + "EnableLogConsole": true } \ No newline at end of file diff --git a/WinchConsole/LogSocketListener.cs b/WinchConsole/LogSocketListener.cs index cd8495b9..f072b9d2 100644 --- a/WinchConsole/LogSocketListener.cs +++ b/WinchConsole/LogSocketListener.cs @@ -22,21 +22,15 @@ public LogSocketListener() } - public void Init() + public void Run() { - var listener = new TcpListener(IPAddress.Loopback, 0); - listener.Start(); - _port = ((IPEndPoint)listener.LocalEndpoint).Port; - WriteByType(LogLevel.INFO, $"Found available port {_port}"); - listener.Stop(); - - WinchConfig.SetProperty("LogPort", $"{_port}"); - - SetupSocketListener(); - } + var portStr = WinchConfig.GetProperty("LogPort", string.Empty); + + if (string.IsNullOrEmpty(portStr) || !int.TryParse(portStr, out _port)) + { + return; + } - private void SetupSocketListener() - { WriteByType(LogLevel.INFO, $"Setting up socket listener {_port}"); try { diff --git a/WinchConsole/Program.cs b/WinchConsole/Program.cs index 24f4ca74..f5b1b7d8 100644 --- a/WinchConsole/Program.cs +++ b/WinchConsole/Program.cs @@ -24,7 +24,7 @@ static void Main(string[] args) } else { - new LogSocketListener().Init(); + new LogSocketListener().Run(); } } } From 32bd83d1e39e8bb197ef2b038b4c9f8afe93a766 Mon Sep 17 00:00:00 2001 From: Nick Date: Tue, 26 Dec 2023 15:31:44 -0500 Subject: [PATCH 04/17] Fix error when multiple messages come in at once --- WinchConsole/LogSocketListener.cs | 44 ++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/WinchConsole/LogSocketListener.cs b/WinchConsole/LogSocketListener.cs index f072b9d2..0854e8d6 100644 --- a/WinchConsole/LogSocketListener.cs +++ b/WinchConsole/LogSocketListener.cs @@ -1,5 +1,7 @@ using Newtonsoft.Json; using System; +using System.Collections.Generic; +using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; @@ -84,14 +86,7 @@ private void ProcessMessage(byte[] bytes, int count) { var message = Encoding.UTF8.GetString(bytes, 0, count); - ProcessJson(message); - - // OWML would split messages into multiple jsons but that bugs out here - // when we get a message that has a json object in it or just new lines generally - // weird - - /* - var jsons = message.Split('\n'); + var jsons = message.Split('\n').SelectMany(SplitMessage); foreach (var json in jsons) { @@ -102,7 +97,38 @@ private void ProcessMessage(byte[] bytes, int count) ProcessJson(json); } - */ + } + + /// + /// Message can come in containing multiple JSON objects, we have to split them up into separate strings to parse + /// + /// + /// + private string[] SplitMessage(string message) + { + var jsons = new List(); + var jsonStart = 0; + var bracketCount = 0; + for (int i = 0; i < message.Length; i++) + { + if (message[i] == '{') + { + bracketCount++; + + } + else if (message[i] == '}') + { + bracketCount--; + if (bracketCount == 0) + { + var json = message.Substring(jsonStart, i + 1 - jsonStart); + jsons.Add(json); + jsonStart = i + 1; + } + } + } + + return jsons.Any() ? jsons.ToArray() : new string[] { message }; } private void ProcessJson(string json) From 686de0b269611e9d8efba286361990b0559a9572 Mon Sep 17 00:00:00 2001 From: Nick Date: Tue, 26 Dec 2023 15:36:29 -0500 Subject: [PATCH 05/17] Remove unnecessary split --- WinchConsole/LogSocketListener.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/WinchConsole/LogSocketListener.cs b/WinchConsole/LogSocketListener.cs index 0854e8d6..7945907a 100644 --- a/WinchConsole/LogSocketListener.cs +++ b/WinchConsole/LogSocketListener.cs @@ -5,7 +5,6 @@ using System.Net; using System.Net.Sockets; using System.Text; -using System.Threading.Tasks; using Winch.Config; using Winch.Logging; @@ -86,7 +85,7 @@ private void ProcessMessage(byte[] bytes, int count) { var message = Encoding.UTF8.GetString(bytes, 0, count); - var jsons = message.Split('\n').SelectMany(SplitMessage); + var jsons = SplitMessage(message); foreach (var json in jsons) { From 894d4513e38b60b65308cd9b3b4098212053a6e3 Mon Sep 17 00:00:00 2001 From: Nick Date: Tue, 26 Dec 2023 15:40:05 -0500 Subject: [PATCH 06/17] Add some owml credit --- WinchConsole/Program.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/WinchConsole/Program.cs b/WinchConsole/Program.cs index f5b1b7d8..e4c71d5a 100644 --- a/WinchConsole/Program.cs +++ b/WinchConsole/Program.cs @@ -1,8 +1,12 @@ using System; using System.Diagnostics; -using System.Linq; using Winch; +/* + * Winch console logs were adapted from the log console for the Outer Wilds Mods Loader (OWML) under MIT license + * https://github.com/ow-mods/owml + */ + namespace WinchConsole { internal class Program From ec0fd65d131a5b609cbd08ab46723d3bea5b0287 Mon Sep 17 00:00:00 2001 From: Nick Date: Tue, 26 Dec 2023 15:44:52 -0500 Subject: [PATCH 07/17] Update Program.cs --- WinchConsole/Program.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/WinchConsole/Program.cs b/WinchConsole/Program.cs index e4c71d5a..0c0c5f13 100644 --- a/WinchConsole/Program.cs +++ b/WinchConsole/Program.cs @@ -19,9 +19,6 @@ static void Main(string[] args) var currentProcess = Process.GetCurrentProcess(); var duplicates = Process.GetProcessesByName(currentProcess.ProcessName); - // Let the existing console handle logs - // For example, loading with the manager loads the game then it gets relaunched via Steam opening two consoles - // However only the first console shows text if (duplicates.Length > 1) { currentProcess.Kill(); From dbe8cf563bb161eb2bb8eff932387ad4bfcdd60d Mon Sep 17 00:00:00 2001 From: xen-42 Date: Tue, 26 Dec 2023 15:47:34 -0500 Subject: [PATCH 08/17] Update build.yml --- .github/workflows/build.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 34e69521..635f450e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -23,6 +23,10 @@ jobs: - name: Build Winch run: dotnet build -c ${{ inputs.build_type }} + - name: Copy WinchConsole into Winch folder + run: | + mv WinchConsole/bin/* Winch/bin/* + - name: Upload Winch Artifact uses: actions/upload-artifact@v3 with: From 97bd46c8d0b2f87f72b998df7b3de629ce326134 Mon Sep 17 00:00:00 2001 From: xen-42 Date: Tue, 26 Dec 2023 15:49:54 -0500 Subject: [PATCH 09/17] Update build.yml --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 635f450e..50425457 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -25,7 +25,7 @@ jobs: - name: Copy WinchConsole into Winch folder run: | - mv WinchConsole/bin/* Winch/bin/* + mv WinchConsole/* Winch/* - name: Upload Winch Artifact uses: actions/upload-artifact@v3 From d048fd792b730c99f34e15136f52726a40905945 Mon Sep 17 00:00:00 2001 From: Nick Date: Tue, 26 Dec 2023 15:52:36 -0500 Subject: [PATCH 10/17] Don't append to output path for winch console --- WinchConsole/WinchConsole.csproj | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/WinchConsole/WinchConsole.csproj b/WinchConsole/WinchConsole.csproj index 6e9f9d82..18ee2928 100644 --- a/WinchConsole/WinchConsole.csproj +++ b/WinchConsole/WinchConsole.csproj @@ -1,9 +1,11 @@ - + Exe net48 11 + false + false From 1261ac6588969440a4b4271d4365069a3fbf345c Mon Sep 17 00:00:00 2001 From: xen-42 Date: Tue, 26 Dec 2023 15:53:24 -0500 Subject: [PATCH 11/17] Update build.yml --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 50425457..635f450e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -25,7 +25,7 @@ jobs: - name: Copy WinchConsole into Winch folder run: | - mv WinchConsole/* Winch/* + mv WinchConsole/bin/* Winch/bin/* - name: Upload Winch Artifact uses: actions/upload-artifact@v3 From b17cd087e872a63af57aa7c9495e35f8d261f57f Mon Sep 17 00:00:00 2001 From: xen-42 Date: Tue, 26 Dec 2023 15:56:30 -0500 Subject: [PATCH 12/17] Update build.yml --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 635f450e..10baae45 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -25,7 +25,7 @@ jobs: - name: Copy WinchConsole into Winch folder run: | - mv WinchConsole/bin/* Winch/bin/* + mv WinchConsole/bin/* Winch/bin/ - name: Upload Winch Artifact uses: actions/upload-artifact@v3 From 600504b5604c6469b9ffaf93e87bf6cbc8a1678a Mon Sep 17 00:00:00 2001 From: xen-42 Date: Tue, 26 Dec 2023 15:58:03 -0500 Subject: [PATCH 13/17] Update build.yml --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 10baae45..65ee8303 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -25,7 +25,7 @@ jobs: - name: Copy WinchConsole into Winch folder run: | - mv WinchConsole/bin/* Winch/bin/ + cp -r WinchConsole/bin/* Winch/bin/ - name: Upload Winch Artifact uses: actions/upload-artifact@v3 From 9cbc0006e10df2d574061eae446e64d085de1f7c Mon Sep 17 00:00:00 2001 From: Nick Date: Tue, 26 Dec 2023 16:02:33 -0500 Subject: [PATCH 14/17] Include WinchCommon in the nuget --- Winch/Winch.nuspec | 1 + 1 file changed, 1 insertion(+) diff --git a/Winch/Winch.nuspec b/Winch/Winch.nuspec index f507f1e8..c401bb68 100644 --- a/Winch/Winch.nuspec +++ b/Winch/Winch.nuspec @@ -14,5 +14,6 @@ + From d2c43181928d79edae7f57c4cd0164b2107fcfa9 Mon Sep 17 00:00:00 2001 From: Nick Date: Wed, 27 Dec 2023 00:29:31 -0500 Subject: [PATCH 15/17] Rename console property to match the file one, make this 0.3.1 not 0.4.0 --- Winch/Logging/Logger.cs | 2 +- Winch/mod_meta.json | 2 +- WinchCommon/Config/DefaultConfig.json | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Winch/Logging/Logger.cs b/Winch/Logging/Logger.cs index 3a6512b7..5701b92b 100644 --- a/Winch/Logging/Logger.cs +++ b/Winch/Logging/Logger.cs @@ -34,7 +34,7 @@ public Logger() CleanupLogs(); } - _writeLogsToConsole = WinchConfig.GetProperty("EnableLogConsole", true); + _writeLogsToConsole = WinchConfig.GetProperty("WriteLogsToConsole", true); if (_writeLogsToConsole) { diff --git a/Winch/mod_meta.json b/Winch/mod_meta.json index 7cd7f35c..427e4340 100644 --- a/Winch/mod_meta.json +++ b/Winch/mod_meta.json @@ -2,5 +2,5 @@ "Name": "Winch", "Author": "Hacktix", "ModGUID": "hacktix.winch", - "Version": "0.4.0" + "Version": "0.3.1" } diff --git a/WinchCommon/Config/DefaultConfig.json b/WinchCommon/Config/DefaultConfig.json index 7a732993..264dc3ec 100644 --- a/WinchCommon/Config/DefaultConfig.json +++ b/WinchCommon/Config/DefaultConfig.json @@ -1,9 +1,9 @@ { "WriteLogsToFile": true, + "WriteLogsToConsole": false, "LogLevel": "DEBUG", "LogsFolder": "Logs", "DetailedLogSources": false, "EnableDeveloperConsole": true, - "MaxLogFiles": 10, - "EnableLogConsole": true + "MaxLogFiles": 10 } \ No newline at end of file From d46c2c48fbdb16c395975de0128d21259f869c86 Mon Sep 17 00:00:00 2001 From: Nick Date: Wed, 27 Dec 2023 00:33:10 -0500 Subject: [PATCH 16/17] Update Resources.Designer.cs --- WinchCommon/Properties/Resources.Designer.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/WinchCommon/Properties/Resources.Designer.cs b/WinchCommon/Properties/Resources.Designer.cs index e3f866b0..09afcb00 100644 --- a/WinchCommon/Properties/Resources.Designer.cs +++ b/WinchCommon/Properties/Resources.Designer.cs @@ -63,6 +63,7 @@ internal Resources() { /// /// Looks up a localized string similar to { /// "WriteLogsToFile": true, + /// "WriteLogsToConsole": false, /// "LogLevel": "DEBUG", /// "LogsFolder": "Logs", /// "DetailedLogSources": false, From 29dff118bd25171a4eb045b22a594c254bdff281 Mon Sep 17 00:00:00 2001 From: Nick Date: Wed, 27 Dec 2023 00:35:20 -0500 Subject: [PATCH 17/17] Fix nuspec path --- Winch/Winch.nuspec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Winch/Winch.nuspec b/Winch/Winch.nuspec index c401bb68..a1634ad0 100644 --- a/Winch/Winch.nuspec +++ b/Winch/Winch.nuspec @@ -13,7 +13,7 @@ MIT - - + +