Decompiled source of VacationPlanner v2.2.0

com.github.strangebasis.VacationPlanner.dll

Decompiled 2 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using VacationPlanner.Patches;
using Zorro.ControllerSupport;
using Zorro.Core;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("com.github.strangebasis.VacationPlanner")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("2.2.0.0")]
[assembly: AssemblyInformationalVersion("2.2.0+b135ed6ed399b8833fb5b95a6ec6cfb41888996b")]
[assembly: AssemblyProduct("com.github.strangebasis.VacationPlanner")]
[assembly: AssemblyTitle("VacationPlanner")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.2.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace BepInEx
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class BepInAutoPluginAttribute : Attribute
	{
		public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace BepInEx.Preloader.Core.Patching
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class PatcherAutoPluginAttribute : Attribute
	{
		public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace VacationPlanner
{
	public class BiomeController : MonoBehaviour
	{
		private static string? _defaultBiomeId;

		private static int _defaultLevelIndex = -1;

		private static GameObject? _spawnedKiosk;

		private static Material? _cachedSignMaterial = null;

		private static bool _materialSearchComplete = false;

		private static Texture2D? _cachedCustomTexture = null;

		private static Vector3 _lastLoggedHitPoint = Vector3.zero;

		private static Vector3 _lastLoggedHitNormal = Vector3.up;

		private static bool _hasLoggedPosition = false;

		private static string? _cachedTexturePropertyName = null;

		public static string? DefaultBiomeId => _defaultBiomeId;

		public static string? SelectedBiome2
		{
			get
			{
				return LevelOverridePatch.DesiredBiome2;
			}
			set
			{
				LevelOverridePatch.DesiredBiome2 = value;
			}
		}

		public static string? SelectedBiome3
		{
			get
			{
				return LevelOverridePatch.DesiredBiome3;
			}
			set
			{
				LevelOverridePatch.DesiredBiome3 = value;
			}
		}

		public static string? SelectedBiome4
		{
			get
			{
				return LevelOverridePatch.DesiredBiome4;
			}
			set
			{
				LevelOverridePatch.DesiredBiome4 = value;
			}
		}

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

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

		private void Update()
		{
			UpdateDefaultBiomeInfo();
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			if (((Scene)(ref scene)).name == "Airport")
			{
				((MonoBehaviour)this).StartCoroutine(SpawnKioskAndUICoroutine());
			}
		}

		private IEnumerator SpawnKioskAndUICoroutine()
		{
			yield return (object)new WaitForSeconds(0.5f);
			BiomeVotingMenu.Create();
			AirportCheckInKiosk val = Object.FindAnyObjectByType<AirportCheckInKiosk>();
			AirportInviteFriendsKiosk val2 = Object.FindAnyObjectByType<AirportInviteFriendsKiosk>();
			if ((Object)(object)val != (Object)null && (Object)(object)val2 != (Object)null)
			{
				if (!_materialSearchComplete)
				{
					FindAndCacheSignMaterial(((Component)val2).gameObject, "Add Player Kiosk@4x");
					_materialSearchComplete = true;
				}
				GameObject val3 = Object.Instantiate<GameObject>(((Component)val2).gameObject);
				((Object)val3).name = "BiomeVotingKiosk";
				val3.transform.position = ((Component)val).transform.position + ((Component)val).transform.up * 2.262f;
				val3.transform.rotation = ((Component)val).transform.rotation;
				val3.transform.localScale = ((Component)val2).transform.localScale * 2.2f;
				if ((Object)(object)_cachedSignMaterial != (Object)null)
				{
					ReplaceTextureOnClone(val3);
				}
				AirportInviteFriendsKiosk component = val3.GetComponent<AirportInviteFriendsKiosk>();
				if ((Object)(object)component != (Object)null)
				{
					Object.Destroy((Object)(object)component);
				}
				val3.AddComponent<BiomeVotingKiosk>();
				_spawnedKiosk = val3;
				Plugin.Log.LogInfo((object)"BiomeVotingKiosk spawned in Airport (scaled 2.3x)!");
				DisplayWorldSpaceOverlay();
			}
			else if ((Object)(object)val != (Object)null)
			{
				GameObject val4 = new GameObject("BiomeVotingKiosk");
				val4.transform.position = ((Component)val).transform.position - ((Component)val).transform.forward * 3f;
				val4.transform.rotation = ((Component)val).transform.rotation;
				GameObject val5 = GameObject.CreatePrimitive((PrimitiveType)3);
				((Object)val5).name = "KioskMesh";
				val5.transform.SetParent(val4.transform, false);
				val5.transform.localScale = new Vector3(2f, 4f, 1f);
				val5.transform.localPosition = new Vector3(0f, 2f, 0f);
				BoxCollider val6 = val4.AddComponent<BoxCollider>();
				val6.center = new Vector3(0f, 2f, 0f);
				val6.size = new Vector3(3f, 5f, 2f);
				val4.AddComponent<BiomeVotingKiosk>();
				_spawnedKiosk = val4;
				Plugin.Log.LogInfo((object)"BiomeVotingKiosk spawned (fallback cube, scaled 2x)!");
			}
			else
			{
				Plugin.Log.LogError((object)"Could not find kiosks for positioning reference!");
			}
		}

		private void UpdateDefaultBiomeInfo()
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			if (_defaultBiomeId != null)
			{
				return;
			}
			try
			{
				MapBaker instance = SingletonAsset<MapBaker>.Instance;
				NextLevelService service = GameHandler.GetService<NextLevelService>();
				if ((Object)(object)instance != (Object)null && service != null && service.Data.IsSome)
				{
					_defaultLevelIndex = service.Data.Value.CurrentLevelIndex + NextLevelService.debugLevelIndexOffset;
					_defaultBiomeId = instance.GetBiomeID(_defaultLevelIndex);
					Plugin.Log.LogInfo((object)$"Default biome for today: {_defaultBiomeId} (Level {_defaultLevelIndex})");
				}
			}
			catch
			{
			}
		}

		public static string BiomeIdToFriendly(string? biomeId)
		{
			if (string.IsNullOrEmpty(biomeId))
			{
				return "Loading...";
			}
			string text = (biomeId.Contains('T') ? "Tropics" : "Roots");
			string text2 = (biomeId.Contains('A') ? "Alpine" : "Mesa");
			string text3 = ((biomeId[biomeId.Length - 1] == 'S') ? "Gloom + Citadel" : "Caldera + Kiln");
			return text + " + " + text2 + " + " + text3;
		}

		public static string GetDefaultBiome2()
		{
			if (_defaultBiomeId == null)
			{
				return "T";
			}
			if (!_defaultBiomeId.Contains('T'))
			{
				return "R";
			}
			return "T";
		}

		public static string GetDefaultBiome3()
		{
			if (_defaultBiomeId == null)
			{
				return "M";
			}
			if (!_defaultBiomeId.Contains('A'))
			{
				return "M";
			}
			return "A";
		}

		public static string GetDefaultBiome4()
		{
			if (string.IsNullOrEmpty(_defaultBiomeId))
			{
				return "V";
			}
			if (_defaultBiomeId[_defaultBiomeId.Length - 1] != 'S')
			{
				return "V";
			}
			return "S";
		}

		public static void UpdateWorldSpaceOverlay()
		{
			GameObject val = GameObject.Find("BiomeWorldOverlay");
			if (!((Object)(object)val != (Object)null))
			{
				return;
			}
			MeshRenderer component = val.GetComponent<MeshRenderer>();
			if ((Object)(object)component != (Object)null)
			{
				Texture2D val2 = LoadOverlayTexture();
				if ((Object)(object)val2 != (Object)null)
				{
					((Renderer)component).material.mainTexture = (Texture)(object)val2;
					((Renderer)component).material.SetTexture("_BaseMap", (Texture)(object)val2);
					Plugin.Log.LogInfo((object)"Updated overlay texture to reflect new biome selection");
				}
			}
		}

		private void FindAndCacheSignMaterial(GameObject originalKiosk, string targetTextureName)
		{
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Invalid comparison between Unknown and I4
			Plugin.Log.LogInfo((object)"Searching for sign material (one-time discovery)...");
			MeshRenderer[] componentsInChildren = originalKiosk.GetComponentsInChildren<MeshRenderer>();
			Plugin.Log.LogInfo((object)$"Found {componentsInChildren.Length} renderers in kiosk");
			MeshRenderer[] array = componentsInChildren;
			foreach (MeshRenderer val in array)
			{
				Plugin.Log.LogInfo((object)$"Renderer: {((Object)val).name} has {((Renderer)val).sharedMaterials.Length} materials");
				Material[] sharedMaterials = ((Renderer)val).sharedMaterials;
				foreach (Material val2 in sharedMaterials)
				{
					if (!((Object)(object)val2 != (Object)null))
					{
						continue;
					}
					Plugin.Log.LogInfo((object)("  Material: " + ((Object)val2).name + ", Shader: " + ((Object)val2.shader).name));
					ManualLogSource log = Plugin.Log;
					Texture mainTexture = val2.mainTexture;
					log.LogInfo((object)("    mainTexture: " + (((mainTexture != null) ? ((Object)mainTexture).name : null) ?? "null")));
					Shader shader = val2.shader;
					int propertyCount = shader.GetPropertyCount();
					for (int k = 0; k < propertyCount; k++)
					{
						ShaderPropertyType propertyType = shader.GetPropertyType(k);
						if ((int)propertyType == 4)
						{
							string propertyName = shader.GetPropertyName(k);
							Texture texture = val2.GetTexture(propertyName);
							Plugin.Log.LogInfo((object)("    [" + propertyName + "]: " + (((texture != null) ? ((Object)texture).name : null) ?? "null")));
							if ((Object)(object)texture != (Object)null && ((Object)texture).name == targetTextureName)
							{
								_cachedSignMaterial = val2;
								_cachedTexturePropertyName = propertyName;
								Plugin.Log.LogInfo((object)("✓ FOUND: Material '" + ((Object)val2).name + "' property '" + propertyName + "' = '" + targetTextureName + "'"));
								return;
							}
						}
					}
				}
			}
			Plugin.Log.LogWarning((object)("Could not find material with texture '" + targetTextureName + "'"));
		}

		private void ReplaceTextureOnClone(GameObject clonedKiosk)
		{
			if ((Object)(object)_cachedSignMaterial == (Object)null || _cachedTexturePropertyName == null)
			{
				return;
			}
			MeshRenderer[] componentsInChildren = clonedKiosk.GetComponentsInChildren<MeshRenderer>();
			MeshRenderer[] array = componentsInChildren;
			foreach (MeshRenderer val in array)
			{
				for (int j = 0; j < ((Renderer)val).materials.Length; j++)
				{
					if ((Object)(object)((Renderer)val).materials[j].shader == (Object)(object)_cachedSignMaterial.shader && ((Object)((Renderer)val).materials[j]).name.Contains(((Object)_cachedSignMaterial).name.Replace(" (Instance)", "")))
					{
						Texture2D val2 = LoadCustomTexture();
						if ((Object)(object)val2 != (Object)null)
						{
							((Renderer)val).materials[j].SetTexture(_cachedTexturePropertyName, (Texture)(object)val2);
							Plugin.Log.LogInfo((object)("Texture replaced on clone (property: " + _cachedTexturePropertyName + ")!"));
						}
						return;
					}
				}
			}
		}

		private Texture2D? LoadCustomTexture()
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected O, but got Unknown
			if ((Object)(object)_cachedCustomTexture != (Object)null)
			{
				return _cachedCustomTexture;
			}
			string text = Path.Combine(Paths.PluginPath, "strangebasisdevs-VacationPlanner", "kiosk_texture.png");
			if (File.Exists(text))
			{
				byte[] array = File.ReadAllBytes(text);
				_cachedCustomTexture = new Texture2D(2, 2);
				ImageConversion.LoadImage(_cachedCustomTexture, array);
				Plugin.Log.LogInfo((object)("Custom texture loaded and cached from " + text));
				return _cachedCustomTexture;
			}
			Plugin.Log.LogError((object)("Could not find custom texture at " + text));
			return null;
		}

		private void DumpAllSceneTextures()
		{
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Invalid comparison between Unknown and I4
			Plugin.Log.LogInfo((object)"=== DUMPING ALL SCENE TEXTURES ===");
			MeshRenderer[] array = Object.FindObjectsByType<MeshRenderer>((FindObjectsSortMode)0);
			Plugin.Log.LogInfo((object)$"Found {array.Length} renderers in scene");
			MeshRenderer[] array2 = array;
			foreach (MeshRenderer val in array2)
			{
				Plugin.Log.LogInfo((object)("\nGameObject: " + GetFullPath(((Component)val).gameObject)));
				Material[] sharedMaterials = ((Renderer)val).sharedMaterials;
				foreach (Material val2 in sharedMaterials)
				{
					if (!((Object)(object)val2 != (Object)null))
					{
						continue;
					}
					Plugin.Log.LogInfo((object)("  Material: " + ((Object)val2).name));
					Plugin.Log.LogInfo((object)("    Shader: " + ((Object)val2.shader).name));
					Shader shader = val2.shader;
					for (int k = 0; k < shader.GetPropertyCount(); k++)
					{
						if ((int)shader.GetPropertyType(k) == 4)
						{
							string propertyName = shader.GetPropertyName(k);
							Texture texture = val2.GetTexture(propertyName);
							if ((Object)(object)texture != (Object)null)
							{
								Plugin.Log.LogInfo((object)$"      [{propertyName}]: {((Object)texture).name} ({texture.width}x{texture.height})");
							}
						}
					}
				}
			}
			Plugin.Log.LogInfo((object)"=== DUMP COMPLETE ===");
		}

		private string GetFullPath(GameObject obj)
		{
			string text = ((Object)obj).name;
			Transform parent = obj.transform.parent;
			while ((Object)(object)parent != (Object)null)
			{
				text = ((Object)parent).name + "/" + text;
				parent = parent.parent;
			}
			return text;
		}

		private void LogScreenPositionForOverlay()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			Vector3 mousePosition = Input.mousePosition;
			Vector3 val = Camera.main.ScreenToViewportPoint(mousePosition);
			Plugin.Log.LogInfo((object)"=== SCREEN POSITION LOG ===");
			Plugin.Log.LogInfo((object)$"Mouse Screen Position: {mousePosition.x:F0}, {mousePosition.y:F0}");
			Plugin.Log.LogInfo((object)$"Viewport Position: {val.x:F3}, {val.y:F3}");
			Plugin.Log.LogInfo((object)$"Screen Resolution: {Screen.width}x{Screen.height}");
			Plugin.Log.LogInfo((object)"For overlay rectangle, use viewport coordinates:");
			Plugin.Log.LogInfo((object)$"  new Rect({val.x:F3}f, {val.y:F3}f, width, height)");
			Plugin.Log.LogInfo((object)"===========================");
			LogWorldPlacementInfo();
		}

		private void LogWorldPlacementInfo()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//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_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: 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)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: 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_0277: Unknown result type (might be due to invalid IL or missing references)
			//IL_029c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_02be: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0303: Unknown result type (might be due to invalid IL or missing references)
			//IL_0314: Unknown result type (might be due to invalid IL or missing references)
			Ray val = Camera.main.ScreenPointToRay(Input.mousePosition);
			RaycastHit val2 = default(RaycastHit);
			if (Physics.Raycast(val, ref val2, 100f))
			{
				_lastLoggedHitPoint = ((RaycastHit)(ref val2)).point;
				_lastLoggedHitNormal = ((RaycastHit)(ref val2)).normal;
				_hasLoggedPosition = true;
				Plugin.Log.LogInfo((object)"=== WORLD PLACEMENT INFO ===");
				Plugin.Log.LogInfo((object)$"Hit Point: ({((RaycastHit)(ref val2)).point.x:F3}, {((RaycastHit)(ref val2)).point.y:F3}, {((RaycastHit)(ref val2)).point.z:F3})");
				Plugin.Log.LogInfo((object)$"Hit Normal: ({((RaycastHit)(ref val2)).normal.x:F3}, {((RaycastHit)(ref val2)).normal.y:F3}, {((RaycastHit)(ref val2)).normal.z:F3})");
				Plugin.Log.LogInfo((object)$"Hit Distance: {((RaycastHit)(ref val2)).distance:F3}");
				Plugin.Log.LogInfo((object)("Hit GameObject: " + GetFullPath(((Component)((RaycastHit)(ref val2)).collider).gameObject)));
				ManualLogSource log = Plugin.Log;
				Collider collider = ((RaycastHit)(ref val2)).collider;
				object obj;
				if (collider == null)
				{
					obj = null;
				}
				else
				{
					Renderer component = ((Component)collider).GetComponent<Renderer>();
					if (component == null)
					{
						obj = null;
					}
					else
					{
						Material material = component.material;
						obj = ((material != null) ? ((Object)material).name : null);
					}
				}
				if (obj == null)
				{
					obj = "N/A";
				}
				log.LogInfo((object)("Hit Material: " + (string?)obj));
				Quaternion val3 = Quaternion.LookRotation(-((RaycastHit)(ref val2)).normal);
				Plugin.Log.LogInfo((object)$"Suggested Rotation (faces surface): ({((Quaternion)(ref val3)).eulerAngles.x:F1}, {((Quaternion)(ref val3)).eulerAngles.y:F1}, {((Quaternion)(ref val3)).eulerAngles.z:F1})");
				Vector3 val4 = ((Component)Camera.main).transform.position - ((RaycastHit)(ref val2)).point;
				Quaternion val5 = Quaternion.LookRotation(-((Vector3)(ref val4)).normalized);
				Plugin.Log.LogInfo((object)$"Suggested Rotation (faces camera): ({((Quaternion)(ref val5)).eulerAngles.x:F1}, {((Quaternion)(ref val5)).eulerAngles.y:F1}, {((Quaternion)(ref val5)).eulerAngles.z:F1})");
				Plugin.Log.LogInfo((object)"=== SUGGESTED CODE ===");
				Plugin.Log.LogInfo((object)$"transform.position = new Vector3({((RaycastHit)(ref val2)).point.x:F3}f, {((RaycastHit)(ref val2)).point.y:F3}f, {((RaycastHit)(ref val2)).point.z:F3}f);");
				Plugin.Log.LogInfo((object)$"transform.rotation = Quaternion.Euler({((Quaternion)(ref val3)).eulerAngles.x:F1}f, {((Quaternion)(ref val3)).eulerAngles.y:F1}f, {((Quaternion)(ref val3)).eulerAngles.z:F1}f);");
				Plugin.Log.LogInfo((object)"// Or for camera-facing:");
				Plugin.Log.LogInfo((object)$"transform.rotation = Quaternion.Euler({((Quaternion)(ref val5)).eulerAngles.x:F1}f, {((Quaternion)(ref val5)).eulerAngles.y:F1}f, {((Quaternion)(ref val5)).eulerAngles.z:F1}f);");
				Plugin.Log.LogInfo((object)"Press NUMPAD1 to place overlay at this position!");
				Plugin.Log.LogInfo((object)"===========================");
			}
			else
			{
				Plugin.Log.LogInfo((object)"No world hit detected - raycast didn't hit anything");
			}
		}

		private void DisplayWorldSpaceOverlay()
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: 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_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Expected O, but got Unknown
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Expected O, but got Unknown
			GameObject val = GameObject.Find("BiomeWorldOverlay");
			bool flag = (Object)(object)val != (Object)null;
			if ((Object)(object)val == (Object)null)
			{
				val = GameObject.CreatePrimitive((PrimitiveType)5);
				((Object)val).name = "BiomeWorldOverlay";
				Collider component = val.GetComponent<Collider>();
				if ((Object)(object)component != (Object)null)
				{
					Object.Destroy((Object)(object)component);
				}
			}
			val.transform.position = new Vector3(1.807f, 5.136f, 103.626f);
			val.transform.rotation = Quaternion.Euler(0f, 90f, 0f);
			val.transform.localScale = new Vector3(5.7f, 0.75f, 1f);
			MeshRenderer component2 = val.GetComponent<MeshRenderer>();
			if ((Object)(object)component2 != (Object)null)
			{
				Texture2D val2 = LoadOverlayTexture();
				if ((Object)(object)val2 != (Object)null)
				{
					if (flag)
					{
						((Renderer)component2).material.mainTexture = (Texture)(object)val2;
						((Renderer)component2).material.SetTexture("_BaseMap", (Texture)(object)val2);
						Plugin.Log.LogInfo((object)"Updated existing overlay texture");
					}
					else
					{
						Material val3 = new Material(Shader.Find("Universal Render Pipeline/Lit"));
						val3.mainTexture = (Texture)(object)val2;
						val3.SetTexture("_BaseMap", (Texture)(object)val2);
						val3.SetFloat("_Surface", 0f);
						val3.SetFloat("_Blend", 0f);
						((Renderer)component2).material = val3;
					}
				}
				else
				{
					Material val4 = new Material(Shader.Find("Universal Render Pipeline/Lit"));
					val4.color = new Color(1f, 0.5f, 0f, 0.9f);
					((Renderer)component2).material = val4;
				}
			}
			Plugin.Log.LogInfo((object)$"World space overlay created covering airport sign at {val.transform.position}");
		}

		private static Texture2D? LoadOverlayTexture()
		{
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Expected O, but got Unknown
			string text = LevelOverridePatch.DesiredBiome2?.ToUpper() ?? GetDefaultBiome2();
			string text2 = LevelOverridePatch.DesiredBiome3?.ToUpper() ?? GetDefaultBiome3();
			string text3 = ((text == "T") ? "tropics" : "roots");
			string text4 = ((text2 == "A") ? "alpine" : "mesa");
			string path = text3 + "_" + text4 + "_sign.png";
			string text5 = Path.Combine(Paths.PluginPath, "strangebasisdevs-VacationPlanner", path);
			if (File.Exists(text5))
			{
				byte[] array = File.ReadAllBytes(text5);
				Texture2D val = new Texture2D(2, 2);
				ImageConversion.LoadImage(val, array);
				Plugin.Log.LogInfo((object)("Overlay texture loaded from " + text5));
				return val;
			}
			Plugin.Log.LogWarning((object)("Could not find overlay texture at " + text5));
			return null;
		}

		private void PlaceOverlayAtLoggedPosition(string overlayName)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: 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_007f: 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_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Expected O, but got Unknown
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Expected O, but got Unknown
			if (!_hasLoggedPosition)
			{
				Plugin.Log.LogWarning((object)"No logged position available. Press NUMPAD0 first to log a position.");
				return;
			}
			GameObject val = GameObject.Find(overlayName);
			if ((Object)(object)val == (Object)null)
			{
				val = GameObject.CreatePrimitive((PrimitiveType)5);
				((Object)val).name = overlayName;
				Collider component = val.GetComponent<Collider>();
				if ((Object)(object)component != (Object)null)
				{
					Object.Destroy((Object)(object)component);
				}
			}
			val.transform.position = _lastLoggedHitPoint + _lastLoggedHitNormal * 0.01f;
			val.transform.rotation = Quaternion.LookRotation(-_lastLoggedHitNormal);
			val.transform.localScale = new Vector3(1f, 1f, 1f);
			MeshRenderer component2 = val.GetComponent<MeshRenderer>();
			if ((Object)(object)component2 != (Object)null)
			{
				Texture2D val2 = LoadOverlayTexture();
				if ((Object)(object)val2 != (Object)null)
				{
					Material val3 = new Material(Shader.Find("Universal Render Pipeline/Lit"));
					val3.mainTexture = (Texture)(object)val2;
					val3.SetTexture("_BaseMap", (Texture)(object)val2);
					val3.SetFloat("_Surface", 0f);
					val3.SetFloat("_Blend", 0f);
					((Renderer)component2).material = val3;
				}
				else
				{
					Material val4 = new Material(Shader.Find("Universal Render Pipeline/Lit"));
					val4.color = new Color(1f, 0.5f, 0f, 0.9f);
					((Renderer)component2).material = val4;
				}
			}
			Plugin.Log.LogInfo((object)$"Overlay '{overlayName}' placed at logged position: {_lastLoggedHitPoint}, normal: {_lastLoggedHitNormal}");
			LogCurrentOverlayTransform(val.transform);
		}

		private void AdjustOverlayScale(string overlayName, float widthDelta, float heightDelta)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: 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_006e: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = GameObject.Find(overlayName);
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogWarning((object)("No overlay '" + overlayName + "' to adjust. Place one first with NUMPAD1."));
				return;
			}
			Vector3 localScale = val.transform.localScale;
			Vector3 localScale2 = default(Vector3);
			((Vector3)(ref localScale2))..ctor(Mathf.Max(0.1f, localScale.x + widthDelta), Mathf.Max(0.1f, localScale.y + heightDelta), localScale.z);
			val.transform.localScale = localScale2;
			LogCurrentOverlayTransform(val.transform);
		}

		private void AdjustOverlayPosition(string overlayName, float deltaX, float deltaY, float deltaZ)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = GameObject.Find(overlayName);
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogWarning((object)("No overlay '" + overlayName + "' to adjust. Place one first with NUMPAD1."));
				return;
			}
			Vector3 position = val.transform.position;
			Vector3 position2 = position + new Vector3(deltaX, deltaY, deltaZ);
			val.transform.position = position2;
			LogCurrentOverlayTransform(val.transform);
		}

		private void LogCurrentOverlayTransform(Transform transform)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: 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_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: 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_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: 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_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: 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_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			Plugin.Log.LogInfo((object)"=== OVERLAY TRANSFORM ===");
			Plugin.Log.LogInfo((object)$"Position: ({transform.position.x:F3}, {transform.position.y:F3}, {transform.position.z:F3})");
			ManualLogSource log = Plugin.Log;
			Quaternion rotation = transform.rotation;
			object arg = ((Quaternion)(ref rotation)).eulerAngles.x;
			rotation = transform.rotation;
			object arg2 = ((Quaternion)(ref rotation)).eulerAngles.y;
			rotation = transform.rotation;
			log.LogInfo((object)$"Rotation: ({arg:F1}, {arg2:F1}, {((Quaternion)(ref rotation)).eulerAngles.z:F1})");
			Plugin.Log.LogInfo((object)$"Scale: ({transform.localScale.x:F3}, {transform.localScale.y:F3}, {transform.localScale.z:F3})");
			Plugin.Log.LogInfo((object)"=== READY-TO-USE CODE ===");
			Plugin.Log.LogInfo((object)$"overlayGO.transform.position = new Vector3({transform.position.x:F3}f, {transform.position.y:F3}f, {transform.position.z:F3}f);");
			ManualLogSource log2 = Plugin.Log;
			rotation = transform.rotation;
			object arg3 = ((Quaternion)(ref rotation)).eulerAngles.x;
			rotation = transform.rotation;
			object arg4 = ((Quaternion)(ref rotation)).eulerAngles.y;
			rotation = transform.rotation;
			log2.LogInfo((object)$"overlayGO.transform.rotation = Quaternion.Euler({arg3:F1}f, {arg4:F1}f, {((Quaternion)(ref rotation)).eulerAngles.z:F1}f);");
			Plugin.Log.LogInfo((object)$"overlayGO.transform.localScale = new Vector3({transform.localScale.x:F3}f, {transform.localScale.y:F3}f, {transform.localScale.z:F3}f);");
			Plugin.Log.LogInfo((object)"===========================");
		}
	}
	public class BiomeVotingKiosk : MonoBehaviour, IInteractible
	{
		private MaterialPropertyBlock? mpb;

		private MeshRenderer[]? _mr;

		private MeshRenderer[] meshRenderers
		{
			get
			{
				if (_mr == null)
				{
					_mr = ((Component)this).GetComponentsInChildren<MeshRenderer>();
				}
				return _mr;
			}
		}

		public void Awake()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			mpb = new MaterialPropertyBlock();
		}

		public bool IsInteractible(Character interactor)
		{
			return true;
		}

		public void Interact(Character interactor)
		{
			Plugin.Log.LogInfo((object)$"BiomeVotingKiosk Interact - Menu exists: {(Object)(object)BiomeVotingMenu.Instance != (Object)null}");
			if ((Object)(object)BiomeVotingMenu.Instance != (Object)null)
			{
				if (((MenuWindow)BiomeVotingMenu.Instance).isOpen)
				{
					((MenuWindow)BiomeVotingMenu.Instance).Close();
				}
				else
				{
					((MenuWindow)BiomeVotingMenu.Instance).Open();
				}
			}
			else
			{
				Plugin.Log.LogError((object)"BiomeVotingMenu.Instance is null!");
			}
		}

		public void HoverEnter()
		{
			if (mpb == null)
			{
				return;
			}
			mpb.SetFloat(Item.PROPERTY_INTERACTABLE, 1f);
			MeshRenderer[] array = meshRenderers;
			foreach (MeshRenderer val in array)
			{
				if (val != null)
				{
					((Renderer)val).SetPropertyBlock(mpb);
				}
			}
		}

		public void HoverExit()
		{
			if (mpb == null)
			{
				return;
			}
			mpb.SetFloat(Item.PROPERTY_INTERACTABLE, 0f);
			MeshRenderer[] array = meshRenderers;
			foreach (MeshRenderer val in array)
			{
				if (val != null)
				{
					((Renderer)val).SetPropertyBlock(mpb);
				}
			}
		}

		public Vector3 Center()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			return ((Component)this).transform.position + Vector3.up;
		}

		public Transform GetTransform()
		{
			return ((Component)this).transform;
		}

		public string GetInteractionText()
		{
			return "SELECT DESTINATION";
		}

		public string GetName()
		{
			return "DESTINATION KIOSK";
		}
	}
	public class BiomeVotingMenu : MenuWindow
	{
		private GUIStyle? _boxStyle;

		private GUIStyle? _labelStyle;

		private GUIStyle? _headerStyle;

		private GUIStyle? _buttonStyle;

		private GUIStyle? _selectedButtonStyle;

		private GUIStyle? _voteStyle;

		private GUIStyle? _winnerStyle;

		private GUIStyle? _tooltipStyle;

		private Texture2D? _borderTexture;

		private Texture2D? _xTexture;

		private int _selectedRow;

		private int _selectedCol;

		private float _navigationCooldown;

		private const float NavigationDelay = 0.15f;

		private InputScheme _currentInputScheme;

		public static BiomeVotingMenu? Instance { get; private set; }

		public override bool openOnStart => false;

		public override bool selectOnOpen => false;

		public override bool closeOnPause => true;

		public override bool closeOnUICancel => true;

		public override bool autoHideOnClose => true;

		public override bool blocksPlayerInput => true;

		public override bool showCursorWhileOpen => true;

		public static BiomeVotingMenu Create()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			if ((Object)(object)Instance != (Object)null)
			{
				return Instance;
			}
			GameObject val = new GameObject("BiomeVotingMenu");
			BiomeVotingMenu biomeVotingMenu = (Instance = val.AddComponent<BiomeVotingMenu>());
			((MenuWindow)biomeVotingMenu).StartClosed();
			Plugin.Log.LogInfo((object)"BiomeVotingMenu created");
			return biomeVotingMenu;
		}

		private void Awake()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			_currentInputScheme = InputHandler.GetCurrentUsedInputScheme();
			InputHandler instance = RetrievableResourceSingleton<InputHandler>.Instance;
			instance.InputSchemeChanged = (Action<InputScheme>)Delegate.Combine(instance.InputSchemeChanged, new Action<InputScheme>(OnInputSchemeChanged));
		}

		public override void OnOpen()
		{
			Plugin.Log.LogInfo((object)"BiomeVotingMenu OnOpen - cursor should show now");
			LevelOverridePatch.EnsureBiomeMapBuilt();
			_selectedRow = 0;
			_selectedCol = 0;
			_navigationCooldown = 0f;
		}

		public override void OnClose()
		{
			Plugin.Log.LogInfo((object)"BiomeVotingMenu OnClose");
		}

		private void Update()
		{
			((MenuWindow)this).Update();
			if (((MenuWindow)this).isOpen && ((MenuWindow)this).inputActive)
			{
				HandleControllerInput();
			}
		}

		private void HandleControllerInput()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: 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_003a: 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_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			UIInputHandler instance = Singleton<UIInputHandler>.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			Vector2 wheelNavigationVector = instance.wheelNavigationVector;
			_navigationCooldown -= Time.deltaTime;
			if (_navigationCooldown <= 0f && wheelNavigationVector != Vector2.zero)
			{
				if (Mathf.Abs(wheelNavigationVector.x) > Mathf.Abs(wheelNavigationVector.y))
				{
					if (wheelNavigationVector.x > 0.5f)
					{
						_selectedCol = (_selectedCol + 1) % 2;
						_navigationCooldown = 0.15f;
					}
					else if (wheelNavigationVector.x < -0.5f)
					{
						_selectedCol = (_selectedCol - 1 + 2) % 2;
						_navigationCooldown = 0.15f;
					}
				}
				else if (wheelNavigationVector.y > 0.5f)
				{
					_selectedRow = Mathf.Max(0, _selectedRow - 1);
					_navigationCooldown = 0.15f;
				}
				else if (wheelNavigationVector.y < -0.5f)
				{
					_selectedRow = Mathf.Min(3, _selectedRow + 1);
					_navigationCooldown = 0.15f;
				}
			}
			if (instance.confirmWasPressed)
			{
				ExecuteSelectedButton();
				instance.confirmWasPressed = false;
			}
		}

		private void ExecuteSelectedButton()
		{
			bool inRoom = PhotonNetwork.InRoom;
			string effectiveBiome = GetEffectiveBiome2(inRoom);
			string effectiveBiome2 = GetEffectiveBiome3(inRoom);
			string effectiveBiome3 = GetEffectiveBiome4(inRoom);
			switch (_selectedRow)
			{
			case 0:
				if (_selectedCol == 0)
				{
					if (LevelOverridePatch.IsBiome2BranchAvailable("T", effectiveBiome2, effectiveBiome3))
					{
						if (inRoom)
						{
							NetworkSync.VoteForBiome2("T");
							break;
						}
						BiomeController.SelectedBiome2 = "T";
						BiomeController.UpdateWorldSpaceOverlay();
					}
				}
				else if (LevelOverridePatch.IsBiome2BranchAvailable("R", effectiveBiome2, effectiveBiome3))
				{
					if (inRoom)
					{
						NetworkSync.VoteForBiome2("R");
						break;
					}
					BiomeController.SelectedBiome2 = "R";
					BiomeController.UpdateWorldSpaceOverlay();
				}
				break;
			case 1:
				if (_selectedCol == 0)
				{
					if (LevelOverridePatch.IsBiome3BranchAvailable("A", effectiveBiome, effectiveBiome3))
					{
						if (inRoom)
						{
							NetworkSync.VoteForBiome3("A");
							break;
						}
						BiomeController.SelectedBiome3 = "A";
						BiomeController.UpdateWorldSpaceOverlay();
					}
				}
				else if (LevelOverridePatch.IsBiome3BranchAvailable("M", effectiveBiome, effectiveBiome3))
				{
					if (inRoom)
					{
						NetworkSync.VoteForBiome3("M");
						break;
					}
					BiomeController.SelectedBiome3 = "M";
					BiomeController.UpdateWorldSpaceOverlay();
				}
				break;
			case 2:
				if (_selectedCol == 0)
				{
					if (LevelOverridePatch.IsBiome4BranchAvailable("V", effectiveBiome, effectiveBiome2))
					{
						if (inRoom)
						{
							NetworkSync.VoteForBiome4("V");
							break;
						}
						BiomeController.SelectedBiome4 = "V";
						BiomeController.UpdateWorldSpaceOverlay();
					}
				}
				else if (LevelOverridePatch.IsBiome4BranchAvailable("S", effectiveBiome, effectiveBiome2))
				{
					if (inRoom)
					{
						NetworkSync.VoteForBiome4("S");
						break;
					}
					BiomeController.SelectedBiome4 = "S";
					BiomeController.UpdateWorldSpaceOverlay();
				}
				break;
			case 3:
				if (_selectedCol == 0)
				{
					if (inRoom)
					{
						NetworkSync.ClearMyVotes();
						break;
					}
					LevelOverridePatch.ClearOverrides();
					BiomeController.UpdateWorldSpaceOverlay();
				}
				else
				{
					((MenuWindow)this).Close();
				}
				break;
			}
		}

		private GUIStyle GetButtonStyle(bool isVoted)
		{
			if (!isVoted)
			{
				return _buttonStyle;
			}
			return _selectedButtonStyle;
		}

		private static string GetEffectiveBiome2(bool inRoom)
		{
			if (inRoom)
			{
				int votesTropics = NetworkSync.VotesTropics;
				int votesRoots = NetworkSync.VotesRoots;
				if (votesTropics > votesRoots)
				{
					return "T";
				}
				if (votesRoots > votesTropics)
				{
					return "R";
				}
				return BiomeController.GetDefaultBiome2();
			}
			return BiomeController.SelectedBiome2 ?? BiomeController.GetDefaultBiome2();
		}

		private static string GetEffectiveBiome3(bool inRoom)
		{
			if (inRoom)
			{
				int votesAlpine = NetworkSync.VotesAlpine;
				int votesMesa = NetworkSync.VotesMesa;
				if (votesAlpine > votesMesa)
				{
					return "A";
				}
				if (votesMesa > votesAlpine)
				{
					return "M";
				}
				return BiomeController.GetDefaultBiome3();
			}
			return BiomeController.SelectedBiome3 ?? BiomeController.GetDefaultBiome3();
		}

		private static string GetEffectiveBiome4(bool inRoom)
		{
			if (inRoom)
			{
				int votesVolcano = NetworkSync.VotesVolcano;
				int votesSwamp = NetworkSync.VotesSwamp;
				if (votesVolcano > votesSwamp)
				{
					return "V";
				}
				if (votesSwamp > votesVolcano)
				{
					return "S";
				}
				return BiomeController.GetDefaultBiome4();
			}
			return BiomeController.SelectedBiome4 ?? BiomeController.GetDefaultBiome4();
		}

		private static string FriendlyBiome2(string v)
		{
			if (!(v == "T"))
			{
				return "Roots";
			}
			return "Tropics";
		}

		private static string FriendlyBiome3(string v)
		{
			if (!(v == "A"))
			{
				return "Mesa";
			}
			return "Alpine";
		}

		private static string FriendlyBiome4(string v)
		{
			if (!(v == "V"))
			{
				return "Swamp";
			}
			return "Volcano";
		}

		private static string BuildUnavailableMessage(string friendlyName, LevelOverridePatch.BranchAvailability info, string otherALabel, string otherBLabel)
		{
			if (info.IsGloballyUnavailable)
			{
				return friendlyName + " is not available at all right now";
			}
			List<string> list = new List<string>();
			if (info.ChangingOtherAWouldHelp)
			{
				list.Add(otherALabel);
			}
			if (info.ChangingOtherBWouldHelp)
			{
				list.Add(otherBLabel);
			}
			if (list.Count == 0)
			{
				return friendlyName + " cannot be voted on with the current " + otherALabel + " + " + otherBLabel + " combination";
			}
			return friendlyName + " cannot be voted on until at least one of the following results changes: " + string.Join(" and/or ", list);
		}

		private void OnInputSchemeChanged(InputScheme scheme)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			_currentInputScheme = scheme;
		}

		private void OnDestroy()
		{
			((MenuWindow)this).OnDestroy();
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
			InputHandler instance = RetrievableResourceSingleton<InputHandler>.Instance;
			instance.InputSchemeChanged = (Action<InputScheme>)Delegate.Remove(instance.InputSchemeChanged, new Action<InputScheme>(OnInputSchemeChanged));
		}

		private void OnGUI()
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: 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_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0217: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Expected O, but got Unknown
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0265: Unknown result type (might be due to invalid IL or missing references)
			//IL_026b: Invalid comparison between Unknown and I4
			//IL_0257: Unknown result type (might be due to invalid IL or missing references)
			//IL_028f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d1: Expected O, but got Unknown
			//IL_02d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0318: Unknown result type (might be due to invalid IL or missing references)
			//IL_031e: Invalid comparison between Unknown and I4
			//IL_030a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0342: Unknown result type (might be due to invalid IL or missing references)
			//IL_0416: Unknown result type (might be due to invalid IL or missing references)
			//IL_04cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_04de: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0518: Unknown result type (might be due to invalid IL or missing references)
			//IL_051f: Expected O, but got Unknown
			//IL_051f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0566: Unknown result type (might be due to invalid IL or missing references)
			//IL_056c: Invalid comparison between Unknown and I4
			//IL_0558: Unknown result type (might be due to invalid IL or missing references)
			//IL_0591: Unknown result type (might be due to invalid IL or missing references)
			//IL_05cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_05d3: Expected O, but got Unknown
			//IL_05d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_061a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0620: Invalid comparison between Unknown and I4
			//IL_060c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0645: Unknown result type (might be due to invalid IL or missing references)
			//IL_0719: Unknown result type (might be due to invalid IL or missing references)
			//IL_07ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_07e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_06b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_081b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0822: Expected O, but got Unknown
			//IL_0822: Unknown result type (might be due to invalid IL or missing references)
			//IL_0869: Unknown result type (might be due to invalid IL or missing references)
			//IL_086f: Invalid comparison between Unknown and I4
			//IL_085b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0894: Unknown result type (might be due to invalid IL or missing references)
			//IL_08cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_08d6: Expected O, but got Unknown
			//IL_08d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_091d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0923: Invalid comparison between Unknown and I4
			//IL_090f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0948: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a48: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a5b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a67: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a91: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a97: Invalid comparison between Unknown and I4
			//IL_09b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ab8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ac5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ae1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ae7: Invalid comparison between Unknown and I4
			//IL_0b08: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b2a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b53: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b58: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b5f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b66: Expected O, but got Unknown
			//IL_0b7e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b8d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0be0: Unknown result type (might be due to invalid IL or missing references)
			if (!((MenuWindow)this).isOpen)
			{
				return;
			}
			InitStyles();
			GUI.tooltip = string.Empty;
			bool inRoom = PhotonNetwork.InRoom;
			float num = 400f;
			float num2 = (inRoom ? 465 : 345);
			float num3 = ((float)Screen.width - num) / 2f;
			float num4 = ((float)Screen.height - num2) / 2f;
			GUI.Box(new Rect(num3, num4, num, num2), "", _boxStyle);
			float num5 = num3 + 15f;
			float num6 = num4 + 15f;
			float num7 = num - 30f;
			GUI.Label(new Rect(num5, num6, num7, 30f), "DESTINATION SELECTION", _headerStyle);
			num6 += 40f;
			string text = BiomeController.BiomeIdToFriendly(BiomeController.DefaultBiomeId);
			GUI.Label(new Rect(num5, num6, num7, 20f), "Today's Default: " + text, _labelStyle);
			num6 += 35f;
			string effectiveBiome = GetEffectiveBiome2(inRoom);
			string effectiveBiome2 = GetEffectiveBiome3(inRoom);
			string effectiveBiome3 = GetEffectiveBiome4(inRoom);
			GUI.Label(new Rect(num5, num6, num7, 20f), "JUNGLE REGION:", _labelStyle);
			num6 += 25f;
			string text2 = (inRoom ? NetworkSync.MyVoteBiome2 : BiomeController.SelectedBiome2);
			bool flag = text2 == "T";
			bool flag2 = text2 == "R";
			LevelOverridePatch.BranchAvailability info = LevelOverridePatch.EvaluateBiome2Branch("T", effectiveBiome2, effectiveBiome3);
			LevelOverridePatch.BranchAvailability info2 = LevelOverridePatch.EvaluateBiome2Branch("R", effectiveBiome2, effectiveBiome3);
			bool isAvailable = info.IsAvailable;
			bool isAvailable2 = info2.IsAvailable;
			Rect val = default(Rect);
			((Rect)(ref val))..ctor(num5, num6, 150f, 35f);
			Rect val2 = default(Rect);
			((Rect)(ref val2))..ctor(num5 + 160f, num6, 150f, 35f);
			bool flag3 = ((Rect)(ref val)).Contains(Event.current.mousePosition);
			bool flag4 = ((Rect)(ref val2)).Contains(Event.current.mousePosition);
			string text3 = (isAvailable ? "" : BuildUnavailableMessage("Tropics", info, FriendlyBiome3(effectiveBiome2), FriendlyBiome4(effectiveBiome3)));
			GUIContent val3 = new GUIContent("TROPICS", text3);
			if (GUI.Button(val, val3, GetButtonStyle(flag)) && isAvailable)
			{
				if (inRoom)
				{
					NetworkSync.VoteForBiome2("T");
				}
				else
				{
					BiomeController.SelectedBiome2 = "T";
					BiomeController.UpdateWorldSpaceOverlay();
				}
			}
			if (!isAvailable)
			{
				GUI.DrawTexture(val, (Texture)(object)_xTexture);
			}
			if (((int)_currentInputScheme == 1 && _selectedRow == 0 && _selectedCol == 0) || (flag3 && !flag))
			{
				GUI.DrawTexture(val, (Texture)(object)_borderTexture);
			}
			string text4 = (isAvailable2 ? "" : BuildUnavailableMessage("Roots", info2, FriendlyBiome3(effectiveBiome2), FriendlyBiome4(effectiveBiome3)));
			GUIContent val4 = new GUIContent("ROOTS", text4);
			if (GUI.Button(val2, val4, GetButtonStyle(flag2)) && isAvailable2)
			{
				if (inRoom)
				{
					NetworkSync.VoteForBiome2("R");
				}
				else
				{
					BiomeController.SelectedBiome2 = "R";
					BiomeController.UpdateWorldSpaceOverlay();
				}
			}
			if (!isAvailable2)
			{
				GUI.DrawTexture(val2, (Texture)(object)_xTexture);
			}
			if (((int)_currentInputScheme == 1 && _selectedRow == 0 && _selectedCol == 1) || (flag4 && !flag2))
			{
				GUI.DrawTexture(val2, (Texture)(object)_borderTexture);
			}
			num6 += 40f;
			if (inRoom)
			{
				int votesTropics = NetworkSync.VotesTropics;
				int votesRoots = NetworkSync.VotesRoots;
				string defaultBiome = BiomeController.GetDefaultBiome2();
				bool flag5 = votesTropics > votesRoots || (votesTropics == votesRoots && defaultBiome == "T");
				string arg = (flag5 ? "Tropics" : "Roots");
				GUI.Label(new Rect(num5, num6, num7, 20f), $"  Votes: Tropics {votesTropics} | Roots {votesRoots}  →  Winner: {arg}", ((flag5 && votesTropics > 0) || (!flag5 && votesRoots > 0)) ? _winnerStyle : _voteStyle);
				num6 += 25f;
			}
			else
			{
				num6 += 15f;
			}
			GUI.Label(new Rect(num5, num6, num7, 20f), "MOUNTAIN REGION:", _labelStyle);
			num6 += 25f;
			string text5 = (inRoom ? NetworkSync.MyVoteBiome3 : BiomeController.SelectedBiome3);
			bool flag6 = text5 == "A";
			bool flag7 = text5 == "M";
			LevelOverridePatch.BranchAvailability info3 = LevelOverridePatch.EvaluateBiome3Branch("A", effectiveBiome, effectiveBiome3);
			LevelOverridePatch.BranchAvailability info4 = LevelOverridePatch.EvaluateBiome3Branch("M", effectiveBiome, effectiveBiome3);
			bool isAvailable3 = info3.IsAvailable;
			bool isAvailable4 = info4.IsAvailable;
			Rect val5 = default(Rect);
			((Rect)(ref val5))..ctor(num5, num6, 150f, 35f);
			Rect val6 = default(Rect);
			((Rect)(ref val6))..ctor(num5 + 160f, num6, 150f, 35f);
			bool flag8 = ((Rect)(ref val5)).Contains(Event.current.mousePosition);
			bool flag9 = ((Rect)(ref val6)).Contains(Event.current.mousePosition);
			string text6 = (isAvailable3 ? "" : BuildUnavailableMessage("Alpine", info3, FriendlyBiome2(effectiveBiome), FriendlyBiome4(effectiveBiome3)));
			GUIContent val7 = new GUIContent("ALPINE", text6);
			if (GUI.Button(val5, val7, GetButtonStyle(flag6)) && isAvailable3)
			{
				if (inRoom)
				{
					NetworkSync.VoteForBiome3("A");
				}
				else
				{
					BiomeController.SelectedBiome3 = "A";
					BiomeController.UpdateWorldSpaceOverlay();
				}
			}
			if (!isAvailable3)
			{
				GUI.DrawTexture(val5, (Texture)(object)_xTexture);
			}
			if (((int)_currentInputScheme == 1 && _selectedRow == 1 && _selectedCol == 0) || (flag8 && !flag6))
			{
				GUI.DrawTexture(val5, (Texture)(object)_borderTexture);
			}
			string text7 = (isAvailable4 ? "" : BuildUnavailableMessage("Mesa", info4, FriendlyBiome2(effectiveBiome), FriendlyBiome4(effectiveBiome3)));
			GUIContent val8 = new GUIContent("MESA", text7);
			if (GUI.Button(val6, val8, GetButtonStyle(flag7)) && isAvailable4)
			{
				if (inRoom)
				{
					NetworkSync.VoteForBiome3("M");
				}
				else
				{
					BiomeController.SelectedBiome3 = "M";
					BiomeController.UpdateWorldSpaceOverlay();
				}
			}
			if (!isAvailable4)
			{
				GUI.DrawTexture(val6, (Texture)(object)_xTexture);
			}
			if (((int)_currentInputScheme == 1 && _selectedRow == 1 && _selectedCol == 1) || (flag9 && !flag7))
			{
				GUI.DrawTexture(val6, (Texture)(object)_borderTexture);
			}
			num6 += 40f;
			if (inRoom)
			{
				int votesAlpine = NetworkSync.VotesAlpine;
				int votesMesa = NetworkSync.VotesMesa;
				string defaultBiome2 = BiomeController.GetDefaultBiome3();
				bool flag10 = votesAlpine > votesMesa || (votesAlpine == votesMesa && defaultBiome2 == "A");
				string arg2 = (flag10 ? "Alpine" : "Mesa");
				GUI.Label(new Rect(num5, num6, num7, 20f), $"  Votes: Alpine {votesAlpine} | Mesa {votesMesa}  →  Winner: {arg2}", ((flag10 && votesAlpine > 0) || (!flag10 && votesMesa > 0)) ? _winnerStyle : _voteStyle);
				num6 += 25f;
			}
			else
			{
				num6 += 15f;
			}
			GUI.Label(new Rect(num5, num6, num7, 20f), "FINAL ASCENT:", _labelStyle);
			num6 += 25f;
			string text8 = (inRoom ? NetworkSync.MyVoteBiome4 : BiomeController.SelectedBiome4);
			bool flag11 = text8 == "V";
			bool flag12 = text8 == "S";
			LevelOverridePatch.BranchAvailability info5 = LevelOverridePatch.EvaluateBiome4Branch("V", effectiveBiome, effectiveBiome2);
			LevelOverridePatch.BranchAvailability info6 = LevelOverridePatch.EvaluateBiome4Branch("S", effectiveBiome, effectiveBiome2);
			bool isAvailable5 = info5.IsAvailable;
			bool isAvailable6 = info6.IsAvailable;
			Rect val9 = default(Rect);
			((Rect)(ref val9))..ctor(num5, num6, 150f, 35f);
			Rect val10 = default(Rect);
			((Rect)(ref val10))..ctor(num5 + 160f, num6, 150f, 35f);
			bool flag13 = ((Rect)(ref val9)).Contains(Event.current.mousePosition);
			bool flag14 = ((Rect)(ref val10)).Contains(Event.current.mousePosition);
			string text9 = (isAvailable5 ? "" : BuildUnavailableMessage("Volcano", info5, FriendlyBiome2(effectiveBiome), FriendlyBiome3(effectiveBiome2)));
			GUIContent val11 = new GUIContent("VOLCANO", text9);
			if (GUI.Button(val9, val11, GetButtonStyle(flag11)) && isAvailable5)
			{
				if (inRoom)
				{
					NetworkSync.VoteForBiome4("V");
				}
				else
				{
					BiomeController.SelectedBiome4 = "V";
					BiomeController.UpdateWorldSpaceOverlay();
				}
			}
			if (!isAvailable5)
			{
				GUI.DrawTexture(val9, (Texture)(object)_xTexture);
			}
			if (((int)_currentInputScheme == 1 && _selectedRow == 2 && _selectedCol == 0) || (flag13 && !flag11))
			{
				GUI.DrawTexture(val9, (Texture)(object)_borderTexture);
			}
			string text10 = (isAvailable6 ? "" : BuildUnavailableMessage("Swamp", info6, FriendlyBiome2(effectiveBiome), FriendlyBiome3(effectiveBiome2)));
			GUIContent val12 = new GUIContent("SWAMP", text10);
			if (GUI.Button(val10, val12, GetButtonStyle(flag12)) && isAvailable6)
			{
				if (inRoom)
				{
					NetworkSync.VoteForBiome4("S");
				}
				else
				{
					BiomeController.SelectedBiome4 = "S";
					BiomeController.UpdateWorldSpaceOverlay();
				}
			}
			if (!isAvailable6)
			{
				GUI.DrawTexture(val10, (Texture)(object)_xTexture);
			}
			if (((int)_currentInputScheme == 1 && _selectedRow == 2 && _selectedCol == 1) || (flag14 && !flag12))
			{
				GUI.DrawTexture(val10, (Texture)(object)_borderTexture);
			}
			num6 += 40f;
			if (inRoom)
			{
				int votesVolcano = NetworkSync.VotesVolcano;
				int votesSwamp = NetworkSync.VotesSwamp;
				string defaultBiome3 = BiomeController.GetDefaultBiome4();
				bool flag15 = votesVolcano > votesSwamp || (votesVolcano == votesSwamp && defaultBiome3 == "V");
				string arg3 = (flag15 ? "Volcano" : "Swamp");
				GUI.Label(new Rect(num5, num6, num7, 20f), $"  Votes: Volcano {votesVolcano} | Swamp {votesSwamp}  →  Winner: {arg3}", ((flag15 && votesVolcano > 0) || (!flag15 && votesSwamp > 0)) ? _winnerStyle : _voteStyle);
				num6 += 25f;
			}
			else
			{
				num6 += 15f;
			}
			Rect val13 = default(Rect);
			((Rect)(ref val13))..ctor(num5, num6, 150f, 30f);
			Rect val14 = default(Rect);
			((Rect)(ref val14))..ctor(num5 + 160f, num6, 150f, 30f);
			bool flag16 = ((Rect)(ref val13)).Contains(Event.current.mousePosition);
			bool flag17 = ((Rect)(ref val14)).Contains(Event.current.mousePosition);
			if (GUI.Button(val13, "CLEAR", GetButtonStyle(isVoted: false)))
			{
				if (inRoom)
				{
					NetworkSync.ClearMyVotes();
				}
				else
				{
					LevelOverridePatch.ClearOverrides();
					BiomeController.UpdateWorldSpaceOverlay();
				}
			}
			if (((int)_currentInputScheme == 1 && _selectedRow == 3 && _selectedCol == 0) || flag16)
			{
				GUI.DrawTexture(val13, (Texture)(object)_borderTexture);
			}
			if (GUI.Button(val14, "CLOSE", GetButtonStyle(isVoted: false)))
			{
				((MenuWindow)this).Close();
			}
			if (((int)_currentInputScheme == 1 && _selectedRow == 3 && _selectedCol == 1) || flag17)
			{
				GUI.DrawTexture(val14, (Texture)(object)_borderTexture);
			}
			num6 += 35f;
			GUI.Label(new Rect(num5, num6, num7, 20f), "Press ESC to close", _voteStyle);
			if (!string.IsNullOrEmpty(GUI.tooltip))
			{
				Vector2 mousePosition = Event.current.mousePosition;
				GUIContent val15 = new GUIContent(GUI.tooltip);
				float num8 = 240f;
				float num9 = _tooltipStyle.CalcHeight(val15, num8);
				float num10 = mousePosition.x + 16f;
				float num11 = mousePosition.y + 16f;
				if (num10 + num8 > (float)Screen.width)
				{
					num10 = (float)Screen.width - num8 - 4f;
				}
				if (num11 + num9 > (float)Screen.height)
				{
					num11 = (float)Screen.height - num9 - 4f;
				}
				GUI.Label(new Rect(num10, num11, num8, num9), val15, _tooltipStyle);
			}
		}

		private void InitStyles()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Expected O, but got Unknown
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Expected O, but got Unknown
			//IL_0118: 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: Expected O, but got Unknown
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0225: Unknown result type (might be due to invalid IL or missing references)
			//IL_022f: Expected O, but got Unknown
			//IL_0256: Unknown result type (might be due to invalid IL or missing references)
			//IL_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_0271: Expected O, but got Unknown
			//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e6: Expected O, but got Unknown
			//IL_030a: Unknown result type (might be due to invalid IL or missing references)
			//IL_032a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0334: Expected O, but got Unknown
			//IL_0355: Unknown result type (might be due to invalid IL or missing references)
			if (_boxStyle == null)
			{
				_boxStyle = new GUIStyle(GUI.skin.box);
				_boxStyle.normal.background = MakeTex(2, 2, new Color(0.08f, 0.06f, 0.04f, 0.95f));
				_labelStyle = new GUIStyle(GUI.skin.label);
				_labelStyle.normal.textColor = Color.white;
				_labelStyle.fontSize = 16;
				_headerStyle = new GUIStyle(_labelStyle);
				_headerStyle.fontStyle = (FontStyle)1;
				_headerStyle.fontSize = 22;
				_headerStyle.normal.textColor = new Color(1f, 0.85f, 0.4f);
				_headerStyle.alignment = (TextAnchor)4;
				_buttonStyle = new GUIStyle(GUI.skin.button);
				_buttonStyle.fontSize = 16;
				_buttonStyle.fontStyle = (FontStyle)1;
				_buttonStyle.normal.textColor = Color.white;
				_buttonStyle.hover.background = _buttonStyle.normal.background;
				_buttonStyle.active.background = _buttonStyle.normal.background;
				_selectedButtonStyle = new GUIStyle(_buttonStyle);
				_selectedButtonStyle.normal.background = MakeTex(2, 2, new Color(0.2f, 0.5f, 0.2f, 1f));
				_selectedButtonStyle.hover.background = _selectedButtonStyle.normal.background;
				_selectedButtonStyle.active.background = _selectedButtonStyle.normal.background;
				_selectedButtonStyle.normal.textColor = Color.yellow;
				_borderTexture = MakeBorderTex(4, 4, new Color(0.5f, 0.8f, 1f, 0.6f));
				_voteStyle = new GUIStyle(_labelStyle);
				_voteStyle.fontSize = 14;
				_voteStyle.normal.textColor = new Color(0.7f, 0.7f, 0.7f);
				_winnerStyle = new GUIStyle(_labelStyle);
				_winnerStyle.fontSize = 14;
				_winnerStyle.fontStyle = (FontStyle)1;
				_winnerStyle.normal.textColor = new Color(1f, 0.84f, 0f);
				_xTexture = MakeXTex(32, new Color(0.9f, 0.15f, 0.15f, 0.95f), 3);
				_tooltipStyle = new GUIStyle(_labelStyle);
				_tooltipStyle.fontSize = 13;
				_tooltipStyle.fontStyle = (FontStyle)0;
				_tooltipStyle.normal.textColor = Color.white;
				_tooltipStyle.wordWrap = true;
				_tooltipStyle.padding = new RectOffset(6, 6, 4, 4);
				_tooltipStyle.normal.background = MakeTex(2, 2, new Color(0.05f, 0.05f, 0.05f, 0.97f));
			}
		}

		private static Texture2D MakeTex(int width, int height, Color col)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			Color[] array = (Color[])(object)new Color[width * height];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = col;
			}
			Texture2D val = new Texture2D(width, height);
			val.SetPixels(array);
			val.Apply();
			return val;
		}

		private static Texture2D MakeBorderTex(int width, int height, Color borderCol)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected O, but got Unknown
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			Color[] array = (Color[])(object)new Color[width * height];
			for (int i = 0; i < array.Length; i++)
			{
				int num = i % width;
				int num2 = i / width;
				bool flag = num == 0 || num == width - 1 || num2 == 0 || num2 == height - 1;
				array[i] = (flag ? borderCol : Color.clear);
			}
			Texture2D val = new Texture2D(width, height);
			val.SetPixels(array);
			val.Apply();
			return val;
		}

		private static Texture2D MakeXTex(int size, Color col, int thickness)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Expected O, but got Unknown
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: 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)
			Color[] array = (Color[])(object)new Color[size * size];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = Color.clear;
			}
			for (int j = 0; j < size; j++)
			{
				for (int k = -thickness; k <= thickness; k++)
				{
					int num = j + k;
					if (num >= 0 && num < size)
					{
						array[num * size + j] = col;
					}
					int num2 = size - 1 - j + k;
					if (num2 >= 0 && num2 < size)
					{
						array[num2 * size + j] = col;
					}
				}
			}
			Texture2D val = new Texture2D(size, size);
			val.SetPixels(array);
			val.Apply();
			return val;
		}
	}
	public class NetworkSync : MonoBehaviourPunCallbacks
	{
		private const string VOTE_PREFIX_B2 = "VP_V2_";

		private const string VOTE_PREFIX_B3 = "VP_V3_";

		private const string VOTE_PREFIX_B4 = "VP_V4_";

		private static NetworkSync? _instance;

		private static bool _initialized;

		public static int VotesTropics { get; private set; }

		public static int VotesRoots { get; private set; }

		public static int VotesAlpine { get; private set; }

		public static int VotesMesa { get; private set; }

		public static int VotesVolcano { get; private set; }

		public static int VotesSwamp { get; private set; }

		public static string? MyVoteBiome2 { get; private set; }

		public static string? MyVoteBiome3 { get; private set; }

		public static string? MyVoteBiome4 { get; private set; }

		public static bool IsAvailable
		{
			get
			{
				if (_initialized)
				{
					return PhotonNetwork.InRoom;
				}
				return false;
			}
		}

		public static bool IsMasterClient => PhotonNetwork.IsMasterClient;

		private void Awake()
		{
			if ((Object)(object)_instance != (Object)null && (Object)(object)_instance != (Object)(object)this)
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
				return;
			}
			_instance = this;
			_initialized = true;
			MyVoteBiome2 = null;
			MyVoteBiome3 = null;
			MyVoteBiome4 = null;
			Plugin.Log.LogInfo((object)"NetworkSync initialized (Continuous Voting System)");
		}

		public override void OnEnable()
		{
			((MonoBehaviourPunCallbacks)this).OnEnable();
			SceneManager.sceneLoaded += OnSceneLoaded;
		}

		public override void OnDisable()
		{
			((MonoBehaviourPunCallbacks)this).OnDisable();
			SceneManager.sceneLoaded -= OnSceneLoaded;
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			if (((Scene)(ref scene)).name == "Airport")
			{
				Plugin.Log.LogInfo((object)"[NetworkSync] Returned to Airport - Clearing votes");
				MyVoteBiome2 = null;
				MyVoteBiome3 = null;
				MyVoteBiome4 = null;
				if (PhotonNetwork.InRoom)
				{
					ClearMyVotes();
				}
				LevelOverridePatch.ClearOverrides();
			}
		}

		public static void VoteForBiome2(string vote)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Expected O, but got Unknown
			//IL_0054: Expected O, but got Unknown
			if (PhotonNetwork.InRoom && (!(vote != "T") || !(vote != "R")))
			{
				MyVoteBiome2 = vote;
				string key = "VP_V2_" + PhotonNetwork.LocalPlayer.ActorNumber;
				Hashtable val = new Hashtable();
				((Dictionary<object, object>)val).Add((object)key, (object)vote);
				Hashtable val2 = val;
				PhotonNetwork.CurrentRoom.SetCustomProperties(val2, (Hashtable)null, (WebFlags)null);
				Plugin.Log.LogInfo((object)("[VOTE] Biome2 vote submitted: " + vote));
			}
		}

		public static void VoteForBiome3(string vote)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Expected O, but got Unknown
			//IL_0054: Expected O, but got Unknown
			if (PhotonNetwork.InRoom && (!(vote != "A") || !(vote != "M")))
			{
				MyVoteBiome3 = vote;
				string key = "VP_V3_" + PhotonNetwork.LocalPlayer.ActorNumber;
				Hashtable val = new Hashtable();
				((Dictionary<object, object>)val).Add((object)key, (object)vote);
				Hashtable val2 = val;
				PhotonNetwork.CurrentRoom.SetCustomProperties(val2, (Hashtable)null, (WebFlags)null);
				Plugin.Log.LogInfo((object)("[VOTE] Biome3 vote submitted: " + vote));
			}
		}

		public static void VoteForBiome4(string vote)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Expected O, but got Unknown
			//IL_0054: Expected O, but got Unknown
			if (PhotonNetwork.InRoom && (!(vote != "V") || !(vote != "S")))
			{
				MyVoteBiome4 = vote;
				string key = "VP_V4_" + PhotonNetwork.LocalPlayer.ActorNumber;
				Hashtable val = new Hashtable();
				((Dictionary<object, object>)val).Add((object)key, (object)vote);
				Hashtable val2 = val;
				PhotonNetwork.CurrentRoom.SetCustomProperties(val2, (Hashtable)null, (WebFlags)null);
				Plugin.Log.LogInfo((object)("[VOTE] Biome4 vote submitted: " + vote));
			}
		}

		public static void ClearMyVotes()
		{
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Expected O, but got Unknown
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Expected O, but got Unknown
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Expected O, but got Unknown
			//IL_009e: Expected O, but got Unknown
			if (PhotonNetwork.InRoom)
			{
				MyVoteBiome2 = null;
				MyVoteBiome3 = null;
				MyVoteBiome4 = null;
				string key = "VP_V2_" + PhotonNetwork.LocalPlayer.ActorNumber;
				string key2 = "VP_V3_" + PhotonNetwork.LocalPlayer.ActorNumber;
				string key3 = "VP_V4_" + PhotonNetwork.LocalPlayer.ActorNumber;
				Hashtable val = new Hashtable();
				((Dictionary<object, object>)val).Add((object)key, (object)"");
				((Dictionary<object, object>)val).Add((object)key2, (object)"");
				((Dictionary<object, object>)val).Add((object)key3, (object)"");
				Hashtable val2 = val;
				PhotonNetwork.CurrentRoom.SetCustomProperties(val2, (Hashtable)null, (WebFlags)null);
				Plugin.Log.LogInfo((object)"[VOTE] Cleared my votes");
			}
		}

		public unsafe static void CountVotesAndUpdateOverride()
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			VotesTropics = 0;
			VotesRoots = 0;
			VotesAlpine = 0;
			VotesMesa = 0;
			VotesVolcano = 0;
			VotesSwamp = 0;
			if (!PhotonNetwork.InRoom)
			{
				return;
			}
			Hashtable customProperties = ((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties;
			DictionaryEntryEnumerator enumerator = customProperties.GetEnumerator();
			try
			{
				while (((DictionaryEntryEnumerator)(ref enumerator)).MoveNext())
				{
					DictionaryEntry current = ((DictionaryEntryEnumerator)(ref enumerator)).Current;
					string text = (current.Key as string) ?? "";
					string text2 = (current.Value as string) ?? "";
					if (string.IsNullOrEmpty(text2))
					{
						continue;
					}
					if (text.StartsWith("VP_V2_"))
					{
						if (text2 == "T")
						{
							VotesTropics++;
						}
						else if (text2 == "R")
						{
							VotesRoots++;
						}
					}
					else if (text.StartsWith("VP_V3_"))
					{
						if (text2 == "A")
						{
							VotesAlpine++;
						}
						else if (text2 == "M")
						{
							VotesMesa++;
						}
					}
					else if (text.StartsWith("VP_V4_"))
					{
						if (text2 == "V")
						{
							VotesVolcano++;
						}
						else if (text2 == "S")
						{
							VotesSwamp++;
						}
					}
				}
			}
			finally
			{
				((IDisposable)(*(DictionaryEntryEnumerator*)(&enumerator))/*cast due to .constrained prefix*/).Dispose();
			}
			string text3 = null;
			if (VotesTropics > VotesRoots)
			{
				text3 = "T";
			}
			else if (VotesRoots > VotesTropics)
			{
				text3 = "R";
			}
			string text4 = null;
			if (VotesAlpine > VotesMesa)
			{
				text4 = "A";
			}
			else if (VotesMesa > VotesAlpine)
			{
				text4 = "M";
			}
			string text5 = null;
			if (VotesVolcano > VotesSwamp)
			{
				text5 = "V";
			}
			else if (VotesSwamp > VotesVolcano)
			{
				text5 = "S";
			}
			LevelOverridePatch.DesiredBiome2 = text3;
			LevelOverridePatch.DesiredBiome3 = text4;
			LevelOverridePatch.DesiredBiome4 = text5;
			BiomeController.UpdateWorldSpaceOverlay();
			Plugin.Log.LogInfo((object)string.Format("[VOTE] Tally Updated: T:{0} R:{1} (Winner: {2}) | A:{3} M:{4} (Winner: {5}) | V:{6} S:{7} (Winner: {8})", VotesTropics, VotesRoots, text3 ?? "Default", VotesAlpine, VotesMesa, text4 ?? "Default", VotesVolcano, VotesSwamp, text5 ?? "Default"));
		}

		public override void OnRoomPropertiesUpdate(Hashtable propertiesThatChanged)
		{
			CountVotesAndUpdateOverride();
		}

		public override void OnJoinedRoom()
		{
			Plugin.Log.LogInfo((object)$"[CALLBACK] OnJoinedRoom - IsMasterClient={PhotonNetwork.IsMasterClient}");
			LevelOverridePatch.ClearOverrides();
			CountVotesAndUpdateOverride();
			Hashtable customProperties = ((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties;
			string key = "VP_V2_" + PhotonNetwork.LocalPlayer.ActorNumber;
			string key2 = "VP_V3_" + PhotonNetwork.LocalPlayer.ActorNumber;
			string key3 = "VP_V4_" + PhotonNetwork.LocalPlayer.ActorNumber;
			if (((Dictionary<object, object>)(object)customProperties).TryGetValue((object)key, out object value) && value is string text && !string.IsNullOrEmpty(text))
			{
				MyVoteBiome2 = text;
			}
			if (((Dictionary<object, object>)(object)customProperties).TryGetValue((object)key2, out object value2) && value2 is string text2 && !string.IsNullOrEmpty(text2))
			{
				MyVoteBiome3 = text2;
			}
			if (((Dictionary<object, object>)(object)customProperties).TryGetValue((object)key3, out object value3) && value3 is string text3 && !string.IsNullOrEmpty(text3))
			{
				MyVoteBiome4 = text3;
			}
		}
	}
	[BepInPlugin("com.github.strangebasis.VacationPlanner", "VacationPlanner", "2.2.0")]
	public class Plugin : BaseUnityPlugin
	{
		private readonly Harmony _harmony = new Harmony("com.github.strangebasis.VacationPlanner");

		private static ConfigEntry<bool>? _debugLogging;

		public const string Id = "com.github.strangebasis.VacationPlanner";

		internal static ManualLogSource Log { get; private set; }

		internal static bool DebugLoggingEnabled => _debugLogging?.Value ?? false;

		public static string Name => "VacationPlanner";

		public static string Version => "2.2.0";

		private void Awake()
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Log.LogInfo((object)("Plugin " + Name + " is loaded!"));
			_debugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "EnableVerboseLogging", false, "Enables verbose MapBaker/MapHandler diagnostic dumps used for development. Leave off for normal play.");
			_harmony.PatchAll(Assembly.GetExecutingAssembly());
			GameObject val = new GameObject("VacationPlanner_Controller");
			val.AddComponent<BiomeController>();
			val.AddComponent<NetworkSync>();
			Object.DontDestroyOnLoad((Object)(object)val);
			Log.LogInfo((object)"BiomeController and NetworkSync initialized");
		}
	}
}
namespace VacationPlanner.Patches
{
	[HarmonyPatch]
	public static class GameStartPatch
	{
		[HarmonyPatch(typeof(AirportCheckInKiosk), "LoadIslandMaster")]
		[HarmonyPrefix]
		public static void LoadIslandMaster_Prefix()
		{
			Plugin.Log.LogInfo((object)"[GameStartPatch] LoadIslandMaster starting...");
			Plugin.Log.LogInfo((object)("[GameStartPatch] Overrides active: B2=" + (LevelOverridePatch.DesiredBiome2 ?? "Default") + ", B3=" + (LevelOverridePatch.DesiredBiome3 ?? "Default") + ", B4=" + (LevelOverridePatch.DesiredBiome4 ?? "Default")));
		}
	}
	[HarmonyPatch(typeof(MapBaker))]
	public static class LevelOverridePatch
	{
		public struct BranchAvailability
		{
			public bool IsAvailable { get; set; }

