Decompiled source of REPO Compatibility Patch v1.1.2

patchers/REPOCompatibilityPatcher.dll

Decompiled a week 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.Logging;
using Microsoft.CodeAnalysis;
using Mono.Cecil;
using Mono.Cecil.Cil;

[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("REPOCompatibilityPatcher")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("REPOCompatibilityPatcher")]
[assembly: AssemblyTitle("REPOCompatibilityPatcher")]
[assembly: AssemblyVersion("1.0.0.0")]
[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 REPOCompatibilityPatcher
{
	public static class Patcher
	{
		private static readonly ManualLogSource Log = Logger.CreateLogSource("REPOCompatibilityPatch");

		public static IEnumerable<string> TargetDLLs { get; } = new string[1] { "Assembly-CSharp.dll" };

		public static void Initialize()
		{
			try
			{
				string path = Path.Combine(Paths.BepInExRootPath ?? Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "BepInEx")), "patchers", "plugins");
				if (!Directory.Exists(path))
				{
					Directory.CreateDirectory(path);
					Log.LogInfo((object)"Created directory 'patchers/plugins' to prevent SADmodelfix DirectoryNotFoundException.");
				}
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("[Initialize] Note: " + ex.Message));
			}
		}

		public static void Patch(AssemblyDefinition assembly)
		{
			Log.LogInfo((object)"=== Starting In-Memory Assembly-CSharp Compatibility Patching ===");
			ModuleDefinition mainModule = assembly.MainModule;
			AddOverload(mainModule, "PlayerController", "OverrideSpeed", 2, -1f);
			AddOverload(mainModule, "PlayerHealth", "Hurt", 3, false);
			AddOverload(mainModule, "PostProcessing", "VignetteOverride", 7, 999);
			AddOverload(mainModule, "ParticleScriptExplosion", "Spawn", 8, 0f);
			AddOverload(mainModule, "PhysGrabObjectImpactDetector", "DestroyObject", 1, false);
			AddOverload(mainModule, "PlayerVoiceChat", "OverridePitch", 5, 0f);
			AddOverload(mainModule, "ChatManager", "PossessChat", 8, "");
			AddOverload(mainModule, "PlayerAvatar", "Spawn", 2, false);
			AddOverload(mainModule, "PlayerHealth", "HurtOther", 4, false);
			AddOverload(mainModule, "EnemyNavMeshAgent", "Warp", 1, false);
			AddOverload(mainModule, "Sound", "PlayLoop", 4, 1f);
			AddOverload(mainModule, "PhysGrabber", "OverrideGrabRelease", 0, -1, 0.5f);
			Log.LogInfo((object)"=== Assembly-CSharp Compatibility Patching Finished Successfully ===");
		}

		private static void AddOverload(ModuleDefinition module, string typeName, string methodName, int oldArgCount, params object[] extraDefaults)
		{
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Expected O, but got Unknown
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Expected O, but got Unknown
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_022f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0299: Unknown result type (might be due to invalid IL or missing references)
			//IL_0292: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				TypeDefinition type = module.GetType(typeName);
				if (type == null)
				{
					Log.LogWarning((object)("Type '" + typeName + "' not found in Assembly-CSharp; skipping '" + methodName + "'."));
					return;
				}
				List<MethodDefinition> list = (from m in (IEnumerable<MethodDefinition>)type.Methods
					where ((MemberReference)m).Name == methodName && ((MethodReference)m).Parameters.Count > oldArgCount
					orderby ((MethodReference)m).Parameters.Count
					select m).ToList();
				if (list.Count == 0)
				{
					Log.LogWarning((object)$"No target method '{typeName}.{methodName}' found with > {oldArgCount} parameters.");
					return;
				}
				MethodDefinition target = list.First();
				if (((IEnumerable<MethodDefinition>)type.Methods).Any((MethodDefinition m) => ((MemberReference)m).Name == methodName && m.IsStatic == target.IsStatic && ((MethodReference)m).Parameters.Count == oldArgCount))
				{
					Log.LogInfo((object)$"Overload '{typeName}.{methodName}({oldArgCount} args)' already present; skipping.");
					return;
				}
				MethodAttributes val = (MethodAttributes)134;
				if (target.IsStatic)
				{
					val = (MethodAttributes)(val | 0x10);
				}
				MethodDefinition val2 = new MethodDefinition(methodName, val, ((MethodReference)target).ReturnType);
				for (int num = 0; num < oldArgCount; num++)
				{
					((MethodReference)val2).Parameters.Add(new ParameterDefinition(((ParameterReference)((MethodReference)target).Parameters[num]).Name, (ParameterAttributes)0, ((ParameterReference)((MethodReference)target).Parameters[num]).ParameterType));
				}
				val2.Body.MaxStackSize = oldArgCount + 1 + extraDefaults.Length + 1;
				ILProcessor iLProcessor = val2.Body.GetILProcessor();
				if (!target.IsStatic)
				{
					iLProcessor.Emit(OpCodes.Ldarg_0);
				}
				for (int num2 = 0; num2 < oldArgCount; num2++)
				{
					iLProcessor.Emit(OpCodes.Ldarg, ((MethodReference)val2).Parameters[num2]);
				}
				foreach (object v in extraDefaults)
				{
					EmitConstant(iLProcessor, v);
				}
				iLProcessor.Emit(target.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, (MethodReference)(object)target);
				iLProcessor.Emit(OpCodes.Ret);
				type.Methods.Add(val2);
				Log.LogInfo((object)$"Added compat overload {typeName}.{methodName}({oldArgCount} args) -> {((MethodReference)target).Parameters.Count}-arg target.");
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"Failed to add overload for {typeName}.{methodName}: {arg}");
			}
		}

		private static void EmitConstant(ILProcessor il, object? v)
		{
			//IL_0004: 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_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: 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)
			if (v == null)
			{
				il.Emit(OpCodes.Ldnull);
			}
			else if (v is bool flag)
			{
				il.Emit(flag ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0);
			}
			else if (v is int num)
			{
				il.Emit(OpCodes.Ldc_I4, num);
			}
			else if (v is float num2)
			{
				il.Emit(OpCodes.Ldc_R4, num2);
			}
			else if (v is double num3)
			{
				il.Emit(OpCodes.Ldc_R8, num3);
			}
			else if (v is string text)
			{
				il.Emit(OpCodes.Ldstr, text);
			}
			else
			{
				il.Emit(OpCodes.Ldnull);
			}
		}
	}
}

