Decompiled source of TeleportationMap v0.1.15

BepInEx/plugins/TeleportationMap.dll

Decompiled 5 days ago
using System;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace TeleportationMap;

[BepInPlugin("chadi7bark.howtofish.teleportationmap", "Teleportation Map", "0.1.14")]
public sealed class TeleportationMapPlugin : BaseUnityPlugin
{
	private const float WorldToMapXScale = 0.0006040856f;

	private const float WorldToMapXOffset = 0.5680561f;

	private const float WorldToMapZScale = -0.0005951446f;

	private const float WorldToMapZOffset = 0.4647192f;

	private const float LighthouseMapCenterU = 0.459947f;

	private const float LighthouseMapCenterV = 0.094246f;

	private const float LighthouseWorldCenterX = -202.596f;

	private const float LighthouseWorldCenterZ = 601.437f;

	private const float IslandTeleportY = 1.5f;

	private const float AnywhereFallbackY = 3f;

	private const float GroundProbeStartY = 250f;

	private const float GroundProbeDistance = 500f;

	private const float GroundSpawnOffsetY = 1.75f;

	private const int IslandScenePhysicsSettleFrames = 12;

	private const double IslandSceneLoadTimeoutSeconds = 8.0;

	private static readonly string[] IslandNames = new string[5] { "Lighthouse Island", "Shed Island", "Tropical Island", "Casino Island", "Volcano Island" };

	private static readonly float[] IslandWorldX = new float[5] { -200f, 500f, 310f, -150f, -700f };

	private static readonly float[] IslandWorldZ = new float[5] { 600f, -100f, -570f, -770f, -560f };

	private static readonly string[] IslandSceneNames = new string[5] { "Island1", "Island2", "Island3", "Island4", "Island5" };

	private static readonly float[] IslandMapMinU = new float[5] { 0.420707f, 0.836483f, 0.69433f, 0.435497f, 0.064092f };

	private static readonly float[] IslandMapMaxU = new float[5] { 0.486442f, 0.913722f, 0.795399f, 0.527527f, 0.221857f };

	private static readonly float[] IslandMapMinV = new float[5] { 0.08662f, 0.506574f, 0.764114f, 0.887858f, 0.740139f };

	private static readonly float[] IslandMapMaxV = new float[5] { 0.137664f, 0.569219f, 0.846868f, 0.949729f, 0.864656f };

	private static readonly float[] LockedIslandMinX = new float[5] { -219.67f, 479.53f, 276f, -177.33f, -780.6f };

	private static readonly float[] LockedIslandMaxX = new float[5] { -180.26f, 527.49f, 345.83f, -127.74f, -623.63f };

	private static readonly float[] LockedIslandMinZ = new float[5] { 580.5f, -128.28f, -605.58f, -791.01f, -633.57f };

	private static readonly float[] LockedIslandMaxZ = new float[5] { 616.84f, -83.55f, -537.14f, -743.53f, -485.97f };

	private static readonly float[] LighthouseMapPolyU = new float[8] { 0.484f, 0.4785f, 0.4635f, 0.4475f, 0.4408f, 0.446f, 0.46f, 0.476f };

	private static readonly float[] LighthouseMapPolyV = new float[8] { 0.1015f, 0.09f, 0.0868f, 0.0888f, 0.1005f, 0.1105f, 0.119f, 0.112f };

	private static readonly float[] LighthouseWorldPolyX = new float[8] { -180.8f, -187f, -197f, -211.5f, -219f, -212.5f, -199.5f, -186f };

	private static readonly float[] LighthouseWorldPolyZ = new float[8] { 598.5f, 608f, 612f, 608f, 597f, 586f, 581f, 586f };

	private static readonly float[] IslandBoundsScanRadius = new float[5] { 120f, 130f, 150f, 140f, 190f };

	private static readonly float[] GroundProbeOffsetX = new float[21]
	{
		0f, 2f, -2f, 0f, 0f, 2f, 2f, -2f, -2f, 4f,
		-4f, 0f, 0f, 4f, 4f, -4f, -4f, 6f, -6f, 0f,
		0f
	};

	private static readonly float[] GroundProbeOffsetZ = new float[21]
	{
		0f, 0f, 0f, 2f, -2f, 2f, -2f, 2f, -2f, 0f,
		0f, 4f, -4f, 4f, -4f, 4f, -4f, 0f, 0f, 6f,
		-6f
	};

	private object _mapTexture;

	private int _mapWidth = 1217;

	private int _mapHeight = 1293;

	private object _camera;

	private bool _fullMapOpen;

	private float _frozenMapYaw;

	private bool _frozenMapYawValid;

	private bool _oldCursorVisible;

	private object _oldCursorLock;

	private int _frameCounter;

	private Type _inputType;

	private Type _keyCodeType;

	private Type _guiType;

	private Type _rectType;

	private Type _colorType;

	private Type _textureType;

	private Type _texture2DType;

	private Type _textureFormatType;

	private Type _textureWrapModeType;

	private Type _filterModeType;

	private Type _scaleModeType;

	private Type _screenType;

	private Type _cameraType;

	private Type _cursorType;

	private Type _cursorLockModeType;

	private Type _imageConversionType;

	private Type _playerCameraType;

	private Type _playerType;

	private Type _guiStyleType;

	private Type _textAnchorType;

	private Type _guiUtilityType;

	private Type _vector2Type;

	private Type _vector3Type;

	private Type _serverType;

	private Type _physicsType;

	private Type _colliderType;

	private Type _raycastHitType;

	private Type _queryTriggerInteractionType;

	private Type _sceneManagerType;

	private Type _sceneType;

	private Type _loadSceneModeType;

	private object _localPlayer;

	private object _server;

	private object _localPlayerTransform;

	private FieldInfo _playerTransformField;

	private FieldInfo _playerCameraField;

	private FieldInfo _playerCameraRotField;

	private FieldInfo _playerCamObjectField;

	private MethodInfo _serverTeleportPlayer;

	private MethodInfo _playerLocalTeleport;

	private MethodInfo _physicsRaycastAll;

	private MethodInfo _sceneGetByName;

	private MethodInfo _sceneLoadSceneAsync;

	private MethodInfo _sceneLoadScene;

	private string _lastYawSource = "none";

	private object _playerCamera;

	private MethodInfo _toggleMouse;

	private PropertyInfo _playerCameraEnabled;

	private bool _oldPlayerCameraEnabled = true;

	private bool _playerCameraDisabledByMap;

	private MethodInfo _getKeyDown;

	private MethodInfo _getMouseButtonDown;

	private MethodInfo _drawTextureUv;

	private MethodInfo _drawTexture4;

	private MethodInfo _drawTexture2;

	private MethodInfo _label2;

	private MethodInfo _label3;

	private PropertyInfo _guiColor;

	private PropertyInfo _screenWidth;

	private PropertyInfo _screenHeight;

	private PropertyInfo _cameraMain;

	private PropertyInfo _mousePosition;

	private PropertyInfo _cursorVisible;

	private PropertyInfo _cursorLockState;

	private PropertyInfo _guiMatrix;

	private MethodInfo _rotateAroundPivot;

	private object _keyM;

	private object _keyEscape;

	private object _scaleStretch;

	private object _cursorNone;

	private object _whiteTexture;

	private object _whiteColor;

	private object _yellowColor;

	private object _blackColor;

	private object _black78;

	private object _haloColor;

	private object _softGoldColor;

	private object _centerColor;

	private object _indicatorStyle;

	private object _indicatorShadowStyle;

	private object _haloStyle;

	private object _ringStyle;

	private object _centerStyle;

	private int _hoveredIsland = -1;

	private readonly bool[] _islandBoundsValid = new bool[5];

	private readonly float[] _islandMinX = new float[5];

	private readonly float[] _islandMaxX = new float[5];

	private readonly float[] _islandMinZ = new float[5];

	private readonly float[] _islandMaxZ = new float[5];

	private readonly int[] _islandBoundsColliderCount = new int[5];

	private int _pendingTeleportIsland = -1;

	private float _pendingTeleportYaw;

	private float _pendingTeleportWorldX;

	private float _pendingTeleportWorldZ;

	private float _pendingTeleportMapU;

	private float _pendingTeleportMapV;

	private bool _pendingTeleportUseIslandMapping;

	private bool _pendingTeleportPreferIslandLand;

	private bool _pendingSceneLoadRequested;

	private int _pendingSceneReadyFrame = -1;

	private DateTime _pendingTeleportStartedUtc;

	private void LogInfo(string message)
	{
		Console.WriteLine("[Teleportation Map] " + message);
	}

	private void LogWarning(string message)
	{
		Console.WriteLine("[Teleportation Map] [WARNING] " + message);
	}

	private void LogError(string message)
	{
		Console.WriteLine("[Teleportation Map] [ERROR] " + message);
	}

	private void Awake()
	{
		LogInfo("============================================================");
		LogInfo(" TELEPORTATION MAP v0.1.14 BEPINEX / LIGHTHOUSE POLYGON");
		LogInfo(" Author: chadi7bark");
		LogInfo("============================================================");
		LogInfo("M = open/close full map");
		LogInfo("BepInEx 5 port of v0.1.14: locked coordinates + Lighthouse shoreline polygon + triangulated map/world mapping.");
		if (!InitializeUnityApi())
		{
			LogError("Teleportation Map could not initialize the Unity runtime API.");
			return;
		}
		LoadMapTexture();
		RefreshCamera();
		InitializeLockedIslandBounds();
		LogInfo("LIGHTHOUSE POLYGON -> 8 shoreline vertices; raft excluded; anchor map=(0.459947,0.094246) world=(-202.596,601.437).");
	}

	private void Update()
	{
		_frameCounter++;
		ProcessPendingIslandTeleport();
		if (_inputType == null && !InitializeUnityApi())
		{
			return;
		}
		if (GetKeyDown(_keyM))
		{
			if (_fullMapOpen)
			{
				CloseFullMap();
			}
			else
			{
				OpenFullMap();
			}
		}
		if (_fullMapOpen && GetKeyDown(_keyEscape))
		{
			CloseFullMap();
		}
		if (_fullMapOpen && GetMouseButtonDown(0) && TryHandleMapClick())
		{
			return;
		}
		if (_fullMapOpen)
		{
			ForceCursorUnlocked();
			if (_frameCounter % 15 == 0)
			{
				RefreshPlayerCamera();
				if (_playerCamera != null && _playerCameraEnabled != null)
				{
					try
					{
						_playerCameraEnabled.SetValue(_playerCamera, false, null);
					}
					catch
					{
					}
				}
			}
		}
		if (_camera == null || _frameCounter % 30 == 0)
		{
			RefreshCamera();
		}
		else if (_localPlayerTransform == null || _frameCounter % 30 == 0)
		{
			RefreshLocalPlayer();
		}
	}

	private void OnGUI()
	{
		if (_mapTexture != null && !(_guiType == null) && _fullMapOpen)
		{
			DrawFullMap();
		}
	}