			public bool IsGloballyUnavailable { get; set; }

			public bool ChangingOtherAWouldHelp { get; set; }

			public bool ChangingOtherBWouldHelp { get; set; }
		}

		private static Dictionary<string, List<int>>? _biomeToLevels;

		private const bool UseTestBiomeMapOverride = false;

		private const int PosBiome2 = 1;

		private const int PosBiome3 = 2;

		private const int PosBiome4 = -1;

		public static string? DesiredBiome2 { get; set; }

		public static string? DesiredBiome3 { get; set; }

		public static string? DesiredBiome4 { get; set; }

		public static void ClearOverrides()
		{
			DesiredBiome2 = null;
			DesiredBiome3 = null;
			DesiredBiome4 = null;
			Plugin.Log.LogInfo((object)"Biome overrides cleared");
		}

		public static void InvalidateCache()
		{
			_biomeToLevels = null;
		}

		public static void EnsureBiomeMapBuilt()
		{
			if (_biomeToLevels == null)
			{
				MapBaker instance = SingletonAsset<MapBaker>.Instance;
				if ((Object)(object)instance != (Object)null)
				{
					_biomeToLevels = BuildBiomeToLevels(instance);
				}
			}
		}

		private static Dictionary<string, List<int>> BuildTestBiomeToLevels()
		{
			return new Dictionary<string, List<int>>
			{
				["STAS"] = new List<int> { 0 },
				["STMS"] = new List<int> { 1 },
				["SRAS"] = new List<int> { 2 }
			};
		}

