using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Threading; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Newtonsoft.Json.Linq; using Peak.Network; using Photon.Pun; using Photon.Realtime; using Steamworks; using UnityEngine; using Zorro.Settings; using com.quackandcheese.LocalMultiplayer.Helpers; using com.quackandcheese.LocalMultiplayer.Objects; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("Ashley.MeshSplitter")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: IgnoresAccessChecksTo("com.rlabrecque.steamworks.net")] [assembly: IgnoresAccessChecksTo("DemiLib")] [assembly: IgnoresAccessChecksTo("DOTween")] [assembly: IgnoresAccessChecksTo("DOTweenPro")] [assembly: IgnoresAccessChecksTo("HBAO.Runtime")] [assembly: IgnoresAccessChecksTo("HBAO.Universal.Runtime")] [assembly: IgnoresAccessChecksTo("LightVolume.Runtime")] [assembly: IgnoresAccessChecksTo("Newtonsoft.Json")] [assembly: IgnoresAccessChecksTo("Photon3Unity3D")] [assembly: IgnoresAccessChecksTo("PhotonChat")] [assembly: IgnoresAccessChecksTo("PhotonRealtime")] [assembly: IgnoresAccessChecksTo("PhotonUnityNetworking.Demos")] [assembly: IgnoresAccessChecksTo("PhotonUnityNetworking")] [assembly: IgnoresAccessChecksTo("PhotonUnityNetworking.Utilities")] [assembly: IgnoresAccessChecksTo("PhotonVoice.API")] [assembly: IgnoresAccessChecksTo("PhotonVoice")] [assembly: IgnoresAccessChecksTo("PhotonVoice.PUN")] [assembly: IgnoresAccessChecksTo("pworld")] [assembly: IgnoresAccessChecksTo("sc.posteffects.runtime")] [assembly: IgnoresAccessChecksTo("Sirenix.OdinInspector.Attributes")] [assembly: IgnoresAccessChecksTo("Sirenix.OdinInspector.Modules.Unity.Addressables")] [assembly: IgnoresAccessChecksTo("Sirenix.OdinInspector.Modules.UnityLocalization")] [assembly: IgnoresAccessChecksTo("Sirenix.Serialization.Config")] [assembly: IgnoresAccessChecksTo("Sirenix.Serialization")] [assembly: IgnoresAccessChecksTo("Sirenix.Utilities")] [assembly: IgnoresAccessChecksTo("Tayx.Graphy")] [assembly: IgnoresAccessChecksTo("unity-websocket-sharp")] [assembly: IgnoresAccessChecksTo("Unity.Addressables")] [assembly: IgnoresAccessChecksTo("Unity.AI.Navigation")] [assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging")] [assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging.DocCodeExamples")] [assembly: IgnoresAccessChecksTo("Unity.Burst")] [assembly: IgnoresAccessChecksTo("Unity.Burst.Unsafe")] [assembly: IgnoresAccessChecksTo("Unity.Cinemachine")] [assembly: IgnoresAccessChecksTo("Unity.Collections")] [assembly: IgnoresAccessChecksTo("Unity.Collections.LowLevel.ILSupport")] [assembly: IgnoresAccessChecksTo("Unity.InputSystem")] [assembly: IgnoresAccessChecksTo("Unity.InputSystem.ForUI")] [assembly: IgnoresAccessChecksTo("Unity.InputSystem.RebindingUI")] [assembly: IgnoresAccessChecksTo("Unity.InternalAPIEngineBridge.004")] [assembly: IgnoresAccessChecksTo("Unity.InternalAPIEngineBridge.013")] [assembly: IgnoresAccessChecksTo("Unity.Localization")] [assembly: IgnoresAccessChecksTo("Unity.Mathematics")] [assembly: IgnoresAccessChecksTo("Unity.MemoryProfiler")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Center.Common")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Playmode.Common.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Playmode")] [assembly: IgnoresAccessChecksTo("Unity.Networking.Transport")] [assembly: IgnoresAccessChecksTo("Unity.Profiling.Core")] [assembly: IgnoresAccessChecksTo("Unity.Rendering.LightTransport.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipeline.Universal.ShaderLibrary")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime.Shared")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.ShaderLibrary")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.GPUDriven.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Universal.2D.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Universal.Config.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Universal.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Universal.Shaders")] [assembly: IgnoresAccessChecksTo("Unity.ResourceManager")] [assembly: IgnoresAccessChecksTo("Unity.ScriptableBuildPipeline")] [assembly: IgnoresAccessChecksTo("Unity.Services.Authentication")] [assembly: IgnoresAccessChecksTo("Unity.Services.Authentication.PlayerAccounts")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Analytics")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Components")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Configuration")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Device")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments.Internal")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Internal")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Networking")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Registration")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Scheduler")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Telemetry")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Threading")] [assembly: IgnoresAccessChecksTo("Unity.Services.Multiplayer")] [assembly: IgnoresAccessChecksTo("Unity.Services.QoS")] [assembly: IgnoresAccessChecksTo("Unity.Services.Wire.Internal")] [assembly: IgnoresAccessChecksTo("Unity.Splines")] [assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")] [assembly: IgnoresAccessChecksTo("Unity.Timeline")] [assembly: IgnoresAccessChecksTo("Unity.UnifiedRayTracing.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.VisualEffectGraph.Runtime")] [assembly: IgnoresAccessChecksTo("UnityEngine.AccessibilityModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.AdaptivePerformanceModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.AIModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.AMDModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.AndroidJNIModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.AnimationModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.ARModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.AssetBundleModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.AudioModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.ClothModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.ClusterInputModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.ClusterRendererModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.ContentLoadModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.CoreModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.CrashReportingModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.DirectorModule")] [assembly: IgnoresAccessChecksTo("UnityEngine")] [assembly: IgnoresAccessChecksTo("UnityEngine.DSPGraphModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.GameCenterModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.GIModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.GraphicsStateCollectionSerializerModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.GridModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.HierarchyCoreModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.HierarchyModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.HotReloadModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.IdentifiersModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.ImageConversionModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.IMGUIModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.InputForUIModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.InputLegacyModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.InputModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.InsightsModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.JSONSerializeModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.LocalizationModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.MarshallingModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.MultiplayerModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.NVIDIAModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.ParticleSystemModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.PerformanceReportingModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.Physics2DModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.PhysicsBackendPhysXModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.PhysicsModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.PropertiesModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.RenderAs2DModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.RuntimeInitializeOnLoadManagerInitializerModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.ScreenCaptureModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.ShaderRuntimeModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.ShaderVariantAnalyticsModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.SharedInternalsModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.SpriteMaskModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.SpriteShapeModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.StreamingModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.SubstanceModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.SubsystemsModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.TerrainModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.TerrainPhysicsModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.TextCoreFontEngineModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.TextCoreTextEngineModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.TextRenderingModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.TilemapModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.TLSModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.UI")] [assembly: IgnoresAccessChecksTo("UnityEngine.UIElementsModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.UIModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.UmbraModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.UnityAnalyticsCommonModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.UnityAnalyticsModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.UnityConnectModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.UnityConsentModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.UnityCurlModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.UnityTestProtocolModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.UnityWebRequestAssetBundleModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.UnityWebRequestAudioModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.UnityWebRequestModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.UnityWebRequestTextureModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.UnityWebRequestWWWModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.VectorGraphicsModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.VehiclesModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.VFXModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.VideoModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.VirtualTexturingModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.VRModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.WindModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.XRModule")] [assembly: IgnoresAccessChecksTo("UnityUIExtensions")] [assembly: IgnoresAccessChecksTo("websocket-sharp")] [assembly: IgnoresAccessChecksTo("Whinarn.UnityMeshSimplifier.Runtime")] [assembly: IgnoresAccessChecksTo("Zorro.AutoLOD")] [assembly: IgnoresAccessChecksTo("Zorro.ControllerSupport")] [assembly: IgnoresAccessChecksTo("Zorro.Core.Runtime")] [assembly: IgnoresAccessChecksTo("Zorro.JiggleBones")] [assembly: IgnoresAccessChecksTo("Zorro.PhotonUtility")] [assembly: IgnoresAccessChecksTo("Zorro.Settings.Runtime")] [assembly: IgnoresAccessChecksTo("Zorro.UI.Runtime")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("com.quackandcheese.LocalMultiplayer")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.5.0")] [assembly: AssemblyInformationalVersion("1.0.5+6fa95029dda180d27ff10d1625b0e1f2569aa3da")] [assembly: AssemblyProduct("com.quackandcheese.LocalMultiplayer")] [assembly: AssemblyTitle("LocalMultiplayer")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.5.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [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 BepInEx { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] internal sealed class BepInAutoPluginAttribute : Attribute { public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace BepInEx.Preloader.Core.Patching { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] internal sealed class PatcherAutoPluginAttribute : Attribute { public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace LocalMultiplayer.Patches { [HarmonyPatch(typeof(NetworkingUtilities))] internal static class NetworkingUtilitiesPatch { [HarmonyPatch("LoadUserID")] [HarmonyPrefix] private static bool LoadUserIDPatch(ref AuthenticationValues __result) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown __result = new AuthenticationValues { AuthType = (CustomAuthenticationType)255, UserId = Guid.NewGuid().ToString() }; return false; } } [HarmonyPatch(typeof(SteamLobbyAPI))] internal static class SteamLobbyAPIPatch { [HarmonyPatch("PlayerIsInLobby")] [HarmonyPrefix] private static bool PlayerIsInLobbyPatch(ref bool __result) { __result = true; return false; } } } namespace com.quackandcheese.LocalMultiplayer { internal static class ConfigManager { public static ConfigFile ConfigFile { get; private set; } public static ConfigEntry ExtendedLogging { get; private set; } public static ConfigEntry Photon_AppIdRealtime { get; private set; } public static ConfigEntry Photon_AppIdVoice { get; private set; } public static void Initialize(ConfigFile configFile) { ConfigFile = configFile; BindConfigs(); } private static void BindConfigs() { ExtendedLogging = ConfigFile.Bind("General", "ExtendedLogging", false, "Enable extended logging."); Photon_AppIdRealtime = ConfigFile.Bind("Photon", "AppIdRealtime", "", "The App ID of your Photon Pun application."); Photon_AppIdVoice = ConfigFile.Bind("Photon", "AppIdVoice", "", "The App ID of your Photon Voice application."); } } [BepInPlugin("com.quackandcheese.LocalMultiplayer", "LocalMultiplayer", "1.0.5")] public class Plugin : BaseUnityPlugin { public const string Id = "com.quackandcheese.LocalMultiplayer"; internal static ManualLogSource Log { get; private set; } internal static Plugin Instance { get; private set; } internal static ConfigFile Config { get; private set; } internal static Harmony? Harmony { get; set; } public static string Name => "LocalMultiplayer"; public static string Version => "1.0.5"; private void Awake() { Instance = this; Log = ((BaseUnityPlugin)this).Logger; Config = Utils.CreateGlobalConfigFile((BaseUnityPlugin)(object)this); Patch(); ConfigManager.Initialize(Config); Log.LogInfo((object)("Plugin " + Name + " is loaded!")); } internal void Patch() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown if (Harmony == null) { Harmony = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID); } Log.LogDebug((object)"Patching..."); Harmony.PatchAll(); Log.LogDebug((object)"Finished patching!"); } } internal static class SteamAccountManager { public static SteamAccount SpoofAccount; private static bool _initialized; public static SteamAccount RealAccount { get; private set; } public static bool IsUsingSpoofAccount => SpoofAccount != default(SteamAccount); public static void Initialize() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) if (!_initialized) { RealAccount = new SteamAccount(SteamFriends.GetPersonaName(), SteamUser.GetSteamID().m_SteamID); CreateSpoofAccounts(); Application.quitting += UnassignSpoofAccount; _initialized = true; } } private static void CreateSpoofAccounts() { List value = GlobalSaveHelper.SpoofSteamAccounts.Value; int num = 5; if (value.Count < num) { for (int i = value.Count; i < num; i++) { value.Add(new SteamAccount($"Player {i + 2}", SteamHelper.GenerateRandomSteamId())); } GlobalSaveHelper.SpoofSteamAccounts.Value = value; } } public static void AssignSpoofAccount() { if (!IsUsingSpoofAccount) { SteamAccount availableSpoofAccount = GetAvailableSpoofAccount(); AddSpoofAccountInUse(availableSpoofAccount); SpoofAccount = availableSpoofAccount; PhotonNetwork.NickName = availableSpoofAccount.Username; } } public static void UnassignSpoofAccount() { if (IsUsingSpoofAccount) { RemoveSpoofAccountInUse(SpoofAccount); SpoofAccount = default(SteamAccount); PhotonNetwork.NickName = RealAccount.Username; } } public static void ResetSpoofAccountsInUse() { GlobalSaveHelper.SpoofSteamAccountsInUse.Value = new List(); } public static bool TryGetSpoofAccount(ulong steamId, out SteamAccount steamAccount) { List value = GlobalSaveHelper.SpoofSteamAccounts.Value; foreach (SteamAccount item in value) { if (item.SteamId == steamId) { steamAccount = item; return true; } } steamAccount = default(SteamAccount); return false; } private static void UpdateCurrentSpoofAccountData() { if (!IsUsingSpoofAccount) { return; } List value = GlobalSaveHelper.SpoofSteamAccounts.Value; for (int i = 0; i < value.Count; i++) { if (value[i] == SpoofAccount) { value[i] = SpoofAccount; break; } } GlobalSaveHelper.SpoofSteamAccounts.Value = value; } private static List GetAvailableSpoofAccounts() { List list = new List(); List value = GlobalSaveHelper.SpoofSteamAccountsInUse.Value; foreach (SteamAccount item in GlobalSaveHelper.SpoofSteamAccounts.Value) { if (!value.Contains(item)) { list.Add(item); } } return list; } private static SteamAccount GetAvailableSpoofAccount() { List availableSpoofAccounts = GetAvailableSpoofAccounts(); if (availableSpoofAccounts.Count == 0) { Plugin.Log.LogWarning((object)"SteamHelper: No cached spoof steam accounts available. Generating new spoof steam account."); return new SteamAccount($"Player {Random.Range(100, 999)}", SteamHelper.GenerateRandomSteamId()); } return availableSpoofAccounts[0]; } private static void AddSpoofAccountInUse(SteamAccount account) { List value = GlobalSaveHelper.SpoofSteamAccountsInUse.Value; if (!value.Contains(account)) { value.Add(account); GlobalSaveHelper.SpoofSteamAccountsInUse.Value = value; } } private static void RemoveSpoofAccountInUse(SteamAccount account) { List value = GlobalSaveHelper.SpoofSteamAccountsInUse.Value; if (value.Contains(account)) { value.Remove(account); GlobalSaveHelper.SpoofSteamAccountsInUse.Value = value; } } } internal static class Utils { public static string GetPluginPersistentDataPath() { return Path.Combine(Application.persistentDataPath, Plugin.Name); } public static ConfigFile CreateConfigFile(BaseUnityPlugin plugin, string path, string name = null, bool saveOnInit = false) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown BepInPlugin metadata = MetadataHelper.GetMetadata((object)plugin); if (name == null) { name = metadata.GUID; } name += ".cfg"; return new ConfigFile(Path.Combine(path, name), saveOnInit, metadata); } public static ConfigFile CreateLocalConfigFile(BaseUnityPlugin plugin, string name = null, bool saveOnInit = false) { return CreateConfigFile(plugin, Paths.ConfigPath, name, saveOnInit); } public static ConfigFile CreateGlobalConfigFile(BaseUnityPlugin plugin, string name = null, bool saveOnInit = false) { string pluginPersistentDataPath = GetPluginPersistentDataPath(); if (name == null) { name = "global"; } return CreateConfigFile(plugin, pluginPersistentDataPath, name, saveOnInit); } } } namespace com.quackandcheese.LocalMultiplayer.Patches { [HarmonyPatch(typeof(MainMenu))] internal static class MenuPageMainPatch { [HarmonyPatch("Start")] [HarmonyPostfix] private static void StartPatch() { SteamAccountManager.UnassignSpoofAccount(); } [HarmonyPatch("PlaySoloClicked")] [HarmonyPrefix] private static bool PlaySoloClickedPatch(ref MainMenu __instance) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) SteamAccountManager.AssignSpoofAccount(); PhotonNetworkHelper.SetPhotonServerSettings(); GameHandler.GetService().TryJoinLobby(new CSteamID(GlobalSaveHelper.SteamLobbyId.Value)); return false; } } [HarmonyPatch(typeof(NetworkConnector))] internal static class NetworkConnectorPatch { [HarmonyPatch("Start")] [HarmonyPostfix] private static void StartPatch() { PhotonNetworkHelper.SetPhotonServerSettings(); } } [HarmonyPatch(typeof(SettingsHandler))] internal static class SettingsHandlerPatch { [HarmonyPatch("SaveSetting")] [HarmonyPrefix] private static bool SaveSettingPatch(ref Setting setting) { if (!SteamAccountManager.IsUsingSpoofAccount) { return true; } return false; } } [HarmonyPatch] internal static class SteamClientPatch { [HarmonyPatch(typeof(SteamFriends), "GetPersonaName")] [HarmonyPrefix] private static bool GetPersonaNamePatch(ref string __result) { if (!SteamAccountManager.IsUsingSpoofAccount) { return true; } __result = SteamAccountManager.SpoofAccount.Username; return false; } [HarmonyPatch(typeof(SteamUser), "GetSteamID")] [HarmonyPrefix] private static bool GetSteamIDPatch(ref CSteamID __result) { //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) if (!SteamAccountManager.IsUsingSpoofAccount) { return true; } __result = new CSteamID(SteamAccountManager.SpoofAccount.SteamId); return false; } } [HarmonyPatch(typeof(SteamLobbyHandler))] internal static class SteamLobbyHandlerPatch { [HarmonyPatch("OnLobbyCreated")] [HarmonyPostfix] private static void OnLobbyCreatedPatch(ref LobbyCreated_t param) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 if ((int)param.m_eResult == 1) { GlobalSaveHelper.SteamLobbyId.Value = param.m_ulSteamIDLobby; SteamAccountManager.ResetSpoofAccountsInUse(); } } [HarmonyPatch("OnLobbyChat")] [HarmonyPrefix] private static bool OnLobbyChatPatch(ref LobbyChatMsg_t param) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) if (!SteamAccountManager.IsUsingSpoofAccount && param.m_ulSteamIDUser == SteamUser.GetSteamID().m_SteamID) { param.m_ulSteamIDUser = SteamAccountManager.SpoofAccount.SteamId; } return true; } } [HarmonyPatch(typeof(SteamManager))] internal static class SteamManagerPatch { [HarmonyPatch("Awake")] [HarmonyPostfix] [HarmonyPriority(800)] private static void AwakePatch() { SteamAccountManager.Initialize(); } } } namespace com.quackandcheese.LocalMultiplayer.Objects { internal class JsonSave : IDisposable { private JObject _data; private readonly Mutex _mutex; private const int _mutexTimeoutMs = 5000; private bool _disposed; public string DirectoryPath { get; private set; } public string FileName { get; private set; } public string FilePath => Path.Combine(DirectoryPath, FileName); public JsonSave(string directoryPath, string fileName) { DirectoryPath = directoryPath; FileName = fileName; string name = "Global\\JsonSave_" + fileName.Replace(Path.DirectorySeparatorChar, '_'); _mutex = new Mutex(initiallyOwned: false, name); RefreshData(); Application.quitting += Dispose; } public bool KeyExists(string key) { RefreshData(); JObject data = _data; if (data == null) { return false; } return data.ContainsKey(key); } public T Load(string key, T defaultValue = default(T)) { if (!TryLoad(key, out var value)) { return defaultValue; } return value; } public bool TryLoad(string key, out T value) { value = default(T); RefreshData(); if (_data == null) { Plugin.Log.LogError((object)("TryLoad: Data is null. Key: " + key)); return false; } JToken val = default(JToken); if (_data.TryGetValue(key, ref val)) { try { value = val.ToObject(); return true; } catch (Exception ex) { Plugin.Log.LogError((object)("TryLoad: Failed to deserialize key '" + key + "'. " + ex.Message)); } } return false; } public bool Save(string key, T value) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown bool flag = false; try { flag = _mutex.WaitOne(5000); if (!flag) { Plugin.Log.LogWarning((object)"Save: Could not acquire mutex."); return false; } RefreshData(); if (_data == null) { _data = new JObject(); } _data[key] = JToken.FromObject((object)value); return WriteFile(_data); } catch (Exception ex) { Plugin.Log.LogError((object)("Save: Error saving key '" + key + "'. " + ex.Message)); return false; } finally { if (flag) { _mutex.ReleaseMutex(); } } } private JObject ReadFile() { //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Expected O, but got Unknown //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown try { if (!File.Exists(FilePath)) { Plugin.Log.LogWarning((object)("ReadFile: Save file not found at \"" + FilePath + "\". Creating new.")); return new JObject(); } using FileStream stream = new FileStream(FilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); using StreamReader streamReader = new StreamReader(stream, Encoding.UTF8); return JObject.Parse(streamReader.ReadToEnd()); } catch (Exception ex) { Plugin.Log.LogError((object)("ReadFile: Failed to read file \"" + FilePath + "\". " + ex.Message)); return new JObject(); } } private bool WriteFile(JObject data) { try { if (!Directory.Exists(DirectoryPath)) { Directory.CreateDirectory(DirectoryPath); } File.WriteAllText(FilePath, ((object)data).ToString(), Encoding.UTF8); return true; } catch (Exception ex) { Plugin.Log.LogError((object)("WriteFile: Failed to write file \"" + FilePath + "\". " + ex.Message)); return false; } } private void RefreshData() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown _data = ReadFile(); if (_data == null) { Plugin.Log.LogError((object)"RefreshData: Data is null. Creating new."); _data = new JObject(); } } public void Dispose() { if (!_disposed) { _mutex?.Dispose(); _disposed = true; } } } internal class JsonSaveValue(JsonSave jsonSave, string key, T defaultValue = default(T)) { public JsonSave JsonSave { get; private set; } = jsonSave; public string Key { get; private set; } = key; public T DefaultValue { get; private set; } = defaultValue; public T Value { get { return Load(); } set { Save(value); } } public bool HasValue { get { T value; return TryLoad(out value); } } public T Load() { return JsonSave.Load(Key, DefaultValue); } public bool TryLoad(out T value) { return JsonSave.TryLoad(Key, out value); } public void Save(T value) { JsonSave.Save(Key, value); } } public struct SteamAccount : IEquatable { public string Username; public ulong SteamId; public SteamAccount(string username, ulong steamId) { Username = username; SteamId = steamId; } public bool Equals(SteamAccount other) { return SteamId == other.SteamId; } public override bool Equals(object obj) { if (obj is SteamAccount other) { return Equals(other); } return false; } public static bool operator ==(SteamAccount a, SteamAccount b) { return a.Equals(b); } public static bool operator !=(SteamAccount a, SteamAccount b) { return !a.Equals(b); } public override int GetHashCode() { return SteamId.GetHashCode(); } } } namespace com.quackandcheese.LocalMultiplayer.Helpers { internal static class GlobalSaveHelper { public static JsonSave JsonSave { get; private set; } public static JsonSaveValue SteamLobbyId { get; private set; } public static JsonSaveValue> SpoofSteamAccounts { get; private set; } public static JsonSaveValue> SpoofSteamAccountsInUse { get; private set; } static GlobalSaveHelper() { JsonSave = new JsonSave(Utils.GetPluginPersistentDataPath(), "GlobalSave"); SteamLobbyId = new JsonSaveValue(JsonSave, "SteamLobbyId", 0uL); SpoofSteamAccounts = new JsonSaveValue>(JsonSave, "SpoofSteamAccounts", new List()); SpoofSteamAccountsInUse = new JsonSaveValue>(JsonSave, "SpoofSteamAccountsInUse", new List()); } public static bool KeyExists(string key) { return JsonSave.KeyExists(key); } public static T Load(string key, T defaultValue = default(T)) { return JsonSave.Load(key, defaultValue); } public static bool TryLoad(string key, out T value) { return JsonSave.TryLoad(key, out value); } public static bool Save(string key, T value) { return JsonSave.Save(key, value); } } internal static class PhotonNetworkHelper { public static void SetPhotonServerSettings() { AppSettings appSettings = PhotonNetwork.PhotonServerSettings.AppSettings; appSettings.AppIdRealtime = ConfigManager.Photon_AppIdRealtime.Value; appSettings.AppIdVoice = ConfigManager.Photon_AppIdVoice.Value; } } internal static class SteamHelper { public static ulong GenerateRandomSteamId() { ulong num = 76561197960265728uL; Random random = new Random(); uint num2 = (uint)random.Next(0, int.MaxValue); num2 += (uint)random.Next(0, int.MaxValue); return num + num2; } } } namespace com.quackandcheese.LocalMultiplayer.Extensions { internal static class StringExtensions { public static ulong ToUlong(this string value) { if (ulong.TryParse(value, out var result)) { return result; } return 0uL; } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }