Decompiled source of Whisper v1.0.0

Whisper.dll

Decompiled a week ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using JetBrains.Annotations;
using Microsoft.CodeAnalysis;
using Steamworks;
using UnityEngine;
using Whisper.Services;
using whisper;
using whisper.Config;
using whisper.Core;

[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("Whisper")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+1ddb199e8b1ec52a7c91442715b971d231617784")]
[assembly: AssemblyProduct("Whisper")]
[assembly: AssemblyTitle("Whisper")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 Whisper.Services
{
	public sealed class WhisperLogger : IWhisperLogger, IDisposable
	{
		private readonly ManualLogSource _log = Logger.CreateLogSource(pluginName);

		public WhisperLogger(string pluginName)
		{
		}

		private static string FormatMessage(object data, [CanBeNull] string domain)
		{
			if (!string.IsNullOrWhiteSpace(domain))
			{
				return $"[{domain}] {data}";
			}
			return data?.ToString();
		}

		public void Fatal(object data, string domain = null)
		{
			_log.LogFatal((object)FormatMessage(data, domain));
		}

		public void Error(object data, string domain = null)
		{
			_log.LogError((object)FormatMessage(data, domain));
		}

		public void Warning(object data, string domain = null)
		{
			_log.LogWarning((object)FormatMessage(data, domain));
		}

		public void Message(object data, string domain = null)
		{
			_log.LogMessage((object)FormatMessage(data, domain));
		}

		public void Info(object data, string domain = null)
		{
			_log.LogInfo((object)FormatMessage(data, domain));
		}

		public void Debug(object data, string domain = null)
		{
			if (ModSystem.ConfigData.EnableDebugLogs.Value)
			{
				_log.LogDebug((object)FormatMessage(data, domain));
			}
		}

		public void Dispose()
		{
			Logger.Sources.Remove((ILogSource)(object)_log);
		}
	}
}
namespace whisper
{
	internal static class Constants
	{
		public const string PluginName = "Whisper";

		public const string PluginGuid = "com.harukadev.magearena.whisper";
	}
	[BepInProcess("MageArena.exe")]
	[BepInPlugin("com.harukadev.magearena.whisper", "Whisper", "1.0.0")]
	[BepInIncompatibility("com.magearena.hostsettings")]
	public class ModSystem : BaseUnityPlugin
	{
		internal static IWhisperLogger Log;

		internal static WhisperConfig ConfigData;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			Log = new WhisperLogger("Whisper");
			ConfigData = new WhisperConfig(((BaseUnityPlugin)this).Config);
			_harmony = new Harmony("com.harukadev.magearena.whisper");
			_harmony.PatchAll();
			Log.Info("is loaded!");
		}

		private void OnDestroy()
		{
			Log.Info("mod unloaded");
			Log.Dispose();
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
}
namespace whisper.Patches
{
	[HarmonyPatch(typeof(BootstrapManager), "GetLobbiesList")]
	internal class PatchGetLobbiesList
	{
		private const string DomainName = "LobbyDiscovery";

		private static bool Prefix(BootstrapManager __instance)
		{
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			if (!ModSystem.ConfigData.Enabled.Value)
			{
				ModSystem.Log.Debug("Whisper disabled — using vanilla lobby discovery", "LobbyDiscovery");
				return true;
			}
			ModSystem.Log.Debug("Intercepting GetLobbiesList", "LobbyDiscovery");
			if (__instance.lobbyIDs.Count > 0)
			{
				ModSystem.Log.Debug($"Clearing {__instance.lobbyIDs.Count} cached lobby IDs", "LobbyDiscovery");
				__instance.lobbyIDs.Clear();
			}
			SteamMatchmaking.AddRequestLobbyListDistanceFilter(ResolveDistanceFilter(ModSystem.ConfigData.LobbyDistance.Value));
			ModSystem.Log.Info($"Applied distance filter: {ModSystem.ConfigData.LobbyDistance.Value}", "LobbyDiscovery");
			SteamMatchmaking.AddRequestLobbyListResultCountFilter(Mathf.Clamp(ModSystem.ConfigData.MaxLobbyResults.Value, 1, 250));
			ModSystem.Log.Debug($"Result count filter set to {ModSystem.ConfigData.MaxLobbyResults.Value}", "LobbyDiscovery");
			string version = Application.version;
			if (!ModSystem.ConfigData.IgnoreGameVersion.Value)
			{
				SteamMatchmaking.AddRequestLobbyListStringFilter("Version", version, (ELobbyComparison)0);
			}
			SteamMatchmaking.AddRequestLobbyListStringFilter("closed", "0", (ELobbyComparison)0);
			string text = (ModSystem.ConfigData.IgnoreGameVersion.Value ? "IGNORED" : version);
			ModSystem.Log.Debug("Applied filters: Version=" + text + ", closed=0", "LobbyDiscovery");
			SteamMatchmaking.RequestLobbyList();
			ModSystem.Log.Info("Lobby list request sent", "LobbyDiscovery");
			return false;
		}

		private static ELobbyDistanceFilter ResolveDistanceFilter(FilterOptionsEnum option)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			return (ELobbyDistanceFilter)(option switch
			{
				FilterOptionsEnum.SameRegion => 0, 
				FilterOptionsEnum.NearbyRegion => 1, 
				FilterOptionsEnum.Continent => 2, 
				FilterOptionsEnum.Global => 3, 
				_ => 3, 
			});
		}
	}
	[HarmonyPatch(typeof(BootstrapManager), "OnGetLobbyList")]
	internal static class PatchOnGetLobbyList
	{
		private const string Domain = "LobbyDiscovery.OnGetLobbyList";

		private static float _lastInterceptTime;

		private static bool Prefix(BootstrapManager __instance, LobbyMatchList_t result)
		{
			//IL_007c: 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)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			if (!ModSystem.ConfigData.Enabled.Value)
			{
				ModSystem.Log.Debug("Whisper disabled — falling back to vanilla lobby discovery", "LobbyDiscovery.OnGetLobbyList");
				return true;
			}
			if (Time.realtimeSinceStartup - _lastInterceptTime < 0.5f)
			{
				ModSystem.Log.Debug("Skipping lobby intercept (rate limited)", "LobbyDiscovery.OnGetLobbyList");
				return true;
			}
			_lastInterceptTime = Time.realtimeSinceStartup;
			if ((Object)(object)FindPublicLobbies.instance == (Object)null)
			{
				ModSystem.Log.Warning("FindPublicLobbies instance not available — aborting custom injection", "LobbyDiscovery.OnGetLobbyList");
				return true;
			}
			uint nLobbiesMatching = result.m_nLobbiesMatching;
			ModSystem.Log.Info($"Steam returned {nLobbiesMatching} lobbies — injecting without vanilla filters", "LobbyDiscovery.OnGetLobbyList");
			if (nLobbiesMatching == 0)
			{
				ModSystem.Log.Warning("No lobbies returned — falling back to vanilla behavior", "LobbyDiscovery.OnGetLobbyList");
				return true;
			}
			if (FindPublicLobbies.instance.listOfLobbies.Count > 0)
			{
				ModSystem.Log.Debug("Destroying cached lobbies", "LobbyDiscovery.OnGetLobbyList");
				FindPublicLobbies.instance.DestroyLobbies();
			}
			__instance.lobbyIDs.Clear();
			for (int i = 0; i < nLobbiesMatching; i++)
			{
				CSteamID lobbyByIndex = SteamMatchmaking.GetLobbyByIndex(i);
				__instance.lobbyIDs.Add(lobbyByIndex);
				SteamMatchmaking.RequestLobbyData(lobbyByIndex);
				ModSystem.Log.Debug($"Injected lobby {lobbyByIndex.m_SteamID}", "LobbyDiscovery.OnGetLobbyList");
			}
			ModSystem.Log.Info($"Lobby injection complete — injected {__instance.lobbyIDs.Count}", "LobbyDiscovery.OnGetLobbyList");
			return false;
		}
	}
}
namespace whisper.Core
{
	public interface IWhisperLogger : IDisposable
	{
		void Fatal(object data, [CanBeNull] string domain = null);

		void Error(object data, [CanBeNull] string domain = null);

		void Warning(object data, [CanBeNull] string domain = null);

		void Message(object data, [CanBeNull] string domain = null);

		void Info(object data, [CanBeNull] string domain = null);

		void Debug(object data, [CanBeNull] string domain = null);
	}
}
namespace whisper.Config
{
	public class WhisperConfig
	{
		public readonly ConfigEntry<bool> Enabled = config.Bind<bool>("General", "Enabled", true, "Toggle the mod");

		public readonly ConfigEntry<FilterOptionsEnum> LobbyDistance = config.Bind<FilterOptionsEnum>("Lobby Discovery", "LobbyDistance", FilterOptionsEnum.Global, "How far Steam should search for lobbies.");

		public readonly ConfigEntry<int> MaxLobbyResults = config.Bind<int>("Lobby Discovery", "MaxLobbyResults", 100, new ConfigDescription("Maximum number of lobbies requested from Steam.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(20, 250), Array.Empty<object>()));

		public readonly ConfigEntry<bool> IgnoreLobbySizeFilter = config.Bind<bool>("Lobby Discovery", "IgnoreLobbySizeFilter", true, "Ignores the game's original lobby size filter (2p / 8p).");

		public readonly ConfigEntry<bool> IgnoreGameVersion = config.Bind<bool>("Compatibility", "IgnoreGameVersion", false, "Allows joining lobbies with different game versions (unsafe).");

		public readonly ConfigEntry<bool> DisableWhisperPatch = config.Bind<bool>("Compatibility", "DisableWhisperPatch", false, "Disables Whisper lobby discovery and uses the game's original behavior.");

		public readonly ConfigEntry<bool> EnableDebugLogs = config.Bind<bool>("Debug", "EnableDebugLogs", false, "Enables verbose debug logging.");

		public WhisperConfig(ConfigFile config)
		{
		}//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Expected O, but got Unknown

	}
	public enum FilterOptionsEnum
	{
		SameRegion,
		NearbyRegion,
		Continent,
		Global
	}
}