		public static string GetSelectionSummary()
		{
			string desiredBiome = DesiredBiome2;
			string text = ((desiredBiome == "T") ? "Tropics" : ((!(desiredBiome == "R")) ? "Default" : "Roots"));
			string text2 = text;
			string desiredBiome2 = DesiredBiome3;
			text = ((desiredBiome2 == "A") ? "Alpine" : ((!(desiredBiome2 == "M")) ? "Default" : "Mesa"));
			string text3 = text;
			string desiredBiome3 = DesiredBiome4;
			text = ((desiredBiome3 == "V") ? "Caldera/Kiln" : ((!(desiredBiome3 == "S")) ? "Default" : "Gloom/Citadel"));
			string text4 = text;
			return "Biome2: " + text2 + ", Biome3: " + text3 + ", Biome4: " + text4;
		}

		private static Dictionary<string, List<int>> BuildBiomeToLevels(MapBaker baker)
		{
			Dictionary<string, List<int>> dictionary = new Dictionary<string, List<int>>();
			if (baker.BiomeIDs != null)
			{
				for (int i = 0; i < baker.BiomeIDs.Count; i++)
				{
					string key = baker.BiomeIDs[i];
					if (!dictionary.ContainsKey(key))
					{
						dictionary[key] = new List<int>();
					}
					dictionary[key].Add(i);
				}
				Plugin.Log.LogInfo((object)$"[LevelOverride] Built dynamic biome mapping with {dictionary.Count} biome types:");
				foreach (KeyValuePair<string, List<int>> item in dictionary)
				{
					Plugin.Log.LogInfo((object)("  " + item.Key + " -> [" + string.Join(", ", item.Value) + "]"));
				}
			}
			return dictionary;
		}

