Decompiled source of Log Backup v1.0.0

Log_Backup.dll

Decompiled 4 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using LethalCompanyInputUtils.Api;
using UnityEngine;
using UnityEngine.InputSystem;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("Log_Backup")]
[assembly: AssemblyDescription("This mod provides a simple way for user to point out issues")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Log_Backup")]
[assembly: AssemblyTitle("Log_Backup")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Log_Backup;

public class LogBackupInputs : LcInputActions
{
	[InputAction("<Keyboard>/f9", Name = "Log Backup Marker", ActionId = "log_backup_marker")]
	public InputAction MarkerKey { get; set; }
}
[BepInPlugin("LKK.Log_Backup", "Log_Backup", "1.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class Log_BackupPlugin : BaseUnityPlugin
{
	private static class RunningCode
	{
		private static readonly Dictionary<string, float> Seen = new Dictionary<string, float>();

		private static readonly Dictionary<string, MethodBase> Methods = new Dictionary<string, MethodBase>();

		private static readonly HashSet<MethodBase> ThisFrame = new HashSet<MethodBase>();

		private static int _frame = -1;

		public static bool Pending;

		public static void Apply(Harmony harmony)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			HarmonyMethod val = new HarmonyMethod(AccessTools.Method(typeof(RunningCode), "Capture", (Type[])null, (Type[])null));
			foreach (Type item in AccessTools.AllTypes())
			{
				if (item.IsAbstract || item.IsInterface || item.IsGenericTypeDefinition || item == typeof(Log_BackupPlugin) || !typeof(MonoBehaviour).IsAssignableFrom(item))
				{
					continue;
				}
				foreach (MethodInfo declaredMethod in AccessTools.GetDeclaredMethods(item))
				{
					if ((!(declaredMethod.Name != "Update") || !(declaredMethod.Name != "LateUpdate") || !(declaredMethod.Name != "FixedUpdate")) && !declaredMethod.IsStatic)
					{
						try
						{
							harmony.Patch((MethodBase)declaredMethod, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
						}
						catch
						{
						}
					}
				}
			}
		}

		public static void Capture(MethodBase __originalMethod)
		{
			try
			{
				if (Time.frameCount != _frame)
				{
					_frame = Time.frameCount;
					ThisFrame.Clear();
				}
				if (ThisFrame.Add(__originalMethod))
				{
					string key = __originalMethod.DeclaringType.Name + "." + __originalMethod.Name;
					Seen[key] = Time.time;
					Methods[key] = __originalMethod;
				}
				if (Pending)
				{
					Pending = false;
					float cutoff = Time.time - 5f;
					IEnumerable<string> values = from kv in Seen
						where kv.Value >= cutoff
						orderby kv.Value descending
						select "  " + (IsModPatched(Methods[kv.Key]) ? "* " : "") + kv.Key;
					Debug.Log((object)("[Log_Backup] Running in the last 5 seconds:\n" + string.Join("\n", values)));
				}
			}
			catch
			{
			}
		}

		private static bool IsModPatched(MethodBase m)
		{
			try
			{
				Patches patchInfo = Harmony.GetPatchInfo(m);
				if (patchInfo == null)
				{
					return false;
				}
				return patchInfo.Prefixes.Any((Patch p) => p.owner != "LKK.Log_Backup") || patchInfo.Postfixes.Any((Patch p) => p.owner != "LKK.Log_Backup") || patchInfo.Transpilers.Any((Patch p) => p.owner != "LKK.Log_Backup") || patchInfo.Finalizers.Any((Patch p) => p.owner != "LKK.Log_Backup");
			}
			catch
			{
				return false;
			}
		}
	}

	public const string PLUGIN_GUID = "LKK.Log_Backup";

	public const string PLUGIN_NAME = "Log_Backup";

	public const string PLUGIN_VERSION = "1.0.0";

	public const string PLUGIN_VERSION_FULL = "1.0.0.0";

	private const string MarkerToken = "Log_Backup::MARKER";

	private const string CrashMarker = "Crash!!!";

	private const string InputUtilsGuid = "com.rune580.LethalCompanyInputUtils";

	public static ManualLogSource logger;

	public static Log_BackupPlugin Instance;

	private bool _markerPressed;

	private bool _quitHandled;

	private Key _markerFallbackKey;

	private ConfigEntry<bool> _runningCode;

	private string _backupFolder;

	private string _playerLogPath;

	private string _playerPrevLogPath;

	private string _logOutputPath;

	private InputAction _fallbackAction;

	private void Awake()
	{
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f0: Expected O, but got Unknown
		Instance = this;
		logger = ((BaseUnityPlugin)this).Logger;
		((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
		_markerFallbackKey = ((BaseUnityPlugin)this).Config.Bind<Key>("Log_Backup", "MarkerFallbackKey", (Key)102, "Fallback key used when InputUtils is not loaded.").Value;
		_runningCode = ((BaseUnityPlugin)this).Config.Bind<bool>("Log_Backup", "RunningCode", false, "When enabled, records which Update/LateUpdate/FixedUpdate methods ran in the last 5 seconds and prints them when the marker key is pressed. This requires patching those methods.");
		_playerLogPath = Application.consoleLogPath;
		_playerPrevLogPath = Path.Combine(Path.GetDirectoryName(_playerLogPath), "Player-prev.log");
		_logOutputPath = Path.Combine(Paths.BepInExRootPath, "LogOutput.log");
		_backupFolder = Path.Combine(Paths.BepInExRootPath, "Log_Backup", DateTime.Now.ToString("MM-dd-yyyy_HH-mm-ss"));
		TryBackupPrevLog();
		SetupMarkerInput();
		if (_runningCode.Value)
		{
			try
			{
				RunningCode.Apply(new Harmony("LKK.Log_Backup"));
			}
			catch
			{
			}
		}
	}

	private void OnMarkerPerformed(CallbackContext context)
	{
		_markerPressed = true;
		string text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
		Debug.Log((object)("[Log_Backup] Log_Backup::MARKER " + text));
		if (_runningCode.Value)
		{
			RunningCode.Pending = true;
		}
		try
		{
			if ((Object)(object)HUDManager.Instance != (Object)null)
			{
				HUDManager.Instance.DisplayTip("Log_Backup", "Marker logged at " + text, false, false, "Log_Backup_Tip");
			}
		}
		catch
		{
		}
	}

	private void OnApplicationQuit()
	{
		if (!_quitHandled && _markerPressed)
		{
			_quitHandled = true;
			CopyLog(_playerLogPath, "Player");
			CopyLog(_logOutputPath, "LogOutput");
		}
	}

	private void CopyLog(string source, string tag)
	{
		if (!File.Exists(source))
		{
			return;
		}
		EnsureBackupFolder();
		string text = Path.Combine(_backupFolder, tag + ".log");
		try
		{
			File.Copy(source, text, overwrite: true);
			logger.LogInfo((object)("[Log_Backup] backed up " + text));
		}
		catch (Exception arg)
		{
			logger.LogError((object)$"[Log_Backup] {arg}");
		}
	}

	private void TryBackupPrevLog()
	{
		if (!File.Exists(_playerPrevLogPath))
		{
			return;
		}
		string text;
		try
		{
			text = File.ReadAllText(_playerPrevLogPath);
		}
		catch (Exception arg)
		{
			logger.LogError((object)$"[Log_Backup] {arg}");
			return;
		}
		if (!text.Contains("Crash!!!") && !text.Contains("Log_Backup::MARKER"))
		{
			return;
		}
		EnsureBackupFolder();
		string text2 = Path.Combine(_backupFolder, "Player-prev.log");
		try
		{
			File.Copy(_playerPrevLogPath, text2, overwrite: true);
			logger.LogInfo((object)("[Log_Backup] backed up " + text2));
		}
		catch (Exception arg2)
		{
			logger.LogError((object)$"[Log_Backup] {arg2}");
		}
	}

	private void EnsureBackupFolder()
	{
		if (!Directory.Exists(_backupFolder))
		{
			Directory.CreateDirectory(_backupFolder);
		}
	}

	private void SetupMarkerInput()
	{
		if (Chainloader.PluginInfos.ContainsKey("com.rune580.LethalCompanyInputUtils"))
		{
			TrySetupInputUtils();
		}
		else
		{
			SetupFallbackInput();
		}
	}

	private void TrySetupInputUtils()
	{
		try
		{
			new LogBackupInputs().MarkerKey.performed += OnMarkerPerformed;
		}
		catch (Exception ex)
		{
			logger.LogWarning((object)("[Log_Backup] LethalCompanyInputUtils keybind setup failed: " + ex.Message));
			SetupFallbackInput();
		}
	}

	private void SetupFallbackInput()
	{
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Expected O, but got Unknown
		string text = "<Keyboard>/" + ((object)Unsafe.As<Key, Key>(ref _markerFallbackKey)/*cast due to .constrained prefix*/).ToString().ToLowerInvariant();
		try
		{
			_fallbackAction = new InputAction("Log_Backup Marker", (InputActionType)1, text, (string)null, (string)null, (string)null);
			_fallbackAction.performed += OnMarkerPerformed;
			_fallbackAction.Enable();
		}
		catch (Exception ex)
		{
			logger.LogError((object)("[Log_Backup] Failed to bind fallback input " + text + ": " + ex.Message));
		}
	}
}