Decompiled source of IKEASimulator Fixer v1.0.0

IKEASimulator_Fixer.dll

Decompiled 7 hours ago
using System;
using System.Collections;
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 BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using IKEASimulator_Fixer.Patches;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("")]
[assembly: AssemblyCompany("sasnews")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+0b87d15f3ef4e643400cec9f0e8e83de13e340b0")]
[assembly: AssemblyProduct("IKEASimulator_Fixer")]
[assembly: AssemblyTitle("IKEASimulator_Fixer")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[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.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]
	[Microsoft.CodeAnalysis.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]
	[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 IKEASimulator_Fixer
{
	[HarmonyPatch(typeof(PlayerController))]
	internal static class ExamplePlayerControllerPatch
	{
		[HarmonyPrefix]
		[HarmonyPatch("Start")]
		private static void Start_Prefix(PlayerController __instance)
		{
			IKEASimulator_Fixer.Logger.LogDebug((object)$"{__instance} Start Prefix");
		}

		[HarmonyPostfix]
		[HarmonyPatch("Start")]
		private static void Start_Postfix(PlayerController __instance)
		{
			IKEASimulator_Fixer.Logger.LogDebug((object)$"{__instance} Start Postfix");
		}
	}
	[BepInPlugin("sasnews.IKEASimulator_Fixer", "IKEASimulator_Fixer", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class IKEASimulator_Fixer : BaseUnityPlugin
	{
		public const string PluginGUID = "sasnews.IKEASimulator_Fixer";

		public const string PluginName = "IKEASimulator_Fixer";

		public const string PluginVersion = "1.0.0";

		private static bool _ikeaPatched;

		internal static IKEASimulator_Fixer Instance { get; private set; }

		internal static ManualLogSource Logger => Instance._logger;

		private ManualLogSource _logger => ((BaseUnityPlugin)this).Logger;

		internal Harmony? Harmony { get; private set; }

		public static ConfigEntry<bool> EnableImmediatePhysics { get; private set; }

		private void Awake()
		{
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Expected O, but got Unknown
			Instance = this;
			((Component)this).gameObject.transform.parent = null;
			((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
			EnableImmediatePhysics = ((BaseUnityPlugin)this).Config.Bind<bool>("Physics", "EnableImmediatePhysics", false, "true: オブジェクトがスポーン直後から落下する\nfalse: つかむまで固定される(デフォルト)");
			EnableImmediatePhysics.SettingChanged += OnImmediatePhysicsSettingChanged;
			Logger.LogInfo((object)"=================================================");
			Logger.LogInfo((object)"IKEASimulator_Fixer v1.0.0");
			Logger.LogInfo((object)"REPOLib 3.x Compatibility Patch");
			Logger.LogInfo((object)$"EnableImmediatePhysics: {EnableImmediatePhysics.Value}");
			Logger.LogInfo((object)"=================================================");
			Harmony = new Harmony("sasnews.IKEASimulator_Fixer");
			AppDomain.CurrentDomain.AssemblyLoad += OnAssemblyLoad;
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				if (assembly.GetName().Name == "IKEASimulator")
				{
					Logger.LogWarning((object)"IKEASimulator already loaded - attempting late patch");
					ApplyIKEAPatches(assembly);
					break;
				}
			}
			Logger.LogInfo((object)"Waiting for IKEASimulator to load...");
			Logger.LogInfo((object)"=================================================");
		}

		private void OnAssemblyLoad(object? sender, AssemblyLoadEventArgs args)
		{
			if (args.LoadedAssembly.GetName().Name == "IKEASimulator")
			{
				Logger.LogInfo((object)"=================================================");
				Logger.LogInfo((object)"→ IKEASimulator.dll detected loading!");
				Logger.LogInfo((object)"=================================================");
				ApplyIKEAPatches(args.LoadedAssembly);
			}
		}

		private void ApplyIKEAPatches(Assembly ikeaAssembly)
		{
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Expected O, but got Unknown
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Expected O, but got Unknown
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Expected O, but got Unknown
			if (_ikeaPatched)
			{
				Logger.LogInfo((object)"(Patches already applied)");
				return;
			}
			try
			{
				Type type = ikeaAssembly.GetType("IKEASimulator.IKEASimulator");
				if (type == null)
				{
					Logger.LogError((object)"Could not find IKEASimulator.IKEASimulator type!");
					return;
				}
				Logger.LogInfo((object)"Applying critical patches BEFORE Awake executes...");
				MethodInfo methodInfo = AccessTools.Method(type, "Awake", (Type[])null, (Type[])null);
				if (methodInfo != null)
				{
					HarmonyMethod val = new HarmonyMethod(typeof(IKEACriticalPatches), "Awake_Prefix", (Type[])null);
					Harmony.Patch((MethodBase)methodInfo, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					Logger.LogInfo((object)"  ✓ IKEASimulator.Awake → COMPLETE TAKEOVER");
				}
				else
				{
					Logger.LogError((object)"  ✗ Could not find Awake method!");
				}
				MethodInfo methodInfo2 = AccessTools.Method(type, "Start", (Type[])null, (Type[])null);
				if (methodInfo2 != null)
				{
					HarmonyMethod val2 = new HarmonyMethod(typeof(IKEACriticalPatches), "Start_Prefix", (Type[])null);
					Harmony.Patch((MethodBase)methodInfo2, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					Logger.LogInfo((object)"  ✓ IKEASimulator.Start → COMPLETE TAKEOVER");
				}
				MethodInfo methodInfo3 = AccessTools.Method(type, "Patch", (Type[])null, (Type[])null);
				if (methodInfo3 != null)
				{
					HarmonyMethod val3 = new HarmonyMethod(typeof(IKEACriticalPatches), "Patch_Prefix", (Type[])null);
					Harmony.Patch((MethodBase)methodInfo3, val3, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					Logger.LogInfo((object)"  ✓ IKEASimulator.Patch → BLOCKED (IL incompatible patches)");
				}
				ApplyNetworkManagerPatches(ikeaAssembly);
				ApplySafetyPatches();
				_ikeaPatched = true;
				Logger.LogInfo((object)"=================================================");
				Logger.LogInfo((object)"✓ All critical patches applied successfully!");
				Logger.LogInfo((object)"=================================================");
			}
			catch (Exception arg)
			{
				Logger.LogError((object)$"Failed to apply patches: {arg}");
			}
		}

		private void ApplyNetworkManagerPatches(Assembly ikeaAssembly)
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Expected O, but got Unknown
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Expected O, but got Unknown
			try
			{
				Type type = ikeaAssembly.GetType("IKEASimulator.NetworkManager");
				if (type == null)
				{
					Logger.LogWarning((object)"  NetworkManager type not found - skipping NM patches");
					return;
				}
				MethodInfo methodInfo = AccessTools.Method(type, "OnCreatedRoom", (Type[])null, (Type[])null);
				if (methodInfo != null)
				{
					HarmonyMethod val = new HarmonyMethod(typeof(NetworkManagerPatches), "OnCreatedRoom_Prefix", (Type[])null);
					Harmony.Patch((MethodBase)methodInfo, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					Logger.LogInfo((object)"  ✓ NetworkManager.OnCreatedRoom → Fixed");
				}
				MethodInfo methodInfo2 = AccessTools.Method(type, "SingleplayerRoomData", (Type[])null, (Type[])null);
				if (methodInfo2 != null)
				{
					HarmonyMethod val2 = new HarmonyMethod(typeof(NetworkManagerPatches), "SingleplayerRoomData_Prefix", (Type[])null);
					Harmony.Patch((MethodBase)methodInfo2, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					Logger.LogInfo((object)"  ✓ NetworkManager.SingleplayerRoomData → Fixed");
				}
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("  NetworkManager patches partially failed: " + ex.Message));
			}
		}

		private void ApplySafetyPatches()
		{
			try
			{
				ClientRoomDataPatches.ApplyPatches(Harmony);
				PathMapperPatches.ApplyPatches(Harmony);
				FurnitureConversionPatches.ApplyPatches(Harmony);
				DestructionSafetyPatches.ApplyPatches(Harmony);
				Harmony.CreateClassProcessor(typeof(ModuleSafetyPatch)).Patch();
				Logger.LogInfo((object)"  ✓ Module.Start safety finalizer");
				Harmony.CreateClassProcessor(typeof(LevelGeneratorSafetyPatch)).Patch();
				Logger.LogInfo((object)"  ✓ LevelGenerator.ModuleGeneration safety finalizer");
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("Safety patches partially failed: " + ex.Message));
			}
		}

		private void OnDestroy()
		{
			AppDomain.CurrentDomain.AssemblyLoad -= OnAssemblyLoad;
			EnableImmediatePhysics.SettingChanged -= OnImmediatePhysicsSettingChanged;
			Harmony? harmony = Harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		private void OnImmediatePhysicsSettingChanged(object? sender, EventArgs e)
		{
			if (!EnableImmediatePhysics.Value)
			{
				Logger.LogInfo((object)"EnableImmediatePhysics disabled - new objects will be fixed until grabbed");
				return;
			}
			Logger.LogInfo((object)"EnableImmediatePhysics enabled - enabling physics on all existing objects...");
			try
			{
				Type type = AccessTools.TypeByName("IKEASimulator.PropsParenting");
				if (type == null)
				{
					return;
				}
				FieldInfo fieldInfo = AccessTools.Field(type, "allowMovement");
				if (!(fieldInfo == null))
				{
					Object[] array = Object.FindObjectsOfType(type);
					int num = 0;
					Object[] array2 = array;
					foreach (Object obj in array2)
					{
						fieldInfo.SetValue(obj, true);
						num++;
					}
					Logger.LogInfo((object)$"  ✓ Enabled physics on {num} objects");
				}
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("Failed to enable physics on existing objects: " + ex.Message));
			}
		}
	}
}
namespace IKEASimulator_Fixer.Patches
{
	public static class ClientRoomDataPatches
	{
		private static ManualLogSource Logger => IKEASimulator_Fixer.Logger;

		public static void ApplyPatches(Harmony harmony)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Expected O, but got Unknown
			Type type = AccessTools.TypeByName("IKEASimulator.NetworkManager");
			if (type != null)
			{
				MethodInfo methodInfo = AccessTools.Method(type, "OnJoinedRoom", (Type[])null, (Type[])null);
				if (methodInfo != null)
				{
					harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(ClientRoomDataPatches), "OnJoinedRoom_Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					Logger.LogInfo((object)"    ✓ NetworkManager.OnJoinedRoom → Patched");
				}
			}
		}

		public static void OnJoinedRoom_Postfix(object __instance)
		{
			try
			{
				Logger.LogInfo((object)"[ClientRoomData] Joined Room. Checking for RoomData...");
				MonoBehaviour val = (MonoBehaviour)((__instance is MonoBehaviour) ? __instance : null);
				if ((Object)(object)val == (Object)null)
				{
					return;
				}
				Type type = __instance.GetType();
				FieldInfo fieldInfo = AccessTools.Field(type, "roomData");
				object? obj = fieldInfo?.GetValue(__instance);
				GameObject val2 = (GameObject)((obj is GameObject) ? obj : null);
				if (!((Object)(object)val2 == (Object)null))
				{
					return;
				}
				Logger.LogInfo((object)"[ClientRoomData] RoomData missing on Client. Instantiating locally...");
				GameObject val3 = null;
				string prefabId = "managers/roomdata";
				val3 = IKEACriticalPatches.GetPrefab(prefabId);
				if ((Object)(object)val3 == (Object)null)
				{
					foreach (KeyValuePair<string, GameObject> prefab in IKEACriticalPatches.Prefabs)
					{
						if (prefab.Key.ToLower().Contains("roomdata"))
						{
							val3 = prefab.Value;
							break;
						}
					}
				}
				if ((Object)(object)val3 != (Object)null)
				{
					GameObject val4 = Object.Instantiate<GameObject>(val3);
					fieldInfo?.SetValue(__instance, val4);
					Logger.LogInfo((object)("[ClientRoomData] RoomData instantiated: " + ((Object)val4).name));
					Type type2 = AccessTools.TypeByName("IKEASimulator.PathMapper");
					if (type2 != null)
					{
						Component component = val4.GetComponent(type2);
						AccessTools.Property(type, "PathMapper")?.SetValue(__instance, component);
					}
				}
				else
				{
					Logger.LogError((object)"[ClientRoomData] Failed to find RoomData prefab!");
				}
			}
			catch (Exception arg)
			{
				Logger.LogError((object)$"OnJoinedRoom_Postfix error: {arg}");
			}
		}
	}
	public static class DestructionSafetyPatches
	{
		private static ManualLogSource Logger => IKEASimulator_Fixer.Logger;

		public static void ApplyPatches(Harmony harmony)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Expected O, but got Unknown
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Expected O, but got Unknown
			try
			{
				Type type = AccessTools.TypeByName("PhysGrabObjectImpactDetector");
				if (type != null)
				{
					MethodInfo methodInfo = AccessTools.Method(type, "BreakRPC", (Type[])null, (Type[])null);
					if (methodInfo != null)
					{
						harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(DestructionSafetyPatches), "BreakRPC_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
						Logger.LogInfo((object)"    ✓ PhysGrabObjectImpactDetector.BreakRPC → Patched (Safety Wrapper)");
					}
					MethodInfo methodInfo2 = AccessTools.Method(type, "DestroyObjectRPC", (Type[])null, (Type[])null);
					if (methodInfo2 != null)
					{
						harmony.Patch((MethodBase)methodInfo2, new HarmonyMethod(typeof(DestructionSafetyPatches), "DestroyObjectRPC_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
						Logger.LogInfo((object)"    ✓ PhysGrabObjectImpactDetector.DestroyObjectRPC → Patched (Safety Wrapper)");
					}
				}
			}
			catch (Exception arg)
			{
				Logger.LogError((object)$"DestructionSafetyPatches.ApplyPatches failed: {arg}");
			}
		}

		public static bool BreakRPC_Prefix(object __instance, PhotonMessageInfo _info)
		{
			try
			{
				Component val = (Component)((__instance is Component) ? __instance : null);
				if ((Object)(object)val == (Object)null)
				{
					Logger.LogWarning((object)"[Safety] BreakRPC skipped: instance is null or not a Component");
					return false;
				}
				if ((Object)(object)val.gameObject == (Object)null)
				{
					Logger.LogWarning((object)"[Safety] BreakRPC skipped: gameObject is null");
					return false;
				}
				return true;
			}
			catch (Exception ex)
			{
				Logger.LogError((object)("[Safety] BreakRPC_Prefix Error: " + ex.Message));
				return false;
			}
		}

		public static bool DestroyObjectRPC_Prefix(object __instance, PhotonMessageInfo _info)
		{
			try
			{
				Component val = (Component)((__instance is Component) ? __instance : null);
				if ((Object)(object)val == (Object)null)
				{
					Logger.LogWarning((object)"[Safety] DestroyObjectRPC skipped: instance is null or not a Component");
					return false;
				}
				if ((Object)(object)val.gameObject == (Object)null)
				{
					Logger.LogWarning((object)"[Safety] DestroyObjectRPC skipped: gameObject is null");
					return false;
				}
				return true;
			}
			catch (Exception ex)
			{
				Logger.LogError((object)("[Safety] DestroyObjectRPC_Prefix Error: " + ex.Message));
				return false;
			}
		}
	}
	public static class FurnitureConversionPatches
	{
		[CompilerGenerated]
		private sealed class <EnableMovementAfterDelay>d__27 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public object propsParenting;

			public Type propsParentingType;

			private FieldInfo <allowMovementField>5__1;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <EnableMovementAfterDelay>d__27(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<allowMovementField>5__1 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0026: Unknown result type (might be due to invalid IL or missing references)
				//IL_0030: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForSeconds(2f);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					try
					{
						<allowMovementField>5__1 = AccessTools.Field(propsParentingType, "allowMovement");
						if (<allowMovementField>5__1 != null)
						{
							<allowMovementField>5__1.SetValue(propsParenting, true);
						}
						<allowMovementField>5__1 = null;
					}
					catch
					{
					}
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <RunPrefabSpawning>d__29 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public IEnumerator original;

			private List<Action> <spawnActions>5__1;

			private int <toSpawn>5__2;

			private object <pathMapper>5__3;

			private List<Action> <actionsToRun>5__4;

			private List<Action>.Enumerator <>s__5;

			private Action <action>5__6;

			private MethodInfo <clearMethod>5__7;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <RunPrefabSpawning>d__29(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				int num = <>1__state;
				if (num == -3 || num == 2)
				{
					try
					{
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<spawnActions>5__1 = null;
				<pathMapper>5__3 = null;
				<actionsToRun>5__4 = null;
				<>s__5 = default(List<Action>.Enumerator);
				<action>5__6 = null;
				<clearMethod>5__7 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				try
				{
					switch (<>1__state)
					{
					default:
						return false;
					case 0:
						<>1__state = -1;
						goto IL_005d;
					case 1:
						<>1__state = -1;
						goto IL_005d;
					case 2:
						{
							<>1__state = -3;
							<action>5__6 = null;
							goto IL_0156;
						}
						IL_005d:
						if (original.MoveNext())
						{
							<>2__current = original.Current;
							<>1__state = 1;
							return true;
						}
						<spawnActions>5__1 = GetSpawnActions();
						<toSpawn>5__2 = GetToSpawn();
						Logger.LogInfo((object)$"Furniture conversion: {<spawnActions>5__1?.Count ?? 0} actions, ToSpawn: {<toSpawn>5__2}");
						if (<spawnActions>5__1 == null || <spawnActions>5__1.Count <= 0)
						{
							break;
						}
						<actionsToRun>5__4 = new List<Action>(<spawnActions>5__1);
						<spawnActions>5__1.Clear();
						<>s__5 = <actionsToRun>5__4.GetEnumerator();
						<>1__state = -3;
						goto IL_0156;
						IL_0156:
						if (<>s__5.MoveNext())
						{
							<action>5__6 = <>s__5.Current;
							<action>5__6();
							<>2__current = null;
							<>1__state = 2;
							return true;
						}
						<>m__Finally1();
						<>s__5 = default(List<Action>.Enumerator);
						<actionsToRun>5__4 = null;
						break;
					}
					_spawnedField?.SetValue(null, 0);
					_toSpawnField?.SetValue(null, 0);
					<pathMapper>5__3 = GetPathMapper();
					if (<pathMapper>5__3 != null)
					{
						<clearMethod>5__7 = AccessTools.Method(<pathMapper>5__3.GetType(), "ClearAllPaths", (Type[])null, (Type[])null);
						<clearMethod>5__7?.Invoke(<pathMapper>5__3, null);
						<clearMethod>5__7 = null;
					}
					return false;
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			private void <>m__Finally1()
			{
				<>1__state = -1;
				((IDisposable)<>s__5).Dispose();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private static FieldInfo? _toSpawnField;

		private static FieldInfo? _spawnedField;

		private static FieldInfo? _spawnActionsField;

		private static FieldInfo? _furnitureLimitField;

		private static object? _cachedWrapper;

		private static bool _wrapperInitialized;

		private static ManualLogSource Logger => IKEASimulator_Fixer.Logger;

		public static void ApplyPatches(Harmony harmony)
		{
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Expected O, but got Unknown
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Expected O, but got Unknown
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Expected O, but got Unknown
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Expected O, but got Unknown
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: Expected O, but got Unknown
			try
			{
				Type type = AccessTools.TypeByName("IKEASimulator.IKEASimulator");
				if (type != null)
				{
					_toSpawnField = AccessTools.Field(type, "ToSpawn");
					_spawnedField = AccessTools.Field(type, "Spawned");
					_spawnActionsField = AccessTools.Field(type, "SpawnActions");
					_furnitureLimitField = AccessTools.Field(type, "FurnitureLimit");
					Logger.LogInfo((object)$"    IKEASimulator fields: ToSpawn={_toSpawnField != null}, SpawnActions={_spawnActionsField != null}");
				}
				Type type2 = AccessTools.TypeByName("Module");
				if (type2 != null)
				{
					MethodInfo methodInfo = AccessTools.Method(type2, "Start", (Type[])null, (Type[])null);
					if (methodInfo != null)
					{
						HarmonyMethod val = new HarmonyMethod(typeof(FurnitureConversionPatches), "ModuleStart_Prefix", (Type[])null);
						HarmonyMethod val2 = new HarmonyMethod(typeof(FurnitureConversionPatches), "ModuleStart_Postfix", (Type[])null);
						harmony.Patch((MethodBase)methodInfo, val, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
						Logger.LogInfo((object)"    ✓ Module.Start → Patched");
					}
				}
				Type type3 = AccessTools.TypeByName("LevelGenerator");
				if (type3 != null)
				{
					MethodInfo methodInfo2 = AccessTools.Method(type3, "ModuleGeneration", (Type[])null, (Type[])null);
					if (methodInfo2 != null)
					{
						HarmonyMethod val3 = new HarmonyMethod(typeof(FurnitureConversionPatches), "ModuleGeneration_Postfix", (Type[])null);
						harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, val3, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
						Logger.LogInfo((object)"    ✓ LevelGenerator.ModuleGeneration → Patched");
					}
				}
				Type type4 = AccessTools.TypeByName("PhysGrabObject");
				if (type4 != null)
				{
					MethodInfo methodInfo3 = AccessTools.Method(type4, "GrabStarted", (Type[])null, (Type[])null);
					if (methodInfo3 != null)
					{
						harmony.Patch((MethodBase)methodInfo3, (HarmonyMethod)null, new HarmonyMethod(typeof(FurnitureConversionPatches), "PhysGrabObject_GrabStarted_Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
						Logger.LogInfo((object)"    ✓ PhysGrabObject.GrabStarted → Patched");
					}
					MethodInfo methodInfo4 = AccessTools.Method(type4, "GrabStartedRPC", (Type[])null, (Type[])null);
					if (methodInfo4 != null)
					{
						harmony.Patch((MethodBase)methodInfo4, (HarmonyMethod)null, new HarmonyMethod(typeof(FurnitureConversionPatches), "PhysGrabObject_GrabStartedRPC_Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
						Logger.LogInfo((object)"    ✓ PhysGrabObject.GrabStartedRPC → Patched");
					}
				}
			}
			catch (Exception arg)
			{
				Logger.LogError((object)$"FurnitureConversionPatches.ApplyPatches failed: {arg}");
			}
		}

		private static int GetToSpawn()
		{
			if (_toSpawnField != null)
			{
				return (int)_toSpawnField.GetValue(null);
			}
			return 0;
		}

		private static void SetToSpawn(int value)
		{
			_toSpawnField?.SetValue(null, value);
		}

		private static void IncrementToSpawn()
		{
			if (_toSpawnField != null)
			{
				int num = (int)_toSpawnField.GetValue(null);
				_toSpawnField.SetValue(null, num + 1);
			}
		}

		private static List<Action>? GetSpawnActions()
		{
			if (_spawnActionsField != null)
			{
				return _spawnActionsField.GetValue(null) as List<Action>;
			}
			return null;
		}

		private static int GetFurnitureLimit()
		{
			if (_furnitureLimitField != null)
			{
				object value = _furnitureLimitField.GetValue(null);
				if (value != null)
				{
					PropertyInfo propertyInfo = AccessTools.Property(value.GetType(), "Value");
					if (propertyInfo != null)
					{
						return (int)(propertyInfo.GetValue(value) ?? ((object)(-1)));
					}
				}
			}
			return -1;
		}

		public static void PhysGrabObject_GrabStarted_Postfix(object __instance)
		{
			try
			{
				if (IsMultiplayer())
				{
					return;
				}
				Component val = (Component)((__instance is Component) ? __instance : null);
				if (!((Object)(object)val != (Object)null))
				{
					return;
				}
				Type type = AccessTools.TypeByName("IKEASimulator.PropsParenting");
				if (type != null)
				{
					Component component = val.gameObject.GetComponent(type);
					if ((Object)(object)component != (Object)null)
					{
						AccessTools.Method(type, "OnGrabStarted", (Type[])null, (Type[])null)?.Invoke(component, null);
					}
				}
			}
			catch
			{
			}
		}

		public static void PhysGrabObject_GrabStartedRPC_Postfix(object __instance)
		{
			try
			{
				Component val = (Component)((__instance is Component) ? __instance : null);
				if (!((Object)(object)val != (Object)null))
				{
					return;
				}
				Type type = AccessTools.TypeByName("IKEASimulator.PropsParenting");
				if (type != null)
				{
					Component component = val.gameObject.GetComponent(type);
					if ((Object)(object)component != (Object)null)
					{
						AccessTools.Method(type, "OnGrabStarted", (Type[])null, (Type[])null)?.Invoke(component, null);
					}
				}
			}
			catch
			{
			}
		}

		private static bool IsMasterClientOrSingleplayer()
		{
			try
			{
				Type type = AccessTools.TypeByName("SemiFunc");
				MethodInfo methodInfo = AccessTools.Method(type, "IsMasterClientOrSingleplayer", (Type[])null, (Type[])null);
				if (methodInfo != null)
				{
					return (bool)methodInfo.Invoke(null, null);
				}
			}
			catch
			{
			}
			return true;
		}

		private static bool RunIsLevel()
		{
			try
			{
				Type type = AccessTools.TypeByName("SemiFunc");
				MethodInfo methodInfo = AccessTools.Method(type, "RunIsLevel", (Type[])null, (Type[])null);
				if (methodInfo != null)
				{
					return (bool)methodInfo.Invoke(null, null);
				}
			}
			catch
			{
			}
			return false;
		}

		private static bool IsMultiplayer()
		{
			try
			{
				Type type = AccessTools.TypeByName("SemiFunc");
				MethodInfo methodInfo = AccessTools.Method(type, "IsMultiplayer", (Type[])null, (Type[])null);
				if (methodInfo != null)
				{
					return (bool)methodInfo.Invoke(null, null);
				}
			}
			catch
			{
			}
			return false;
		}

		private static object? GetWrapper()
		{
			if (_wrapperInitialized)
			{
				return _cachedWrapper;
			}
			_wrapperInitialized = true;
			try
			{
				GameObject prefab = IKEACriticalPatches.GetPrefab("FurnitureWrapper");
				if ((Object)(object)prefab != (Object)null)
				{
					Type type = AccessTools.TypeByName("ValuableObject");
					if (type != null)
					{
						_cachedWrapper = prefab.GetComponent(type);
						if (_cachedWrapper != null)
						{
							Logger.LogInfo((object)"    FurnitureWrapper obtained from cache");
							return _cachedWrapper;
						}
					}
				}
				Logger.LogWarning((object)"    FurnitureWrapper not found in cache");
			}
			catch (Exception ex)
			{
				Logger.LogError((object)("GetWrapper error: " + ex.Message));
			}
			return null;
		}

		private static object? GetNetworkManager()
		{
			return IKEACriticalPatches.CachedNetworkManager;
		}

		private static object? GetPathMapper()
		{
			object networkManager = GetNetworkManager();
			if (networkManager == null)
			{
				return null;
			}
			try
			{
				return AccessTools.Property(networkManager.GetType(), "PathMapper")?.GetValue(networkManager);
			}
			catch
			{
			}
			return null;
		}

		public static void ModuleStart_Prefix(object __instance)
		{
			try
			{
				bool flag = IsMasterClientOrSingleplayer();
				bool flag2 = RunIsLevel();
				MonoBehaviour val = (MonoBehaviour)((__instance is MonoBehaviour) ? __instance : null);
				string text = ((val != null) ? ((Object)val).name : null) ?? "unknown";
				if ((Object)(object)val != (Object)null)
				{
					string text2 = ((Object)val).name;
					Transform parent = ((Component)val).transform.parent;
					while ((Object)(object)parent != (Object)null)
					{
						text2 = ((Object)parent).name + "/" + text2;
						parent = parent.parent;
					}
					Logger.LogInfo((object)("[Prefix] Module: " + text + ", FullPath: " + text2));
					if (!flag && flag2 && (Object)(object)((Component)val).transform.parent == (Object)null)
					{
						GameObject val2 = GameObject.Find("Level Generator");
						if ((Object)(object)val2 != (Object)null)
						{
							Transform val3 = val2.transform.Find("Level");
							if ((Object)(object)val3 != (Object)null)
							{
								((Component)val).transform.SetParent(val3, true);
								Logger.LogInfo((object)("  [Fix] Reparented " + text + " to Level Generator/Level"));
							}
						}
					}
				}
				Logger.LogInfo((object)$"[Prefix] Module: {text}, IsMaster: {flag}, RunIsLevel: {flag2}");
				if (!flag2 || (Object)(object)val == (Object)null)
				{
					return;
				}
				if (!IsMultiplayer())
				{
					object networkManager = GetNetworkManager();
					if (networkManager != null)
					{
						AccessTools.Method(networkManager.GetType(), "SingleplayerRoomData", (Type[])null, (Type[])null)?.Invoke(networkManager, null);
					}
				}
				Type type = AccessTools.TypeByName("IKEASimulator.PropSwitchContext");
				if (type == null)
				{
					return;
				}
				Component val4 = ((Component)val).gameObject.AddComponent(type);
				if ((Object)(object)val4 == (Object)null)
				{
					return;
				}
				AccessTools.Field(type, "ModuleName")?.SetValue(val4, ((Object)val).name);
				if (!flag)
				{
					return;
				}
				object pathMapper = GetPathMapper();
				if (pathMapper != null)
				{
					MethodInfo methodInfo = AccessTools.Method(pathMapper.GetType(), "MapPath", (Type[])null, (Type[])null);
					if (methodInfo != null)
					{
						object value = methodInfo.Invoke(pathMapper, new object[1] { ((Object)val).name });
						AccessTools.Field(type, "PathId")?.SetValue(val4, value);
					}
				}
				else
				{
					object networkManager2 = GetNetworkManager();
					Logger.LogWarning((object)("  [Prefix] PathMapper is null! NetworkManager: " + ((networkManager2 != null) ? "found" : "NULL")));
				}
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("ModuleStart_Prefix error: " + ex.Message));
			}
		}

		public static void ModuleStart_Postfix(object __instance)
		{
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_0220: Expected O, but got Unknown
			//IL_02b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02be: Expected O, but got Unknown
			//IL_0380: Unknown result type (might be due to invalid IL or missing references)
			//IL_0387: Expected O, but got Unknown
			//IL_03f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0403: Unknown result type (might be due to invalid IL or missing references)
			//IL_0408: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				bool flag = IsMasterClientOrSingleplayer();
				bool flag2 = RunIsLevel();
				MonoBehaviour val = (MonoBehaviour)((__instance is MonoBehaviour) ? __instance : null);
				string arg = ((val != null) ? ((Object)val).name : null) ?? "unknown";
				Logger.LogInfo((object)$"[Postfix] Module: {arg}, IsMaster: {flag}, RunIsLevel: {flag2}");
				if (!flag2 || (Object)(object)val == (Object)null)
				{
					return;
				}
				object wrapper = GetWrapper();
				if (wrapper == null)
				{
					Logger.LogWarning((object)"FurnitureWrapper not found");
					return;
				}
				Type type = AccessTools.TypeByName("IKEASimulator.PropSwitchContext");
				if (type == null)
				{
					Logger.LogWarning((object)"PropSwitchContext type not found");
					return;
				}
				Component component = ((Component)val).gameObject.GetComponent(type);
				if ((Object)(object)component == (Object)null)
				{
					Logger.LogWarning((object)("PropSwitchContext not found on " + ((Object)val).name));
					return;
				}
				FieldInfo fieldInfo = AccessTools.Field(type, "ModuleName");
				FieldInfo fieldInfo2 = AccessTools.Field(type, "PathId");
				string text = fieldInfo?.GetValue(component) as string;
				int? num = fieldInfo2?.GetValue(component) as int?;
				if (text == null)
				{
					Logger.LogWarning((object)"  ModuleName is null, skipping");
					return;
				}
				if (flag && !num.HasValue)
				{
					Logger.LogWarning((object)"  PathId is null on Master, skipping spawn");
					return;
				}
				Type type2 = AccessTools.TypeByName("IKEASimulator.PropUtils");
				if (type2 != null)
				{
					AccessTools.Field(type2, "ModuleName")?.SetValue(null, text);
					AccessTools.Field(type2, "PathId")?.SetValue(null, num);
				}
				Transform val2 = null;
				foreach (Transform item in ((Component)val).transform)
				{
					Transform val3 = item;
					if (((Object)val3).name.Contains(" Props ") && ((Object)val3).name.StartsWith("-") && ((Object)val3).name.EndsWith("-"))
					{
						val2 = val3;
						break;
					}
				}
				if ((Object)(object)val2 == (Object)null)
				{
					return;
				}
				Transform val4 = null;
				foreach (Transform item2 in val2)
				{
					Transform val5 = item2;
					if (((Object)val5).name == "Props")
					{
						val4 = val5;
						break;
					}
				}
				if ((Object)(object)val4 == (Object)null)
				{
					return;
				}
				int furnitureLimit = GetFurnitureLimit();
				int num2 = 0;
				List<Action> list = null;
				if (flag)
				{
					list = GetSpawnActions();
					if (list == null)
					{
						return;
					}
				}
				GameObject wrapperPrefab = IKEACriticalPatches.GetPrefab("FurnitureWrapper");
				if ((Object)(object)wrapperPrefab == (Object)null)
				{
					return;
				}
				foreach (Transform item3 in val4)
				{
					Transform val6 = item3;
					if (furnitureLimit != -1 && GetToSpawn() >= furnitureLimit)
					{
						break;
					}
					if (!HasValidCollider(val6) || !HasMeshRenderer(val6))
					{
						continue;
					}
					IncrementToSpawn();
					num2++;
					string propName = ((Object)val6).name;
					Vector3 position = val6.position;
					Quaternion rotation = val6.rotation;
					if (!flag || !num.HasValue)
					{
						continue;
					}
					int capturedPathId = num.Value;
					list?.Add(delegate
					{
						//IL_0018: Unknown result type (might be due to invalid IL or missing references)
						//IL_0023: Unknown result type (might be due to invalid IL or missing references)
						try
						{
							SpawnFurnitureWrapper(wrapperPrefab, position, rotation, capturedPathId, propName);
						}
						catch (Exception ex2)
						{
							Logger.LogWarning((object)("Spawn error for " + propName + ": " + ex2.Message));
						}
					});
				}
				if (num2 > 0)
				{
					Logger.LogInfo((object)$"Found {num2} Props in {text} (Disabled)");
				}
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("ModuleStart_Postfix error: " + ex.Message));
			}
		}

		private static bool HasValidCollider(Transform transform)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Expected O, but got Unknown
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Expected O, but got Unknown
			MeshCollider component = ((Component)transform).GetComponent<MeshCollider>();
			if ((Object)(object)component != (Object)null && !component.convex)
			{
				return false;
			}
			foreach (Transform item in transform)
			{
				Transform val = item;
				MeshCollider component2 = ((Component)val).GetComponent<MeshCollider>();
				if ((Object)(object)component2 != (Object)null && !component2.convex)
				{
					return false;
				}
			}
			if ((Object)(object)((Component)transform).GetComponent<BoxCollider>() != (Object)null || (Object)(object)((Component)transform).GetComponent<SphereCollider>() != (Object)null || (Object)(object)((Component)transform).GetComponent<CapsuleCollider>() != (Object)null)
			{
				if (transform.childCount <= 0)
				{
					return true;
				}
				foreach (Transform item2 in transform)
				{
					Transform transform2 = item2;
					if (HasValidCollider(transform2))
					{
						return true;
					}
				}
			}
			foreach (Transform item3 in transform)
			{
				Transform transform3 = item3;
				if (HasValidCollider(transform3))
				{
					return true;
				}
			}
			return false;
		}

		private static bool HasMeshRenderer(Transform transform)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			if ((Object)(object)((Component)transform).GetComponent<MeshRenderer>() != (Object)null)
			{
				return true;
			}
			foreach (Transform item in transform)
			{
				Transform transform2 = item;
				if (HasMeshRenderer(transform2))
				{
					return true;
				}
			}
			return false;
		}

		private static void SpawnFurnitureWrapper(GameObject prefab, Vector3 position, Quaternion rotation, int pathId, string propName)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: 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_001d: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				GameObject val = IKEACriticalPatches.SpawnPrefab("furniturewrapper", position, rotation);
				if ((Object)(object)val == (Object)null)
				{
					val = Object.Instantiate<GameObject>(prefab, position, rotation);
					Logger.LogDebug((object)"  FurnitureWrapper spawned via direct Instantiate (fallback)");
				}
				if (!((Object)(object)val != (Object)null))
				{
					return;
				}
				Type type = AccessTools.TypeByName("IKEASimulator.PropsParenting");
				if (type != null)
				{
					Component component = val.GetComponent(type);
					if ((Object)(object)component != (Object)null)
					{
						Type type2 = AccessTools.TypeByName("Photon.Pun.PhotonView");
						Component val2 = ((type2 != null) ? val.GetComponent(type2) : null);
						bool flag = false;
						if ((Object)(object)val2 != (Object)null && IsMultiplayer())
						{
							MethodInfo methodInfo = AccessTools.Method(type2, "RPC", new Type[3]
							{
								typeof(string),
								typeof(RpcTarget),
								typeof(object[])
							}, (Type[])null);
							if (methodInfo != null)
							{
								methodInfo.Invoke(val2, new object[3]
								{
									"SetPropPathRPC",
									(object)(RpcTarget)0,
									new object[2] { pathId, propName }
								});
								flag = true;
								Logger.LogInfo((object)("    [Spawn] Sent SetPropPathRPC(All) for " + propName));
							}
						}
						if (!flag)
						{
							MethodInfo methodInfo2 = AccessTools.Method(type, "SetPropPathRPC", (Type[])null, (Type[])null);
							if (methodInfo2 != null)
							{
								methodInfo2.Invoke(component, new object[2] { pathId, propName });
								Logger.LogDebug((object)("    [Spawn] Invoked SetPropPathRPC (Direct) for " + propName));
							}
						}
						if (IKEASimulator_Fixer.EnableImmediatePhysics.Value)
						{
							MonoBehaviour val3 = (MonoBehaviour)(object)((component is MonoBehaviour) ? component : null);
							if ((Object)(object)val3 != (Object)null)
							{
								val3.StartCoroutine(EnableMovementAfterDelay(component, type));
							}
						}
					}
				}
				if (_spawnedField != null)
				{
					int num = (int)_spawnedField.GetValue(null);
					_spawnedField.SetValue(null, num + 1);
				}
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("SpawnFurnitureWrapper error: " + ex.Message));
			}
		}

		[IteratorStateMachine(typeof(<EnableMovementAfterDelay>d__27))]
		private static IEnumerator EnableMovementAfterDelay(object propsParenting, Type propsParentingType)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <EnableMovementAfterDelay>d__27(0)
			{
				propsParenting = propsParenting,
				propsParentingType = propsParentingType
			};
		}

		public static void ModuleGeneration_Postfix(object __instance, ref IEnumerator __result)
		{
			__result = RunPrefabSpawning(__result);
		}

		[IteratorStateMachine(typeof(<RunPrefabSpawning>d__29))]
		private static IEnumerator RunPrefabSpawning(IEnumerator original)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <RunPrefabSpawning>d__29(0)
			{
				original = original
			};
		}
	}
	public static class PathMapperPatches
	{
		public const byte MapPathEventCode = 142;

		private static ManualLogSource Logger => IKEASimulator_Fixer.Logger;

		public static void ApplyPatches(Harmony harmony)
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Expected O, but got Unknown
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Expected O, but got Unknown
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Expected O, but got Unknown
			try
			{
				Type type = AccessTools.TypeByName("IKEASimulator.PathMapper");
				if (type == null)
				{
					Logger.LogWarning((object)"    ✗ PathMapper type not found");
					return;
				}
				MethodInfo methodInfo = AccessTools.Method(type, "Start", (Type[])null, (Type[])null);
				if (methodInfo != null)
				{
					harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(PathMapperPatches), "Start_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					Logger.LogInfo((object)"    ✓ PathMapper.Start → Patched (Event Register)");
				}
				MethodInfo methodInfo2 = AccessTools.Method(type, "OnDestroy", (Type[])null, (Type[])null);
				if (methodInfo2 != null)
				{
					harmony.Patch((MethodBase)methodInfo2, new HarmonyMethod(typeof(PathMapperPatches), "OnDestroy_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					Logger.LogInfo((object)"    ✓ PathMapper.OnDestroy → Patched");
				}
				MethodInfo methodInfo3 = AccessTools.Method(type, "MapPath", (Type[])null, (Type[])null);
				if (methodInfo3 != null)
				{
					harmony.Patch((MethodBase)methodInfo3, new HarmonyMethod(typeof(PathMapperPatches), "MapPath_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					Logger.LogInfo((object)"    ✓ PathMapper.MapPath → Patched (Event Raise)");
				}
			}
			catch (Exception arg)
			{
				Logger.LogError((object)$"PathMapperPatches.ApplyPatches failed: {arg}");
			}
		}

		public static bool MapPath_Prefix(object __instance, string path, ref int __result)
		{
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Expected O, but got Unknown
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Type type = __instance.GetType();
				FieldInfo fieldInfo = AccessTools.Field(type, "nextPathId");
				FieldInfo fieldInfo2 = AccessTools.Field(type, "pathMap");
				if (fieldInfo == null || fieldInfo2 == null)
				{
					return true;
				}
				int num = (int)fieldInfo.GetValue(__instance);
				if (fieldInfo2.GetValue(__instance) is IDictionary dictionary)
				{
					dictionary[num] = path;
					Logger.LogDebug((object)$"[PathMapper.MapPath] Added: {num} → {path}");
					if (PhotonNetwork.InRoom)
					{
						object[] array = new object[2] { num, path };
						RaiseEventOptions val = new RaiseEventOptions
						{
							Receivers = (ReceiverGroup)0,
							CachingOption = (EventCaching)4
						};
						PhotonNetwork.RaiseEvent((byte)142, (object)array, val, SendOptions.SendReliable);
					}
				}
				fieldInfo.SetValue(__instance, num + 1);
				__result = num;
				return false;
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("[PathMapper.MapPath] Error: " + ex.Message));
				return true;
			}
		}

		public static bool Start_Prefix(object __instance)
		{
			try
			{
				PhotonNetwork.NetworkingClient.EventReceived += OnEvent;
				object cachedNetworkManager = IKEACriticalPatches.CachedNetworkManager;
				if (cachedNetworkManager == null)
				{
					return false;
				}
				PropertyInfo propertyInfo = AccessTools.Property(cachedNetworkManager.GetType(), "PathMapper");
				if (propertyInfo != null)
				{
					propertyInfo.SetValue(cachedNetworkManager, __instance);
					Logger.LogInfo((object)"    [PathMapper] Configured NetworkManager.PathMapper reference");
				}
				else
				{
					Logger.LogWarning((object)"    [PathMapper] Could not find PathMapper property on NetworkManager!");
				}
				Component val = (Component)((__instance is Component) ? __instance : null);
				if ((Object)(object)val == (Object)null)
				{
					return false;
				}
				MethodInfo methodInfo = AccessTools.Method(cachedNetworkManager.GetType(), "SetRoomData", (Type[])null, (Type[])null);
				if (methodInfo != null)
				{
					methodInfo.Invoke(cachedNetworkManager, new object[1] { val.gameObject });
				}
				Object.DontDestroyOnLoad((Object)(object)val.gameObject);
				return false;
			}
			catch (Exception)
			{
				return false;
			}
		}

		public static bool OnDestroy_Prefix()
		{
			try
			{
				PhotonNetwork.NetworkingClient.EventReceived -= OnEvent;
				return false;
			}
			catch
			{
				return false;
			}
		}

		private static void OnEvent(EventData photonEvent)
		{
			if (photonEvent.Code != 142)
			{
				return;
			}
			try
			{
				object[] array = (object[])photonEvent.CustomData;
				int num = (int)array[0];
				string value = (string)array[1];
				object cachedNetworkManager = IKEACriticalPatches.CachedNetworkManager;
				if (cachedNetworkManager != null)
				{
					object obj = AccessTools.Property(cachedNetworkManager.GetType(), "PathMapper")?.GetValue(cachedNetworkManager);
					if (obj != null && AccessTools.Field(obj.GetType(), "pathMap")?.GetValue(obj) is IDictionary dictionary)
					{
						dictionary[num] = value;
					}
				}
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("OnEvent error: " + ex.Message));
			}
		}
	}
	[HarmonyPatch(typeof(Harmony), "PatchAll", new Type[] { typeof(Assembly) })]
	internal static class HarmonyPatchAllFinalizer
	{
		private static bool _patchesApplied;

		[HarmonyPrefix]
		private static bool Prefix(Harmony __instance, Assembly assembly)
		{
			if (assembly == null)
			{
				return true;
			}
			string text = assembly.GetName().Name ?? "";
			if (text == "IKEASimulator" || text.Contains("IKEASimulator"))
			{
				IKEASimulator_Fixer.Logger.LogInfo((object)"=================================================");
				IKEASimulator_Fixer.Logger.LogInfo((object)"→ Intercepted IKEASimulator Harmony.PatchAll()");
				IKEASimulator_Fixer.Logger.LogInfo((object)"  SKIPPING all IKEASimulator patches (IL incompatible)");
				if (!_patchesApplied)
				{
					IKEASimulator_Fixer.Logger.LogInfo((object)"  Applying REPOLib 3.x compatible patches...");
					try
					{
						IKEASimulator_Fixer.Logger.LogInfo((object)"  ✓ Patches handled by Fixer!");
						_patchesApplied = true;
					}
					catch (Exception ex)
					{
						IKEASimulator_Fixer.Logger.LogError((object)("  ✗ Failed to apply patches: " + ex.Message));
						IKEASimulator_Fixer.Logger.LogDebug((object)ex.ToString());
					}
				}
				else
				{
					IKEASimulator_Fixer.Logger.LogInfo((object)"  (Patches already applied)");
				}
				IKEASimulator_Fixer.Logger.LogInfo((object)"=================================================");
				return false;
			}
			return true;
		}

		[HarmonyFinalizer]
		private static Exception? Finalizer(Exception? __exception, Harmony __instance, Assembly assembly)
		{
			if (__exception != null)
			{
				string text = assembly?.GetName().Name ?? "unknown";
				if (text.Contains("IKEASimulator"))
				{
					IKEASimulator_Fixer.Logger.LogWarning((object)"=================================================");
					IKEASimulator_Fixer.Logger.LogWarning((object)"⊗ Suppressed Harmony.PatchAll() error from IKEASimulator");
					IKEASimulator_Fixer.Logger.LogInfo((object)("  → Error: " + __exception.Message));
					IKEASimulator_Fixer.Logger.LogWarning((object)"=================================================");
					return null;
				}
			}
			return __exception;
		}
	}
	public static class IKEACriticalPatches
	{
		private static ManualLogSource Logger => IKEASimulator_Fixer.Logger;

		public static AssetBundle? LoadedBundle { get; private set; }

		public static Dictionary<string, GameObject> Prefabs { get; } = new Dictionary<string, GameObject>(StringComparer.OrdinalIgnoreCase);


		public static Dictionary<string, object> PrefabRefs { get; } = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);


		public static object? IKEAInstance { get; private set; }

		public static bool Initialized { get; private set; }

		public static object? CachedNetworkManager { get; private set; }

		public static GameObject? ManagerInstance { get; private set; }

		public static bool Awake_Prefix(object __instance)
		{
			try
			{
				Logger.LogInfo((object)"=== IKEASimulator Fixer: Awake Override ===");
				IKEAInstance = __instance;
				Type type = __instance.GetType();
				PropertyInfo propertyInfo = AccessTools.Property(type, "Instance");
				if (propertyInfo != null && propertyInfo.GetSetMethod(nonPublic: true) != null)
				{
					propertyInfo.SetValue(null, __instance);
					Logger.LogInfo((object)"  ✓ IKEASimulator.Instance set");
				}
				else
				{
					FieldInfo fieldInfo = AccessTools.Field(type, "<Instance>k__BackingField");
					if (fieldInfo != null)
					{
						fieldInfo.SetValue(null, __instance);
						Logger.LogInfo((object)"  ✓ IKEASimulator.Instance set (via backing field)");
					}
				}
				ConfigureLogging(__instance);
				LoadAssetBundleSafe(__instance);
				if ((Object)(object)LoadedBundle != (Object)null)
				{
					RegisterAllResources();
				}
				SetInstanceFields(__instance);
				Initialized = true;
				Logger.LogInfo((object)"=== Awake Override Complete ===");
				return false;
			}
			catch (Exception arg)
			{
				Logger.LogError((object)$"Awake_Prefix error: {arg}");
				return false;
			}
		}

		public static bool Start_Prefix(object __instance)
		{
			try
			{
				Logger.LogInfo((object)"=== IKEASimulator Fixer: Start Override ===");
				Component val = (Component)((__instance is Component) ? __instance : null);
				if ((Object)(object)val == (Object)null)
				{
					Logger.LogError((object)"  Instance is not a Component!");
					return false;
				}
				string prefabId = "managers/ikeasimulatormanager";
				GameObject prefab = GetPrefab(prefabId);
				if ((Object)(object)prefab == (Object)null)
				{
					foreach (KeyValuePair<string, GameObject> prefab2 in Prefabs)
					{
						if (prefab2.Key.Contains("manager") || prefab2.Key.Contains("ikeasimulator"))
						{
							Logger.LogDebug((object)("    Available prefab: " + prefab2.Key));
						}
					}
					Logger.LogWarning((object)"  IKEASimulatorManager prefab not found in cache");
					Logger.LogWarning((object)"  NetworkManager will not be initialized - some features may not work");
					return false;
				}
				GameObject val2 = Object.Instantiate<GameObject>(prefab, val.transform);
				if ((Object)(object)val2 != (Object)null)
				{
					ManagerInstance = val2;
					Type type = AccessTools.TypeByName("IKEASimulator.NetworkManager");
					if (type != null)
					{
						Component val3 = (Component)(CachedNetworkManager = val2.GetComponent(type));
						Type type2 = __instance.GetType();
						FieldInfo fieldInfo = AccessTools.Field(type2, "networkManager");
						if (fieldInfo != null && (Object)(object)val3 != (Object)null)
						{
							fieldInfo.SetValue(__instance, val3);
							Logger.LogInfo((object)"  ✓ NetworkManager component obtained and cached");
						}
						else
						{
							Logger.LogWarning((object)$"  NetworkManager setup: nmField={fieldInfo != null}, nmComponent={(Object)(object)val3 != (Object)null}");
						}
					}
					val2.transform.parent = null;
					((Object)val2).hideFlags = (HideFlags)61;
					Object.DontDestroyOnLoad((Object)(object)val2);
					Logger.LogInfo((object)"  ✓ IKEASimulatorManager instantiated locally");
				}
				Logger.LogInfo((object)"Initializing IKEASimulator Mod (via Fixer)");
				Logger.LogInfo((object)"=== Start Override Complete ===");
				return false;
			}
			catch (Exception arg)
			{
				Logger.LogError((object)$"Start_Prefix error: {arg}");
				return false;
			}
		}

		public static bool Patch_Prefix()
		{
			Logger.LogInfo((object)"  → Skipping IKEASimulator.Patch() (IL incompatible with REPOLib 3.x)");
			return false;
		}

		private static void ConfigureLogging(object instance)
		{
			try
			{
				Logger.LogInfo((object)"  ✓ Logging configured via BepInEx");
			}
			catch (Exception ex)
			{
				Logger.LogDebug((object)("ConfigureLogging: " + ex.Message));
			}
		}

		private static void LoadAssetBundleSafe(object instance)
		{
			try
			{
				BaseUnityPlugin val = (BaseUnityPlugin)((instance is BaseUnityPlugin) ? instance : null);
				if ((Object)(object)val == (Object)null)
				{
					return;
				}
				string location = val.Info.Location;
				string path = Path.GetDirectoryName(location) ?? "";
				string text = Path.Combine(path, "IKEASimulator.bundle");
				Logger.LogInfo((object)("  Loading bundle: " + text));
				if (!File.Exists(text))
				{
					Logger.LogError((object)"  ✗ Bundle file not found!");
					return;
				}
				if ((Object)(object)LoadedBundle != (Object)null)
				{
					Logger.LogInfo((object)"  Bundle already loaded");
					return;
				}
				LoadedBundle = AssetBundle.LoadFromFile(text);
				if ((Object)(object)LoadedBundle != (Object)null)
				{
					Logger.LogInfo((object)"  ✓ AssetBundle loaded successfully");
				}
				else
				{
					Logger.LogError((object)"  ✗ AssetBundle.LoadFromFile returned null");
				}
			}
			catch (Exception arg)
			{
				Logger.LogError((object)$"LoadAssetBundleSafe error: {arg}");
			}
		}

		private static void RegisterAllResources()
		{
			Logger.LogInfo((object)"  Registering resources with REPOLib 3.x...");
			Type type = AccessTools.TypeByName("REPOLib.Modules.NetworkPrefabs");
			Type type2 = AccessTools.TypeByName("REPOLib.Modules.Valuables");
			MethodInfo methodInfo = ((type != null) ? AccessTools.Method(type, "RegisterNetworkPrefab", new Type[2]
			{
				typeof(string),
				typeof(GameObject)
			}, (Type[])null) : null);
			MethodInfo methodInfo2 = ((type2 != null) ? AccessTools.Method(type2, "RegisterValuable", new Type[1] { typeof(GameObject) }, (Type[])null) : null);
			Logger.LogInfo((object)"    REPOLib API:");
			Logger.LogInfo((object)("      NetworkPrefabs.RegisterNetworkPrefab: " + ((methodInfo != null) ? "✓" : "✗")));
			Logger.LogInfo((object)("      Valuables.RegisterValuable: " + ((methodInfo2 != null) ? "✓" : "✗")));
			if ((Object)(object)LoadedBundle == (Object)null)
			{
				return;
			}
			string[] allAssetNames = LoadedBundle.GetAllAssetNames();
			foreach (string text in allAssetNames)
			{
				if (text.EndsWith(".prefab"))
				{
					GameObject val = LoadedBundle.LoadAsset<GameObject>(text);
					if ((Object)(object)val != (Object)null && (text.Contains("/valuables/") || text.Contains("/assets/")) && !text.ToLowerInvariant().Contains("manager") && !text.ToLowerInvariant().Contains("roomdata"))
					{
						OptimizeNetworkPrefab(val, text);
					}
				}
			}
			string[] allAssetNames2 = LoadedBundle.GetAllAssetNames();
			int num = 0;
			int num2 = 0;
			string[] array = allAssetNames2;
			foreach (string text2 in array)
			{
				try
				{
					if (!text2.EndsWith(".prefab"))
					{
						continue;
					}
					GameObject val2 = LoadedBundle.LoadAsset<GameObject>(text2);
					if ((Object)(object)val2 == (Object)null)
					{
						continue;
					}
					string text3 = ExtractPrefabId(text2);
					if (text2.Contains("/assets/") && methodInfo != null)
					{
						try
						{
							object obj = methodInfo.Invoke(null, new object[2] { text3, val2 });
							Prefabs[text3] = val2;
							if (obj != null)
							{
								PrefabRefs[text3] = obj;
								num++;
							}
						}
						catch (TargetInvocationException ex)
						{
							Logger.LogDebug((object)("      " + text3 + ": " + ex.InnerException?.Message));
							Prefabs[text3] = val2;
						}
					}
					else
					{
						if (!text2.Contains("/valuables/") || !(methodInfo2 != null))
						{
							continue;
						}
						try
						{
							methodInfo2.Invoke(null, new object[1] { val2 });
							num2++;
							string text4 = ((Object)val2).name.ToLowerInvariant();
							Prefabs[text4] = val2;
							if (!(text4 == "furniturewrapper") || !(methodInfo != null))
							{
								continue;
							}
							try
							{
								object obj2 = methodInfo.Invoke(null, new object[2] { text4, val2 });
								if (obj2 != null)
								{
									PrefabRefs[text4] = obj2;
									Logger.LogInfo((object)("      Cached valuable as NetworkPrefab: " + text4));
								}
							}
							catch (Exception ex2)
							{
								Logger.LogDebug((object)("      FurnitureWrapper NetworkPrefab registration: " + ex2.Message));
							}
						}
						catch (TargetInvocationException ex3)
						{
							Logger.LogDebug((object)("      Valuable " + ((Object)val2).name + ": " + ex3.InnerException?.Message));
						}
						continue;
					}
				}
				catch (Exception ex4)
				{
					Logger.LogDebug((object)("      Error processing " + text2 + ": " + ex4.Message));
				}
			}
			Logger.LogInfo((object)"    Registration results:");
			Logger.LogInfo((object)$"      Network Prefabs: {num} registered, {Prefabs.Count} cached");
			Logger.LogInfo((object)$"      Valuables: {num2}");
		}

		private static string ExtractPrefabId(string assetPath)
		{
			int num = assetPath.IndexOf("/assets/", StringComparison.OrdinalIgnoreCase);
			if (num >= 0 && num + 8 < assetPath.Length)
			{
				string text = assetPath.Substring(num + 8);
				return text.Replace(".prefab", "");
			}
			return Path.GetFileNameWithoutExtension(assetPath);
		}

		private static void SetInstanceFields(object instance)
		{
			try
			{
				Type type = instance.GetType();
				FieldInfo fieldInfo = AccessTools.Field(type, "assetBundle");
				if (fieldInfo != null)
				{
					fieldInfo.SetValue(instance, LoadedBundle);
				}
				FieldInfo fieldInfo2 = AccessTools.Field(type, "prefabs");
				if (fieldInfo2 != null)
				{
					fieldInfo2.SetValue(instance, Prefabs);
				}
				Logger.LogInfo((object)"  ✓ Instance fields configured");
			}
			catch (Exception ex)
			{
				Logger.LogDebug((object)("SetInstanceFields: " + ex.Message));
			}
		}

		public static GameObject? GetPrefab(string prefabId)
		{
			string text = prefabId?.ToLowerInvariant() ?? "";
			if (Prefabs.TryGetValue(text, out GameObject value))
			{
				return value;
			}
			foreach (KeyValuePair<string, GameObject> prefab in Prefabs)
			{
				if (prefab.Key.EndsWith(text) || prefab.Key.EndsWith("/" + text))
				{
					return prefab.Value;
				}
			}
			return null;
		}

		public static GameObject? SpawnPrefab(string prefabId, Vector3 position, Quaternion rotation)
		{
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				string text = prefabId?.ToLowerInvariant() ?? "";
				if (PrefabRefs.TryGetValue(text, out object value))
				{
					Type type = AccessTools.TypeByName("REPOLib.Modules.NetworkPrefabs");
					if (type != null)
					{
						MethodInfo methodInfo = AccessTools.Method(type, "SpawnNetworkPrefab", new Type[5]
						{
							value.GetType(),
							typeof(Vector3),
							typeof(Quaternion),
							typeof(byte),
							typeof(object[])
						}, (Type[])null);
						if (methodInfo != null)
						{
							object obj = methodInfo.Invoke(null, new object[5]
							{
								value,
								position,
								rotation,
								(byte)0,
								null
							});
							if (obj != null)
							{
								Logger.LogInfo((object)("    [Spawn] Networked Spawn Success: " + text));
								return (GameObject?)((obj is GameObject) ? obj : null);
							}
						}
					}
				}
				Logger.LogWarning((object)("    [Spawn] Falling back to Local Instantiation for " + text));
				GameObject prefab = GetPrefab(text);
				if ((Object)(object)prefab != (Object)null)
				{
					GameObject val = Object.Instantiate<GameObject>(prefab, position, rotation);
					if ((Object)(object)val != (Object)null)
					{
						Type type2 = AccessTools.TypeByName("Photon.Pun.PhotonView");
						if (type2 != null)
						{
						}
						Logger.LogInfo((object)$"    [Spawn] Local Instantiated: {((Object)val).name} at {position}");
						return val;
					}
				}
				Logger.LogWarning((object)("    SpawnPrefab failed for '" + prefabId + "'"));
				return null;
			}
			catch (Exception arg)
			{
				Logger.LogError((object)$"SpawnPrefab error for {prefabId}: {arg}");
				return null;
			}
		}

		private static void OptimizeNetworkPrefab(GameObject prefab, string prefabName)
		{
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				PhotonView val2 = prefab.GetComponent<PhotonView>();
				if ((Object)(object)val2 == (Object)null)
				{
					val2 = prefab.AddComponent<PhotonView>();
					Logger.LogDebug((object)("    [Optimize] Added PhotonView to " + ((Object)prefab).name));
				}
				PhotonTransformView val3 = prefab.GetComponent<PhotonTransformView>();
				if ((Object)(object)val3 == (Object)null)
				{
					val3 = prefab.AddComponent<PhotonTransformView>();
					Logger.LogDebug((object)("    [Optimize] Added PhotonTransformView to " + ((Object)prefab).name));
				}
				SetBool(val3, "m_SynchronizePosition", val: true);
				SetBool(val3, "m_SynchronizeRotation", val: true);
				if (!val2.ObservedComponents.Contains((Component)(object)val3))
				{
					val2.ObservedComponents.Add((Component)(object)val3);
					val2.Synchronization = (ViewSynchronization)3;
				}
				Logger.LogInfo((object)$"    [Optimize] Configured {((Object)prefab).name}: PV={(Object)(object)val2 != (Object)null}, PTV={(Object)(object)val3 != (Object)null}");
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("    [Optimize] Failed to optimize " + ((Object)prefab).name + ": " + ex.Message));
			}
			static void SetBool(object target, string name, bool val)
			{
				FieldInfo fieldInfo = AccessTools.Field(target.GetType(), name);
				if (fieldInfo != null)
				{
					fieldInfo.SetValue(target, val);
				}
			}
		}
	}
	public static class NetworkManagerPatches
	{
		[CompilerGenerated]
		private sealed class <InstantiateRoomDataFixed>d__4 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public object networkManager;

			private Type <photonNetworkType>5__1;

			private bool <isMasterClient>5__2;

			private Type <nmType>5__3;

			private FieldInfo <roomDataField>5__4;

			private GameObject <existingRoomData>5__5;

			private FieldInfo <retryCountField>5__6;

			private int <retryCount>5__7;

			private PropertyInfo <isMasterClientProp>5__8;

			private GameObject <roomData>5__9;

			private Type <pathMapperType>5__10;

			private Component <pathMapperComponent>5__11;

			private PropertyInfo <pathMapperProp>5__12;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <InstantiateRoomDataFixed>d__4(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<photonNetworkType>5__1 = null;
				<nmType>5__3 = null;
				<roomDataField>5__4 = null;
				<existingRoomData>5__5 = null;
				<retryCountField>5__6 = null;
				<isMasterClientProp>5__8 = null;
				<roomData>5__9 = null;
				<pathMapperType>5__10 = null;
				<pathMapperComponent>5__11 = null;
				<pathMapperProp>5__12 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_025d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0267: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
				{
					<>1__state = -1;
					<photonNetworkType>5__1 = AccessTools.TypeByName("Photon.Pun.PhotonNetwork");
					<isMasterClient>5__2 = false;
					if (<photonNetworkType>5__1 != null)
					{
						<isMasterClientProp>5__8 = AccessTools.Property(<photonNetworkType>5__1, "IsMasterClient");
						if (<isMasterClientProp>5__8 != null)
						{
							<isMasterClient>5__2 = (bool)(<isMasterClientProp>5__8.GetValue(null) ?? ((object)false));
						}
						<isMasterClientProp>5__8 = null;
					}
					if (!<isMasterClient>5__2)
					{
						return false;
					}
					<nmType>5__3 = networkManager.GetType();
					<roomDataField>5__4 = AccessTools.Field(<nmType>5__3, "roomData");
					ref GameObject reference = ref <existingRoomData>5__5;
					object? obj = <roomDataField>5__4?.GetValue(networkManager);
					reference = (GameObject)((obj is GameObject) ? obj : null);
					if ((Object)(object)<existingRoomData>5__5 != (Object)null)
					{
						return false;
					}
					<retryCountField>5__6 = AccessTools.Field(<nmType>5__3, "retryCount");
					<retryCount>5__7 = (int)(<retryCountField>5__6?.GetValue(networkManager) ?? ((object)0));
					break;
				}
				case 1:
					<>1__state = -1;
					<roomData>5__9 = null;
					break;
				}
				if (<retryCount>5__7 < 5)
				{
					<roomData>5__9 = InstantiateRoomDataLocal();
					if ((Object)(object)<roomData>5__9 != (Object)null)
					{
						<roomDataField>5__4?.SetValue(networkManager, <roomData>5__9);
						<pathMapperType>5__10 = AccessTools.TypeByName("IKEASimulator.PathMapper");
						if (<pathMapperType>5__10 != null)
						{
							<pathMapperComponent>5__11 = <roomData>5__9.GetComponent(<pathMapperType>5__10);
							<pathMapperProp>5__12 = AccessTools.Property(<nmType>5__3, "PathMapper");
							<pathMapperProp>5__12?.SetValue(networkManager, <pathMapperComponent>5__11);
							<pathMapperComponent>5__11 = null;
							<pathMapperProp>5__12 = null;
						}
						Logger.LogDebug((object)"  InstantiateRoomData: RoomData instantiated locally");
						return false;
					}
					<retryCount>5__7++;
					<retryCountField>5__6?.SetValue(networkManager, <retryCount>5__7);
					<>2__current = (object)new WaitForSeconds(0.5f);
					<>1__state = 1;
					return true;
				}
				Logger.LogWarning((object)"  InstantiateRoomData: Failed to create RoomData after 5 retries");
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private static ManualLogSource Logger => IKEASimulator_Fixer.Logger;

		public static bool OnCreatedRoom_Prefix(object __instance)
		{
			try
			{
				Logger.LogDebug((object)"NetworkManager.OnCreatedRoom intercepted");
				MonoBehaviour val = (MonoBehaviour)((__instance is MonoBehaviour) ? __instance : null);
				if ((Object)(object)val == (Object)null)
				{
					return true;
				}
				val.StartCoroutine(InstantiateRoomDataFixed(__instance));
				return false;
			}
			catch (Exception arg)
			{
				Logger.LogError((object)$"OnCreatedRoom_Prefix error: {arg}");
				return false;
			}
		}

		public static bool SingleplayerRoomData_Prefix(object __instance)
		{
			try
			{
				Logger.LogDebug((object)"NetworkManager.SingleplayerRoomData intercepted");
				Type type = __instance.GetType();
				AccessTools.Field(type, "isSingleplayer")?.SetValue(__instance, true);
				FieldInfo fieldInfo = AccessTools.Field(type, "roomData");
				object? obj = fieldInfo?.GetValue(__instance);
				GameObject val = (GameObject)((obj is GameObject) ? obj : null);
				if ((Object)(object)val != (Object)null)
				{
					return false;
				}
				GameObject val2 = InstantiateRoomDataLocal();
				if ((Object)(object)val2 != (Object)null)
				{
					fieldInfo?.SetValue(__instance, val2);
					Type type2 = AccessTools.TypeByName("IKEASimulator.PathMapper");
					if (type2 != null)
					{
						Component component = val2.GetComponent(type2);
						AccessTools.Property(type, "PathMapper")?.SetValue(__instance, component);
					}
					Logger.LogDebug((object)"  SingleplayerRoomData: RoomData instantiated locally");
				}
				return false;
			}
			catch (Exception arg)
			{
				Logger.LogError((object)$"SingleplayerRoomData_Prefix error: {arg}");
				return false;
			}
		}

		[IteratorStateMachine(typeof(<InstantiateRoomDataFixed>d__4))]
		private static IEnumerator InstantiateRoomDataFixed(object networkManager)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <InstantiateRoomDataFixed>d__4(0)
			{
				networkManager = networkManager
			};
		}

		private static GameObject? InstantiateRoomDataLocal()
		{
			try
			{
				string prefabId = "managers/roomdata";
				GameObject val = IKEACriticalPatches.GetPrefab(prefabId);
				if ((Object)(object)val == (Object)null)
				{
					foreach (KeyValuePair<string, GameObject> prefab in IKEACriticalPatches.Prefabs)
					{
						if (prefab.Key.ToLower().Contains("roomdata"))
						{
							val = prefab.Value;
							Logger.LogDebug((object)("  Found RoomData prefab with key: " + prefab.Key));
							break;
						}
					}
				}
				if ((Object)(object)val == (Object)null)
				{
					Logger.LogWarning((object)"  RoomData prefab not found in cache");
					return null;
				}
				return Object.Instantiate<GameObject>(val);
			}
			catch (Exception arg)
			{
				Logger.LogError((object)$"InstantiateRoomDataLocal error: {arg}");
				return null;
			}
		}
	}
	[HarmonyPatch(typeof(Module), "Start")]
	internal static class ModuleSafetyPatch
	{
		[HarmonyFinalizer]
		private static Exception? Finalizer(Exception? __exception, Module __instance)
		{
			if (__exception != null && __exception is NullReferenceException)
			{
				string text = __exception.StackTrace ?? "";
				if (text.Contains("IKEASimulator"))
				{
					IKEASimulator_Fixer.Logger.LogWarning((object)("Suppressed IKEASimulator NullReferenceException in Module.Start for " + (((__instance != null) ? ((Object)__instance).name : null) ?? "unknown")));
					return null;
				}
			}
			return __exception;
		}
	}
	[HarmonyPatch(typeof(LevelGenerator), "ModuleGeneration")]
	internal static class LevelGeneratorSafetyPatch
	{
		[HarmonyFinalizer]
		private static Exception? Finalizer(Exception? __exception)
		{
			if (__exception != null && __exception is NullReferenceException)
			{
				string text = __exception.StackTrace ?? "";
				if (text.Contains("IKEASimulator"))
				{
					IKEASimulator_Fixer.Logger.LogWarning((object)"Suppressed IKEASimulator NullReferenceException in LevelGenerator.ModuleGeneration");
					return null;
				}
			}
			return __exception;
		}
	}
}