		[HarmonyPatch("GetLevel")]
		[HarmonyPrefix]
		public static void GetLevel_Prefix(MapBaker __instance, ref int levelIndex)
		{
			if (DesiredBiome2 != null || DesiredBiome3 != null || DesiredBiome4 != null)
			{
				if (_biomeToLevels == null)
				{
					_biomeToLevels = BuildBiomeToLevels(__instance);
				}
				int num = levelIndex;
				int num2 = __instance.BiomeIDs?.Count ?? 1;
				string biomeIdForLevel = GetBiomeIdForLevel(__instance, levelIndex);
				string biome = DesiredBiome2?.ToUpper() ?? (biomeIdForLevel.Contains("T") ? "T" : "R");
				string biome2 = DesiredBiome3?.ToUpper() ?? (biomeIdForLevel.Contains("A") ? "A" : "M");
				char c = ((biomeIdForLevel.Length > 0) ? biomeIdForLevel[biomeIdForLevel.Length - 1] : 'V');
				string biome3 = DesiredBiome4?.ToUpper() ?? c.ToString();
				int num3 = num % num2;
				string text = ResolveAchievableBiomeId(biome, biome2, biome3, biomeIdForLevel, num3, num2);
				List<int> value;
				if (biomeIdForLevel == text)
				{
					Plugin.Log.LogInfo((object)$"[LevelOverride] Level {levelIndex} already has {text}");
				}
				else if (_biomeToLevels.TryGetValue(text, out value) && value.Count > 0)
				{
					int num4 = value[num3 % value.Count];
					Plugin.Log.LogInfo((object)$"[LevelOverride] Redirecting level {num} (actual={num3}, {biomeIdForLevel}) -> {num4} ({text})");
					levelIndex = num4;
				}
				else
				{
					Plugin.Log.LogWarning((object)("[LevelOverride] Unknown biome combo: " + text + ". Available: " + string.Join(", ", _biomeToLevels.Keys)));
				}
			}
		}

