Decompiled source of AnErrorOccuredLobbyCleanup v1.0.11

BepInEx/plugins/ZaboomafooW-AnErrorOccuredLobbyCleanup-v1.0.11.dll

Decompiled 2 months ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using AnErrorOccuredLobbyCleanup.Controllers;
using BepInEx;
using BepInEx.Logging;
using Microsoft.CodeAnalysis;
using Steamworks;
using Steamworks.Data;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("AnErrorOccuredLobbyCleanup")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.11.0")]
[assembly: AssemblyInformationalVersion("1.0.11")]
[assembly: AssemblyProduct("AnErrorOccuredLobbyCleanup")]
[assembly: AssemblyTitle("AnErrorOccuredLobbyCleanup")]
[assembly: AssemblyVersion("1.0.11.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace AnErrorOccuredLobbyCleanup
{
	[BepInPlugin("ZaboomafooW.AnErrorOccuredLobbyCleanup", "An Error Occured Lobby Cleanup", "1.0.11")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "ZaboomafooW.AnErrorOccuredLobbyCleanup";

		public const string PluginName = "An Error Occured Lobby Cleanup";

		public const string PluginVersion = "1.0.11";

		private SteamLobbyCleanupController _cleanupController;

		private void Awake()
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[An Error Occured Lobby Cleanup] Loaded v1.0.11");
			_cleanupController = new SteamLobbyCleanupController(((BaseUnityPlugin)this).Logger);
			_cleanupController.Start();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[An Error Occured Lobby Cleanup] Hook succeeded: Steam lobby and scene cleanup callbacks attached.");
		}

		private void OnApplicationQuit()
		{
			if (_cleanupController != null)
			{
				_cleanupController.Shutdown();
				_cleanupController = null;
			}
		}
	}
}
namespace AnErrorOccuredLobbyCleanup.Controllers
{
	internal sealed class SteamLobbyCleanupController
	{
		private readonly ManualLogSource _logger;

		private ulong _cachedLobbyId;

		private ulong _cachedHostSteamId;

		private bool _isSubscribed;

		public SteamLobbyCleanupController(ManualLogSource logger)
		{
			_logger = logger;
		}

		public void Start()
		{
			if (!_isSubscribed)
			{
				SteamMatchmaking.OnLobbyEntered += OnLobbyEntered;
				SteamMatchmaking.OnLobbyMemberLeave += OnLobbyMemberLeave;
				SteamMatchmaking.OnLobbyMemberDisconnected += OnLobbyMemberDisconnected;
				SteamMatchmaking.OnLobbyMemberKicked += OnLobbyMemberKicked;
				SteamMatchmaking.OnLobbyMemberBanned += OnLobbyMemberBanned;
				SceneManager.sceneLoaded += OnSceneLoaded;
				_isSubscribed = true;
			}
		}

		public void Shutdown()
		{
			LeaveRetainedLobbyOnApplicationQuit();
			ClearHostCache();
			if (_isSubscribed)
			{
				SteamMatchmaking.OnLobbyEntered -= OnLobbyEntered;
				SteamMatchmaking.OnLobbyMemberLeave -= OnLobbyMemberLeave;
				SteamMatchmaking.OnLobbyMemberDisconnected -= OnLobbyMemberDisconnected;
				SteamMatchmaking.OnLobbyMemberKicked -= OnLobbyMemberKicked;
				SteamMatchmaking.OnLobbyMemberBanned -= OnLobbyMemberBanned;
				SceneManager.sceneLoaded -= OnSceneLoaded;
				_isSubscribed = false;
			}
		}

		private void LeaveRetainedLobbyOnApplicationQuit()
		{
			GameNetworkManager instance = GameNetworkManager.Instance;
			if (!((Object)(object)instance == (Object)null) && !instance.disableSteam && instance.currentLobby.HasValue)
			{
				_logger.LogInfo((object)"[An Error Occured Lobby Cleanup] Application quitting; exiting current Steam lobby.");
				instance.LeaveCurrentSteamLobby();
			}
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode loadSceneMode)
		{
			if (!(((Scene)(ref scene)).name != "MainMenu"))
			{
				GameNetworkManager instance = GameNetworkManager.Instance;
				if ((Object)(object)instance != (Object)null && !instance.disableSteam && instance.currentLobby.HasValue)
				{
					_logger.LogWarning((object)"[An Error Occured Lobby Cleanup] Feature executed: MainMenu retained an orphaned Steam lobby; cleaning it up so other players don't get \"An error occured!\"");
					instance.LeaveCurrentSteamLobby();
				}
				ClearHostCache();
			}
		}

		private void OnLobbyEntered(Lobby lobby)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			GameNetworkManager instance = GameNetworkManager.Instance;
			if ((Object)(object)instance == (Object)null || instance.disableSteam || !instance.currentLobby.HasValue)
			{
				ClearHostCache();
				return;
			}
			ulong value = ((Lobby)(ref lobby)).Id.Value;
			Lobby value2 = instance.currentLobby.Value;
			if (((Lobby)(ref value2)).Id.Value == value)
			{
				ClearHostCache();
				ulong value3 = ((Lobby)(ref lobby)).Owner.Id.Value;
				if (value != 0L && value3 != 0L)
				{
					_cachedLobbyId = value;
					_cachedHostSteamId = value3;
					_logger.LogDebug((object)string.Format("[{0}] Cached Steam lobby {1} entry owner {2} as provisional host fallback.", "An Error Occured Lobby Cleanup", _cachedLobbyId, _cachedHostSteamId));
				}
			}
		}

		private void OnLobbyMemberLeave(Lobby lobby, Friend friend)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			HandleHostDeparture(lobby, friend, "left");
		}

		private void OnLobbyMemberDisconnected(Lobby lobby, Friend friend)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			HandleHostDeparture(lobby, friend, "disconnected from");
		}

		private void OnLobbyMemberKicked(Lobby lobby, Friend friend, Friend actor)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			HandleHostDeparture(lobby, friend, "was kicked from");
		}

		private void OnLobbyMemberBanned(Lobby lobby, Friend friend, Friend actor)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			HandleHostDeparture(lobby, friend, "was banned from");
		}

		private void HandleHostDeparture(Lobby lobby, Friend friend, string departureReason)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			ulong value = ((Lobby)(ref lobby)).Id.Value;
			if (friend.Id.Value == SteamClient.SteamId.Value)
			{
				HandleLocalLobbyRemoval(value, departureReason);
				return;
			}
			GameNetworkManager instance = GameNetworkManager.Instance;
			if ((Object)(object)instance == (Object)null || instance.disableSteam || instance.isHostingGame)
			{
				return;
			}
			if (!instance.currentLobby.HasValue)
			{
				ClearHostCache();
				return;
			}
			Lobby value2 = instance.currentLobby.Value;
			if (((Lobby)(ref value2)).Id.Value == value)
			{
				if (_cachedLobbyId != 0L && _cachedLobbyId != ((Lobby)(ref value2)).Id.Value)
				{
					ClearHostCache();
				}
				ulong num = ResolveOriginalHostSteamId(value);
				if (num != 0L && friend.Id.Value == num)
				{
					_logger.LogWarning((object)string.Format("[{0}] Feature executed: actual Lethal Company host {1} {2} Steam lobby {3}; cleaning up the orphaned Steam lobby so other players don't get \"An error occured!\"", "An Error Occured Lobby Cleanup", num, departureReason, value));
					QuarantineInheritedLobbyIfOwned(lobby, num);
					instance.LeaveCurrentSteamLobby();
					ClearHostCacheForLobby(value);
				}
			}
		}

		private void QuarantineInheritedLobbyIfOwned(Lobby lobby, ulong hostSteamId)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				ulong value = SteamClient.SteamId.Value;
				if (value != 0L && value != hostSteamId && ((Lobby)(ref lobby)).Owner.Id.Value == value)
				{
					if (((Lobby)(ref lobby)).SetJoinable(false))
					{
						_logger.LogWarning((object)string.Format("[{0}] This client inherited Steam lobby {1}; marked it non-joinable before cleanup.", "An Error Occured Lobby Cleanup", ((Lobby)(ref lobby)).Id.Value));
					}
					else
					{
						_logger.LogWarning((object)string.Format("[{0}] This client inherited Steam lobby {1}, but Steam did not accept the non-joinable quarantine; cleanup will continue.", "An Error Occured Lobby Cleanup", ((Lobby)(ref lobby)).Id.Value));
					}
				}
			}
			catch (Exception ex)
			{
				_logger.LogWarning((object)string.Format("[{0}] Failed to quarantine inherited Steam lobby {1}: {2}. Cleanup will continue.", "An Error Occured Lobby Cleanup", ((Lobby)(ref lobby)).Id.Value, ex.Message));
			}
		}

		private void HandleLocalLobbyRemoval(ulong lobbyId, string removalReason)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			GameNetworkManager instance = GameNetworkManager.Instance;
			if ((Object)(object)instance == (Object)null || instance.disableSteam || instance.isHostingGame)
			{
				ClearHostCacheForLobby(lobbyId);
				return;
			}
			if (!instance.currentLobby.HasValue)
			{
				ClearHostCacheForLobby(lobbyId);
				return;
			}
			Lobby value = instance.currentLobby.Value;
			if (((Lobby)(ref value)).Id.Value != lobbyId)
			{
				ClearHostCacheForLobby(lobbyId);
				return;
			}
			_logger.LogWarning((object)string.Format("[{0}] Feature executed: Steam reports this client {1} lobby {2}; clearing retained local lobby state.", "An Error Occured Lobby Cleanup", removalReason, lobbyId));
			instance.SetCurrentLobbyNull();
			instance.steamIdsInLobby.Clear();
			ClearHostCacheForLobby(lobbyId);
		}

		private ulong ResolveOriginalHostSteamId(ulong lobbyId)
		{
			ulong liveHostSteamId = GetLiveHostSteamId();
			if (liveHostSteamId != 0L)
			{
				if (_cachedLobbyId != lobbyId || _cachedHostSteamId != liveHostSteamId)
				{
					_cachedLobbyId = lobbyId;
					_cachedHostSteamId = liveHostSteamId;
					_logger.LogDebug((object)string.Format("[{0}] Confirmed Lethal Company host {1} for Steam lobby {2} from player slot 0.", "An Error Occured Lobby Cleanup", _cachedHostSteamId, _cachedLobbyId));
				}
				return liveHostSteamId;
			}
			if (_cachedLobbyId == lobbyId)
			{
				return _cachedHostSteamId;
			}
			return 0uL;
		}

		private static ulong GetLiveHostSteamId()
		{
			StartOfRound instance = StartOfRound.Instance;
			if ((Object)(object)instance == (Object)null || instance.allPlayerScripts == null || instance.allPlayerScripts.Length == 0 || (Object)(object)instance.allPlayerScripts[0] == (Object)null)
			{
				return 0uL;
			}
			return instance.allPlayerScripts[0].playerSteamId;
		}

		private void ClearHostCacheForLobby(ulong lobbyId)
		{
			if (_cachedLobbyId == lobbyId)
			{
				ClearHostCache();
			}
		}

		private void ClearHostCache()
		{
			_cachedLobbyId = 0uL;
			_cachedHostSteamId = 0uL;
		}
	}
}