plugins/REPOCompatibilityPatch.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[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("REPOCompatibilityPatch")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("REPOCompatibilityPatch")]
[assembly: AssemblyTitle("REPOCompatibilityPatch")]
[assembly: AssemblyVersion("1.0.0.0")]
[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 REPOCompatibilityPatch
{
	[BepInPlugin("com.pbdde.repocompatibilitypatch", "REPO Compatibility Patch", "1.1.2")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public static Plugin? Instance { get; private set; }

		public static ManualLogSource? Log { get; private set; }

		private void Awake()
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			Log.LogInfo((object)"REPO Compatibility Patch v1.1.2 initialized.");
			EngineOptimizer.ApplyLoadingOptimizations();
			try
			{
				Harmony val = new Harmony("com.pbdde.repocompatibilitypatch");
				ApplyHarmonyAmbiguityFix(val);
				val.PatchAll(typeof(Plugin).Assembly);
				Log.LogInfo((object)"Runtime compatibility patches applied successfully!");
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"Error applying harmony patches: {arg}");
			}
		}

		private void ApplyHarmonyAmbiguityFix(Harmony harmony)
		{
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Expected O, but got Unknown
			try
			{
				MethodInfo method = typeof(AccessTools).GetMethod("Method", new Type[4]
				{
					typeof(Type),
					typeof(string),
					typeof(Type[]),
					typeof(Type[])
				});
				MethodInfo method2 = typeof(AccessTools).GetMethod("DeclaredMethod", new Type[4]
				{
					typeof(Type),
					typeof(string),
					typeof(Type[]),
					typeof(Type[])
				});
				HarmonyMethod val = new HarmonyMethod(AccessTools.Method(typeof(HarmonyAmbiguityFix), "MethodPrefix", (Type[])null, (Type[])null));
				if (method != null)
				{
					harmony.Patch((MethodBase)method, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				if (method2 != null)
				{
					harmony.Patch((MethodBase)method2, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				ManualLogSource? log = Log;
				if (log != null)
				{
					log.LogInfo((object)"[Compatibility] Universal Harmony ambiguity resolver installed: auto-resolves overloaded methods for LevelScaling, Illagers, and all plugins.");
				}
			}
			catch (Exception ex)
			{
				ManualLogSource? log2 = Log;
				if (log2 != null)
				{
					log2.LogWarning((object)("[Compatibility] Note installing Harmony ambiguity resolver: " + ex.Message));
				}
			}
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "com.pbdde.repocompatibilitypatch";

		public const string PLUGIN_NAME = "REPO Compatibility Patch";

		public const string PLUGIN_VERSION = "1.1.2";
	}
	public static class HarmonyAmbiguityFix
	{
		public static bool MethodPrefix(Type type, string name, Type[]? parameters, Type[]? generics, ref MethodInfo __result)
		{
			if (type == null || name == null || parameters != null)
			{
				return true;
			}
			try
			{
				List<MethodInfo> list = (from m in type.GetMethods(AccessTools.allDeclared)
					where m.Name == name
					select m).ToList();
				if (list.Count > 1)
				{
					__result = list.OrderByDescending((MethodInfo m) => m.GetParameters().Length).First();
					return false;
				}
			}
			catch
			{
			}
			return true;
		}
	}
	public static class EngineOptimizer
	{
		private static int originalVSync = 1;

		private static int originalFrameRate = -1;

		private static bool restored = false;

		public static void ApplyLoadingOptimizations()
		{
			try
			{
				originalVSync = QualitySettings.vSyncCount;
				originalFrameRate = Application.targetFrameRate;
				QualitySettings.vSyncCount = 0;
				Application.targetFrameRate = 500;
				Application.backgroundLoadingPriority = (ThreadPriority)4;
				QualitySettings.asyncUploadTimeSlice = 16;
				QualitySettings.asyncUploadBufferSize = 64;
				QualitySettings.asyncUploadPersistentBuffer = true;
				ManualLogSource? log = Plugin.Log;
				if (log != null)
				{
					log.LogInfo((object)"[Performance] Engine asset loading pipeline accelerated (backgroundLoadingPriority=High, asyncUploadTimeSlice=16ms, asyncUploadBufferSize=64MB, uncapped loading framerate).");
				}
			}
			catch (Exception ex)
			{
				ManualLogSource? log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogWarning((object)("[Performance] Notice configuring engine parameters: " + ex.Message));
				}
			}
			try
			{
				Type type = AccessTools.TypeByName("REPOLib.BundleLoader");
				if (type != null)
				{
					AccessTools.Method(type, "add_OnAllBundlesLoaded", new Type[1] { typeof(Action) }, (Type[])null)?.Invoke(null, new object[1]
					{
						new Action(RestoreSettings)
					});
				}
			}
			catch
			{
			}
		}

		public static void RestoreSettings()
		{
			if (restored)
			{
				return;
			}
			restored = true;
			try
			{
				QualitySettings.vSyncCount = originalVSync;
				Application.targetFrameRate = originalFrameRate;
				ManualLogSource? log = Plugin.Log;
				if (log != null)
				{
					log.LogInfo((object)$"[Performance] Loading complete. Restored game VSync ({originalVSync}) and TargetFrameRate ({originalFrameRate}).");
				}
			}
			catch
			{
			}
		}
	}
	[HarmonyPatch(typeof(MenuPageMain), "Start")]
	public static class MainMenuReachedPatch
	{
		[HarmonyPostfix]
		public static void Postfix()
		{
			EngineOptimizer.RestoreSettings();
		}
	}
	[HarmonyPatch]
	public static class RepolibLogOptimizer
	{
		[HarmonyPrepare]
		public static bool Prepare()
		{
			return AccessTools.TypeByName("REPOLib.Logger") != null;
		}

		[HarmonyTargetMethod]
		public static MethodBase TargetMethod()
		{
			return AccessTools.Method("REPOLib.Logger:LogDebug", (Type[])null, (Type[])null);
		}

		[HarmonyPrefix]
		public static bool Prefix(object data)
		{
			if (data is string text && text.StartsWith("Fixed AudioMixerGroup"))
			{
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(AsyncInstantiateOperation), "SetIntegrationTimeMS")]
	public static class FastAsyncInstantiatePatch
	{
		[HarmonyPrefix]
		public static void Prefix(ref float integrationTimeMS)
		{
			if (integrationTimeMS < 16f)
			{
				integrationTimeMS = 16f;
			}
		}
	}
	[HarmonyPatch(typeof(LevelGenerator), "PrefabLoadCheck")]
	public static class PrefabLoadTimeoutFix
	{
		private static readonly FieldInfo? pauseField = AccessTools.Field(typeof(LevelGenerator), "prefabLoadPause");

		private static readonly MethodInfo? refreshMethod = AccessTools.Method("Photon.Pun.PhotonNetwork:IncomingMessagesPauseRefresh", (Type[])null, (Type[])null);

		[HarmonyPrefix]
		public static bool Prefix(LevelGenerator __instance)
		{
			try
			{
				if (pauseField != null && pauseField.GetValue(__instance) is IDisposable disposable)
				{
					refreshMethod?.Invoke(null, new object[1] { disposable });
				}
			}
			catch (Exception ex)
			{
				ManualLogSource? log = Plugin.Log;
				if (log != null)
				{
					log.LogDebug((object)("[PrefabLoadCheck] Refresh note: " + ex.Message));
				}
			}
			return false;
		}
	}
	[HarmonyPatch]
	public static class REPOLibValuableFixes
	{
		[HarmonyPrepare]
		public static bool Prepare()
		{
			return AccessTools.TypeByName("REPOLib.Modules.Valuables") != null;
		}

		[HarmonyTargetMethod]
		public static MethodBase TargetMethod()
		{
			return AccessTools.Method(AccessTools.TypeByName("REPOLib.Modules.Valuables"), "RegisterValuable", new Type[2]
			{
				typeof(ValuableObject),
				typeof(List<string>)
			}, (Type[])null);
		}

		[HarmonyPrefix]
		public static bool Prefix(ref ValuableObject? valuableObject, List<string> presetNames, ref object? __result)
		{
			if ((Object)(object)valuableObject == (Object)null)
			{
				__result = null;
				return false;
			}
			if ((Object)(object)((Component)valuableObject).gameObject != (Object)null)
			{
				string name = ((Object)((Component)valuableObject).gameObject).name;
				string key = "Valuables/" + name;
				try
				{
					Type type = AccessTools.TypeByName("REPOLib.Modules.NetworkPrefabs");
					if (type != null)
					{
						PropertyInfo propertyInfo = AccessTools.Property(type, "Prefabs");
						if (propertyInfo != null && propertyInfo.GetValue(null) is IReadOnlyDictionary<string, GameObject> readOnlyDictionary && readOnlyDictionary.TryGetValue(key, out var value) && (Object)(object)value != (Object)(object)((Component)valuableObject).gameObject)
						{
							string text = name + "_Alt";
							int num = 2;
							while (readOnlyDictionary.ContainsKey("Valuables/" + text))
							{
								text = $"{name}_Alt{num++}";
							}
							ManualLogSource? log = Plugin.Log;
							if (log != null)
							{
								log.LogInfo((object)("Resolved duplicate valuable prefab name: '" + name + "' -> '" + text + "'. Both valuables will now register successfully."));
							}
							((Object)((Component)valuableObject).gameObject).name = text;
						}
					}
				}
				catch (Exception ex)
				{
					ManualLogSource? log2 = Plugin.Log;
					if (log2 != null)
					{
						log2.LogDebug((object)("Notice in duplicate valuable check: " + ex.Message));
					}
				}
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(StatsManager), "LoadGame")]
	public static class SaveLoadSafetyPatch
	{
		[HarmonyPrefix]
		public static void Prefix(string fileName, List<string> backupList)
		{
			ManualLogSource? log = Plugin.Log;
			if (log != null)
			{
				log.LogInfo((object)$"[SafeLoad] Loading save game '{fileName}' with {backupList?.Count ?? 0} backup(s)...");
			}
		}

		[HarmonyFinalizer]
		public static Exception? Finalizer(Exception? __exception, string fileName)
		{
			if (__exception != null)
			{
				ManualLogSource? log = Plugin.Log;
				if (log != null)
				{
					log.LogError((object)("[SafeLoad] Recovered from exception during LoadGame for '" + fileName + "': " + __exception.Message));
				}
				try
				{
					if ((Object)(object)StatsManager.instance != (Object)null)
					{
						Traverse obj = Traverse.Create((object)StatsManager.instance).Field("saveFileReady");
						if (obj != null)
						{
							obj.SetValue((object)true);
						}
					}
				}
				catch
				{
				}
				return null;
			}
			return null;
		}
	}
	[HarmonyPatch(typeof(SteamLobbyManager), "HostLobby")]
	public static class LobbyHostDiagnosticPatch
	{
		[HarmonyPrefix]
		public static void Prefix(bool _open)
		{
			ManualLogSource? log = Plugin.Log;
			if (log != null)
			{
				log.LogInfo((object)$"[Lobby] HostLobby called (Private={!_open}). Ensuring clean network state.");
			}
		}
	}
}