		[HarmonyPatch("GetBiomeID")]
		[HarmonyPostfix]
		public static void GetBiomeID_Postfix(MapBaker __instance, int levelIndex, ref string __result)
		{
			if (DesiredBiome2 != null || DesiredBiome3 != null || DesiredBiome4 != null)
			{
				if (_biomeToLevels == null)
				{
					_biomeToLevels = BuildBiomeToLevels(__instance);
				}
				string biome = DesiredBiome2?.ToUpper() ?? (__result.Contains("T") ? "T" : "R");
				string biome2 = DesiredBiome3?.ToUpper() ?? (__result.Contains("A") ? "A" : "M");
				char c = ((__result.Length > 0) ? __result[__result.Length - 1] : 'V');
				string biome3 = DesiredBiome4?.ToUpper() ?? c.ToString();
				int referenceIndex = levelIndex % (__instance.BiomeIDs?.Count ?? 1);
				int totalLevels = __instance.BiomeIDs?.Count ?? 1;
				string text = ResolveAchievableBiomeId(biome, biome2, biome3, __result, referenceIndex, totalLevels);
				if (__result != text)
				{
					Plugin.Log.LogInfo((object)("[LevelOverride] BiomeID override: " + __result + " -> " + text));
					__result = text;
				}
			}
		}

