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
+
+
+
+
+
+
+
+