Decompiled source of SafeLogoutTimer v0.9.3

plugins/SafeLogoutTimer/SafeLogoutTimer.dll

Decompiled a month ago
using System.Collections;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using HarmonyLib;
using Jotunn.Utils;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("SafeLogoutTimer")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("SafeLogoutTimer")]
[assembly: AssemblyTitle("SafeLogoutTimer")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace SafeLogoutTimer;

[BepInPlugin("local.valheim.safelogouttimer", "Safe Logout Timer", "0.9.3")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
public sealed class Plugin : BaseUnityPlugin
{
	private enum CountdownAction
	{
		None,
		Logout,
		Quit
	}

	[HarmonyPatch(typeof(Menu), "OnLogoutYes")]
	private static class MenuLogoutPatch
	{
		private static bool Prefix(Menu __instance)
		{
			if (!((Object)(object)_instance == (Object)null))
			{
				return _instance.BeginCountdown(__instance, CountdownAction.Logout);
			}
			return true;
		}
	}

	[HarmonyPatch(typeof(Menu), "OnQuitYes")]
	private static class MenuQuitPatch
	{
		private static bool Prefix(Menu __instance)
		{
			if (!((Object)(object)_instance == (Object)null))
			{
				return _instance.BeginCountdown(__instance, CountdownAction.Quit);
			}
			return true;
		}
	}

	[HarmonyPatch(typeof(Menu), "Show")]
	private static class MenuShowPatch
	{
		private static bool Prefix()
		{
			if ((Object)(object)_instance == (Object)null || _instance._countdownAction == CountdownAction.None)
			{
				return true;
			}
			int seconds = Mathf.Max(0, Mathf.CeilToInt(_instance._countdownEnd - Time.realtimeSinceStartup));
			_instance.ShowCountdownMessage(seconds);
			return false;
		}
	}

	[HarmonyPatch(typeof(Player), "OnDamaged")]
	private static class PlayerDamagedPatch
	{
		private static void Postfix(Player __instance, HitData hit)
		{
			if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer && hit != null && hit.GetTotalDamage() > 0f)
			{
				_instance?.CancelForAction();
			}
		}
	}

	[HarmonyPatch(typeof(Humanoid), "StartAttack")]
	private static class PlayerAttackPatch
	{
		private static void Postfix(Humanoid __instance, bool __result)
		{
			if (__result && (Object)(object)__instance == (Object)(object)Player.m_localPlayer)
			{
				_instance?.CancelForAction();
			}
		}
	}

	public const string PluginGuid = "local.valheim.safelogouttimer";

	public const string PluginName = "Safe Logout Timer";

	public const string PluginVersion = "0.9.3";

	private const int LogoutSeconds = 10;

	private const float MovementToleranceMeters = 0.75f;

	private static Plugin _instance;

	private static bool _allowVanillaAction;

	private CountdownAction _countdownAction;

	private Menu _countdownMenu;

	private Vector3 _countdownStartPosition;

	private float _countdownEnd;

	private int _lastShownSecond = -1;

	private Coroutine _countdownCoroutine;

	private void Awake()
	{
		_instance = this;
		Harmony.CreateAndPatchAll(typeof(Plugin).Assembly, "local.valheim.safelogouttimer");
		((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("{0} {1} loaded; timer={2}s, Alt+F4 ignored", "Safe Logout Timer", "0.9.3", 10));
	}

	private void OnDestroy()
	{
		if ((Object)(object)_instance == (Object)(object)this)
		{
			_instance = null;
		}
	}

	private bool BeginCountdown(Menu menu, CountdownAction action)
	{
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		if (_allowVanillaAction || (Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)ZNet.instance == (Object)null)
		{
			return true;
		}
		if (_countdownAction != CountdownAction.None)
		{
			int seconds = Mathf.Max(0, Mathf.CeilToInt(_countdownEnd - Time.realtimeSinceStartup));
			menu.Hide();
			ShowCountdownMessage(seconds);
			return false;
		}
		_countdownAction = action;
		_countdownMenu = menu;
		_countdownStartPosition = ((Component)Player.m_localPlayer).transform.position;
		_countdownEnd = Time.realtimeSinceStartup + 10f;
		_lastShownSecond = -1;
		menu.Hide();
		ShowCountdownMessage(10);
		((BaseUnityPlugin)this).Logger.LogInfo((object)$"Started {action} countdown ({10}s)");
		_countdownCoroutine = ((MonoBehaviour)this).StartCoroutine(CountdownRoutine());
		return false;
	}

	private IEnumerator CountdownRoutine()
	{
		while (_countdownAction != CountdownAction.None)
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead())
			{
				CancelCountdown(null);
				break;
			}
			float num = 0.5625f;
			Vector3 val = ((Component)localPlayer).transform.position - _countdownStartPosition;
			if (((Vector3)(ref val)).sqrMagnitude > num)
			{
				CancelCountdown("Wylogowanie anulowane — poruszyłeś się");
				break;
			}
			int num2 = Mathf.Max(0, Mathf.CeilToInt(_countdownEnd - Time.realtimeSinceStartup));
			if (num2 != _lastShownSecond)
			{
				ShowCountdownMessage(num2);
			}
			if (Time.realtimeSinceStartup >= _countdownEnd)
			{
				ExecuteVanillaAction();
				break;
			}
			yield return null;
		}
	}

	private void ShowCountdownMessage(int seconds)
	{
		_lastShownSecond = seconds;
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer != (Object)null)
		{
			((Character)localPlayer).Message((MessageType)2, (seconds > 0) ? $"Wylogowanie za {seconds} s — nie ruszaj się" : "Wylogowywanie…", 0, (Sprite)null, false);
		}
	}

	private void CancelCountdown(string reason)
	{
		if (_countdownAction != CountdownAction.None)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"Cancelled {_countdownAction} countdown");
			_countdownAction = CountdownAction.None;
			_countdownMenu = null;
			_countdownCoroutine = null;
			if (!string.IsNullOrEmpty(reason) && (Object)(object)Player.m_localPlayer != (Object)null)
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, reason, 0, (Sprite)null, false);
			}
		}
	}

	private void ExecuteVanillaAction()
	{
		CountdownAction countdownAction = _countdownAction;
		Menu countdownMenu = _countdownMenu;
		_countdownAction = CountdownAction.None;
		_countdownMenu = null;
		_countdownCoroutine = null;
		if ((Object)(object)countdownMenu == (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"Countdown completed, but the menu instance is no longer available");
			return;
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)$"Completed {countdownAction} countdown; invoking the original game action");
		_allowVanillaAction = true;
		try
		{
			switch (countdownAction)
			{
			case CountdownAction.Logout:
				countdownMenu.OnLogoutYes();
				break;
			case CountdownAction.Quit:
				countdownMenu.OnQuitYes();
				break;
			}
		}
		finally
		{
			_allowVanillaAction = false;
		}
	}

	private void CancelForAction()
	{
		CancelCountdown("Wylogowanie anulowane — wykonałeś akcję");
	}
}