		private static string ResolveAchievableBiomeId(string biome2, string biome3, string biome4, string fallbackCurrent, int referenceIndex, int totalLevels)
		{
			string text = "S" + biome2 + biome3 + biome4;
			if (_biomeToLevels == null || _biomeToLevels.Count == 0)
			{
				return text;
			}
			if (_biomeToLevels.ContainsKey(text))
			{
				return text;
			}
			string text2 = FindClosestKeyMatching(referenceIndex, totalLevels, (string key) => key.Length >= 3 && key[1] == biome2[0] && key[2] == biome3[0]);
			if (text2 != null)
			{
				Plugin.Log.LogWarning((object)("[LevelOverride] " + text + " isn't baked into this build (biome4 branch '" + biome4 + "' may not be available). Falling back to closest match " + text2 + "."));
				return text2;
			}
			string text3 = FindClosestKeyMatching(referenceIndex, totalLevels, (string key) => key.Length >= 2 && key[1] == biome2[0]);
			if (text3 != null)
			{
				Plugin.Log.LogWarning((object)("[LevelOverride] " + text + " isn't baked into this build. Falling back to closest biome2-only match " + text3 + "."));
				return text3;
			}
			Plugin.Log.LogWarning((object)("[LevelOverride] No baked level matches even a partial override for " + text + ". Available: " + string.Join(", ", _biomeToLevels.Keys)));
			return fallbackCurrent;
		}