	private bool InitializeUnityApi()
	{
		try
		{
			_inputType = ResolveType("UnityEngine.Input", "UnityEngine.InputLegacyModule", "UnityEngine.CoreModule");
			_keyCodeType = ResolveType("UnityEngine.KeyCode", "UnityEngine.InputLegacyModule", "UnityEngine.CoreModule");
			_guiType = ResolveType("UnityEngine.GUI", "UnityEngine.IMGUIModule");
			_rectType = ResolveType("UnityEngine.Rect", "UnityEngine.CoreModule");
			_colorType = ResolveType("UnityEngine.Color", "UnityEngine.CoreModule");
			_textureType = ResolveType("UnityEngine.Texture", "UnityEngine.CoreModule");
			_texture2DType = ResolveType("UnityEngine.Texture2D", "UnityEngine.CoreModule");
			_textureFormatType = ResolveType("UnityEngine.TextureFormat", "UnityEngine.CoreModule");
			_textureWrapModeType = ResolveType("UnityEngine.TextureWrapMode", "UnityEngine.CoreModule");
			_filterModeType = ResolveType("UnityEngine.FilterMode", "UnityEngine.CoreModule");
			_scaleModeType = ResolveType("UnityEngine.ScaleMode", "UnityEngine.IMGUIModule", "UnityEngine.CoreModule");
			_screenType = ResolveType("UnityEngine.Screen", "UnityEngine.CoreModule");
			_cameraType = ResolveType("UnityEngine.Camera", "UnityEngine.CoreModule");
			_cursorType = ResolveType("UnityEngine.Cursor", "UnityEngine.CoreModule");
			_cursorLockModeType = ResolveType("UnityEngine.CursorLockMode", "UnityEngine.CoreModule");
			_imageConversionType = ResolveType("UnityEngine.ImageConversion", "UnityEngine.ImageConversionModule");
			_playerCameraType = ResolveType("PlayerCamera", "Assembly-CSharp");
			_playerType = ResolveType("Player", "Assembly-CSharp");
			_guiStyleType = ResolveType("UnityEngine.GUIStyle", "UnityEngine.IMGUIModule");
			_textAnchorType = ResolveType("UnityEngine.TextAnchor", "UnityEngine.TextRenderingModule", "UnityEngine.CoreModule");
			_guiUtilityType = ResolveType("UnityEngine.GUIUtility", "UnityEngine.IMGUIModule");
			_vector2Type = ResolveType("UnityEngine.Vector2", "UnityEngine.CoreModule");
			_vector3Type = ResolveType("UnityEngine.Vector3", "UnityEngine.CoreModule");
			_serverType = ResolveType("Server", "Assembly-CSharp");
			_physicsType = ResolveType("UnityEngine.Physics", "UnityEngine.PhysicsModule");
			_colliderType = ResolveType("UnityEngine.Collider", "UnityEngine.PhysicsModule");
			_raycastHitType = ResolveType("UnityEngine.RaycastHit", "UnityEngine.PhysicsModule");
			_queryTriggerInteractionType = ResolveType("UnityEngine.QueryTriggerInteraction", "UnityEngine.PhysicsModule");
			_sceneManagerType = ResolveType("UnityEngine.SceneManagement.SceneManager", "UnityEngine.CoreModule");
			_sceneType = ResolveType("UnityEngine.SceneManagement.Scene", "UnityEngine.CoreModule");
			_loadSceneModeType = ResolveType("UnityEngine.SceneManagement.LoadSceneMode", "UnityEngine.CoreModule");
			if (_inputType == null || _keyCodeType == null || _guiType == null || _rectType == null || _colorType == null || _textureType == null || _texture2DType == null || _screenType == null || _cameraType == null)
			{
				return false;
			}
			_getKeyDown = FindStaticMethod(_inputType, "GetKeyDown", new Type[1] { _keyCodeType });
			_getMouseButtonDown = FindStaticMethod(_inputType, "GetMouseButtonDown", new Type[1] { typeof(int) });
			_mousePosition = _inputType.GetProperty("mousePosition", BindingFlags.Static | BindingFlags.Public);
			_drawTextureUv = FindStaticMethod(_guiType, "DrawTextureWithTexCoords", new Type[4]
			{
				_rectType,
				_textureType,
				_rectType,
				typeof(bool)
			});
			_drawTexture4 = ((_scaleModeType == null) ? null : FindStaticMethod(_guiType, "DrawTexture", new Type[4]
			{
				_rectType,
				_textureType,
				_scaleModeType,
				typeof(bool)
			}));
			_drawTexture2 = FindStaticMethod(_guiType, "DrawTexture", new Type[2] { _rectType, _textureType });
			_label2 = FindStaticMethod(_guiType, "Label", new Type[2]
			{
				_rectType,
				typeof(string)
			});
			_label3 = ((_guiStyleType == null) ? null : FindStaticMethod(_guiType, "Label", new Type[3]
			{
				_rectType,
				typeof(string),
				_guiStyleType
			}));
			_guiColor = _guiType.GetProperty("color", BindingFlags.Static | BindingFlags.Public);
			_guiMatrix = _guiType.GetProperty("matrix", BindingFlags.Static | BindingFlags.Public);
			if (_guiUtilityType != null && _vector2Type != null)
			{
				_rotateAroundPivot = FindStaticMethod(_guiUtilityType, "RotateAroundPivot", new Type[2]
				{
					typeof(float),
					_vector2Type
				});
			}
			_screenWidth = _screenType.GetProperty("width", BindingFlags.Static | BindingFlags.Public);
			_screenHeight = _screenType.GetProperty("height", BindingFlags.Static | BindingFlags.Public);
			_cameraMain = _cameraType.GetProperty("main", BindingFlags.Static | BindingFlags.Public);
			if (_cursorType != null)
			{
				_cursorVisible = _cursorType.GetProperty("visible", BindingFlags.Static | BindingFlags.Public);
				_cursorLockState = _cursorType.GetProperty("lockState", BindingFlags.Static | BindingFlags.Public);
			}
			_keyM = Enum.Parse(_keyCodeType, "M");
			_keyEscape = Enum.Parse(_keyCodeType, "Escape");
			if (_scaleModeType != null)
			{
				_scaleStretch = Enum.Parse(_scaleModeType, "StretchToFill");
			}
			if (_cursorLockModeType != null)
			{
				_cursorNone = Enum.Parse(_cursorLockModeType, "None");
			}
			_whiteColor = NewColor(1f, 1f, 1f, 1f);
			_yellowColor = NewColor(0.97f, 0.83f, 0.18f, 1f);
			_blackColor = NewColor(0f, 0f, 0f, 1f);
			_black78 = NewColor(0f, 0f, 0f, 0.78f);
			_haloColor = NewColor(0f, 0f, 0f, 0.58f);
			_softGoldColor = NewColor(1f, 0.72f, 0.1f, 0.95f);
			_centerColor = NewColor(1f, 0.96f, 0.72f, 1f);
			PropertyInfo property = _texture2DType.GetProperty("whiteTexture", BindingFlags.Static | BindingFlags.Public);
			if (property != null)
			{
				_whiteTexture = property.GetValue(null, null);
			}
			BuildIndicatorStyles(32);
			ResolveTeleportApi();
			ResolvePhysicsApi();
			ResolveSceneApi();
			return _getKeyDown != null && _screenWidth != null && _screenHeight != null && _label2 != null;
		}
		catch (Exception ex)
		{
			LogError("Unity reflection setup failed: " + ex);
			return false;
		}
	}

	private void LoadMapTexture()
	{
		string text = Path.Combine(Environment.CurrentDirectory, "UserData", "TeleportationMap", "TeleportationMap.png");
		if (!File.Exists(text))
		{
			LogError("Map image was not found: " + text);
			return;
		}
		try
		{
			object obj = CreateTexture2D();
			if (obj == null)
			{
				LogError("Could not construct Unity Texture2D.");
				return;
			}
			SetPropertyIfPresent(obj, "name", "TeleportationMapTexture");
			if (_textureWrapModeType != null)
			{
				SetPropertyIfPresent(obj, "wrapMode", Enum.Parse(_textureWrapModeType, "Clamp"));
			}
			if (_filterModeType != null)
			{
				SetPropertyIfPresent(obj, "filterMode", Enum.Parse(_filterModeType, "Bilinear"));
			}
			byte[] data = File.ReadAllBytes(text);
			if (!LoadPngIntoTexture(obj, data))
			{
				LogError("Unity could not decode TeleportationMap.png.");
				return;
			}
			_mapTexture = obj;
			_mapWidth = ReadIntProperty(obj, "width", _mapWidth);
			_mapHeight = ReadIntProperty(obj, "height", _mapHeight);
			LogInfo("Loaded custom map texture: " + _mapWidth + "x" + _mapHeight);
		}
		catch (Exception ex)
		{
			LogError("Failed to load map texture: " + ex);
		}
	}

	private object CreateTexture2D()
	{
		try
		{
			if (_textureFormatType != null)
			{
				object obj = Enum.Parse(_textureFormatType, "RGBA32");
				ConstructorInfo constructor = _texture2DType.GetConstructor(new Type[4]
				{
					typeof(int),
					typeof(int),
					_textureFormatType,
					typeof(bool)
				});
				if (constructor != null)
				{
					return constructor.Invoke(new object[4] { 2, 2, obj, false });
				}
			}
			ConstructorInfo constructor2 = _texture2DType.GetConstructor(new Type[2]
			{
				typeof(int),
				typeof(int)
			});
			if (constructor2 != null)
			{
				return constructor2.Invoke(new object[2] { 2, 2 });
			}
		}
		catch (Exception ex)
		{
			LogError("Texture2D constructor failed: " + ex);
		}
		return null;
	}

	private bool LoadPngIntoTexture(object texture, byte[] data)
	{
		if (_imageConversionType == null)
		{
			_imageConversionType = ResolveType("UnityEngine.ImageConversion", "UnityEngine.ImageConversionModule");
		}
		_playerCameraType = ResolveType("PlayerCamera", "Assembly-CSharp");
		_playerType = ResolveType("Player", "Assembly-CSharp");
		_guiStyleType = ResolveType("UnityEngine.GUIStyle", "UnityEngine.IMGUIModule");
		_textAnchorType = ResolveType("UnityEngine.TextAnchor", "UnityEngine.TextRenderingModule", "UnityEngine.CoreModule");
		_guiUtilityType = ResolveType("UnityEngine.GUIUtility", "UnityEngine.IMGUIModule");
		_vector2Type = ResolveType("UnityEngine.Vector2", "UnityEngine.CoreModule");
		if (_imageConversionType == null)
		{
			return false;
		}
		MethodInfo[] methods = _imageConversionType.GetMethods(BindingFlags.Static | BindingFlags.Public);
		foreach (MethodInfo methodInfo in methods)
		{
			if (methodInfo.Name != "LoadImage")
			{
				continue;
			}
			ParameterInfo[] parameters = methodInfo.GetParameters();
			if (parameters.Length == 3 && !(parameters[0].ParameterType.FullName != "UnityEngine.Texture2D") && !(parameters[1].ParameterType != typeof(byte[])) && !(parameters[2].ParameterType != typeof(bool)))
			{
				object obj = methodInfo.Invoke(null, new object[3] { texture, data, false });
				if (obj is bool)
				{
					return (bool)obj;
				}
				return false;
			}
		}
		return false;
	}

	private void RefreshCamera()
	{
		try
		{
			if (_cameraMain != null)
			{
				_camera = _cameraMain.GetValue(null, null);
			}
			RefreshPlayerCamera();
			RefreshLocalPlayer();
		}
		catch
		{
			_camera = null;
		}
	}

