Decompiled source of QuickRejoin v3.0.0

QuotaReroll.dll

Decompiled 8 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("QuotaReroll")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("QuotaReroll")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("d9c049c8-f290-4a04-853c-55008cb1c07d")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace QuickRejoin;

[BepInPlugin("com.myself.quickrejoin", "Quick Rejoin Mod", "3.0.0")]
public class Plugin : BaseUnityPlugin
{
	internal static ManualLogSource Log;

	private void Awake()
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Expected O, but got Unknown
		Log = ((BaseUnityPlugin)this).Logger;
		Log.LogInfo((object)"=== Quick Rejoin v3.0.0 Loaded ===");
		GameObject val = new GameObject("QuickRejoinManager");
		Object.DontDestroyOnLoad((Object)(object)val);
		((Object)val).hideFlags = (HideFlags)61;
		val.AddComponent<RejoinManager>();
		Log.LogInfo((object)"Quick Rejoin initialized");
	}
}
internal class RejoinManager : MonoBehaviour
{
	[CompilerGenerated]
	private sealed class <RerollCoroutine>d__22 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public bool isShop;

		public bool isHost;

		public RejoinManager <>4__this;

		private float <waitTime>5__1;

		private RunManager <runManager>5__2;

		private string <currentScene>5__3;

		private bool <sceneChanged>5__4;