		private static string? FindClosestKeyMatching(int referenceIndex, int totalLevels, Func<string, bool> predicate)
		{
			string result = null;
			int num = int.MaxValue;
			foreach (KeyValuePair<string, List<int>> biomeToLevel in _biomeToLevels)
			{
				if (!predicate(biomeToLevel.Key))
				{
					continue;
				}
				foreach (int item in biomeToLevel.Value)
				{
					int num2 = CyclicDistance(item, referenceIndex, totalLevels);
					if (num2 < num)
					{
						num = num2;
						result = biomeToLevel.Key;
					}
				}
			}
			return result;
		}

		private static int CyclicDistance(int a, int b, int totalLevels)
		{
			if (totalLevels <= 0)
			{
				return Math.Abs(a - b);
			}
			int num = Math.Abs(a - b) % totalLevels;
			return Math.Min(num, totalLevels - num);
		}

		private static char? NormalizeLeader(string? leader)
		{
			if (!string.IsNullOrEmpty(leader))
			{
				return leader.ToUpper()[0];
			}
			return null;
		}

		private static bool KeyMatchesPosition(string key, int position, char value)
		{
			if (position == -1)
			{
				if (key.Length > 0)
				{
					return key[key.Length - 1] == value;
				}
				return false;
			}
			if (key.Length > position)
			{
				return key[position] == value;
			}
			return false;
		}