	private void DrawFullMap()
	{
		int screenWidth = GetScreenWidth();
		int screenHeight = GetScreenHeight();
		DrawSolidRect(0f, 0f, screenWidth, screenHeight, _black78);
		GetMapRect(screenWidth, screenHeight, out var mapX, out var mapY, out var mapW, out var mapH);
		object rect = NewRect(mapX, mapY, mapW, mapH);
		SetGuiColor(_whiteColor);
		DrawTexture(rect, _mapTexture);
		GetNavigationState(out var x, out var z, out var yawDegrees);
		if (_frozenMapYawValid)
		{
			yawDegrees = _frozenMapYaw;
		}
		WorldToMapNormalizedAuto(x, z, out var u, out var screenV, out var _);
		float centerX = mapX + u * mapW;
		float centerY = mapY + screenV * mapH;
		DrawPlayerIndicator(centerX, centerY, yawDegrees, Clamp(mapW * 0.035f, 26f, 46f));
		_hoveredIsland = FindIslandUnderMouse(mapX, mapY, mapW, mapH);
		SetGuiColor(_whiteColor);
		DrawLabel(NewRect(12f, 10f, (float)screenWidth - 24f, 28f), "TELEPORTATION MAP");
		string text;
		if (TryGetMapMouseWorld(mapX, mapY, mapW, mapH, out var worldX, out var worldZ))
		{
			int num = FindNearestIsland(worldX, worldZ);
			text = "LEFT CLICK TO TELEPORT  |  X=" + worldX.ToString("0") + " Z=" + worldZ.ToString("0");
			if (_hoveredIsland >= 0)
			{
				text = text + "  |  " + IslandNames[_hoveredIsland];
				text = ((!_islandBoundsValid[_hoveredIsland]) ? (text + " locked mapping") : (text + " LOCKED-MAPPED"));
			}
			else if (num >= 0)
			{
				text = text + "  |  nearest: " + IslandNames[num];
			}
		}
		else
		{
			text = "LEFT CLICK ANYWHERE ON THE MAP TO TELEPORT  |  M or ESC = close";
		}
		DrawLabel(NewRect(12f, (float)screenHeight - 30f, (float)screenWidth - 24f, 24f), text);
	}

	private bool TryHandleMapClick()
	{
		int screenWidth = GetScreenWidth();
		int screenHeight = GetScreenHeight();
		GetMapRect(screenWidth, screenHeight, out var mapX, out var mapY, out var mapW, out var mapH);
		if (!TryGetMapMouseNormalized(mapX, mapY, mapW, mapH, out var u, out var v))
		{
			return false;
		}
		int num = FindIslandAtNormalized(u, v);
		bool preferIslandLand = num >= 0;
		MapNormalizedToWorldAuto(u, v, out var worldX, out var worldZ, out var mappedIsland);
		int num2 = num;
		if (num2 < 0)
		{
			num2 = mappedIsland;
		}
		if (num2 < 0)
		{
			num2 = FindNearestIsland(worldX, worldZ);
		}
		if (num2 < 0)
		{
			return false;
		}
		float yaw = (_frozenMapYawValid ? _frozenMapYaw : 0f);
		if (!BeginMapTeleport(worldX, worldZ, num2, yaw, preferIslandLand, u, v, num >= 0))
		{
			return false;
		}
		LogInfo("ANYWHERE CLICK -> map=(" + u.ToString("0.0000") + "," + v.ToString("0.0000") + ") world=(" + worldX.ToString("0.00") + ", " + worldZ.ToString("0.00") + ") scene=" + IslandSceneNames[num2] + ((num >= 0) ? "; ISLAND-LOCAL LOCKED BOUNDS requested." : "; global ocean mapping requested."));
		CloseFullMap();
		return true;
	}

	private bool TryGetMapMouseNormalized(float mapX, float mapY, float mapW, float mapH, out float u, out float v)
	{
		u = 0f;
		v = 0f;
		if (!TryGetGuiMousePosition(out var x, out var y))
		{
			return false;
		}
		if (mapW <= 0.01f || mapH <= 0.01f)
		{
			return false;
		}
		if (x < mapX || x > mapX + mapW || y < mapY || y > mapY + mapH)
		{
			return false;
		}
		u = Clamp((x - mapX) / mapW, 0.045f, 0.955f);
		v = Clamp((y - mapY) / mapH, 0.04f, 0.955f);
		return true;
	}

	private bool TryGetMapMouseWorld(float mapX, float mapY, float mapW, float mapH, out float worldX, out float worldZ)
	{
		worldX = 0f;
		worldZ = 0f;
		if (!TryGetMapMouseNormalized(mapX, mapY, mapW, mapH, out var u, out var v))
		{
			return false;
		}
		MapNormalizedToWorldAuto(u, v, out worldX, out worldZ, out var _);
		return true;
	}

	private int FindNearestIsland(float worldX, float worldZ)
	{
		int result = -1;
		float num = float.MaxValue;
		for (int i = 0; i < IslandWorldX.Length && i < IslandWorldZ.Length; i++)
		{
			float num2 = worldX - IslandWorldX[i];
			float num3 = worldZ - IslandWorldZ[i];
			float num4 = num2 * num2 + num3 * num3;
			if (num4 < num)
			{
				num = num4;
				result = i;
			}
		}
		return result;
	}

	private int FindIslandUnderMouse(float mapX, float mapY, float mapW, float mapH)
	{
		if (!TryGetMapMouseNormalized(mapX, mapY, mapW, mapH, out var u, out var v))
		{
			return -1;
		}
		return FindIslandAtNormalized(u, v);
	}

	private int FindIslandAtNormalized(float u, float v)
	{
		if (IsPointInLighthouseMapPolygon(u, v))
		{
			return 0;
		}
		for (int i = 1; i < IslandNames.Length; i++)
		{
			float num = IslandMapMinU[i];
			float num2 = IslandMapMaxU[i];
			float num3 = IslandMapMinV[i];
			float num4 = IslandMapMaxV[i];
			float num5 = (num + num2) * 0.5f;
			float num6 = (num3 + num4) * 0.5f;
			float num7 = Math.Max((num2 - num) * 0.54f, 0.001f);
			float num8 = Math.Max((num4 - num3) * 0.54f, 0.001f);
			float num9 = (u - num5) / num7;
			float num10 = (v - num6) / num8;
			if (num9 * num9 + num10 * num10 <= 1f)
			{
				return i;
			}
		}
		return -1;
	}

	private bool IsPointInLighthouseMapPolygon(float u, float v)
	{
		bool flag = false;
		int num = LighthouseMapPolyU.Length;
		int num2 = num - 1;
		for (int i = 0; i < num; i++)
		{
			float num3 = LighthouseMapPolyU[i];
			float num4 = LighthouseMapPolyV[i];
			float num5 = LighthouseMapPolyU[num2];
			float num6 = LighthouseMapPolyV[num2];
			if (num4 > v != num6 > v)
			{
				float num7 = num6 - num4;
				if (Math.Abs(num7) < 1E-07f)
				{
					num7 = ((num7 < 0f) ? (-1E-07f) : 1E-07f);
				}
				float num8 = (num5 - num3) * (v - num4) / num7 + num3;
				if (u < num8)
				{
					flag = !flag;
				}
			}
			num2 = i;
		}
		return flag;
	}

	private bool TryMapLighthouseMapToWorld(float u, float v, out float worldX, out float worldZ)
	{
		worldX = 0f;
		worldZ = 0f;
		if (!IsPointInLighthouseMapPolygon(u, v))
		{
			return false;
		}
		int num = LighthouseMapPolyU.Length;
		for (int i = 0; i < num; i++)
		{
			int num2 = (i + 1) % num;
			if (TryBarycentric2D(u, v, 0.459947f, 0.094246f, LighthouseMapPolyU[i], LighthouseMapPolyV[i], LighthouseMapPolyU[num2], LighthouseMapPolyV[num2], out var wa, out var wb, out var wc))
			{
				worldX = wa * -202.596f + wb * LighthouseWorldPolyX[i] + wc * LighthouseWorldPolyX[num2];
				worldZ = wa * 601.437f + wb * LighthouseWorldPolyZ[i] + wc * LighthouseWorldPolyZ[num2];
				return true;
			}
		}
		return false;
	}

	private bool TryMapLighthouseWorldToMap(float worldX, float worldZ, out float u, out float v)
	{
		u = 0f;
		v = 0f;
		int num = LighthouseWorldPolyX.Length;
		for (int i = 0; i < num; i++)
		{
			int num2 = (i + 1) % num;
			if (TryBarycentric2D(worldX, worldZ, -202.596f, 601.437f, LighthouseWorldPolyX[i], LighthouseWorldPolyZ[i], LighthouseWorldPolyX[num2], LighthouseWorldPolyZ[num2], out var wa, out var wb, out var wc))
			{
				u = wa * 0.459947f + wb * LighthouseMapPolyU[i] + wc * LighthouseMapPolyU[num2];
				v = wa * 0.094246f + wb * LighthouseMapPolyV[i] + wc * LighthouseMapPolyV[num2];
				return true;
			}
		}
		return false;
	}

	private static bool TryBarycentric2D(float px, float py, float ax, float ay, float bx, float by, float cx, float cy, out float wa, out float wb, out float wc)
	{
		wa = 0f;
		wb = 0f;
		wc = 0f;
		float num = bx - ax;
		float num2 = by - ay;
		float num3 = cx - ax;
		float num4 = cy - ay;
		float num5 = px - ax;
		float num6 = py - ay;
		float num7 = num * num + num2 * num2;
		float num8 = num * num3 + num2 * num4;
		float num9 = num3 * num3 + num4 * num4;
		float num10 = num5 * num + num6 * num2;
		float num11 = num5 * num3 + num6 * num4;
		float num12 = num7 * num9 - num8 * num8;
		if (Math.Abs(num12) < 1E-08f)
		{
			return false;
		}
		wb = (num9 * num10 - num8 * num11) / num12;
		wc = (num7 * num11 - num8 * num10) / num12;
		wa = 1f - wb - wc;
		if (wa >= -0.0006f && wb >= -0.0006f)
		{
			return wc >= -0.0006f;
		}
		return false;
	}

	private bool TryGetGuiMousePosition(out float x, out float y)
	{
		x = 0f;
		y = 0f;
		if (_mousePosition == null)
		{
			return false;
		}
		try
		{
			object value = _mousePosition.GetValue(null, null);
			if (value == null)
			{
				return false;
			}
			FieldInfo field = value.GetType().GetField("x", BindingFlags.Instance | BindingFlags.Public);
			FieldInfo field2 = value.GetType().GetField("y", BindingFlags.Instance | BindingFlags.Public);
			if (field == null || field2 == null)
			{
				return false;
			}
			x = Convert.ToSingle(field.GetValue(value));
			y = (float)GetScreenHeight() - Convert.ToSingle(field2.GetValue(value));
			return true;
		}
		catch
		{
			return false;
		}
	}

	private void GetMapRect(int screenW, int screenH, out float mapX, out float mapY, out float mapW, out float mapH)
	{
		float num = (float)screenW * 0.63f;
		float num2 = (float)screenH * 0.63f;
		float num3 = ((_mapHeight <= 0) ? 1f : ((float)_mapWidth / (float)_mapHeight));
		mapW = num;
		mapH = mapW / num3;
		if (mapH > num2)
		{
			mapH = num2;
			mapW = mapH * num3;
		}
		mapX = ((float)screenW - mapW) * 0.5f;
		mapY = ((float)screenH - mapH) * 0.5f + 10f;
	}

