Decompiled source of MapVoteWithPreview v0.0.2

MapVoteWithPreview.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
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 MapVote;
using MapVoteWithPreview.Preview;
using MenuLib.MonoBehaviors;
using Microsoft.CodeAnalysis;
using MonoMod.RuntimeDetour;
using Photon.Pun;
using REPOLib.Modules;
using TMPro;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.PostProcessing;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: IgnoresAccessChecksTo("Autodesk.Fbx")]
[assembly: IgnoresAccessChecksTo("Discord.Sdk")]
[assembly: IgnoresAccessChecksTo("Domain_Reload")]
[assembly: IgnoresAccessChecksTo("Facepunch.Steamworks.Win64")]
[assembly: IgnoresAccessChecksTo("FbxBuildTestAssets")]
[assembly: IgnoresAccessChecksTo("Klattersynth")]
[assembly: IgnoresAccessChecksTo("Patrick.MapVote")]
[assembly: IgnoresAccessChecksTo("Photon3Unity3D")]
[assembly: IgnoresAccessChecksTo("PhotonChat")]
[assembly: IgnoresAccessChecksTo("PhotonRealtime")]
[assembly: IgnoresAccessChecksTo("PhotonUnityNetworking")]
[assembly: IgnoresAccessChecksTo("PhotonUnityNetworking.Utilities")]
[assembly: IgnoresAccessChecksTo("PhotonVoice.API")]
[assembly: IgnoresAccessChecksTo("PhotonVoice")]
[assembly: IgnoresAccessChecksTo("PhotonVoice.PUN")]
[assembly: IgnoresAccessChecksTo("SingularityGroup.HotReload.Runtime")]
[assembly: IgnoresAccessChecksTo("SingularityGroup.HotReload.Runtime.Public")]
[assembly: IgnoresAccessChecksTo("Sirenix.OdinInspector.Attributes")]
[assembly: IgnoresAccessChecksTo("Sirenix.Serialization.Config")]
[assembly: IgnoresAccessChecksTo("Sirenix.Serialization")]
[assembly: IgnoresAccessChecksTo("Sirenix.Utilities")]
[assembly: IgnoresAccessChecksTo("Unity.AI.Navigation")]
[assembly: IgnoresAccessChecksTo("Unity.Burst")]
[assembly: IgnoresAccessChecksTo("Unity.Burst.Unsafe")]
[assembly: IgnoresAccessChecksTo("Unity.Collections")]
[assembly: IgnoresAccessChecksTo("Unity.Collections.LowLevel.ILSupport")]
[assembly: IgnoresAccessChecksTo("Unity.Formats.Fbx.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem.ForUI")]
[assembly: IgnoresAccessChecksTo("Unity.Mathematics")]
[assembly: IgnoresAccessChecksTo("Unity.MemoryProfiler")]
[assembly: IgnoresAccessChecksTo("Unity.Postprocessing.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.Profiling.Core")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.ShaderLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.Splines")]
[assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")]
[assembly: IgnoresAccessChecksTo("Unity.Timeline")]
[assembly: IgnoresAccessChecksTo("Unity.VisualScripting.Antlr3.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.VisualScripting.Core")]
[assembly: IgnoresAccessChecksTo("Unity.VisualScripting.Flow")]
[assembly: IgnoresAccessChecksTo("Unity.VisualScripting.State")]
[assembly: IgnoresAccessChecksTo("UnityEngine.ARModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.NVIDIAModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.UI")]
[assembly: IgnoresAccessChecksTo("websocket-sharp")]
[assembly: AssemblyCompany("MapVoteWithPreview")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.0.2.0")]
[assembly: AssemblyInformationalVersion("0.0.2+c867a109f2645d317723cb3164d568b519d19519")]
[assembly: AssemblyProduct("MapVoteWithPreview")]
[assembly: AssemblyTitle("MapVoteWithPreview")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.2.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 MapVoteWithPreview
{
	[BepInPlugin("MARCROCK22.MapVoteWithPreview", "MapVoteWithPreview", "0.0.2")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		[HarmonyPatch(typeof(MapVote))]
		internal static class CreateVotePopupPatch
		{
			[HarmonyPatch("CreateVotePopup")]
			[HarmonyPostfix]
			private static void Postfix()
			{
				if (!PreviewEnabled.Value)
				{
					return;
				}
				foreach (VoteOptionButton voteOptionButton in MapVote.VoteOptionButtons)
				{
					if (voteOptionButton.IsRandomButton)
					{
						continue;
					}
					REPOButton button = voteOptionButton.Button;
					string levelName = voteOptionButton.Level;
					Action originalOnClick = button.onClick;
					button.onClick = delegate
					{
						if (!MapVote.DisableInput)
						{
							if (Input.GetKey((KeyCode)304))
							{
								MapPreviewManager.StartPreview(levelName);
							}
							else
							{
								originalOnClick?.Invoke();
							}
						}
					};
				}
			}
		}

		[HarmonyPatch(typeof(VoteOptionButton))]
		internal static class UpdateLabelPatch
		{
			[HarmonyPatch("UpdateLabel")]
			[HarmonyPostfix]
			private static void Postfix(VoteOptionButton __instance)
			{
				VoteOptionButton __instance2 = __instance;
				if (!__instance2.IsRandomButton && PreviewingPlayers.Values.Any((string v) => v == __instance2.Level))
				{
					TextMeshProUGUI labelTMP = __instance2.Button.labelTMP;
					((TMP_Text)labelTMP).text = ((TMP_Text)labelTMP).text + " <color=#808080>(previewing)</color>";
				}
			}
		}

		internal static ManualLogSource Log;

		public static ConfigEntry<bool> PreviewEnabled;

		public static ConfigEntry<float> FreecamSpeed;

		public static NetworkedEvent OnPreviewStart;

		public static NetworkedEvent OnPreviewEnd;

		public static Dictionary<string, string> PreviewingPlayers = new Dictionary<string, string>();

		private readonly Harmony _harmony = new Harmony("MARCROCK22.MapVoteWithPreview");

		private static Hook _setRunLevelHook;

		private static Hook _buttonStartHook;

		private void Awake()
		{
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Expected O, but got Unknown
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Expected O, but got Unknown
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Expected O, but got Unknown
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Expected O, but got Unknown
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			((Component)this).gameObject.transform.parent = null;
			((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
			PreviewEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Preview", "Preview Enabled", true, "When true - enables the map preview freecam feature (Shift+Click on a map)");
			FreecamSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Preview", "Freecam Speed", 10f, new ConfigDescription("Speed of the freecam when previewing a map", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 50f), Array.Empty<object>()));
			GameObject val = new GameObject("MapPreviewManager");
			val.transform.parent = null;
			((Object)val).hideFlags = (HideFlags)61;
			val.AddComponent<MapPreviewManager>();
			OnPreviewStart = new NetworkedEvent("MapVotePreview_Start", (Action<EventData>)HandlePreviewStart);
			OnPreviewEnd = new NetworkedEvent("MapVotePreview_End", (Action<EventData>)HandlePreviewEnd);
			try
			{
				_harmony.PatchAll(typeof(CreateVotePopupPatch));
				_harmony.PatchAll(typeof(UpdateLabelPatch));
				Log.LogInfo((object)"Harmony patches applied");
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"Failed to apply Harmony patches: {arg}");
			}
			_setRunLevelHook = new Hook((MethodBase)AccessTools.DeclaredMethod(typeof(RunManager), "SetRunLevel", (Type[])null, (Type[])null), (Delegate)new Action<Action<RunManager>, RunManager>(HookSetRunLevel));
			_buttonStartHook = new Hook((MethodBase)AccessTools.DeclaredMethod(typeof(MenuPageLobby), "ButtonStart", (Type[])null, (Type[])null), (Delegate)new Action<Action<MenuPageLobby>, MenuPageLobby>(HookButtonStart));
			((BaseUnityPlugin)this).Logger.LogInfo((object)"MapVoteWithPreview v0.0.2 loaded!");
		}

		private static void HookSetRunLevel(Action<RunManager> orig, RunManager self)
		{
			MapPreviewManager.ForceClose();
			orig(self);
		}

		private static void HookButtonStart(Action<MenuPageLobby> orig, MenuPageLobby self)
		{
			MapPreviewManager.ForceClose();
			orig(self);
		}

		private static void HandlePreviewStart(EventData data)
		{
			string[] array = ((string)data.CustomData).Split('|');
			if (array.Length >= 2)
			{
				PreviewingPlayers[array[0]] = array[1];
				MapVote.UpdateButtonLabels();
			}
		}

		private static void HandlePreviewEnd(EventData data)
		{
			string key = (string)data.CustomData;
			PreviewingPlayers.Remove(key);
			MapVote.UpdateButtonLabels();
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "MapVoteWithPreview";

		public const string PLUGIN_NAME = "MapVoteWithPreview";

		public const string PLUGIN_VERSION = "0.0.2";
	}
}
namespace MapVoteWithPreview.Preview
{
	public class FreecamController : MonoBehaviour
	{
		private float _yaw;

		private float _pitch;

		private float _speed;

		private PostProcessVolume _ppVolume;

		private RenderTexture _renderTexture;

		private Camera _camera;

		public void Initialize(float speed, Vector3 startPosition)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			_speed = speed;
			((Component)this).transform.position = startPosition;
			Camera val = ((Component)this).gameObject.AddComponent<Camera>();
			val.nearClipPlane = 0.1f;
			val.farClipPlane = 1000f;
			val.fieldOfView = 75f;
			val.depth = 100f;
			int num = Screen.width / 3;
			int num2 = Screen.height / 3;
			RenderTexture val2 = new RenderTexture(num, num2, 24);
			((Texture)val2).filterMode = (FilterMode)0;
			val.targetTexture = val2;
			_renderTexture = val2;
			_camera = val;
			try
			{
				PostProcessLayer val3 = ((Component)this).gameObject.AddComponent<PostProcessLayer>();
				val3.volumeTrigger = ((Component)this).transform;
				val3.volumeLayer = LayerMask.op_Implicit(-1);
				PostProcessResources[] array = Resources.FindObjectsOfTypeAll<PostProcessResources>();
				if (array != null && array.Length != 0)
				{
					val3.Init(array[0]);
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[PREVIEW] PostProcessLayer setup failed: " + ex.Message));
			}
			((Component)this).gameObject.AddComponent<AudioListener>();
			_yaw = ((Component)this).transform.eulerAngles.y;
			_pitch = ((Component)this).transform.eulerAngles.x;
			Cursor.lockState = (CursorLockMode)0;
			Cursor.visible = true;
		}

		public void ApplyLevelEffects(Level level)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("PreviewPostProcess");
			((Object)val).hideFlags = (HideFlags)61;
			val.transform.SetParent(((Component)this).transform, false);
			_ppVolume = val.AddComponent<PostProcessVolume>();
			_ppVolume.isGlobal = true;
			_ppVolume.priority = 100f;
			PostProcessProfile val2 = ScriptableObject.CreateInstance<PostProcessProfile>();
			Bloom val3 = ScriptableObject.CreateInstance<Bloom>();
			((ParameterOverride<bool>)(object)((PostProcessEffectSettings)val3).enabled).value = true;
			((ParameterOverride)val3.intensity).overrideState = true;
			((ParameterOverride<float>)(object)val3.intensity).value = Mathf.Min(level.BloomIntensity * 0.3f, 3f);
			((ParameterOverride)val3.threshold).overrideState = true;
			((ParameterOverride<float>)(object)val3.threshold).value = Mathf.Max(level.BloomThreshold, 1f);
			val2.AddSettings((PostProcessEffectSettings)(object)val3);
			ColorGrading val4 = ScriptableObject.CreateInstance<ColorGrading>();
			((ParameterOverride<bool>)(object)((PostProcessEffectSettings)val4).enabled).value = true;
			((ParameterOverride)val4.colorFilter).overrideState = true;
			((ParameterOverride<Color>)(object)val4.colorFilter).value = level.ColorFilter;
			((ParameterOverride)val4.temperature).overrideState = true;
			((ParameterOverride<float>)(object)val4.temperature).value = level.ColorTemperature;
			val2.AddSettings((PostProcessEffectSettings)(object)val4);
			Vignette val5 = ScriptableObject.CreateInstance<Vignette>();
			((ParameterOverride<bool>)(object)((PostProcessEffectSettings)val5).enabled).value = true;
			((ParameterOverride)val5.color).overrideState = true;
			((ParameterOverride<Color>)(object)val5.color).value = level.VignetteColor;
			((ParameterOverride)val5.intensity).overrideState = true;
			((ParameterOverride<float>)(object)val5.intensity).value = level.VignetteIntensity;
			((ParameterOverride)val5.smoothness).overrideState = true;
			((ParameterOverride<float>)(object)val5.smoothness).value = level.VignetteSmoothness;
			val2.AddSettings((PostProcessEffectSettings)(object)val5);
			ChromaticAberration val6 = ScriptableObject.CreateInstance<ChromaticAberration>();
			((ParameterOverride<bool>)(object)((PostProcessEffectSettings)val6).enabled).value = true;
			((ParameterOverride)val6.intensity).overrideState = true;
			((ParameterOverride<float>)(object)val6.intensity).value = 0.15f;
			val2.AddSettings((PostProcessEffectSettings)(object)val6);
			Grain val7 = ScriptableObject.CreateInstance<Grain>();
			((ParameterOverride<bool>)(object)((PostProcessEffectSettings)val7).enabled).value = true;
			((ParameterOverride)val7.intensity).overrideState = true;
			((ParameterOverride<float>)(object)val7.intensity).value = 0.3f;
			((ParameterOverride)val7.size).overrideState = true;
			((ParameterOverride<float>)(object)val7.size).value = 1.2f;
			val2.AddSettings((PostProcessEffectSettings)(object)val7);
			MotionBlur val8 = ScriptableObject.CreateInstance<MotionBlur>();
			((ParameterOverride<bool>)(object)((PostProcessEffectSettings)val8).enabled).value = true;
			((ParameterOverride)val8.shutterAngle).overrideState = true;
			((ParameterOverride<float>)(object)val8.shutterAngle).value = 150f;
			((ParameterOverride)val8.sampleCount).overrideState = true;
			((ParameterOverride<int>)(object)val8.sampleCount).value = 8;
			val2.AddSettings((PostProcessEffectSettings)(object)val8);
			AutoExposure val9 = ScriptableObject.CreateInstance<AutoExposure>();
			((ParameterOverride<bool>)(object)((PostProcessEffectSettings)val9).enabled).value = true;
			((ParameterOverride)val9.minLuminance).overrideState = true;
			((ParameterOverride<float>)(object)val9.minLuminance).value = -2f;
			((ParameterOverride)val9.maxLuminance).overrideState = true;
			((ParameterOverride<float>)(object)val9.maxLuminance).value = 2f;
			val2.AddSettings((PostProcessEffectSettings)(object)val9);
			_ppVolume.profile = val2;
			Plugin.Log.LogInfo((object)$"[PREVIEW] Applied post-processing: bloom={level.BloomIntensity}, colorFilter={level.ColorFilter}, vignette={level.VignetteIntensity}, +chromaticAberration, grain, motionBlur, autoExposure");
		}

		private void Update()
		{
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: 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_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			if (Input.GetMouseButton(1))
			{
				Cursor.lockState = (CursorLockMode)1;
				Cursor.visible = false;
				_yaw += Input.GetAxis("Mouse X") * 3f;
				_pitch -= Input.GetAxis("Mouse Y") * 3f;
				_pitch = Mathf.Clamp(_pitch, -90f, 90f);
				((Component)this).transform.rotation = Quaternion.Euler(_pitch, _yaw, 0f);
			}
			else
			{
				Cursor.lockState = (CursorLockMode)0;
				Cursor.visible = true;
			}
			float num = _speed;
			if (Input.GetKey((KeyCode)304))
			{
				num *= 3f;
			}
			Vector3 val = Vector3.zero;
			if (Input.GetKey((KeyCode)119))
			{
				val += ((Component)this).transform.forward;
			}
			if (Input.GetKey((KeyCode)115))
			{
				val -= ((Component)this).transform.forward;
			}
			if (Input.GetKey((KeyCode)97))
			{
				val -= ((Component)this).transform.right;
			}
			if (Input.GetKey((KeyCode)100))
			{
				val += ((Component)this).transform.right;
			}
			if (Input.GetKey((KeyCode)32))
			{
				val += Vector3.up;
			}
			if (Input.GetKey((KeyCode)306))
			{
				val -= Vector3.up;
			}
			Transform transform = ((Component)this).transform;
			transform.position += ((Vector3)(ref val)).normalized * num * Time.deltaTime;
		}

		private void OnGUI()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Invalid comparison between Unknown and I4
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_renderTexture != (Object)null && (int)Event.current.type == 7)
			{
				GUI.DrawTexture(new Rect(0f, 0f, (float)Screen.width, (float)Screen.height), (Texture)(object)_renderTexture, (ScaleMode)0);
			}
		}

		private void OnDestroy()
		{
			Cursor.lockState = (CursorLockMode)0;
			Cursor.visible = true;
			if ((Object)(object)_ppVolume != (Object)null && (Object)(object)_ppVolume.profile != (Object)null)
			{
				Object.Destroy((Object)(object)_ppVolume.profile);
			}
			if ((Object)(object)_renderTexture != (Object)null)
			{
				if ((Object)(object)_camera != (Object)null)
				{
					_camera.targetTexture = null;
				}
				Object.Destroy((Object)(object)_renderTexture);
			}
		}
	}
	public enum PreviewState
	{
		Idle,
		Loading,
		Previewing,
		Unloading
	}
	public class MapPreviewManager : MonoBehaviour
	{
		private class PreviewTile
		{
			public int x;

			public int y;

			public bool active;

			public bool first;

			public Type type;

			public bool connectedTop;

			public bool connectedBot;

			public bool connectedRight;

			public bool connectedLeft;

			public int connections;
		}

		[CompilerGenerated]
		private sealed class <>c__DisplayClass31_0
		{
			public string levelName;

			internal bool <BuildPreview>b__0(Level l)
			{
				return ((Object)l).name == levelName;
			}
		}

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

			private object <>2__current;

			public Level level;

			private Vector3 <previewOrigin>5__2;

			private List<GameObject> <modulesToSpawn>5__3;

			private int <totalModules>5__4;

			private int <gridSize>5__5;

			private int <i>5__6;

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

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

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

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

			private bool MoveNext()
			{
				//IL_002a: Unknown result type (might be due to invalid IL or missing references)
				//IL_002f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0039: Unknown result type (might be due to invalid IL or missing references)
				//IL_0043: Expected O, but got Unknown
				//IL_004e: Unknown result type (might be due to invalid IL or missing references)
				//IL_022d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0249: Unknown result type (might be due to invalid IL or missing references)
				//IL_024e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0253: Unknown result type (might be due to invalid IL or missing references)
				//IL_0266: Unknown result type (might be due to invalid IL or missing references)
				//IL_0268: Unknown result type (might be due to invalid IL or missing references)
				int num = <>1__state;
				if (num != 0)
				{
					if (num != 1)
					{
						return false;
					}
					<>1__state = -1;
					goto IL_02a3;
				}
				<>1__state = -1;
				<previewOrigin>5__2 = new Vector3(0f, -3000f, 0f);
				_previewRoot = new GameObject("MapPreviewRoot");
				_previewRoot.transform.position = <previewOrigin>5__2;
				<modulesToSpawn>5__3 = new List<GameObject>();
				if (level.StartRooms != null)
				{
					foreach (PrefabRef startRoom in level.StartRooms)
					{
						if (startRoom != null)
						{
							GameObject prefab = startRoom.Prefab;
							if ((Object)(object)prefab != (Object)null)
							{
								<modulesToSpawn>5__3.Add(prefab);
							}
						}
					}
				}
				AddPrefabRefs(<modulesToSpawn>5__3, level.ModulesNormal1);
				AddPrefabRefs(<modulesToSpawn>5__3, level.ModulesNormal2);
				AddPrefabRefs(<modulesToSpawn>5__3, level.ModulesNormal3);
				AddPrefabRefs(<modulesToSpawn>5__3, level.ModulesPassage1);
				AddPrefabRefs(<modulesToSpawn>5__3, level.ModulesPassage2);
				AddPrefabRefs(<modulesToSpawn>5__3, level.ModulesPassage3);
				AddPrefabRefs(<modulesToSpawn>5__3, level.ModulesDeadEnd1);
				AddPrefabRefs(<modulesToSpawn>5__3, level.ModulesDeadEnd2);
				AddPrefabRefs(<modulesToSpawn>5__3, level.ModulesDeadEnd3);
				AddPrefabRefs(<modulesToSpawn>5__3, level.ModulesExtraction1);
				AddPrefabRefs(<modulesToSpawn>5__3, level.ModulesExtraction2);
				AddPrefabRefs(<modulesToSpawn>5__3, level.ModulesExtraction3);
				if (<modulesToSpawn>5__3.Count == 0)
				{
					return false;
				}
				<totalModules>5__4 = <modulesToSpawn>5__3.Count;
				<gridSize>5__5 = Mathf.CeilToInt(Mathf.Sqrt((float)<totalModules>5__4));
				<i>5__6 = 0;
				goto IL_02b5;
				IL_02b5:
				if (<i>5__6 < <totalModules>5__4)
				{
					int num2 = <i>5__6 / <gridSize>5__5;
					int num3 = <i>5__6 % <gridSize>5__5;
					Vector3 val = <previewOrigin>5__2 + new Vector3((float)num3 * 15f, 0f, (float)num2 * 15f);
					StripComponents(Object.Instantiate<GameObject>(<modulesToSpawn>5__3[<i>5__6], val, Quaternion.identity, _previewRoot.transform));
					if (<i>5__6 % 3 == 2)
					{
						<>2__current = null;
						<>1__state = 1;
						return true;
					}
					goto IL_02a3;
				}
				return false;
				IL_02a3:
				<i>5__6++;
				goto IL_02b5;
			}

			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 <BuildPreview>d__31 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public string levelName;

			private <>c__DisplayClass31_0 <>8__1;

			private RunManager <runManager>5__2;

			private Level <level>5__3;

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

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

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

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

			private bool MoveNext()
			{
				//IL_0178: Unknown result type (might be due to invalid IL or missing references)
				//IL_017d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0196: Unknown result type (might be due to invalid IL or missing references)
				//IL_019b: Unknown result type (might be due to invalid IL or missing references)
				//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
				//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
				//IL_021f: Unknown result type (might be due to invalid IL or missing references)
				//IL_026e: Unknown result type (might be due to invalid IL or missing references)
				//IL_02b5: Unknown result type (might be due to invalid IL or missing references)
				//IL_02c9: Unknown result type (might be due to invalid IL or missing references)
				//IL_02ce: Unknown result type (might be due to invalid IL or missing references)
				//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
				//IL_02d3: Unknown result type (might be due to invalid IL or missing references)
				//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_02ff: Unknown result type (might be due to invalid IL or missing references)
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>8__1 = new <>c__DisplayClass31_0();
					<>8__1.levelName = levelName;
					State = PreviewState.Loading;
					Plugin.Log.LogInfo((object)("[PREVIEW] Building preview for: " + <>8__1.levelName));
					<runManager>5__2 = Object.FindObjectOfType<RunManager>();
					if ((Object)(object)<runManager>5__2 == (Object)null)
					{
						Plugin.Log.LogError((object)"[PREVIEW] RunManager not found");
						State = PreviewState.Idle;
						return false;
					}
					<level>5__3 = <runManager>5__2.levels.Find((Level l) => ((Object)l).name == <>8__1.levelName);
					if ((Object)(object)<level>5__3 == (Object)null)
					{
						Plugin.Log.LogError((object)("[PREVIEW] Level '" + <>8__1.levelName + "' not found"));
						State = PreviewState.Idle;
						return false;
					}
					if ((Object)(object)MapVote.VotePopup != (Object)null)
					{
						MapVote.VotePopup.ClosePage(true);
					}
					_loadingLevelName = <>8__1.levelName.Replace("Level - ", "");
					_showLoadingScreen = true;
					<>2__current = null;
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					<>2__current = null;
					<>1__state = 2;
					return true;
				case 2:
				{
					<>1__state = -1;
					LevelGenerator levelGen = Object.FindObjectOfType<LevelGenerator>();
					DisableLobby();
					_savedFog = RenderSettings.fog;
					_savedFogColor = RenderSettings.fogColor;
					_savedFogStart = RenderSettings.fogStartDistance;
					_savedFogEnd = RenderSettings.fogEndDistance;
					_savedFogMode = RenderSettings.fogMode;
					_savedAmbientLight = RenderSettings.ambientLight;
					bool flag = false;
					try
					{
						flag = TryProceduralGeneration(<runManager>5__2, <level>5__3, levelGen);
					}
					catch (Exception ex)
					{
						Plugin.Log.LogWarning((object)("[PREVIEW] Procedural generation failed: " + ex.Message + ", falling back to grid"));
					}
					if (!flag)
					{
						<>2__current = ((MonoBehaviour)Instance).StartCoroutine(BuildGridPreview(<level>5__3));
						<>1__state = 3;
						return true;
					}
					break;
				}
				case 3:
					<>1__state = -1;
					break;
				}
				RenderSettings.fog = true;
				RenderSettings.fogColor = <level>5__3.FogColor;
				RenderSettings.fogMode = (FogMode)1;
				RenderSettings.fogStartDistance = <level>5__3.FogStartDistance;
				RenderSettings.fogEndDistance = ((<level>5__3.FogEndDistance > 0f) ? <level>5__3.FogEndDistance : 15f);
				RenderSettings.ambientLight = <level>5__3.AmbientColor;
				RenderSettings.ambientIntensity = 1f;
				RenderSettings.ambientMode = (AmbientMode)3;
				Vector3 startPosition = (Vector3)(((Object)(object)_previewRoot != (Object)null) ? (_previewRoot.transform.position + new Vector3(15f, 8f, 15f)) : new Vector3(0f, 5f, 0f));
				_freecam = new GameObject("MapPreviewFreecam")
				{
					hideFlags = (HideFlags)61
				}.AddComponent<FreecamController>();
				_freecam.Initialize(Plugin.FreecamSpeed.Value, startPosition);
				_freecam.ApplyLevelEffects(<level>5__3);
				_showLoadingScreen = false;
				BroadcastPreviewStart(<>8__1.levelName);
				State = PreviewState.Previewing;
				Plugin.Log.LogInfo((object)("[PREVIEW] Now previewing: " + <>8__1.levelName));
				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 string _previewLevelName;

		private static FreecamController _freecam;

		private static GameObject _previewRoot;

		private static List<GameObject> _disabledRootObjects = new List<GameObject>();

		private static bool _cancelRequested;

		private static bool _savedFog;

		private static Color _savedFogColor;

		private static float _savedFogStart;

		private static float _savedFogEnd;

		private static FogMode _savedFogMode;

		private static Color _savedAmbientLight;

		private const float MODULE_SPACING = 15f;

		private static bool _showLoadingScreen;

		private static string _loadingLevelName;

		private static Texture2D _blackTex;

		private static Level _savedLevel;

		private static readonly HashSet<string> KEEP_ACTIVE = new HashSet<string>
		{
			"MapPreviewRoot", "MapPreviewFreecam", "MapVotePreview", "MapVoteWithPreview", "REPOPingMod", "BepInEx_Manager", "PhotonMono", "PunVoiceClient(Clone)", "NetworkManager", "Steam Manager",
			"PhotonHandler"
		};

		public static MapPreviewManager Instance { get; private set; }

		public static PreviewState State { get; private set; } = PreviewState.Idle;


		private void Awake()
		{
			if ((Object)(object)Instance != (Object)null && (Object)(object)Instance != (Object)(object)this)
			{
				Object.Destroy((Object)(object)this);
			}
			else
			{
				Instance = this;
			}
		}

		public static void StartPreview(string levelName)
		{
			if (State == PreviewState.Idle && Plugin.PreviewEnabled.Value && !((Object)(object)Instance == (Object)null))
			{
				_previewLevelName = levelName;
				_cancelRequested = false;
				((MonoBehaviour)Instance).StartCoroutine(BuildPreview(levelName));
			}
		}

		public static void StopPreview()
		{
			if (State == PreviewState.Previewing && !((Object)(object)Instance == (Object)null))
			{
				CleanupPreview();
				RestoreLobby();
				BroadcastPreviewEnd();
				MapVote.CreateVotePopup(((Object)RunManager.instance.levelCurrent).name != "Level - Lobby");
				State = PreviewState.Idle;
				_previewLevelName = null;
				Plugin.Log.LogInfo((object)"[PREVIEW] Preview closed");
			}
		}

		public static void ForceClose()
		{
			if (State != 0)
			{
				_cancelRequested = true;
				if ((Object)(object)Instance != (Object)null)
				{
					((MonoBehaviour)Instance).StopAllCoroutines();
				}
				CleanupPreview();
				RestoreLobby();
				BroadcastPreviewEnd();
				State = PreviewState.Idle;
				_previewLevelName = null;
				_cancelRequested = false;
			}
		}

		private static void CleanupPreview()
		{
			_showLoadingScreen = false;
			if ((Object)(object)_freecam != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)_freecam).gameObject);
				_freecam = null;
			}
			if ((Object)(object)_previewRoot != (Object)null)
			{
				Object.Destroy((Object)(object)_previewRoot);
				_previewRoot = null;
			}
		}

		public static void HandlePreviewStart(EventData data)
		{
			string[] array = ((string)data.CustomData).Split('|');
			if (array.Length >= 2)
			{
				Plugin.PreviewingPlayers[array[0]] = array[1];
				MapVote.UpdateButtonLabels();
			}
		}

		public static void HandlePreviewEnd(EventData data)
		{
			string key = (string)data.CustomData;
			Plugin.PreviewingPlayers.Remove(key);
			MapVote.UpdateButtonLabels();
		}

		[IteratorStateMachine(typeof(<BuildPreview>d__31))]
		private static IEnumerator BuildPreview(string levelName)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <BuildPreview>d__31(0)
			{
				levelName = levelName
			};
		}

		private static bool GridCheck(PreviewTile[,] grid, int x, int y, int w, int h)
		{
			if (x >= 0 && x < w && y >= 0 && y < h)
			{
				return grid[x, y].active;
			}
			return false;
		}

		private static bool TryProceduralGeneration(RunManager runManager, Level level, LevelGenerator levelGen)
		{
			//IL_0829: Unknown result type (might be due to invalid IL or missing references)
			//IL_07cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_07d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_07e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_07ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_08a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_08c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_08cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_08d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_08d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_08d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_08e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_08ed: Invalid comparison between Unknown and I4
			//IL_09b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_09b8: Invalid comparison between Unknown and I4
			//IL_0923: Unknown result type (might be due to invalid IL or missing references)
			//IL_0928: Unknown result type (might be due to invalid IL or missing references)
			//IL_09ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_09f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f4: Expected O, but got Unknown
			//IL_05fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c90: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c9d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c9f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ca1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0cae: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ccc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0cce: Unknown result type (might be due to invalid IL or missing references)
			//IL_0cd0: Unknown result type (might be due to invalid IL or missing references)
			//IL_04bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e82: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e95: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e9a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e9f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0edd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0edf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ee1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0efc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0efe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0f60: Unknown result type (might be due to invalid IL or missing references)
			//IL_0f73: Unknown result type (might be due to invalid IL or missing references)
			//IL_0f78: Unknown result type (might be due to invalid IL or missing references)
			//IL_0f7d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0fbb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0fbd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0fbf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0fda: Unknown result type (might be due to invalid IL or missing references)
			//IL_0feb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0726: Unknown result type (might be due to invalid IL or missing references)
			//IL_0728: Unknown result type (might be due to invalid IL or missing references)
			//IL_0385: Unknown result type (might be due to invalid IL or missing references)
			//IL_104d: Unknown result type (might be due to invalid IL or missing references)
			//IL_1060: Unknown result type (might be due to invalid IL or missing references)
			//IL_1065: Unknown result type (might be due to invalid IL or missing references)
			//IL_106a: Unknown result type (might be due to invalid IL or missing references)
			//IL_10a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_10aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_10ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_10c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_10c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b8b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b75: Unknown result type (might be due to invalid IL or missing references)
			//IL_030d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0322: Unknown result type (might be due to invalid IL or missing references)
			//IL_112b: Unknown result type (might be due to invalid IL or missing references)
			//IL_113e: Unknown result type (might be due to invalid IL or missing references)
			//IL_1143: Unknown result type (might be due to invalid IL or missing references)
			//IL_1148: Unknown result type (might be due to invalid IL or missing references)
			//IL_1186: Unknown result type (might be due to invalid IL or missing references)
			//IL_1188: Unknown result type (might be due to invalid IL or missing references)
			//IL_118a: Unknown result type (might be due to invalid IL or missing references)
			//IL_11a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_11a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0bf5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0bdf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b90: Unknown result type (might be due to invalid IL or missing references)
			//IL_0bfa: Unknown result type (might be due to invalid IL or missing references)
			Plugin.Log.LogInfo((object)"[PREVIEW] Attempting procedural generation (exact game algorithm)...");
			_savedLevel = runManager.levelCurrent;
			float num = 5f;
			float num2 = 3f * num;
			int num3 = 9;
			int num4 = 9;
			int num5 = Mathf.Max((level.ModuleAmount > 0) ? level.ModuleAmount : 6, 6);
			num5 = Mathf.Min(num5 * 2, num3 * num4 - 1);
			int num6 = Mathf.CeilToInt((float)num5 / 3f);
			int num7 = ((num5 >= 15) ? 4 : ((num5 >= 10) ? 3 : ((num5 >= 8) ? 2 : ((num5 >= 6) ? 1 : 0))));
			PreviewTile[,] array = new PreviewTile[num3, num4];
			for (int i = 0; i < num3; i++)
			{
				for (int j = 0; j < num4; j++)
				{
					array[i, j] = new PreviewTile
					{
						x = i,
						y = j
					};
				}
			}
			int num8 = num3 / 2;
			int num9 = 0;
			array[num8, num9].active = true;
			array[num8, num9].first = true;
			int num10 = num5;
			int num11 = num8;
			int num12 = num9;
			int num13 = 10000;
			while (num10 > 0 && num13-- > 0)
			{
				int num14 = -999;
				int num15 = -999;
				while (num11 + num14 < 0 || num11 + num14 >= num3 || num12 + num15 < 0 || num12 + num15 >= num4)
				{
					num14 = 0;
					num15 = 0;
					switch ((num12 == 1) ? Random.Range(0, 3) : Random.Range(0, 4))
					{
					case 0:
						num14 = -1;
						break;
					case 1:
						num14 = 1;
						break;
					case 2:
						num15 = 1;
						break;
					case 3:
						num15 = -1;
						break;
					}
				}
				num11 += num14;
				num12 += num15;
				if (!array[num11, num12].active)
				{
					array[num11, num12].active = true;
					num10--;
				}
			}
			List<PreviewTile> list = new List<PreviewTile>();
			for (int k = 0; k < num3; k++)
			{
				for (int l = 0; l < num4; l++)
				{
					if (!array[k, l].active)
					{
						int num16 = 0;
						if (GridCheck(array, k, l + 1, num3, num4))
						{
							num16++;
						}
						if (GridCheck(array, k + 1, l, num3, num4))
						{
							num16++;
						}
						if (GridCheck(array, k, l - 1, num3, num4))
						{
							num16++;
						}
						if (GridCheck(array, k - 1, l, num3, num4))
						{
							num16++;
						}
						if (num16 == 1)
						{
							list.Add(array[k, l]);
						}
					}
				}
			}
			PreviewTile item = new PreviewTile
			{
				x = num8,
				y = -1
			};
			List<PreviewTile> list2 = new List<PreviewTile> { item };
			int num17 = num7;
			while (num17 > 0 && list.Count > 0)
			{
				PreviewTile previewTile = null;
				float num18 = 0f;
				foreach (PreviewTile item2 in list)
				{
					float num19 = float.MaxValue;
					foreach (PreviewTile item3 in list2)
					{
						float num20 = Vector2.Distance(new Vector2((float)item3.x, (float)item3.y), new Vector2((float)item2.x, (float)item2.y));
						if (num20 < num19)
						{
							num19 = num20;
						}
					}
					if (num19 > num18)
					{
						num18 = num19;
						previewTile = item2;
					}
				}
				if (previewTile == null)
				{
					break;
				}
				previewTile.type = (Type)3;
				previewTile.active = true;
				list2.Add(previewTile);
				list.Remove(previewTile);
				bool flag = true;
				while (flag)
				{
					flag = false;
					foreach (PreviewTile item4 in list)
					{
						if ((item4.x == previewTile.x && item4.y == previewTile.y - 1) || (item4.x == previewTile.x + 1 && item4.y == previewTile.y) || (item4.x == previewTile.x && item4.y == previewTile.y + 1) || (item4.x == previewTile.x - 1 && item4.y == previewTile.y))
						{
							list.Remove(item4);
							flag = true;
							break;
						}
					}
				}
				num17--;
			}
			int num21 = num6;
			while (num21 > 0 && list.Count > 0)
			{
				PreviewTile previewTile2 = list[Random.Range(0, list.Count)];
				previewTile2.type = (Type)2;
				previewTile2.active = true;
				list2.Add(previewTile2);
				list.Remove(previewTile2);
				bool flag2 = true;
				while (flag2)
				{
					flag2 = false;
					foreach (PreviewTile item5 in list)
					{
						if ((item5.x == previewTile2.x && item5.y == previewTile2.y - 1) || (item5.x == previewTile2.x + 1 && item5.y == previewTile2.y) || (item5.x == previewTile2.x && item5.y == previewTile2.y + 1) || (item5.x == previewTile2.x - 1 && item5.y == previewTile2.y))
						{
							list.Remove(item5);
							flag2 = true;
							break;
						}
					}
				}
				num21--;
			}
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(0f, -3000f, 0f);
			_previewRoot = new GameObject("MapPreviewRoot");
			_previewRoot.transform.position = val;
			List<GameObject> list3 = new List<GameObject>();
			AddPrefabRefs(list3, level.ModulesNormal1);
			AddPrefabRefs(list3, level.ModulesNormal2);
			AddPrefabRefs(list3, level.ModulesNormal3);
			List<GameObject> list4 = new List<GameObject>();
			AddPrefabRefs(list4, level.ModulesPassage1);
			AddPrefabRefs(list4, level.ModulesPassage2);
			AddPrefabRefs(list4, level.ModulesPassage3);
			List<GameObject> list5 = new List<GameObject>();
			AddPrefabRefs(list5, level.ModulesDeadEnd1);
			AddPrefabRefs(list5, level.ModulesDeadEnd2);
			AddPrefabRefs(list5, level.ModulesDeadEnd3);
			List<GameObject> list6 = new List<GameObject>();
			AddPrefabRefs(list6, level.ModulesExtraction1);
			AddPrefabRefs(list6, level.ModulesExtraction2);
			AddPrefabRefs(list6, level.ModulesExtraction3);
			if (level.StartRooms != null && level.StartRooms.Count > 0)
			{
				PrefabRef val2 = level.StartRooms[Random.Range(0, level.StartRooms.Count)];
				if (val2 != null && (Object)(object)val2.Prefab != (Object)null)
				{
					Plugin.Log.LogInfo((object)"[PREVIEW] Start room at origin (0,0,0) — game exact");
					GameObject val3 = Object.Instantiate<GameObject>(val2.Prefab, val, Quaternion.identity, _previewRoot.transform);
					Module component = val3.GetComponent<Module>();
					if ((Object)(object)component != (Object)null)
					{
						component.ConnectingTop = true;
						component.ConnectingBottom = true;
						component.ConnectingRight = false;
						component.ConnectingLeft = false;
						component.First = true;
						component.SetupDone = true;
						ModulePropSwitch[] componentsInChildren = val3.GetComponentsInChildren<ModulePropSwitch>(true);
						foreach (ModulePropSwitch val4 in componentsInChildren)
						{
							val4.Module = component;
							try
							{
								val4.Setup();
							}
							catch
							{
							}
						}
					}
					StripComponents(val3);
				}
			}
			if ((Object)(object)level.ConnectObject != (Object)null)
			{
				Vector3 val5 = val;
				Plugin.Log.LogInfo((object)"[CONN] Truck connection at pos=(0,0,0)");
				StripComponents(Object.Instantiate<GameObject>(level.ConnectObject, val5, Quaternion.identity, _previewRoot.transform));
			}
			Plugin.Log.LogInfo((object)$"[PREVIEW] Start room at grid({num8},{num9}), world origin={val}, moduleWidth={num2}");
			Plugin.Log.LogInfo((object)$"[PREVIEW] Start grid formula: x={(float)num8 * num2 - (float)(num3 / 2) * num2}, z={(float)num9 * num2 + num2 / 2f}");
			int num22 = 0;
			int num23 = 0;
			for (int n = 0; n < num3; n++)
			{
				for (int num24 = 0; num24 < num4; num24++)
				{
					if (!array[n, num24].active)
					{
						continue;
					}
					Vector3 val6 = val + new Vector3((float)n * num2 - (float)(num3 / 2) * num2, 0f, (float)num24 * num2 + num2 / 2f);
					Vector3 val7 = Vector3.zero;
					GameObject val8 = null;
					if ((int)array[n, num24].type == 3)
					{
						if (list6.Count > 0)
						{
							val8 = list6[Random.Range(0, list6.Count)];
						}
						if (GridCheck(array, n, num24 - 1, num3, num4))
						{
							val7 = Vector3.zero;
						}
						if (GridCheck(array, n - 1, num24, num3, num4))
						{
							((Vector3)(ref val7))..ctor(0f, 90f, 0f);
						}
						if (GridCheck(array, n, num24 + 1, num3, num4))
						{
							((Vector3)(ref val7))..ctor(0f, 180f, 0f);
						}
						if (GridCheck(array, n + 1, num24, num3, num4))
						{
							((Vector3)(ref val7))..ctor(0f, -90f, 0f);
						}
					}
					else if ((int)array[n, num24].type == 2)
					{
						if (list5.Count > 0)
						{
							val8 = list5[Random.Range(0, list5.Count)];
						}
						if (GridCheck(array, n, num24 - 1, num3, num4))
						{
							val7 = Vector3.zero;
						}
						if (GridCheck(array, n - 1, num24, num3, num4))
						{
							((Vector3)(ref val7))..ctor(0f, 90f, 0f);
						}
						if (GridCheck(array, n, num24 + 1, num3, num4))
						{
							((Vector3)(ref val7))..ctor(0f, 180f, 0f);
						}
						if (GridCheck(array, n + 1, num24, num3, num4))
						{
							((Vector3)(ref val7))..ctor(0f, -90f, 0f);
						}
					}
					else
					{
						bool flag3 = num23 < ((level.PassageMaxAmount > 0) ? level.PassageMaxAmount : 2);
						bool flag4 = GridCheck(array, n, num24 + 1, num3, num4) && (GridCheck(array, n, num24 - 1, num3, num4) || array[n, num24].first) && !GridCheck(array, n + 1, num24, num3, num4) && !GridCheck(array, n - 1, num24, num3, num4);
						bool flag5 = !array[n, num24].first && GridCheck(array, n + 1, num24, num3, num4) && GridCheck(array, n - 1, num24, num3, num4) && !GridCheck(array, n, num24 + 1, num3, num4) && !GridCheck(array, n, num24 - 1, num3, num4);
						if (flag3 && flag4 && list4.Count > 0)
						{
							val8 = list4[Random.Range(0, list4.Count)];
							val7 = (Vector3)((Random.Range(0, 100) < 50) ? new Vector3(0f, 180f, 0f) : Vector3.zero);
							num23++;
						}
						else if (flag3 && flag5 && list4.Count > 0)
						{
							val8 = list4[Random.Range(0, list4.Count)];
							val7 = ((Random.Range(0, 100) < 50) ? new Vector3(0f, -90f, 0f) : new Vector3(0f, 90f, 0f));
							num23++;
						}
						else
						{
							if (list3.Count > 0)
							{
								val8 = list3[Random.Range(0, list3.Count)];
							}
							float[] array2 = new float[4] { 0f, 90f, 180f, 270f };
							((Vector3)(ref val7))..ctor(0f, array2[Random.Range(0, 4)], 0f);
						}
					}
					if (!((Object)(object)val8 != (Object)null))
					{
						continue;
					}
					Plugin.Log.LogInfo((object)$"[PREVIEW] Module grid({n},{num24}) type={array[n, num24].type} pos={val6 - val} rot={val7} prefab={((Object)val8).name}");
					GameObject val9 = Object.Instantiate<GameObject>(val8, val6, Quaternion.Euler(val7), _previewRoot.transform);
					bool connectingTop = GridCheck(array, n, num24 + 1, num3, num4);
					bool connectingBottom = GridCheck(array, n, num24 - 1, num3, num4) || array[n, num24].first;
					bool connectingRight = GridCheck(array, n + 1, num24, num3, num4);
					bool connectingLeft = GridCheck(array, n - 1, num24, num3, num4);
					Module component2 = val9.GetComponent<Module>();
					if ((Object)(object)component2 != (Object)null)
					{
						component2.ConnectingTop = connectingTop;
						component2.ConnectingBottom = connectingBottom;
						component2.ConnectingRight = connectingRight;
						component2.ConnectingLeft = connectingLeft;
						component2.First = array[n, num24].first;
						component2.SetupDone = true;
						ModulePropSwitch[] componentsInChildren = val9.GetComponentsInChildren<ModulePropSwitch>(true);
						foreach (ModulePropSwitch val10 in componentsInChildren)
						{
							val10.Module = component2;
							try
							{
								val10.Setup();
							}
							catch
							{
							}
						}
					}
					StripComponents(val9);
					num22++;
				}
			}
			if ((Object)(object)level.ConnectObject != (Object)null)
			{
				for (int num25 = 0; num25 < num3; num25++)
				{
					for (int num26 = 0; num26 < num4; num26++)
					{
						if (array[num25, num26].active)
						{
							float num27 = (float)num25 * num2 - (float)(num3 / 2) * num2;
							float num28 = (float)num26 * num2 + num2 / 2f;
							if (num26 + 1 < num4 && array[num25, num26 + 1].active && !array[num25, num26 + 1].connectedBot)
							{
								Vector3 val11 = val + new Vector3(num27, 0f, num28 + num2 / 2f);
								Plugin.Log.LogInfo((object)$"[CONN] Top: grid({num25},{num26})->({num25},{num26 + 1}) pos={val11 - val}");
								StripComponents(Object.Instantiate<GameObject>(level.ConnectObject, val11, Quaternion.identity, _previewRoot.transform));
								array[num25, num26].connectedTop = true;
							}
							if (num25 + 1 < num3 && array[num25 + 1, num26].active && !array[num25 + 1, num26].connectedLeft)
							{
								Vector3 val12 = val + new Vector3(num27 + num2 / 2f, 0f, num28);
								Plugin.Log.LogInfo((object)$"[CONN] Right: grid({num25},{num26})->({num25 + 1},{num26}) pos={val12 - val} rot=90");
								StripComponents(Object.Instantiate<GameObject>(level.ConnectObject, val12, Quaternion.Euler(0f, 90f, 0f), _previewRoot.transform));
								array[num25, num26].connectedRight = true;
							}
							if (num26 - 1 >= 0 && array[num25, num26 - 1].active && !array[num25, num26 - 1].connectedTop)
							{
								Vector3 val13 = val + new Vector3(num27, 0f, num28 - num2 / 2f);
								Plugin.Log.LogInfo((object)$"[CONN] Bottom: grid({num25},{num26})->({num25},{num26 - 1}) pos={val13 - val}");
								StripComponents(Object.Instantiate<GameObject>(level.ConnectObject, val13, Quaternion.identity, _previewRoot.transform));
								array[num25, num26].connectedBot = true;
							}
							if (num25 - 1 >= 0 && array[num25 - 1, num26].active && !array[num25 - 1, num26].connectedRight)
							{
								Vector3 val14 = val + new Vector3(num27 - num2 / 2f, 0f, num28);
								Plugin.Log.LogInfo((object)$"[CONN] Left: grid({num25},{num26})->({num25 - 1},{num26}) pos={val14 - val}");
								StripComponents(Object.Instantiate<GameObject>(level.ConnectObject, val14, Quaternion.identity, _previewRoot.transform));
								array[num25, num26].connectedLeft = true;
							}
						}
					}
				}
			}
			runManager.levelCurrent = _savedLevel;
			Plugin.Log.LogInfo((object)$"[PREVIEW] Procedural generation complete: {num22} modules + start room on {num3}x{num4} grid");
			return num22 > 0;
		}

		[IteratorStateMachine(typeof(<BuildGridPreview>d__35))]
		private static IEnumerator BuildGridPreview(Level level)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <BuildGridPreview>d__35(0)
			{
				level = level
			};
		}

		private static void AddPrefabRefs(List<GameObject> list, List<PrefabRef> source)
		{
			if (source == null)
			{
				return;
			}
			foreach (PrefabRef item in source)
			{
				if (item != null)
				{
					GameObject prefab = item.Prefab;
					if ((Object)(object)prefab != (Object)null)
					{
						list.Add(prefab);
					}
				}
			}
		}

		private static void StripComponents(GameObject obj)
		{
			MonoBehaviour[] componentsInChildren = obj.GetComponentsInChildren<MonoBehaviour>(true);
			foreach (MonoBehaviour val in componentsInChildren)
			{
				if ((Object)(object)val != (Object)null)
				{
					((Behaviour)val).enabled = false;
				}
			}
			Collider[] componentsInChildren2 = obj.GetComponentsInChildren<Collider>(true);
			foreach (Collider val2 in componentsInChildren2)
			{
				if ((Object)(object)val2 != (Object)null)
				{
					val2.enabled = false;
				}
			}
			Rigidbody[] componentsInChildren3 = obj.GetComponentsInChildren<Rigidbody>(true);
			foreach (Rigidbody val3 in componentsInChildren3)
			{
				if ((Object)(object)val3 != (Object)null)
				{
					val3.isKinematic = true;
				}
			}
			AudioSource[] componentsInChildren4 = obj.GetComponentsInChildren<AudioSource>(true);
			foreach (AudioSource val4 in componentsInChildren4)
			{
				if ((Object)(object)val4 != (Object)null)
				{
					((Behaviour)val4).enabled = false;
				}
			}
			Animator[] componentsInChildren5 = obj.GetComponentsInChildren<Animator>(true);
			foreach (Animator val5 in componentsInChildren5)
			{
				if ((Object)(object)val5 != (Object)null)
				{
					((Behaviour)val5).enabled = false;
				}
			}
			ParticleSystem[] componentsInChildren6 = obj.GetComponentsInChildren<ParticleSystem>(true);
			foreach (ParticleSystem val6 in componentsInChildren6)
			{
				if ((Object)(object)val6 != (Object)null)
				{
					val6.Stop();
				}
			}
		}

		private static void DisableLobby()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Invalid comparison between Unknown and I4
			_disabledRootObjects.Clear();
			Scene activeScene = SceneManager.GetActiveScene();
			GameObject[] rootGameObjects = ((Scene)(ref activeScene)).GetRootGameObjects();
			foreach (GameObject val in rootGameObjects)
			{
				if (!((Object)(object)val == (Object)null) && val.activeSelf && !KEEP_ACTIVE.Contains(((Object)val).name) && (int)((Object)val).hideFlags != 61)
				{
					val.SetActive(false);
					_disabledRootObjects.Add(val);
				}
			}
			Plugin.Log.LogInfo((object)$"[PREVIEW] Disabled {_disabledRootObjects.Count} root objects");
		}

		private static void RestoreLobby()
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			foreach (GameObject disabledRootObject in _disabledRootObjects)
			{
				if ((Object)(object)disabledRootObject != (Object)null)
				{
					disabledRootObject.SetActive(true);
				}
			}
			RenderSettings.fog = _savedFog;
			RenderSettings.fogColor = _savedFogColor;
			RenderSettings.fogStartDistance = _savedFogStart;
			RenderSettings.fogEndDistance = _savedFogEnd;
			RenderSettings.fogMode = _savedFogMode;
			RenderSettings.ambientLight = _savedAmbientLight;
			Plugin.Log.LogInfo((object)$"[PREVIEW] Re-enabled {_disabledRootObjects.Count} root objects");
			_disabledRootObjects.Clear();
		}

		private static void BroadcastPreviewStart(string levelName)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			if (SemiFunc.IsMultiplayer())
			{
				string nickName = PhotonNetwork.LocalPlayer.NickName;
				NetworkedEvent onPreviewStart = Plugin.OnPreviewStart;
				if (onPreviewStart != null)
				{
					onPreviewStart.RaiseEvent((object)(nickName + "|" + levelName), NetworkingEvents.RaiseOthers, SendOptions.SendReliable);
				}
			}
		}

		private static void BroadcastPreviewEnd()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			if (SemiFunc.IsMultiplayer())
			{
				string nickName = PhotonNetwork.LocalPlayer.NickName;
				NetworkedEvent onPreviewEnd = Plugin.OnPreviewEnd;
				if (onPreviewEnd != null)
				{
					onPreviewEnd.RaiseEvent((object)nickName, NetworkingEvents.RaiseOthers, SendOptions.SendReliable);
				}
			}
		}

		private void OnGUI()
		{
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Expected O, but got Unknown
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Expected O, but got Unknown
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Expected O, but got Unknown
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			if (_showLoadingScreen)
			{
				if ((Object)(object)_blackTex == (Object)null)
				{
					_blackTex = new Texture2D(1, 1);
					_blackTex.SetPixel(0, 0, Color.black);
					_blackTex.Apply();
				}
				GUI.DrawTexture(new Rect(0f, 0f, (float)Screen.width, (float)Screen.height), (Texture)(object)_blackTex);
				GUIStyle val = new GUIStyle(GUI.skin.label)
				{
					fontSize = 36,
					alignment = (TextAnchor)4
				};
				val.normal.textColor = Color.white;
				GUIStyle val2 = new GUIStyle(GUI.skin.label)
				{
					fontSize = 18,
					alignment = (TextAnchor)4
				};
				val2.normal.textColor = new Color(0.7f, 0.7f, 0.7f);
				GUI.Label(new Rect(0f, (float)Screen.height / 2f - 40f, (float)Screen.width, 50f), _loadingLevelName, val);
				GUI.Label(new Rect(0f, (float)Screen.height / 2f + 20f, (float)Screen.width, 30f), "Loading preview...", val2);
			}
			else if (State == PreviewState.Previewing)
			{
				float num = 150f;
				float num2 = 40f;
				float num3 = ((float)Screen.width - num) / 2f;
				float num4 = (float)Screen.height - num2 - 20f;
				if (GUI.Button(new Rect(num3, num4, num, num2), "Back to Vote"))
				{
					StopPreview();
				}
				string text = (_previewLevelName ?? "").Replace("Level - ", "");
				GUIStyle val3 = new GUIStyle(GUI.skin.label)
				{
					fontSize = 16
				};
				val3.normal.textColor = Color.white;
				GUI.Label(new Rect(10f, 10f, 600f, 30f), "Previewing: " + text + " | WASD move | Mouse look | Shift fast | Space/Ctrl up/down", val3);
			}
		}
	}
}