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("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("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; } }