		private static bool AnyKeyMatches(int targetPos, char targetChar, int constraintPosA, char? constraintValueA, int constraintPosB, char? constraintValueB)
		{
			foreach (string key in _biomeToLevels.Keys)
			{
				if (KeyMatchesPosition(key, targetPos, targetChar) && (!constraintValueA.HasValue || KeyMatchesPosition(key, constraintPosA, constraintValueA.Value)) && (!constraintValueB.HasValue || KeyMatchesPosition(key, constraintPosB, constraintValueB.Value)))
				{
					return true;
				}
			}
			return false;
		}

		private static BranchAvailability Evaluate(int position, string branch, int otherPosA, string? otherLeaderA, int otherPosB, string? otherLeaderB)
		{
			if (_biomeToLevels == null || _biomeToLevels.Count == 0 || string.IsNullOrEmpty(branch))
			{
				return new BranchAvailability
				{
					IsAvailable = true
				};
			}
			char targetChar = branch.ToUpper()[0];
			char? c = NormalizeLeader(otherLeaderA);
			char? c2 = NormalizeLeader(otherLeaderB);
			if (!AnyKeyMatches(position, targetChar, otherPosA, null, otherPosB, null))
			{
				return new BranchAvailability
				{
					IsAvailable = false,
					IsGloballyUnavailable = true
				};
			}
			if (AnyKeyMatches(position, targetChar, otherPosA, c, otherPosB, c2))
			{
				return new BranchAvailability
				{
					IsAvailable = true
				};
			}
			return new BranchAvailability
			{
				IsAvailable = false,
				IsGloballyUnavailable = false,
				ChangingOtherAWouldHelp = AnyKeyMatchesSingleConstraint(position, targetChar, otherPosB, c2),
				ChangingOtherBWouldHelp = AnyKeyMatchesSingleConstraint(position, targetChar, otherPosA, c)
			};
		}

		private static bool AnyKeyMatchesSingleConstraint(int targetPos, char targetChar, int constraintPos, char? constraintValue)
		{
			foreach (string key in _biomeToLevels.Keys)
			{
				if (KeyMatchesPosition(key, targetPos, targetChar) && (!constraintValue.HasValue || KeyMatchesPosition(key, constraintPos, constraintValue.Value)))
				{
					return true;
				}
			}
			return false;
		}

		public static BranchAvailability EvaluateBiome2Branch(string branch, string? biome3Leader = null, string? biome4Leader = null)
		{
			return Evaluate(1, branch, 2, biome3Leader, -1, biome4Leader);
		}

		public static BranchAvailability EvaluateBiome3Branch(string branch, string? biome2Leader = null, string? biome4Leader = null)
		{
			return Evaluate(2, branch, 1, biome2Leader, -1, biome4Leader);
		}

		public static BranchAvailability EvaluateBiome4Branch(string branch, string? biome2Leader = null, string? biome3Leader = null)
		{
			return Evaluate(-1, branch, 1, biome2Leader, 2, biome3Leader);
		}

		public static bool IsBiome2BranchAvailable(string branch, string? biome3Leader = null, string? biome4Leader = null)
		{
			return EvaluateBiome2Branch(branch, biome3Leader, biome4Leader).IsAvailable;
		}

		public static bool IsBiome3BranchAvailable(string branch, string? biome2Leader = null, string? biome4Leader = null)
		{
			return EvaluateBiome3Branch(branch, biome2Leader, biome4Leader).IsAvailable;
		}

		public static bool IsBiome4BranchAvailable(string branch, string? biome2Leader = null, string? biome3Leader = null)
		{
			return EvaluateBiome4Branch(branch, biome2Leader, biome3Leader).IsAvailable;
		}

		private static string GetBiomeIdForLevel(MapBaker baker, int levelIndex)
		{
			if (baker.BiomeIDs == null || baker.BiomeIDs.Count == 0)
			{
				return "STMV";
			}
			return baker.BiomeIDs[levelIndex % baker.BiomeIDs.Count];
		}
	}
	[HarmonyPatch(typeof(MapBaker))]
	public static class MapBakerDebugPatch
	{
		private static bool _hasDumped;

		[HarmonyPatch("GetLevel")]
		[HarmonyPostfix]
		public static void GetLevel_Postfix(MapBaker __instance, int levelIndex, string __result)
		{
			if (Plugin.DebugLoggingEnabled)
			{
				if (!_hasDumped)
				{
					_hasDumped = true;
					DumpMapBakerData(__instance);
				}
				Plugin.Log.LogInfo((object)$"[GetLevel] levelIndex={levelIndex} => result=\"{__result}\"");
			}
		}

		[HarmonyPatch("GetBiomeID")]
		[HarmonyPostfix]
		public static void GetBiomeID_Postfix(MapBaker __instance, int levelIndex, string __result)
		{
			if (Plugin.DebugLoggingEnabled)
			{
				int num = levelIndex % __instance.BiomeIDs.Count;
				Plugin.Log.LogInfo((object)$"[GetBiomeID] levelIndex={levelIndex} (actual={num}) => biomeID=\"{__result}\"");
			}
		}

		private static void DumpMapBakerData(MapBaker baker)
		{
			Plugin.Log.LogInfo((object)"=== MapBaker Data Dump ===");
			ManualLogSource log = Plugin.Log;
			string[] scenePaths = baker.ScenePaths;
			log.LogInfo((object)$"ScenePaths.Length = {((scenePaths != null) ? scenePaths.Length : 0)}");
			if (baker.ScenePaths != null)
			{
				for (int i = 0; i < baker.ScenePaths.Length; i++)
				{
					Plugin.Log.LogInfo((object)$"  ScenePaths[{i}] = \"{baker.ScenePaths[i]}\"");
				}
			}
			Plugin.Log.LogInfo((object)"");
			Plugin.Log.LogInfo((object)$"BiomeIDs.Count = {baker.BiomeIDs?.Count ?? 0}");
			if (baker.BiomeIDs != null)
			{
				for (int j = 0; j < baker.BiomeIDs.Count; j++)
				{
					string text = baker.BiomeIDs[j];
					string arg = DecodeBiomeID(text);
					Plugin.Log.LogInfo((object)$"  BiomeIDs[{j}] = \"{text}\" ({arg})");
				}
			}
			Plugin.Log.LogInfo((object)"");
			Plugin.Log.LogInfo((object)$"selectedBiomes.Count = {baker.selectedBiomes?.Count ?? 0}");
			if (baker.selectedBiomes != null)
			{
				for (int k = 0; k < baker.selectedBiomes.Count; k++)
				{
					BiomeResult val = baker.selectedBiomes[k];
					string text2 = string.Join(", ", val.biomeTypes);
					string text3 = string.Join(", ", val.variantNames ?? new List<string>());
					Plugin.Log.LogInfo((object)$"  selectedBiomes[{k}] biomeTypes=[{text2}] variantNames=[{text3}] => \"{val}\"");
				}
			}
			Plugin.Log.LogInfo((object)"");
			Plugin.Log.LogInfo((object)"=== Level/Biome Correlation ===");
			string[] scenePaths2 = baker.ScenePaths;
			int num = ((scenePaths2 != null) ? scenePaths2.Length : 0);
			int num2 = baker.BiomeIDs?.Count ?? 0;
			Plugin.Log.LogInfo((object)$"ScenePaths has {num} entries, BiomeIDs has {num2} entries");
			if (num > 0 && num2 > 0)
			{
				Plugin.Log.LogInfo((object)$"Ratio: {(float)num2 / (float)num:F2} biomes per level");
				Plugin.Log.LogInfo((object)("Are they 1:1? " + ((num == num2) ? "YES" : "NO")));
			}
			Plugin.Log.LogInfo((object)"=== End MapBaker Data Dump ===");
		}

		private static string DecodeBiomeID(string biomeId)
		{
			if (string.IsNullOrEmpty(biomeId))
			{
				return "empty";
			}
			List<string> list = new List<string>();
			for (int i = 0; i < biomeId.Length; i++)
			{
				char c = biomeId[i];
				bool flag = i == 0;
				bool flag2 = i == biomeId.Length - 1;
				string item = ((flag && c == 'S') ? "Shore" : ((flag2 && c == 'S') ? "Swamp/Gloom+Citadel" : ((!flag2 || c != 'V') ? (c switch
				{
					'T' => "Tropics", 
					'R' => "Roots", 
					'A' => "Alpine", 
					'M' => "Mesa", 
					'V' => "Volcano/Caldera", 
					'K' => "Kiln", 
					'P' => "Peak", 
					_ => $"UNRECOGNIZED_CHAR({c})", 
				}) : "Volcano/Caldera+Kiln")));
				list.Add(item);
			}
			return string.Join(" + ", list);
		}
	}
	[HarmonyPatch(typeof(MapHandler))]
	public static class MapHandlerDebugPatch
	{
		[HarmonyPatch("InitializeMap")]
		[HarmonyPostfix]
		public static void InitializeMap_Postfix()
		{
			if (Plugin.DebugLoggingEnabled && MapHandler.Exists)
			{
				DumpMapHandlerData(Singleton<MapHandler>.Instance);
			}
		}

		[HarmonyPatch("DetectBiomes")]
		[HarmonyPostfix]
		public static void DetectBiomes_Postfix(MapHandler __instance)
		{
			if (Plugin.DebugLoggingEnabled)
			{
				Plugin.Log.LogInfo((object)"[MapHandlerDebug] DetectBiomes() was called.");
				DumpMapHandlerData(__instance);
			}
		}

		private static void DumpMapHandlerData(MapHandler handler)
		{
			Plugin.Log.LogInfo((object)"=== MapHandler Segment Dump ===");
			MapSegment[] segments = handler.segments;
			MapSegment[] variantSegments = handler.variantSegments;
			Plugin.Log.LogInfo((object)$"segments.Length = {((segments != null) ? segments.Length : 0)}");
			if (segments != null)
			{
				for (int i = 0; i < segments.Length; i++)
				{
					DumpSegment($"segments[{i}]", segments[i]);
				}
			}
			Plugin.Log.LogInfo((object)$"variantSegments.Length = {((variantSegments != null) ? variantSegments.Length : 0)}");
			if (variantSegments != null)
			{
				for (int j = 0; j < variantSegments.Length; j++)
				{
					DumpSegment($"variantSegments[{j}]", variantSegments[j]);
				}
			}
			Plugin.Log.LogInfo((object)("MapHandler.biomes (currently detected/active) = [" + string.Join(", ", handler.biomes) + "]"));
			Plugin.Log.LogInfo((object)"=== End MapHandler Segment Dump ===");
		}

		private static void DumpSegment(string label, MapSegment segment)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing reference