		private string <newScene>5__5;

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

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

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

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<runManager>5__2 = null;
			<currentScene>5__3 = null;
			<newScene>5__5 = null;
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			//IL_02d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02de: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Expected O, but got Unknown
			//IL_03a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03af: Expected O, but got Unknown
			//IL_0402: Unknown result type (might be due to invalid IL or missing references)
			//IL_0407: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b6: Expected O, but got Unknown
			//IL_027b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0280: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Expected O, but got Unknown
			Scene activeScene;
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				Plugin.Log.LogInfo((object)string.Format("Starting {0}reroll sequence (Host: {1})...", isShop ? "shop " : "", isHost));
				<waitTime>5__1 = 0f;
				goto IL_00da;
			case 1:
				<>1__state = -1;
				<waitTime>5__1 += 0.5f;
				goto IL_00da;
			case 2:
				<>1__state = -1;
				<waitTime>5__1 += 0.5f;
				goto IL_01b4;
			case 3:
				<>1__state = -1;
				<waitTime>5__1 += 0.5f;
				activeScene = SceneManager.GetActiveScene();
				<newScene>5__5 = ((Scene)(ref activeScene)).name;
				if (<newScene>5__5 != <currentScene>5__3)
				{
					<sceneChanged>5__4 = true;
					Plugin.Log.LogInfo((object)("Scene change detected: " + <currentScene>5__3 + " -> " + <newScene>5__5));
				}
				<newScene>5__5 = null;
				goto IL_033a;
			case 4:
				<>1__state = -1;
				<waitTime>5__1 += 0.5f;
				goto IL_03d2;
			case 5:
				<>1__state = -1;
				break;
			case 6:
				{
					<>1__state = -1;
					break;
				}
				IL_01b4:
				while ((Object)(object)<runManager>5__2 == (Object)null && <waitTime>5__1 < 30f)
				{
					<runManager>5__2 = Object.FindObjectOfType<RunManager>();
					if ((Object)(object)<runManager>5__2 == (Object)null)
					{
						Plugin.Log.LogInfo((object)"Waiting for RunManager...");
						<>2__current = (object)new WaitForSeconds(0.5f);
						<>1__state = 2;
						return true;
					}
				}
				if ((Object)(object)<runManager>5__2 == (Object)null)
				{
					Plugin.Log.LogError((object)"Timeout waiting for RunManager!");
					<>4__this.ResetState();
					return false;
				}
				if (isShop)
				{
					Plugin.Log.LogInfo((object)"Host reloading shop...");
					<runManager>5__2.ChangeLevel(false, false, (ChangeLevelType)5);
				}
				else
				{
					Plugin.Log.LogInfo((object)"Host calling RunManager.ChangeLevel...");
					<runManager>5__2.ChangeLevel(false, false, (ChangeLevelType)1);
				}
				<runManager>5__2 = null;
				goto IL_0391;
				IL_0391:
				<waitTime>5__1 = 0f;
				goto IL_03d2;
				IL_033a:
				if (!<sceneChanged>5__4 && <waitTime>5__1 < 30f)
				{
					<>2__current = (object)new WaitForSeconds(0.5f);
					<>1__state = 3;
					return true;
				}
				if (!<sceneChanged>5__4)
				{
					Plugin.Log.LogWarning((object)"Timeout waiting for scene change from host");
					<>4__this.ResetState();
					return false;
				}
				<currentScene>5__3 = null;
				goto IL_0391;
				IL_03d2:
				activeScene = SceneManager.GetActiveScene();
				if (((Scene)(ref activeScene)).name != "Main" && <waitTime>5__1 < 30f)
				{
					<>2__current = (object)new WaitForSeconds(0.5f);
					<>1__state = 4;
					return true;
				}
				activeScene = SceneManager.GetActiveScene();
				if (((Scene)(ref activeScene)).name != "Main")
				{
					Plugin.Log.LogWarning((object)"Timeout waiting for Main scene");
					<>4__this.ResetState();
					return false;
				}
				Plugin.Log.LogInfo((object)"Main scene loaded, waiting for level generation...");
				if (isShop)
				{
					<>2__current = ((MonoBehaviour)<>4__this).StartCoroutine(<>4__this.WaitForShopReady());
					<>1__state = 5;
					return true;
				}
				<>2__current = ((MonoBehaviour)<>4__this).StartCoroutine(<>4__this.WaitForLevelReady());
				<>1__state = 6;
				return true;
				IL_00da:
				if (!PhotonNetwork.IsConnectedAndReady && PhotonNetwork.IsConnected && <waitTime>5__1 < 30f)
				{
					Plugin.Log.LogInfo((object)"Waiting for Photon connection to be ready...");
					<>2__current = (object)new WaitForSeconds(0.5f);
					<>1__state = 1;
					return true;
				}
				if (<waitTime>5__1 >= 30f)
				{
					Plugin.Log.LogError((object)"Timeout waiting for Photon connection!");
					<>4__this.ResetState();
					return false;
				}
				if (isHost)
				{
					<runManager>5__2 = null;
					<waitTime>5__1 = 0f;
					goto IL_01b4;
				}
				Plugin.Log.LogInfo((object)"Client waiting for host to change level...");
				activeScene = SceneManager.GetActiveScene();
				<currentScene>5__3 = ((Scene)(ref activeScene)).name;
				<waitTime>5__1 = 0f;
				<sceneChanged>5__4 = false;
				goto IL_033a;
			}
			Plugin.Log.LogInfo((object)"Reroll complete!");
			<>4__this.ResetState();
			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 <WaitForLevelReady>d__23 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public RejoinManager <>4__this;

		private float <waitTime>5__1;

		private LevelGenerator <generator>5__2;

		private FieldInfo <generatedField>5__3;

		private bool <generated>5__4;

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

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

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

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<generator>5__2 = null;
			<generatedField>5__3 = null;
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Expected O, but got Unknown
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Expected O, but got Unknown
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Expected O, but got Unknown
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				<waitTime>5__1 = 0f;
				<generator>5__2 = null;
				goto IL_00ac;
			case 1:
				<>1__state = -1;
				<waitTime>5__1 += 0.5f;
				goto IL_00ac;
			case 2:
				<>1__state = -1;
				<waitTime>5__1 += 0.5f;
				goto IL_01a2;
			case 3:
				{
					<>1__state = -1;
					break;
				}
				IL_00ac:
				while ((Object)(object)<generator>5__2 == (Object)null && <waitTime>5__1 < 30f)
				{
					<generator>5__2 = Object.FindObjectOfType<LevelGenerator>();
					if ((Object)(object)<generator>5__2 == (Object)null)
					{
						Plugin.Log.LogInfo((object)"Waiting for LevelGenerator...");
						<>2__current = (object)new WaitForSeconds(0.5f);
						<>1__state = 1;
						return true;
					}
				}
				if ((Object)(object)<generator>5__2 == (Object)null)
				{
					Plugin.Log.LogWarning((object)"Timeout waiting for LevelGenerator");
					return false;
				}
				<generatedField>5__3 = typeof(LevelGenerator).GetField("Generated", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (<generatedField>5__3 != null)
				{
					<waitTime>5__1 = 0f;
					goto IL_01a2;
				}
				Plugin.Log.LogInfo((object)"Could not find Generated field, waiting 3 seconds...");
				<>2__current = (object)new WaitForSeconds(3f);
				<>1__state = 3;
				return true;
				IL_01a2:
				if (<waitTime>5__1 < 30f)
				{
					<generated>5__4 = (bool)<generatedField>5__3.GetValue(<generator>5__2);
					if (<generated>5__4)
					{
						Plugin.Log.LogInfo((object)"Level generation complete!");
						return false;
					}
					<>2__current = (object)new WaitForSeconds(0.5f);
					<>1__state = 2;
					return true;
				}
				Plugin.Log.LogWarning((object)"Timeout waiting for level generation");
				break;
			}
			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 <WaitForShopReady>d__24 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public RejoinManager <>4__this;

		private float <waitTime>5__1;

		private ShopManager <shopManager>5__2;

		private FieldInfo <shoppingListField>5__3;

		private IList <shoppingList>5__4;

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

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

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

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<shopManager>5__2 = null;
			<shoppingListField>5__3 = null;
			<shoppingList>5__4 = null;
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Expected O, but got Unknown
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Expected O, but got Unknown
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Expected O, but got Unknown
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				<waitTime>5__1 = 0f;
				<shopManager>5__2 = null;
				goto IL_00ac;
			case 1:
				<>1__state = -1;
				<waitTime>5__1 += 0.5f;
				goto IL_00ac;
			case 2:
				<>1__state = -1;
				<waitTime>5__1 += 0.5f;
				<shoppingList>5__4 = null;
				goto IL_01d4;
			case 3:
				{
					<>1__state = -1;
					break;
				}
				IL_00ac:
				while ((Object)(object)<shopManager>5__2 == (Object)null && <waitTime>5__1 < 30f)
				{
					<shopManager>5__2 = Object.FindObjectOfType<ShopManager>();
					if ((Object)(object)<shopManager>5__2 == (Object)null)
					{
						Plugin.Log.LogInfo((object)"Waiting for ShopManager...");
						<>2__current = (object)new WaitForSeconds(0.5f);
						<>1__state = 1;
						return true;
					}
				}
				if ((Object)(object)<shopManager>5__2 == (Object)null)
				{
					Plugin.Log.LogWarning((object)"Timeout waiting for ShopManager");
					return false;
				}
				<shoppingListField>5__3 = typeof(ShopManager).GetField("shoppingList", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (<shoppingListField>5__3 != null)
				{
					<waitTime>5__1 = 0f;
					goto IL_01d4;
				}
				Plugin.Log.LogInfo((object)"Could not find shoppingList field, waiting 3 seconds...");
				<>2__current = (object)new WaitForSeconds(3f);
				<>1__state = 3;
				return true;
				IL_01d4:
				if (<waitTime>5__1 < 30f)
				{
					<shoppingList>5__4 = <shoppingListField>5__3.GetValue(<shopManager>5__2) as IList;
					if (<shoppingList>5__4 != null && <shoppingList>5__4.Count > 0)
					{
						Plugin.Log.LogInfo((object)$"Shop ready with {<shoppingList>5__4.Count} items!");
						return false;
					}
					<>2__current = (object)new WaitForSeconds(0.5f);
					<>1__state = 2;
					return true;
				}
				Plugin.Log.LogWarning((object)"Timeout waiting for shop to populate");
				break;
			}
			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 const byte RerollEventCode = 42;

	private const float CheckInterval = 0.5f;

	private const float MaxWaitTime = 30f;

	internal static bool RerollQueued;

	internal static int QueuedSeed;

	internal static bool IsShopReroll;

	private static Harmony _harmony;

	private bool _eventsRegistered;

	private bool _isRerolling;

	private int _lastProcessedSeed;

	private float _lastRerollTime;

	private void Awake()
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Expected O, but got Unknown
		Plugin.Log.LogInfo((object)"RejoinManager Awake");
		_harmony = new Harmony("com.myself.quickrejoin");
		_harmony.PatchAll();
		Plugin.Log.LogInfo((object)"Harmony patches applied");
		Plugin.Log.LogInfo((object)"Reroll key: Backslash (\\)");
		Plugin.Log.LogInfo((object)"Debug key: Equals (=)");
	}

	private void OnEnable()
	{
		SceneManager.sceneLoaded += OnSceneLoaded;
	}

	private void OnDisable()
	{
		SceneManager.sceneLoaded -= OnSceneLoaded;
	}

	private void Start()
	{
		RegisterPhotonEvents();
	}

	private void RegisterPhotonEvents()
	{
		if (!_eventsRegistered && PhotonNetwork.NetworkingClient != null)
		{
			PhotonNetwork.NetworkingClient.EventReceived += OnEventReceived;
			_eventsRegistered = true;
			Plugin.Log.LogInfo((object)"Photon events registered");
		}
	}

	private void Update()
	{
		if (!_eventsRegistered)
		{
			RegisterPhotonEvents();
		}
		if (Input.GetKeyDown((KeyCode)92))
		{
			TryInitiateReroll();
		}
		if (Input.GetKeyDown((KeyCode)61))
		{
			PrintLevelDebug();
		}
	}

	private void PrintLevelDebug()
	{
		Plugin.Log.LogInfo((object)"=== LEVEL DEBUG ===");
		RunManager val = Object.FindObjectOfType<RunManager>();
		if ((Object)(object)val == (Object)null)
		{
			Plugin.Log.LogInfo((object)"RunManager not found");
			return;
		}
		FieldInfo field = typeof(RunManager).GetField("levels", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		if (field != null && field.GetValue(val) is IList list)
		{
			Plugin.Log.LogInfo((object)$"Available levels ({list.Count}):");
			for (int i = 0; i < list.Count; i++)
			{
				object obj = list[i];
				string arg = obj?.ToString() ?? "null";
				Object val2 = (Object)((obj is Object) ? obj : null);
				if (val2 != null)
				{
					arg = val2.name;
				}
				Plugin.Log.LogInfo((object)$"  [{i}] {arg}");
			}
		}
		FieldInfo field2 = typeof(RunManager).GetField("levelCurrent", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		FieldInfo field3 = typeof(RunManager).GetField("previousRunLevel", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		FieldInfo field4 = typeof(RunManager).GetField("levelShop", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		if (field2 != null)
		{
			object? value = field2.GetValue(val);
			Object val3 = (Object)((value is Object) ? value : null);
			Plugin.Log.LogInfo((object)("Current level: " + (((val3 != null) ? val3.name : null) ?? "null")));
		}
		if (field3 != null)
		{
			object? value2 = field3.GetValue(val);
			Object val4 = (Object)((value2 is Object) ? value2 : null);
			Plugin.Log.LogInfo((object)("Previous run level: " + (((val4 != null) ? val4.name : null) ?? "null")));
		}
		if (field4 != null)
		{
			object? value3 = field4.GetValue(val);
			Object val5 = (Object)((value3 is Object) ? value3 : null);
			Plugin.Log.LogInfo((object)("Shop level: " + (((val5 != null) ? val5.name : null) ?? "null")));
		}
		Plugin.Log.LogInfo((object)$"Is Multiplayer: {PhotonNetwork.IsConnected}");
		Plugin.Log.LogInfo((object)$"Is Master Client: {PhotonNetwork.IsMasterClient}");
		PlayerHealth[] array = Object.FindObjectsOfType<PlayerHealth>();
		Plugin.Log.LogInfo((object)$"PlayerHealth instances: {array.Length}");
		PlayerHealth[] array2 = array;
		foreach (PlayerHealth obj2 in array2)
		{
			FieldInfo field5 = typeof(PlayerHealth).GetField("health", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			FieldInfo field6 = typeof(PlayerHealth).GetField("maxHealth", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field5 != null && field6 != null)
			{
				int num = (int)field5.GetValue(obj2);
				int num2 = (int)field6.GetValue(obj2);
				Plugin.Log.LogInfo((object)$"  Player health: {num}/{num2}");
			}
		}
		Plugin.Log.LogInfo((object)"=== END DEBUG ===");
	}

	private void TryInitiateReroll()
	{
		if (_isRerolling)
		{
			Plugin.Log.LogWarning((object)"Reroll already in progress");
			return;
		}
		RunManager val = Object.FindObjectOfType<RunManager>();
		if ((Object)(object)val == (Object)null)
		{
			Plugin.Log.LogWarning((object)"Cannot reroll: RunManager not found");
			return;
		}
		FieldInfo field = typeof(RunManager).GetField("levelCurrent", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		FieldInfo field2 = typeof(RunManager).GetField("levels", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		FieldInfo field3 = typeof(RunManager).GetField("levelShop", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		if (field == null || field2 == null || field3 == null)
		{
			Plugin.Log.LogWarning((object)"Cannot reroll: Could not read RunManager fields");
			return;
		}
		object value = field.GetValue(val);
		IList list = field2.GetValue(val) as IList;
		object value2 = field3.GetValue(val);
		if (value == null || list == null)
		{
			Plugin.Log.LogWarning((object)"Cannot reroll: Level data is null");
			return;
		}
		bool flag = false;
		bool flag2 = value == value2;
		foreach (object item in list)
		{
			if (item == value)
			{
				flag = true;
				break;
			}
		}
		if (!flag && !flag2)
		{
			object obj = ((value is Object) ? value : null);
			string text = ((obj != null) ? ((Object)obj).name : null) ?? "unknown";
			Plugin.Log.LogWarning((object)("Cannot reroll: Not in a run level or shop (current: " + text + ")"));
			return;
		}
		if (PhotonNetwork.IsConnected && !PhotonNetwork.IsMasterClient)
		{
			Plugin.Log.LogWarning((object)"Cannot reroll: Only host can initiate reroll in multiplayer");
			return;
		}
		if (PhotonNetwork.IsConnected)
		{
			Plugin.Log.LogInfo((object)(">>> MULTIPLAYER " + (flag2 ? "SHOP " : "") + "REROLL INITIATED (HOST) <<<"));
		}
		else
		{
			Plugin.Log.LogInfo((object)(">>> SINGLEPLAYER " + (flag2 ? "SHOP " : "") + "REROLL INITIATED <<<"));
		}
		int num = Random.Range(int.MinValue, int.MaxValue);
		Plugin.Log.LogInfo((object)$"New seed: {num}");
		if (PhotonNetwork.IsConnected)
		{
			BroadcastReroll(num, flag2);
		}
		else
		{
			TriggerReroll(num, flag2, isHost: true);
		}
	}

	private void BroadcastReroll(int seed, bool isShop)
	{
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Expected O, but got Unknown
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		Plugin.Log.LogInfo((object)$"[BROADCAST] Seed: {seed}, IsShop: {isShop}");
		object[] array = new object[2] { seed, isShop };
		RaiseEventOptions val = new RaiseEventOptions
		{
			Receivers = (ReceiverGroup)1,
			CachingOption = (EventCaching)0
		};
		PhotonNetwork.RaiseEvent((byte)42, (object)array, val, SendOptions.SendReliable);
	}

	private void TriggerReroll(int seed, bool isShop, bool isHost)
	{
		if (!_isRerolling && (seed != _lastProcessedSeed || !(Time.time - _lastRerollTime < 5f)))
		{
			_isRerolling = true;
			_lastProcessedSeed = seed;
			_lastRerollTime = Time.time;
			Plugin.Log.LogInfo((object)$"[TRIGGER] Reroll with seed: {seed}, IsShop: {isShop}, IsHost: {isHost}");
			QueuedSeed = seed;
			RerollQueued = true;
			IsShopReroll = isShop;
			ResetAllPlayerHealth();
			((MonoBehaviour)this).StartCoroutine(RerollCoroutine(isShop, isHost));
		}
	}

	private void ResetAllPlayerHealth()
	{
		Plugin.Log.LogInfo((object)"Resetting player health...");
		PlayerHealth[] array = Object.FindObjectsOfType<PlayerHealth>();
		FieldInfo field = typeof(PlayerHealth).GetField("health", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		FieldInfo field2 = typeof(PlayerHealth).GetField("maxHealth", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		FieldInfo field3 = typeof(PlayerHealth).GetField("playerAvatar", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		if (field == null || field2 == null)
		{
			Plugin.Log.LogWarning((object)"Could not find health fields via reflection");
			return;
		}
		PlayerHealth[] array2 = array;
		foreach (PlayerHealth obj in array2)
		{
			try
			{
				int num = (int)field.GetValue(obj);
				int num2 = (int)field2.GetValue(obj);
				if (num < num2)
				{
					field.SetValue(obj, num2);
					if (field3 != null && (Object)(object)StatsManager.instance != (Object)null)
					{
						object? value = field3.GetValue(obj);
						PlayerAvatar val = (PlayerAvatar)((value is PlayerAvatar) ? value : null);
						if ((Object)(object)val != (Object)null)
						{
							string text = SemiFunc.PlayerGetSteamID(val);
							if (!string.IsNullOrEmpty(text))
							{
								StatsManager.instance.SetPlayerHealth(text, num2, true);
								Plugin.Log.LogInfo((object)$"Reset health for player {text}: {num} -> {num2}");
							}
						}
					}
					else
					{
						Plugin.Log.LogInfo((object)$"Reset health via reflection: {num} -> {num2}");
					}
				}
				else
				{
					Plugin.Log.LogInfo((object)$"Player health already at max: {num}/{num2}");
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Error resetting player health: " + ex.Message));
			}
		}
	}

	[IteratorStateMachine(typeof(<RerollCoroutine>d__22))]
	private IEnumerator RerollCoroutine(bool isShop, bool isHost)
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <RerollCoroutine>d__22(0)
		{
			<>4__this = this,
			isShop = isShop,
			isHost = isHost
		};
	}

	[IteratorStateMachine(typeof(<WaitForLevelReady>d__23))]
	private IEnumerator WaitForLevelReady()
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <WaitForLevelReady>d__23(0)
		{
			<>4__this = this
		};
	}

	[IteratorStateMachine(typeof(<WaitForShopReady>d__24))]
	private IEnumerator WaitForShopReady()
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <WaitForShopReady>d__24(0)
		{
			<>4__this = this
		};
	}

	private void ResetState()
	{
		_isRerolling = false;
		RerollQueued = false;
		IsShopReroll = false;
	}

	private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
	{
		Plugin.Log.LogInfo((object)("Scene loaded: " + ((Scene)(ref scene)).name));
		_eventsRegistered = false;
		RegisterPhotonEvents();
	}

	private void OnEventReceived(EventData photonEvent)
	{
		if (photonEvent.Code == 42)
		{
			object[] array = (object[])photonEvent.CustomData;
			int num = (int)array[0];
			bool flag = (bool)array[1];
			bool isMasterClient = PhotonNetwork.IsMasterClient;
			if (num != _lastProcessedSeed || Time.time - _lastRerollTime >= 5f)
			{
				Plugin.Log.LogInfo((object)$"[RECEIVED] Reroll event - Seed: {num}, IsShop: {flag}, AmHost: {isMasterClient}");
			}
			TriggerReroll(num, flag, isMasterClient);
		}
	}

	private void OnDestroy()
	{
		Plugin.Log.LogWarning((object)"RejoinManager destroyed");
		SceneManager.sceneLoaded -= OnSceneLoaded;
		if (PhotonNetwork.NetworkingClient != null)
		{
			PhotonNetwork.NetworkingClient.EventReceived -= OnEventReceived;
		}
		if (_harmony != null)
		{
			_harmony.UnpatchSelf();
		}
	}
}
[HarmonyPatch(typeof(RunManager), "SetRunLevel")]
internal static class RunManager_SetRunLevel_Patch
{
	private static bool Prefix(RunManager __instance)
	{
		if (!RejoinManager.RerollQueued || RejoinManager.IsShopReroll)
		{
			return true;
		}
		Plugin.Log.LogInfo((object)$"[HARMONY] Overriding SetRunLevel with seed: {RejoinManager.QueuedSeed}");
		FieldInfo field = typeof(RunManager).GetField("levels", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		FieldInfo field2 = typeof(RunManager).GetField("levelCurrent", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		if (field == null || field2 == null)
		{
			Plugin.Log.LogError((object)"Could not find levels or levelCurrent field!");
			return true;
		}
		if (!(field.GetValue(__instance) is IList list) || list.Count == 0)
		{
			Plugin.Log.LogError((object)"Levels list is null or empty!");
			return true;
		}
		Random.InitState(RejoinManager.QueuedSeed);
		int num = Random.Range(0, list.Count);
		object obj = list[num];
		field2.SetValue(__instance, obj);
		object obj2 = ((obj is Object) ? obj : null);
		string arg = ((obj2 != null) ? ((Object)obj2).name : null) ?? "unknown";
		Plugin.Log.LogInfo((object)$"[HARMONY] Selected level [{num}]: {arg}");
		return false;
	}
}
[HarmonyPatch(typeof(LevelGenerator), "Generate")]
internal static class LevelGenerator_Generate_Patch
{
	private static void Prefix()
	{
		if (RejoinManager.RerollQueued)
		{
			Plugin.Log.LogInfo((object)$"[HARMONY] Seeding RNG before Generate: {RejoinManager.QueuedSeed}");
			Random.InitState(RejoinManager.QueuedSeed);
			if (!RejoinManager.IsShopReroll)
			{
				RejoinManager.RerollQueued = false;
			}
		}
	}
}
[HarmonyPatch(typeof(ShopManager), "ShopInitialize")]
internal static class ShopManager_ShopInitialize_Patch
{
	private static void Prefix()
	{
		if (RejoinManager.RerollQueued && RejoinManager.IsShopReroll)
		{
			Plugin.Log.LogInfo((object)$"[HARMONY] Seeding RNG before ShopInitialize: {RejoinManager.QueuedSeed}");
			Random.InitState(RejoinManager.QueuedSeed);
			RejoinManager.RerollQueued = false;
			RejoinManager.IsShopReroll = false;
		}
	}
}