	private void ResolveSceneApi()
	{
		if (_sceneManagerType == null)
		{
			_sceneManagerType = ResolveType("UnityEngine.SceneManagement.SceneManager", "UnityEngine.CoreModule");
		}
		if (_sceneType == null)
		{
			_sceneType = ResolveType("UnityEngine.SceneManagement.Scene", "UnityEngine.CoreModule");
		}
		if (_loadSceneModeType == null)
		{
			_loadSceneModeType = ResolveType("UnityEngine.SceneManagement.LoadSceneMode", "UnityEngine.CoreModule");
		}
		if (_sceneManagerType == null)
		{
			return;
		}
		try
		{
			_sceneGetByName = _sceneManagerType.GetMethod("GetSceneByName", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(string) }, null);
			if (_loadSceneModeType != null)
			{
				_sceneLoadSceneAsync = _sceneManagerType.GetMethod("LoadSceneAsync", BindingFlags.Static | BindingFlags.Public, null, new Type[2]
				{
					typeof(string),
					_loadSceneModeType
				}, null);
				_sceneLoadScene = _sceneManagerType.GetMethod("LoadScene", BindingFlags.Static | BindingFlags.Public, null, new Type[2]
				{
					typeof(string),
					_loadSceneModeType
				}, null);
			}
		}
		catch
		{
		}
	}

	private bool BeginMapTeleport(float worldX, float worldZ, int island, float yaw, bool preferIslandLand, float mapU, float mapV, bool useIslandMapping)
	{
		if (island < 0 || island >= IslandNames.Length)
		{
			return false;
		}
		if (_pendingTeleportIsland >= 0)
		{
			LogWarning("A map teleport is already waiting for an island scene to load.");
			return false;
		}
		_pendingTeleportIsland = island;
		_pendingTeleportYaw = yaw;
		_pendingTeleportWorldX = worldX;
		_pendingTeleportWorldZ = worldZ;
		_pendingTeleportMapU = mapU;
		_pendingTeleportMapV = mapV;
		_pendingTeleportUseIslandMapping = useIslandMapping;
		_pendingTeleportPreferIslandLand = preferIslandLand;
		_pendingSceneLoadRequested = false;
		_pendingSceneReadyFrame = -1;
		_pendingTeleportStartedUtc = DateTime.UtcNow;
		string text = IslandSceneNames[island];
		if (IsSceneLoaded(text))
		{
			_pendingSceneReadyFrame = _frameCounter + 12;
			LogInfo("Nearest island scene already loaded -> " + text + "; waiting briefly for physics before point ground scan.");
		}
		else
		{
			RequestIslandSceneLoad(text);
		}
		return true;
	}

	private void ProcessPendingIslandTeleport()
	{
		if (_pendingTeleportIsland < 0)
		{
			return;
		}
		if (_pendingTeleportIsland >= IslandNames.Length)
		{
			ClearPendingIslandTeleport();
			return;
		}
		int pendingTeleportIsland = _pendingTeleportIsland;
		string text = IslandSceneNames[pendingTeleportIsland];
		if (!IsSceneLoaded(text))
		{
			if (!_pendingSceneLoadRequested)
			{
				RequestIslandSceneLoad(text);
			}
			if (!((DateTime.UtcNow - _pendingTeleportStartedUtc).TotalSeconds < 8.0))
			{
				LogWarning("Timed out waiting for " + text + "; teleporting with the original fallback if ground is still unavailable.");
				float pendingTeleportYaw = _pendingTeleportYaw;
				float worldX = _pendingTeleportWorldX;
				float worldZ = _pendingTeleportWorldZ;
				bool pendingTeleportPreferIslandLand = _pendingTeleportPreferIslandLand;
				if (_pendingTeleportUseIslandMapping && ScanIslandWorldBounds(pendingTeleportIsland))
				{
					MapIslandNormalizedToWorld(pendingTeleportIsland, _pendingTeleportMapU, _pendingTeleportMapV, out worldX, out worldZ);
				}
				ClearPendingIslandTeleport();
				TeleportToMapPoint(worldX, worldZ, pendingTeleportIsland, pendingTeleportYaw, text, pendingTeleportPreferIslandLand);
			}
		}
		else if (_pendingSceneReadyFrame < 0)
		{
			_pendingSceneReadyFrame = _frameCounter + 12;
			LogInfo("ISLAND SCENE READY -> " + text + "; waiting " + 12 + " frames for colliders.");
		}
		else if (_frameCounter >= _pendingSceneReadyFrame)
		{
			ScanIslandWorldBounds(pendingTeleportIsland);
			float pendingTeleportYaw2 = _pendingTeleportYaw;
			float worldX2 = _pendingTeleportWorldX;
			float worldZ2 = _pendingTeleportWorldZ;
			bool pendingTeleportPreferIslandLand2 = _pendingTeleportPreferIslandLand;
			if (_pendingTeleportUseIslandMapping && _islandBoundsValid[pendingTeleportIsland])
			{
				MapIslandNormalizedToWorld(pendingTeleportIsland, _pendingTeleportMapU, _pendingTeleportMapV, out worldX2, out worldZ2);
				LogInfo("LOCKED ISLAND REMAP -> " + IslandNames[pendingTeleportIsland] + " world=(" + worldX2.ToString("0.00") + ", " + worldZ2.ToString("0.00") + ")");
			}
			ClearPendingIslandTeleport();
			TeleportToMapPoint(worldX2, worldZ2, pendingTeleportIsland, pendingTeleportYaw2, text, pendingTeleportPreferIslandLand2);
		}
	}

	private void ClearPendingIslandTeleport()
	{
		_pendingTeleportIsland = -1;
		_pendingTeleportYaw = 0f;
		_pendingTeleportWorldX = 0f;
		_pendingTeleportWorldZ = 0f;
		_pendingTeleportMapU = 0f;
		_pendingTeleportMapV = 0f;
		_pendingTeleportUseIslandMapping = false;
		_pendingTeleportPreferIslandLand = false;
		_pendingSceneLoadRequested = false;
		_pendingSceneReadyFrame = -1;
	}

	private bool IsSceneLoaded(string sceneName)
	{
		if (string.IsNullOrEmpty(sceneName))
		{
			return false;
		}
		if (_sceneGetByName == null)
		{
			ResolveSceneApi();
		}
		if (_sceneGetByName == null)
		{
			return false;
		}
		try
		{
			object obj = _sceneGetByName.Invoke(null, new object[1] { sceneName });
			if (obj == null)
			{
				return false;
			}
			PropertyInfo property = obj.GetType().GetProperty("isLoaded", BindingFlags.Instance | BindingFlags.Public);
			if (property != null)
			{
				return Convert.ToBoolean(property.GetValue(obj, null));
			}
		}
		catch
		{
		}
		return false;
	}

	private bool RequestIslandSceneLoad(string sceneName)
	{
		if (string.IsNullOrEmpty(sceneName))
		{
			return false;
		}
		if (_sceneManagerType == null || (_sceneLoadSceneAsync == null && _sceneLoadScene == null))
		{
			ResolveSceneApi();
		}
		if (_sceneManagerType == null || _loadSceneModeType == null)
		{
			return false;
		}
		_pendingSceneLoadRequested = true;
		try
		{
			object obj = Enum.Parse(_loadSceneModeType, "Additive");
			if (_sceneLoadSceneAsync != null)
			{
				_sceneLoadSceneAsync.Invoke(null, new object[2] { sceneName, obj });
				LogInfo("ADDITIVE ISLAND LOAD -> " + sceneName + " requested; waiting for scene + collision before teleport.");
				return true;
			}
			if (_sceneLoadScene != null)
			{
				_sceneLoadScene.Invoke(null, new object[2] { sceneName, obj });
				LogInfo("ADDITIVE ISLAND LOAD -> " + sceneName + " requested synchronously.");
				return true;
			}
		}
		catch (Exception ex)
		{
			LogWarning("Could not request island scene load for " + sceneName + ": " + ex.Message);
		}
		return false;
	}

	private void InitializeLockedIslandBounds()
	{
		for (int i = 0; i < IslandNames.Length; i++)
		{
			_islandMinX[i] = LockedIslandMinX[i];
			_islandMaxX[i] = LockedIslandMaxX[i];
			_islandMinZ[i] = LockedIslandMinZ[i];
			_islandMaxZ[i] = LockedIslandMaxZ[i];
			_islandBoundsColliderCount[i] = -1;
			_islandBoundsValid[i] = true;
			LogInfo("LOCKED ISLAND BOUNDS -> " + IslandNames[i] + " X=[" + _islandMinX[i].ToString("0.00") + "," + _islandMaxX[i].ToString("0.00") + "] Z=[" + _islandMinZ[i].ToString("0.00") + "," + _islandMaxZ[i].ToString("0.00") + "]");
		}
	}

	private void RefreshLoadedIslandBounds()
	{
	}

	private bool ScanIslandWorldBounds(int island)
	{
		if (island >= 0 && island < IslandNames.Length)
		{
			return _islandBoundsValid[island];
		}
		return false;
	}

	private static bool LooksLikeIslandTerrainCollider(string name)
	{
		if (string.IsNullOrEmpty(name))
		{
			return false;
		}
		string text = name.ToLowerInvariant();
		string[] array = new string[9] { "island", "terrain", "ground", "rock", "cliff", "sand", "beach", "shore", "land" };
		for (int i = 0; i < array.Length; i++)
		{
			if (text.IndexOf(array[i], StringComparison.Ordinal) >= 0)
			{
				return true;
			}
		}
		return false;
	}

	private void WorldToMapNormalizedAuto(float worldX, float worldZ, out float u, out float screenV, out int mappedIsland)
	{
		if (IsWorldPointNearIslandBounds(0, worldX, worldZ, 8f) && TryMapLighthouseWorldToMap(worldX, worldZ, out u, out screenV))
		{
			mappedIsland = 0;
			return;
		}
		mappedIsland = FindNearestIsland(worldX, worldZ);
		if (mappedIsland >= 0 && mappedIsland < IslandNames.Length && _islandBoundsValid[mappedIsland] && IsWorldPointNearIslandBounds(mappedIsland, worldX, worldZ, 16f))
		{
			float num = InverseLerp(_islandMinX[mappedIsland], _islandMaxX[mappedIsland], worldX);
			float num2 = InverseLerp(_islandMinZ[mappedIsland], _islandMaxZ[mappedIsland], worldZ);
			u = IslandMapMinU[mappedIsland] + num * (IslandMapMaxU[mappedIsland] - IslandMapMinU[mappedIsland]);
			screenV = IslandMapMaxV[mappedIsland] - num2 * (IslandMapMaxV[mappedIsland] - IslandMapMinV[mappedIsland]);
		}
		else
		{
			mappedIsland = -1;
			WorldToMapNormalized(worldX, worldZ, out u, out screenV);
		}
	}

	private void MapNormalizedToWorldAuto(float u, float screenV, out float worldX, out float worldZ, out int mappedIsland)
	{
		if (TryMapLighthouseMapToWorld(u, screenV, out worldX, out worldZ))
		{
			mappedIsland = 0;
			return;
		}
		mappedIsland = FindIslandAtNormalized(u, screenV);
		if (mappedIsland >= 0 && mappedIsland < IslandNames.Length && _islandBoundsValid[mappedIsland])
		{
			MapIslandNormalizedToWorld(mappedIsland, u, screenV, out worldX, out worldZ);
			return;
		}
		mappedIsland = -1;
		MapNormalizedToWorld(u, screenV, out worldX, out worldZ);
	}

	private void MapIslandNormalizedToWorld(int island, float u, float screenV, out float worldX, out float worldZ)
	{
		if (island != 0 || !TryMapLighthouseMapToWorld(u, screenV, out worldX, out worldZ))
		{
			if (island < 0 || island >= IslandNames.Length || !_islandBoundsValid[island])
			{
				MapNormalizedToWorld(u, screenV, out worldX, out worldZ);
				return;
			}
			float num = InverseLerp(IslandMapMinU[island], IslandMapMaxU[island], u);
			float num2 = InverseLerp(IslandMapMaxV[island], IslandMapMinV[island], screenV);
			worldX = _islandMinX[island] + num * (_islandMaxX[island] - _islandMinX[island]);
			worldZ = _islandMinZ[island] + num2 * (_islandMaxZ[island] - _islandMinZ[island]);
		}
	}

	private bool IsWorldPointNearIslandBounds(int island, float worldX, float worldZ, float padding)
	{
		if (island < 0 || island >= IslandNames.Length || !_islandBoundsValid[island])
		{
			return false;
		}
		if (worldX >= _islandMinX[island] - padding && worldX <= _islandMaxX[island] + padding && worldZ >= _islandMinZ[island] - padding)
		{
			return worldZ <= _islandMaxZ[island] + padding;
		}
		return false;
	}

	private void ResolveTeleportApi()
	{
		if (_serverType == null)
		{
			_serverType = ResolveType("Server", "Assembly-CSharp");
		}
		if (_playerType == null)
		{
			_playerType = ResolveType("Player", "Assembly-CSharp");
		}
		if (_vector3Type == null)
		{
			_vector3Type = ResolveType("UnityEngine.Vector3", "UnityEngine.CoreModule");
		}
		if (_serverType != null && _playerType != null && _vector3Type != null)
		{
			_serverTeleportPlayer = _serverType.GetMethod("TeleportPlayer", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[3]
			{
				_playerType,
				_vector3Type,
				typeof(float)
			}, null);
		}
		if (_playerType != null && _vector3Type != null)
		{
			_playerLocalTeleport = _playerType.GetMethod("LocalTeleport", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[3]
			{
				_vector3Type,
				typeof(float),
				typeof(bool)
			}, null);
		}
	}

	private void RefreshServer()
	{
		if (_serverType == null)
		{
			_serverType = ResolveType("Server", "Assembly-CSharp");
		}
		if (_serverType == null)
		{
			return;
		}
		try
		{
			Array array = FindUnityObjectsOfType(_serverType);
			if (array == null || array.Length == 0)
			{
				return;
			}
			object obj = null;
			for (int i = 0; i < array.Length; i++)
			{
				object value = array.GetValue(i);
				if (value != null)
				{
					if (obj == null)
					{
						obj = value;
					}
					if (ReadStringProperty(value, "name") == "Server(Clone)")
					{
						_server = value;
						return;
					}
				}
			}
			_server = obj;
		}
		catch
		{
		}
	}

	private bool TeleportToMapPoint(float requestedX, float requestedZ, int nearestIsland, float yaw, string requiredSceneName, bool preferIslandLand)
	{
		if (_localPlayer == null)
		{
			RefreshLocalPlayer();
		}
		if (_localPlayer == null)
		{
			LogWarning("Teleport failed: live PlayerHolder(Clone) was not found.");
			return false;
		}
		if (_serverTeleportPlayer == null || _playerLocalTeleport == null)
		{
			ResolveTeleportApi();
		}
		if (_server == null)
		{
			RefreshServer();
		}
		float safeX = requestedX;
		float safeY = 3f;
		float safeZ = requestedZ;
		string surfaceName;
		bool flag = TryFindSolidGroundNearIsland(requestedX, requestedZ, requiredSceneName, preferIslandLand, out safeX, out safeY, out safeZ, out surfaceName);
		if (!flag)
		{
			flag = TryFindSolidGroundNearIsland(requestedX, requestedZ, string.Empty, preferIslandLand, out safeX, out safeY, out safeZ, out surfaceName);
		}
		if (flag)
		{
			LogInfo((preferIslandLand ? "ANYWHERE island-land landing -> surface=" : "ANYWHERE ground-safe landing -> surface=") + surfaceName + " pos=(" + safeX.ToString("0.00") + ", " + safeY.ToString("0.00") + ", " + safeZ.ToString("0.00") + ")" + ((nearestIsland >= 0 && nearestIsland < IslandNames.Length) ? (" nearest=" + IslandNames[nearestIsland]) : string.Empty));
		}
		else
		{
			safeX = requestedX;
			safeY = 3f;
			safeZ = requestedZ;
			LogWarning("No solid ground at clicked map point; using exact X/Z fallback at Y=" + 3f.ToString("0.00") + ".");
		}
		object obj = CreateVector3(safeX, safeY, safeZ);
		if (obj == null)
		{
			LogWarning("Teleport failed: Vector3 could not be created.");
			return false;
		}
		if (_server != null && _serverTeleportPlayer != null)
		{
			try
			{
				_serverTeleportPlayer.Invoke(_server, new object[3] { _localPlayer, obj, yaw });
				LogInfo("Teleport route: Server.TeleportPlayer");
				return true;
			}
			catch (Exception ex)
			{
				LogWarning("Server.TeleportPlayer failed: " + ex.Message);
			}
		}
		if (_playerLocalTeleport != null)
		{
			try
			{
				_playerLocalTeleport.Invoke(_localPlayer, new object[3] { obj, yaw, true });
				LogInfo("Teleport route fallback: Player.LocalTeleport");
				return true;
			}
			catch (Exception ex2)
			{
				LogWarning("Player.LocalTeleport fallback failed: " + ex2.Message);
			}
		}
		LogWarning("Teleport failed: no usable native teleport route was available.");
		return false;
	}

	private void ResolvePhysicsApi()
	{
		if (_physicsType == null)
		{
			_physicsType = ResolveType("UnityEngine.Physics", "UnityEngine.PhysicsModule");
		}
		if (_vector3Type == null)
		{
			_vector3Type = ResolveType("UnityEngine.Vector3", "UnityEngine.CoreModule");
		}
		if (_raycastHitType == null)
		{
			_raycastHitType = ResolveType("UnityEngine.RaycastHit", "UnityEngine.PhysicsModule");
		}
		if (_queryTriggerInteractionType == null)
		{
			_queryTriggerInteractionType = ResolveType("UnityEngine.QueryTriggerInteraction", "UnityEngine.PhysicsModule");
		}
		if (_physicsType == null || _vector3Type == null)
		{
			return;
		}
		try
		{
			MethodInfo[] methods = _physicsType.GetMethods(BindingFlags.Static | BindingFlags.Public);
			MethodInfo methodInfo = null;
			foreach (MethodInfo methodInfo2 in methods)
			{
				if (methodInfo2.Name != "RaycastAll")
				{
					continue;
				}
				ParameterInfo[] parameters = methodInfo2.GetParameters();
				if (parameters.Length >= 3 && parameters.Length <= 5 && !(parameters[0].ParameterType != _vector3Type) && !(parameters[1].ParameterType != _vector3Type) && !(parameters[2].ParameterType != typeof(float)) && methodInfo2.ReturnType.IsArray)
				{
					if (parameters.Length == 3)
					{
						_physicsRaycastAll = methodInfo2;
						return;
					}
					if (methodInfo == null)
					{
						methodInfo = methodInfo2;
					}
				}
			}
			_physicsRaycastAll = methodInfo;
		}
		catch
		{
		}
	}

	private bool TryFindSolidGroundNearIsland(float baseX, float baseZ, string requiredSceneName, bool allowLowIslandGround, out float safeX, out float safeY, out float safeZ, out string surfaceName)
	{
		safeX = baseX;
		safeY = 1.5f;
		safeZ = baseZ;
		surfaceName = "none";
		if (_physicsRaycastAll == null)
		{
			ResolvePhysicsApi();
		}
		if (_physicsRaycastAll == null)
		{
			return false;
		}
		if (TryProbeSolidGround(baseX, baseZ, requiredSceneName, allowLowIslandGround, out var groundY, out var surfaceName2, out var lowSurfaceFound))
		{
			safeX = baseX;
			safeY = groundY + 1.75f;
			if (!allowLowIslandGround && safeY < 3f)
			{
				safeY = 3f;
			}
			safeZ = baseZ;
			surfaceName = surfaceName2;
			return true;
		}
		if (lowSurfaceFound)
		{
			LogInfo("Clicked point is over low/submerged ground; keeping exact X/Z and using the water-safe fallback height.");
			return false;
		}
		for (int i = 1; i < GroundProbeOffsetX.Length && i < GroundProbeOffsetZ.Length; i++)
		{
			float num = baseX + GroundProbeOffsetX[i];
			float num2 = baseZ + GroundProbeOffsetZ[i];
			if (TryProbeSolidGround(num, num2, requiredSceneName, allowLowIslandGround, out var groundY2, out var surfaceName3, out var _))
			{
				safeX = num;
				safeY = groundY2 + 1.75f;
				if (!allowLowIslandGround && safeY < 3f)
				{
					safeY = 3f;
				}
				safeZ = num2;
				surfaceName = surfaceName3;
				return true;
			}
		}
		return false;
	}

	private bool TryProbeSolidGround(float x, float z, string requiredSceneName, bool allowLowIslandGround, out float groundY, out string surfaceName, out bool lowSurfaceFound)
	{
		groundY = 0f;
		surfaceName = "none";
		lowSurfaceFound = false;
		if (_physicsRaycastAll == null)
		{
			return false;
		}
		try
		{
			object obj = CreateVector3(x, 250f, z);
			object obj2 = CreateVector3(0f, -1f, 0f);
			if (obj == null || obj2 == null)
			{
				return false;
			}
			ParameterInfo[] parameters = _physicsRaycastAll.GetParameters();
			object[] parameters2;
			if (parameters.Length == 3)
			{
				parameters2 = new object[3] { obj, obj2, 500f };
			}
			else if (parameters.Length == 4)
			{
				parameters2 = new object[4] { obj, obj2, 500f, -1 };
			}
			else
			{
				if (parameters.Length != 5)
				{
					return false;
				}
				object obj3 = null;
				if (_queryTriggerInteractionType != null)
				{
					try
					{
						obj3 = Enum.Parse(_queryTriggerInteractionType, "Ignore");
					}
					catch
					{
						obj3 = Enum.ToObject(_queryTriggerInteractionType, 1);
					}
				}
				parameters2 = new object[5] { obj, obj2, 500f, -1, obj3 };
			}
			if (!(_physicsRaycastAll.Invoke(null, parameters2) is Array { Length: not 0 } array))
			{
				return false;
			}
			bool flag = false;
			float num = float.MinValue;
			string text = "unknown";
			for (int i = 0; i < array.Length; i++)
			{
				object value = array.GetValue(i);
				if (value == null)
				{
					continue;
				}
				object obj5 = ReadPropertyValue(value, "collider");
				if (obj5 == null || ReadBoolProperty(obj5, "isTrigger", fallback: false))
				{
					continue;
				}
				string text2 = ReadStringProperty(obj5, "name");
				string text3 = text2;
				object obj6 = ReadPropertyValue(obj5, "transform");
				if (obj6 != null)
				{
					string text4 = ReadStringProperty(obj6, "name");
					if (!string.IsNullOrEmpty(text4))
					{
						text3 = text3 + "/" + text4;
					}
					object obj7 = ReadPropertyValue(obj6, "gameObject");
					if (obj7 != null)
					{
						string text5 = ReadStringProperty(obj7, "name");
						if (!string.IsNullOrEmpty(text5))
						{
							text3 = text3 + "/" + text5;
						}
					}
				}
				if (LooksLikeNonGroundCollider(text3))
				{
					continue;
				}
				string colliderSceneName = GetColliderSceneName(obj5);
				if (!string.IsNullOrEmpty(requiredSceneName) && !string.Equals(colliderSceneName, requiredSceneName, StringComparison.OrdinalIgnoreCase))
				{
					continue;
				}
				object obj8 = ReadPropertyValue(value, "normal");
				if (obj8 != null && TryReadVector3Y(obj8, out var y) && y < 0.45f)
				{
					continue;
				}
				object obj9 = ReadPropertyValue(value, "point");
				if (obj9 != null && TryReadVector3Y(obj9, out var y2))
				{
					if (!allowLowIslandGround && y2 + 1.75f < 3f)
					{
						lowSurfaceFound = true;
					}
					else if (!flag || y2 > num)
					{
						flag = true;
						num = y2;
						text = (string.IsNullOrEmpty(text2) ? "solid collider" : text2);
					}
				}
			}
			if (flag)
			{
				groundY = num;
				surfaceName = text;
				return true;
			}
		}
		catch (Exception ex)
		{
			LogWarning("Ground probe failed: " + ex.Message);
		}
		return false;
	}

	private static string GetColliderSceneName(object collider)
	{
		if (collider == null)
		{
			return string.Empty;
		}
		try
		{
			object obj = ReadPropertyValue(collider, "gameObject");
			if (obj == null)
			{
				object obj2 = ReadPropertyValue(collider, "transform");
				if (obj2 != null)
				{
					obj = ReadPropertyValue(obj2, "gameObject");
				}
			}
			if (obj == null)
			{
				return string.Empty;
			}
			object obj3 = ReadPropertyValue(obj, "scene");
			if (obj3 == null)
			{
				return string.Empty;
			}
			PropertyInfo property = obj3.GetType().GetProperty("name", BindingFlags.Instance | BindingFlags.Public);
			if (property == null)
			{
				return string.Empty;
			}
			object value = property.GetValue(obj3, null);
			return (value == null) ? string.Empty : value.ToString();
		}
		catch
		{
			return string.Empty;
		}
	}

	private static bool LooksLikeNonGroundCollider(string name)
	{
		if (string.IsNullOrEmpty(name))
		{
			return false;
		}
		string text = name.ToLowerInvariant();
		string[] array = new string[29]
		{
			"water", "ocean", "sea", "trigger", "player", "boat", "item", "creature", "fish", "projectile",
			"bullet", "dynamicobject", "pickup", "radar", "camera", "volume", "killbox", "death", "hurt", "damage",
			"armupper", "armlower", "hand", "ragdoll", "character", "npc", "foot", "head", "hitbox"
		};
		for (int i = 0; i < array.Length; i++)
		{
			if (text.IndexOf(array[i], StringComparison.Ordinal) >= 0)
			{
				return true;
			}
		}
		return false;
	}

	private static object ReadPropertyValue(object instance, string propertyName)
	{
		if (instance == null)
		{
			return null;
		}
		try
		{
			PropertyInfo property = instance.GetType().GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (property != null)
			{
				return property.GetValue(instance, null);
			}
		}
		catch
		{
		}
		return null;
	}

	private static bool ReadBoolProperty(object instance, string propertyName, bool fallback)
	{
		try
		{
			object obj = ReadPropertyValue(instance, propertyName);
			if (obj != null)
			{
				return Convert.ToBoolean(obj);
			}
		}
		catch
		{
		}
		return fallback;
	}

	private static bool TryReadVector3XZ(object vector, out float x, out float z)
	{
		x = 0f;
		z = 0f;
		if (vector == null)
		{
			return false;
		}
		try
		{
			FieldInfo field = vector.GetType().GetField("x", BindingFlags.Instance | BindingFlags.Public);
			FieldInfo field2 = vector.GetType().GetField("z", BindingFlags.Instance | BindingFlags.Public);
			if (field != null && field2 != null)
			{
				x = Convert.ToSingle(field.GetValue(vector));
				z = Convert.ToSingle(field2.GetValue(vector));
				return true;
			}
			PropertyInfo property = vector.GetType().GetProperty("x", BindingFlags.Instance | BindingFlags.Public);
			PropertyInfo property2 = vector.GetType().GetProperty("z", BindingFlags.Instance | BindingFlags.Public);
			if (property != null && property2 != null)
			{
				x = Convert.ToSingle(property.GetValue(vector, null));
				z = Convert.ToSingle(property2.GetValue(vector, null));
				return true;
			}
		}
		catch
		{
		}
		return false;
	}

	private static bool TryReadVector3Y(object vector, out float y)
	{
		y = 0f;
		if (vector == null)
		{
			return false;
		}
		try
		{
			FieldInfo field = vector.GetType().GetField("y", BindingFlags.Instance | BindingFlags.Public);
			if (field != null)
			{
				y = Convert.ToSingle(field.GetValue(vector));
				return true;
			}
			PropertyInfo property = vector.GetType().GetProperty("y", BindingFlags.Instance | BindingFlags.Public);
			if (property != null)
			{
				y = Convert.ToSingle(property.GetValue(vector, null));
				return true;
			}
		}
		catch
		{
		}
		return false;
	}

	private object CreateVector3(float x, float y, float z)
	{
		if (_vector3Type == null)
		{
			_vector3Type = ResolveType("UnityEngine.Vector3", "UnityEngine.CoreModule");
		}
		if (_vector3Type == null)
		{
			return null;
		}
		try
		{
			return Activator.CreateInstance(_vector3Type, x, y, z);
		}
		catch
		{
			return null;
		}
	}

	private bool GetMouseButtonDown(int button)
	{
		if (_getMouseButtonDown == null)
		{
			return false;
		}
		try
		{
			return Convert.ToBoolean(_getMouseButtonDown.Invoke(null, new object[1] { button }));
		}
		catch
		{
			return false;
		}
	}

	private void DrawTexture(object rect, object texture)
	{
		if (_drawTexture4 != null && _scaleStretch != null)
		{
			_drawTexture4.Invoke(null, new object[4] { rect, texture, _scaleStretch, false });
		}
		else if (_drawTexture2 != null)
		{
			_drawTexture2.Invoke(null, new object[2] { rect, texture });
		}
	}

	private void DrawPlayerIndicator(float centerX, float centerY, float yawDegrees, float size)
	{
		int num = (int)Math.Round(size * 1.18f);
		if (num < 25)
		{
			num = 25;
		}
		if (num > 54)
		{
			num = 54;
		}
		BuildIndicatorStyles(num);
		float num2 = size * 1.2f;
		float num3 = size * 0.88f;
		float num4 = size * 0.34f;
		if (_label3 != null && _haloStyle != null && _ringStyle != null)
		{
			SetGuiColor(_whiteColor);
			_label3.Invoke(null, new object[3]
			{
				NewRect(centerX - num2 * 0.5f, centerY - num2 * 0.53f, num2, num2),
				"●",
				_haloStyle
			});
			_label3.Invoke(null, new object[3]
			{
				NewRect(centerX - num3 * 0.5f, centerY - num3 * 0.53f, num3, num3),
				"●",
				_ringStyle
			});
			_label3.Invoke(null, new object[3]
			{
				NewRect(centerX - num3 * 0.38f, centerY - num3 * 0.405f, num3 * 0.76f, num3 * 0.76f),
				"●",
				_haloStyle
			});
		}
		DrawRotatingPointer(centerX, centerY, yawDegrees, size);
		if (_label3 != null && _centerStyle != null)
		{
			SetGuiColor(_whiteColor);
			_label3.Invoke(null, new object[3]
			{
				NewRect(centerX - num4 * 0.5f, centerY - num4 * 0.54f, num4, num4),
				"●",
				_centerStyle
			});
		}
	}

	private void DrawRotatingPointer(float centerX, float centerY, float yawDegrees, float size)
	{
		float num = centerX - size * 0.5f;
		float num2 = centerY - size * 0.62f;
		float num3 = Math.Max(1f, size * 0.055f);
		object obj = null;
		bool flag = false;
		try
		{
			if (_guiMatrix != null && _rotateAroundPivot != null && _vector2Type != null)
			{
				obj = _guiMatrix.GetValue(null, null);
				object obj2 = Activator.CreateInstance(_vector2Type, centerX, centerY);
				_rotateAroundPivot.Invoke(null, new object[2]
				{
					NormalizeAngle(yawDegrees),
					obj2
				});
				flag = true;
			}
			string text = (flag ? "▲" : GetArrowGlyph(yawDegrees));
			if (_label3 != null && _indicatorStyle != null && _indicatorShadowStyle != null)
			{
				SetGuiColor(_whiteColor);
				_label3.Invoke(null, new object[3]
				{
					NewRect(num - num3, num2, size, size),
					text,
					_indicatorShadowStyle
				});
				_label3.Invoke(null, new object[3]
				{
					NewRect(num + num3, num2, size, size),
					text,
					_indicatorShadowStyle
				});
				_label3.Invoke(null, new object[3]
				{
					NewRect(num, num2 - num3, size, size),
					text,
					_indicatorShadowStyle
				});
				_label3.Invoke(null, new object[3]
				{
					NewRect(num, num2 + num3, size, size),
					text,
					_indicatorShadowStyle
				});
				_label3.Invoke(null, new object[3]
				{
					NewRect(num, num2, size, size),
					text,
					_indicatorStyle
				});
			}
			else
			{
				SetGuiColor(_blackColor);
				DrawLabel(NewRect(num - num3, num2, size, size), text);
				DrawLabel(NewRect(num + num3, num2, size, size), text);
				SetGuiColor(_yellowColor);
				DrawLabel(NewRect(num, num2, size, size), text);
			}
		}
		catch
		{
		}
		finally
		{
			if (flag && obj != null && _guiMatrix != null)
			{
				try
				{
					_guiMatrix.SetValue(null, obj, null);
				}
				catch
				{
				}
			}
		}
	}

	private void BuildIndicatorStyles(int fontSize)
	{
		if (_guiStyleType == null)
		{
			return;
		}
		try
		{
			if (_indicatorStyle == null)
			{
				_indicatorStyle = Activator.CreateInstance(_guiStyleType);
			}
			if (_indicatorShadowStyle == null)
			{
				_indicatorShadowStyle = Activator.CreateInstance(_guiStyleType);
			}
			if (_haloStyle == null)
			{
				_haloStyle = Activator.CreateInstance(_guiStyleType);
			}
			if (_ringStyle == null)
			{
				_ringStyle = Activator.CreateInstance(_guiStyleType);
			}
			if (_centerStyle == null)
			{
				_centerStyle = Activator.CreateInstance(_guiStyleType);
			}
			SetPropertyIfPresent(_indicatorStyle, "fontSize", fontSize);
			SetPropertyIfPresent(_indicatorShadowStyle, "fontSize", fontSize);
			SetPropertyIfPresent(_haloStyle, "fontSize", (int)Math.Round((float)fontSize * 1.12f));
			SetPropertyIfPresent(_ringStyle, "fontSize", (int)Math.Round((float)fontSize * 0.88f));
			SetPropertyIfPresent(_centerStyle, "fontSize", Math.Max(10, (int)Math.Round((float)fontSize * 0.34f)));
			if (_textAnchorType != null)
			{
				object value = Enum.Parse(_textAnchorType, "MiddleCenter");
				SetPropertyIfPresent(_indicatorStyle, "alignment", value);
				SetPropertyIfPresent(_indicatorShadowStyle, "alignment", value);
				SetPropertyIfPresent(_haloStyle, "alignment", value);
				SetPropertyIfPresent(_ringStyle, "alignment", value);
				SetPropertyIfPresent(_centerStyle, "alignment", value);
			}
			SetGuiStyleTextColor(_indicatorStyle, _yellowColor);
			SetGuiStyleTextColor(_indicatorShadowStyle, _blackColor);
			SetGuiStyleTextColor(_haloStyle, _haloColor);
			SetGuiStyleTextColor(_ringStyle, _softGoldColor);
			SetGuiStyleTextColor(_centerStyle, _centerColor);
		}
		catch
		{
		}
	}

	private void SetGuiStyleTextColor(object style, object color)
	{
		if (style == null || color == null)
		{
			return;
		}
		try
		{
			PropertyInfo property = style.GetType().GetProperty("normal", BindingFlags.Instance | BindingFlags.Public);
			if (property == null)
			{
				return;
			}
			object value = property.GetValue(style, null);
			if (value != null)
			{
				PropertyInfo property2 = value.GetType().GetProperty("textColor", BindingFlags.Instance | BindingFlags.Public);
				if (property2 != null && property2.CanWrite)
				{
					property2.SetValue(value, color, null);
				}
			}
		}
		catch
		{
		}
	}

	private string GetArrowGlyph(float yawDegrees)
	{
		float num = NormalizeAngle(yawDegrees);
		return ((int)Math.Round((double)num / 45.0) % 8) switch
		{
			0 => "▲", 
			1 => "◥", 
			2 => "▶", 
			3 => "◢", 
			4 => "▼", 
			5 => "◣", 
			6 => "◀", 
			_ => "◤", 
		};
	}

	private void DrawLabel(object rect, string text)
	{
		if (_label2 != null)
		{
			_label2.Invoke(null, new object[2] { rect, text });
		}
	}

	private void DrawSolidRect(float x, float y, float w, float h, object color)
	{
		if (_whiteTexture != null && !(_drawTexture2 == null))
		{
			object guiColor = GetGuiColor();
			SetGuiColor(color);
			_drawTexture2.Invoke(null, new object[2]
			{
				NewRect(x, y, w, h),
				_whiteTexture
			});
			SetGuiColor(guiColor);
		}
	}

	private void GetNavigationState(out float x, out float z, out float yawDegrees)
	{
		x = 0f;
		z = 0f;
		yawDegrees = 0f;
		if (_localPlayerTransform == null || _frameCounter % 30 == 0)
		{
			RefreshLocalPlayer();
		}
		object localPlayerTransform = _localPlayerTransform;
		if (localPlayerTransform == null)
		{
			return;
		}
		try
		{
			PropertyInfo property = localPlayerTransform.GetType().GetProperty("position", BindingFlags.Instance | BindingFlags.Public);
			if (property != null)
			{
				object value = property.GetValue(localPlayerTransform, null);
				if (value != null)
				{
					FieldInfo field = value.GetType().GetField("x", BindingFlags.Instance | BindingFlags.Public);
					FieldInfo field2 = value.GetType().GetField("z", BindingFlags.Instance | BindingFlags.Public);
					if (field != null)
					{
						x = Convert.ToSingle(field.GetValue(value));
					}
					if (field2 != null)
					{
						z = Convert.ToSingle(field2.GetValue(value));
					}
				}
			}
			if (TryGetLivePlayerLookYaw(out var yawDegrees2))
			{
				yawDegrees = yawDegrees2;
				return;
			}
			if (TryGetPlayerCamObjectYaw(out yawDegrees2))
			{
				yawDegrees = yawDegrees2;
				return;
			}
			if (TryGetCameraYaw(out yawDegrees2))
			{
				yawDegrees = yawDegrees2;
				return;
			}
			yawDegrees = ReadTransformYaw(localPlayerTransform);
			_lastYawSource = "LocalPlayer.Transform";
		}
		catch
		{
		}
	}

	private bool TryGetLivePlayerLookYaw(out float yawDegrees)
	{
		yawDegrees = 0f;
		if (_localPlayer == null || _playerType == null)
		{
			return false;
		}
		try
		{
			if (_playerCameraField == null)
			{
				_playerCameraField = _playerType.GetField("_camera", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			}
			if (_playerCameraField == null)
			{
				return false;
			}
			object value = _playerCameraField.GetValue(_localPlayer);
			if (value == null)
			{
				return false;
			}
			if (_playerCameraRotField == null || _playerCameraRotField.DeclaringType != value.GetType())
			{
				_playerCameraRotField = value.GetType().GetField("_rot", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			}
			if (_playerCameraRotField == null)
			{
				return false;
			}
			object value2 = _playerCameraRotField.GetValue(value);
			if (value2 == null)
			{
				return false;
			}
			FieldInfo field = value2.GetType().GetField("y", BindingFlags.Instance | BindingFlags.Public);
			if (field == null)
			{
				return false;
			}
			yawDegrees = NormalizeAngle(Convert.ToSingle(field.GetValue(value2)));
			_lastYawSource = "PlayerCamera._rot.y";
			return true;
		}
		catch
		{
			return false;
		}
	}

	private bool TryGetPlayerCamObjectYaw(out float yawDegrees)
	{
		yawDegrees = 0f;
		if (_localPlayer == null || _playerType == null)
		{
			return false;
		}
		try
		{
			if (_playerCamObjectField == null)
			{
				_playerCamObjectField = _playerType.GetField("<CamObject>k__BackingField", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			}
			if (_playerCamObjectField == null)
			{
				return false;
			}
			object value = _playerCamObjectField.GetValue(_localPlayer);
			if (value == null)
			{
				return false;
			}
			yawDegrees = NormalizeAngle(ReadTransformYaw(value));
			_lastYawSource = "Player.CamObject";
			return true;
		}
		catch
		{
			return false;
		}
	}

	private bool TryGetCameraYaw(out float yawDegrees)
	{
		yawDegrees = 0f;
		if (_camera == null)
		{
			return false;
		}
		try
		{
			PropertyInfo property = _camera.GetType().GetProperty("transform", BindingFlags.Instance | BindingFlags.Public);
			if (property == null)
			{
				return false;
			}
			object value = property.GetValue(_camera, null);
			if (value == null)
			{
				return false;
			}
			yawDegrees = ReadTransformYaw(value);
			_lastYawSource = "Camera.main";
			return true;
		}
		catch
		{
			return false;
		}
	}

	private float ReadTransformYaw(object transform)
	{
		if (transform == null)
		{
			return 0f;
		}
		try
		{
			PropertyInfo property = transform.GetType().GetProperty("eulerAngles", BindingFlags.Instance | BindingFlags.Public);
			if (property == null)
			{
				return 0f;
			}
			object value = property.GetValue(transform, null);
			if (value == null)
			{
				return 0f;
			}
			FieldInfo field = value.GetType().GetField("y", BindingFlags.Instance | BindingFlags.Public);
			if (field != null)
			{
				return Convert.ToSingle(field.GetValue(value));
			}
		}
		catch
		{
		}
		return 0f;
	}

	private void RefreshLocalPlayer()
	{
		if (_playerType == null)
		{
			_playerType = ResolveType("Player", "Assembly-CSharp");
		}
		if (_playerType == null)
		{
			return;
		}
		try
		{
			Array array = FindUnityObjectsOfType(_playerType);
			if (array == null || array.Length == 0)
			{
				return;
			}
			object obj = null;
			object obj2 = null;
			for (int i = 0; i < array.Length; i++)
			{
				object value = array.GetValue(i);
				if (value == null)
				{
					continue;
				}
				object playerNavigationTransform = GetPlayerNavigationTransform(value);
				if (playerNavigationTransform != null)
				{
					string text = ReadStringProperty(value, "name");
					if (text == "PlayerHolder(Clone)")
					{
						obj = value;
						obj2 = playerNavigationTransform;
						break;
					}
					if (obj == null)
					{
						obj = value;
						obj2 = playerNavigationTransform;
					}
				}
			}
			if (obj != null && obj2 != null)
			{
				bool flag = !object.ReferenceEquals(_localPlayer, obj);
				_localPlayer = obj;
				_localPlayerTransform = obj2;
				if (flag)
				{
					LogInfo("Player tracker locked to live PlayerHolder(Clone) Transform.");
				}
			}
		}
		catch
		{
		}
	}

	private object GetPlayerNavigationTransform(object player)
	{
		if (player == null)
		{
			return null;
		}
		try
		{
			if (_playerTransformField == null)
			{
				_playerTransformField = _playerType.GetField("<Transform>k__BackingField", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			}
			if (_playerTransformField != null)
			{
				object value = _playerTransformField.GetValue(player);
				if (value != null)
				{
					return value;
				}
			}
			PropertyInfo property = _playerType.GetProperty("Transform", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (property != null)
			{
				object value2 = property.GetValue(player, null);
				if (value2 != null)
				{
					return value2;
				}
			}
		}
		catch
		{
		}
		return null;
	}

	private Array FindUnityObjectsOfType(Type wantedType)
	{
		try
		{
			Type type = ResolveType("UnityEngine.Object", "UnityEngine.CoreModule");
			if (type != null)
			{
				MethodInfo[] methods = type.GetMethods(BindingFlags.Static | BindingFlags.Public);
				foreach (MethodInfo methodInfo in methods)
				{
					if (methodInfo.Name != "FindObjectsOfType")
					{
						continue;
					}
					ParameterInfo[] parameters = methodInfo.GetParameters();
					object obj = null;
					if (parameters.Length == 1 && parameters[0].ParameterType == typeof(Type))
					{
						obj = methodInfo.Invoke(null, new object[1] { wantedType });
					}
					else
					{
						if (parameters.Length != 2 || !(parameters[0].ParameterType == typeof(Type)) || !(parameters[1].ParameterType == typeof(bool)))
						{
							continue;
						}
						obj = methodInfo.Invoke(null, new object[2] { wantedType, true });
					}
					if (obj is Array { Length: >0 } array)
					{
						return array;
					}
				}
			}
		}
		catch
		{
		}
		try
		{
			Type type2 = ResolveType("UnityEngine.Resources", "UnityEngine.CoreModule");
			if (type2 != null)
			{
				MethodInfo method = type2.GetMethod("FindObjectsOfTypeAll", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(Type) }, null);
				if (method != null)
				{
					return method.Invoke(null, new object[1] { wantedType }) as Array;
				}
			}
		}
		catch
		{
		}
		return null;
	}

	private void OpenFullMap()
	{
		if (!_fullMapOpen)
		{
			SaveCursorState();
			_fullMapOpen = true;
			RefreshPlayerCamera();
			RefreshLocalPlayer();
			GetNavigationState(out var x, out var z, out var yawDegrees);
			_frozenMapYaw = NormalizeAngle(yawDegrees);
			_frozenMapYawValid = true;
			string lastYawSource = _lastYawSource;
			WorldToMapNormalizedAuto(x, z, out var u, out var screenV, out var mappedIsland);
			LogInfo("Map tracker world position: X=" + x.ToString("0.00") + " Z=" + z.ToString("0.00") + " frozenYaw=" + _frozenMapYaw.ToString("0.0") + " source=" + lastYawSource + " -> map=(" + u.ToString("0.000") + "," + screenV.ToString("0.000") + ")" + ((mappedIsland >= 0) ? (" lockedBounds=" + IslandNames[mappedIsland]) : " globalFallback"));
			TryTogglePlayerMouse(unlock: true);
			DisablePlayerCameraForMap();
			ForceCursorUnlocked();
		}
	}

	private void CloseFullMap()
	{
		if (_fullMapOpen)
		{
			_fullMapOpen = false;
			_frozenMapYawValid = false;
			RestorePlayerCameraAfterMap();
			TryTogglePlayerMouse(unlock: false);
			RestoreCursorState();
		}
	}

	private void RefreshPlayerCamera()
	{
		if (_playerCameraType == null)
		{
			_playerCameraType = ResolveType("PlayerCamera", "Assembly-CSharp");
		}
		if (_playerCameraType == null)
		{
			return;
		}
		object obj = null;
		if (_camera != null)
		{
			try
			{
				MethodInfo[] methods = _camera.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public);
				for (int i = 0; i < methods.Length; i++)
				{
					if (obj != null)
					{
						break;
					}
					MethodInfo methodInfo = methods[i];
					if (!(methodInfo.Name != "GetComponentInParent"))
					{
						ParameterInfo[] parameters = methodInfo.GetParameters();
						if (parameters.Length == 1 && parameters[0].ParameterType == typeof(Type))
						{
							obj = methodInfo.Invoke(_camera, new object[1] { _playerCameraType });
						}
						else if (parameters.Length == 2 && parameters[0].ParameterType == typeof(Type) && parameters[1].ParameterType == typeof(bool))
						{
							obj = methodInfo.Invoke(_camera, new object[2] { _playerCameraType, true });
						}
					}
				}
			}
			catch
			{
			}
		}
		if (obj == null)
		{
			obj = FindUnityObjectOfType(_playerCameraType);
		}
		if (obj != null)
		{
			_playerCamera = obj;
			_toggleMouse = _playerCameraType.GetMethod("ToggleMouse", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(bool) }, null);
			_playerCameraEnabled = _playerCameraType.GetProperty("enabled", BindingFlags.Instance | BindingFlags.Public);
		}
	}

	private object FindUnityObjectOfType(Type wantedType)
	{
		try
		{
			Type type = ResolveType("UnityEngine.Object", "UnityEngine.CoreModule");
			if (type == null)
			{
				return null;
			}
			MethodInfo[] methods = type.GetMethods(BindingFlags.Static | BindingFlags.Public);
			foreach (MethodInfo methodInfo in methods)
			{
				if (methodInfo.Name != "FindObjectsOfType")
				{
					continue;
				}
				ParameterInfo[] parameters = methodInfo.GetParameters();
				object obj = null;
				if (parameters.Length == 1 && parameters[0].ParameterType == typeof(Type))
				{
					obj = methodInfo.Invoke(null, new object[1] { wantedType });
				}
				else
				{
					if (parameters.Length != 2 || !(parameters[0].ParameterType == typeof(Type)) || !(parameters[1].ParameterType == typeof(bool)))
					{
						continue;
					}
					obj = methodInfo.Invoke(null, new object[2] { wantedType, true });
				}
				if (!(obj is Array { Length: >0 } array))
				{
					continue;
				}
				for (int j = 0; j < array.Length; j++)
				{
					object value = array.GetValue(j);
					if (value != null)
					{
						return value;
					}
				}
			}
		}
		catch
		{
		}
		try
		{
			Type type2 = ResolveType("UnityEngine.Resources", "UnityEngine.CoreModule");
			if (type2 != null)
			{
				MethodInfo method = type2.GetMethod("FindObjectsOfTypeAll", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(Type) }, null);
				if (method != null && method.Invoke(null, new object[1] { wantedType }) is Array { Length: >0 } array2)
				{
					for (int k = 0; k < array2.Length; k++)
					{
						object value2 = array2.GetValue(k);
						if (value2 != null)
						{
							return value2;
						}
					}
				}
			}
		}
		catch
		{
		}
		return null;
	}

	private void SaveCursorState()
	{
		try
		{
			if (_cursorVisible != null)
			{
				_oldCursorVisible = Convert.ToBoolean(_cursorVisible.GetValue(null, null));
			}
			if (_cursorLockState != null)
			{
				_oldCursorLock = _cursorLockState.GetValue(null, null);
			}
		}
		catch
		{
		}
	}

	private void ForceCursorUnlocked()
	{
		try
		{
			if (_cursorVisible != null)
			{
				_cursorVisible.SetValue(null, true, null);
			}
			if (_cursorLockState != null && _cursorNone != null)
			{
				_cursorLockState.SetValue(null, _cursorNone, null);
			}
		}
		catch
		{
		}
	}

	private void RestoreCursorState()
	{
		try
		{
			if (_cursorVisible != null)
			{
				_cursorVisible.SetValue(null, _oldCursorVisible, null);
			}
			if (_cursorLockState != null && _oldCursorLock != null)
			{
				_cursorLockState.SetValue(null, _oldCursorLock, null);
			}
		}
		catch
		{
		}
	}

	private void DisablePlayerCameraForMap()
	{
		try
		{
			if (_playerCamera == null || _playerCameraEnabled == null)
			{
				RefreshPlayerCamera();
			}
			if (_playerCamera == null || _playerCameraEnabled == null)
			{
				LogWarning("PlayerCamera was not found; cursor unlocked but hard camera lock is unavailable.");
				return;
			}
			_oldPlayerCameraEnabled = Convert.ToBoolean(_playerCameraEnabled.GetValue(_playerCamera, null));
			_playerCameraEnabled.SetValue(_playerCamera, false, null);
			_playerCameraDisabledByMap = true;
			LogInfo("Map camera lock: PlayerCamera disabled.");
		}
		catch (Exception ex)
		{
			LogWarning("Could not disable PlayerCamera: " + ex.Message);
		}
	}

	private void RestorePlayerCameraAfterMap()
	{
		if (!_playerCameraDisabledByMap)
		{
			return;
		}
		try
		{
			if (_playerCamera != null && _playerCameraEnabled != null)
			{
				_playerCameraEnabled.SetValue(_playerCamera, _oldPlayerCameraEnabled, null);
			}
		}
		catch
		{
		}
		_playerCameraDisabledByMap = false;
	}

	private bool TryTogglePlayerMouse(bool unlock)
	{
		try
		{
			if (_playerCamera == null || _toggleMouse == null)
			{
				RefreshPlayerCamera();
			}
			if (_playerCamera == null || _toggleMouse == null)
			{
				return false;
			}
			_toggleMouse.Invoke(_playerCamera, new object[1] { unlock });
			return true;
		}
		catch
		{
			return false;
		}
	}

	private bool GetKeyDown(object key)
	{
		if (_getKeyDown == null || key == null)
		{
			return false;
		}
		try
		{
			return Convert.ToBoolean(_getKeyDown.Invoke(null, new object[1] { key }));
		}
		catch
		{
			return false;
		}
	}

	private int GetScreenWidth()
	{
		try
		{
			return Convert.ToInt32(_screenWidth.GetValue(null, null));
		}
		catch
		{
			return 1920;
		}
	}

	private int GetScreenHeight()
	{
		try
		{
			return Convert.ToInt32(_screenHeight.GetValue(null, null));
		}
		catch
		{
			return 1080;
		}
	}

	private object NewRect(float x, float y, float w, float h)
	{
		return Activator.CreateInstance(_rectType, x, y, w, h);
	}

	private object NewColor(float r, float g, float b, float a)
	{
		return Activator.CreateInstance(_colorType, r, g, b, a);
	}

	private object GetGuiColor()
	{
		try
		{
			return (_guiColor == null) ? _whiteColor : _guiColor.GetValue(null, null);
		}
		catch
		{
			return _whiteColor;
		}
	}

	private void SetGuiColor(object color)
	{
		if (_guiColor == null || color == null)
		{
			return;
		}
		try
		{
			_guiColor.SetValue(null, color, null);
		}
		catch
		{
		}
	}

	private static void SetPropertyIfPresent(object instance, string propertyName, object value)
	{
		if (instance == null)
		{
			return;
		}
		try
		{
			PropertyInfo property = instance.GetType().GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public);
			if (property != null && property.CanWrite)
			{
				property.SetValue(instance, value, null);
			}
		}
		catch
		{
		}
	}

	private static string ReadStringProperty(object instance, string propertyName)
	{
		try
		{
			PropertyInfo property = instance.GetType().GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public);
			if (property != null)
			{
				object value = property.GetValue(instance, null);
				return (value == null) ? string.Empty : value.ToString();
			}
		}
		catch
		{
		}
		return string.Empty;
	}

	private static int ReadIntProperty(object instance, string propertyName, int fallback)
	{
		try
		{
			PropertyInfo property = instance.GetType().GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public);
			if (property != null)
			{
				return Convert.ToInt32(property.GetValue(instance, null));
			}
		}
		catch
		{
		}
		return fallback;
	}

	private static void WorldToMapNormalized(float worldX, float worldZ, out float u, out float screenV)
	{
		u = 0.0006040856f * worldX + 0.5680561f;
		screenV = -0.0005951446f * worldZ + 0.4647192f;
		u = Clamp(u, 0.045f, 0.955f);
		screenV = Clamp(screenV, 0.04f, 0.955f);
	}

	private static void MapNormalizedToWorld(float u, float screenV, out float worldX, out float worldZ)
	{
		worldX = (u - 0.5680561f) / 0.0006040856f;
		worldZ = (screenV - 0.4647192f) / -0.0005951446f;
	}

	private static float NormalizeAngle(float degrees)
	{
		while (degrees < 0f)
		{
			degrees += 360f;
		}
		while (degrees >= 360f)
		{
			degrees -= 360f;
		}
		return degrees;
	}

	private static float InverseLerp(float a, float b, float value)
	{
		if (Math.Abs(b - a) < 0.0001f)
		{
			return 0.5f;
		}
		return Clamp((value - a) / (b - a), 0f, 1f);
	}

	private static float Clamp(float value, float min, float max)
	{
		if (value < min)
		{
			return min;
		}
		if (value > max)
		{
			return max;
		}
		return value;
	}

	private static MethodInfo FindStaticMethod(Type type, string name, Type[] parameterTypes)
	{
		if (type == null)
		{
			return null;
		}
		try
		{
			return type.GetMethod(name, BindingFlags.Static | BindingFlags.Public, null, parameterTypes, null);
		}
		catch
		{
			return null;
		}
	}

	private static Type ResolveType(string fullName, params string[] assemblyNames)
	{
		Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
		for (int i = 0; i < assemblies.Length; i++)
		{
			try
			{
				Type type = assemblies[i].GetType(fullName, throwOnError: false);
				if (type != null)
				{
					return type;
				}
			}
			catch
			{
			}
		}
		if (assemblyNames != null)
		{
			for (int i = 0; i < assemblyNames.Length; i++)
			{
				try
				{
					Assembly assembly = Assembly.Load(assemblyNames[i]);
					Type type2 = assembly.GetType(fullName, throwOnError: false);
					if (type2 != null)
					{
						return type2;
					}
				}
				catch
				{
				}
			}
		}
		return null;
	}
}