Decompiled source of LocalChatRange v1.0.1

LocalChatRange.dll

Decompiled 9 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Rendering;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("LocalChatRange")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1")]
[assembly: AssemblyProduct("LocalChatRange")]
[assembly: AssemblyTitle("LocalChatRange")]
[assembly: AssemblyVersion("1.0.1.0")]
namespace LocalChatRange;

internal static class ChatCommands
{
	public const string CommandApiGuid = "com.on-together-mods.commandapi";

	private static readonly string[] Names = new string[2] { "chatrange", "lcr" };

	private const string Usage = "/chatrange - show/hide the local chat area (hotkey: {0})\n/chatrange on | off\n/chatrange mode always | local | typing\n/chatrange players on | off - highlight players in range\n/chatrange status";

	public static bool TryExecute(string text)
	{
		if (string.IsNullOrEmpty(text) || text[0] != '/')
		{
			return false;
		}
		string[] array = text.Substring(1).Split((char[]?)null, StringSplitOptions.RemoveEmptyEntries);
		if (array.Length == 0 || Array.IndexOf(Names, array[0].ToLowerInvariant()) < 0)
		{
			return false;
		}
		Execute(array.Skip(1).ToArray());
		return true;
	}

	public static void Execute(string[] args)
	{
		//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
		Plugin instance = Plugin.Instance;
		if ((Object)(object)instance == (Object)null)
		{
			return;
		}
		string text = ((args.Length != 0) ? args[0].ToLowerInvariant() : "toggle");
		string text2 = ((args.Length > 1) ? args[1].ToLowerInvariant() : null);
		switch (text)
		{
		case "toggle":
			instance.SetEnabled(!instance.Enabled.Value, notify: true);
			break;
		case "show":
		case "on":
			instance.SetEnabled(enabled: true, notify: true);
			break;
		case "hide":
		case "off":
			instance.SetEnabled(enabled: false, notify: true);
			break;
		case "mode":
		{
			if (TryParseMode(text2, out var mode))
			{
				instance.Mode.Value = mode;
				GameAccess.Notify("Mode: " + Plugin.Describe(mode));
			}
			else
			{
				GameAccess.Notify("Usage: /chatrange mode always | local | typing");
			}
			break;
		}
		case "players":
			if (text2 == "on" || text2 == "off")
			{
				instance.HighlightPlayers.Value = text2 == "on";
				GameAccess.Notify("Highlight players in range: " + text2);
			}
			else
			{
				GameAccess.Notify("Usage: /chatrange players on | off");
			}
			break;
		case "status":
			GameAccess.Notify(instance.DescribeStatus());
			break;
		default:
			GameAccess.Notify($"/chatrange - show/hide the local chat area (hotkey: {instance.ToggleKey.Value})\n/chatrange on | off\n/chatrange mode always | local | typing\n/chatrange players on | off - highlight players in range\n/chatrange status");
			break;
		}
	}

	private static bool TryParseMode(string value, out VisibilityMode mode)
	{
		switch (value)
		{
		case "always":
			mode = VisibilityMode.Always;
			return true;
		case "local":
			mode = VisibilityMode.LocalTabOnly;
			return true;
		case "typing":
			mode = VisibilityMode.WhileTypingLocal;
			return true;
		default:
			mode = VisibilityMode.Always;
			return false;
		}
	}

	public static void RegisterWithCommandApi()
	{
		if (!Chainloader.PluginInfos.TryGetValue("com.on-together-mods.commandapi", out var value) || (Object)(object)value.Instance == (Object)null)
		{
			return;
		}
		try
		{
			Assembly assembly = ((object)value.Instance).GetType().Assembly;
			Type type = assembly.GetType("CommandAPI.CommandRegistry");
			Type type2 = assembly.GetType("CommandAPI.Parameter");
			Type type3 = assembly.GetType("CommandAPI.ParameterType");
			MethodInfo methodInfo = type?.GetMethod("Register", new Type[5]
			{
				typeof(string),
				typeof(string),
				typeof(Action<string[]>),
				typeof(string),
				type2.MakeArrayType()
			});
			if (!(methodInfo == null))
			{
				object obj = Enum.Parse(type3, "String");
				Array array = Array.CreateInstance(type2, 2);
				array.SetValue(Activator.CreateInstance(type2, "action", obj, true, null, null), 0);
				array.SetValue(Activator.CreateInstance(type2, "value", obj, true, null, null), 1);
				Action<string[]> action = Execute;
				string[] names = Names;
				foreach (string text in names)
				{
					methodInfo.Invoke(null, new object[5] { text, "LocalChatRange", action, "Show/hide the local chat range area: on, off, mode, players, status", array });
				}
				Plugin.Log.LogInfo((object)"Registered /chatrange with CommandAPI.");
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("Could not register with CommandAPI (the command still works): " + ex.Message));
		}
	}
}
[HarmonyPatch(typeof(TextChannelManager), "OnEnterPressed")]
internal static class ChatCommandPatch
{
	[HarmonyPrefix]
	[HarmonyPriority(800)]
	private static void Prefix()
	{
		try
		{
			UIManager i = MonoSingleton<UIManager>.I;
			TMP_InputField val = (((Object)(object)i != (Object)null) ? i.MessageInput : null);
			if ((Object)(object)val != (Object)null && ChatCommands.TryExecute(val.text))
			{
				val.text = string.Empty;
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)("Chat command failed: " + ex));
		}
	}
}
internal static class GameAccess
{
	private const float LookupInterval = 1f;

	private static TextChannelManager _chat;

	private static UIManager _ui;

	private static PlayerPanelController _playerPanel;

	private static float _nextChatLookup;

	private static float _nextUiLookup;

	private static float _nextPlayerPanelLookup;

	private static readonly FieldRef<TextChannelManager, TMP_Text> TextPrefabRef = TryFieldRef<TMP_Text>("_textPrefab");

	private static readonly FieldRef<TextChannelManager, List<GameObject>> LocalMessagesRef = TryFieldRef<List<GameObject>>("_messageObjectsLocal");

	public static TextChannelManager Chat
	{
		get
		{
			if ((Object)(object)_chat == (Object)null && Time.unscaledTime >= _nextChatLookup)
			{
				_nextChatLookup = Time.unscaledTime + 1f;
				_chat = NetworkSingleton<TextChannelManager>.I;
			}
			return _chat;
		}
	}

	public static UIManager UI
	{
		get
		{
			if ((Object)(object)_ui == (Object)null && Time.unscaledTime >= _nextUiLookup)
			{
				_nextUiLookup = Time.unscaledTime + 1f;
				_ui = MonoSingleton<UIManager>.I;
			}
			return _ui;
		}
	}

	public static PlayerPanelController PlayerPanel
	{
		get
		{
			if ((Object)(object)_playerPanel == (Object)null && Time.unscaledTime >= _nextPlayerPanelLookup)
			{
				_nextPlayerPanelLookup = Time.unscaledTime + 1f;
				_playerPanel = NetworkSingleton<PlayerPanelController>.I;
			}
			return _playerPanel;
		}
	}

	public static bool IsChatInputFocused()
	{
		UIManager uI = UI;
		if ((Object)(object)uI == (Object)null)
		{
			return false;
		}
		TMP_InputField messageInput = uI.MessageInput;
		if ((Object)(object)messageInput != (Object)null && messageInput.isFocused)
		{
			return true;
		}
		TMP_InputField messageInputField = uI.MessageInputField;
		if ((Object)(object)messageInputField != (Object)null)
		{
			return messageInputField.isFocused;
		}
		return false;
	}

	public static bool IsAnyTextFieldFocused()
	{
		EventSystem current = EventSystem.current;
		if ((Object)(object)current == (Object)null)
		{
			return false;
		}
		GameObject currentSelectedGameObject = current.currentSelectedGameObject;
		if ((Object)(object)currentSelectedGameObject == (Object)null)
		{
			return false;
		}
		TMP_InputField component = currentSelectedGameObject.GetComponent<TMP_InputField>();
		if ((Object)(object)component != (Object)null && component.isFocused)
		{
			return true;
		}
		InputField component2 = currentSelectedGameObject.GetComponent<InputField>();
		if ((Object)(object)component2 != (Object)null)
		{
			return component2.isFocused;
		}
		return false;
	}

	public static float? DetectRadiusFromGameCode()
	{
		MethodInfo methodInfo = AccessTools.Method(typeof(TextChannelManager), "OnChannelMessageReceived", (Type[])null, (Type[])null);
		if (methodInfo == null)
		{
			return null;
		}
		byte[] array = methodInfo.GetMethodBody()?.GetILAsByteArray();
		if (array == null)
		{
			return null;
		}
		for (int i = 0; i + 10 <= array.Length; i++)
		{
			if (array[i] != 40 || array[i + 5] != 34)
			{
				continue;
			}
			MethodBase methodBase;
			try
			{
				methodBase = methodInfo.Module.ResolveMethod(BitConverter.ToInt32(array, i + 1));
			}
			catch (Exception)
			{
				continue;
			}
			if (!(methodBase == null) && !(methodBase.Name != "SqrMagnitude") && !(methodBase.DeclaringType != typeof(Vector3)))
			{
				float num = BitConverter.ToSingle(array, i + 6);
				if (num > 0f && num < 1000000f)
				{
					return Mathf.Sqrt(num);
				}
			}
		}
		return null;
	}

	public static void Notify(string message)
	{
		TextChannelManager chat = Chat;
		if ((Object)(object)chat == (Object)null)
		{
			return;
		}
		string text = "<color=#7FD8FF>[LocalChatRange]</color> " + message;
		try
		{
			if (!chat.Islocal || !TryAddLocalLine(chat, text))
			{
				chat.AddNotification(text);
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("Could not show chat notification: " + ex.Message));
		}
	}

	private static bool TryAddLocalLine(TextChannelManager chat, string text)
	{
		if (TextPrefabRef == null)
		{
			return false;
		}
		UIManager uI = UI;
		Transform val = (((Object)(object)uI != (Object)null) ? uI.TextContentLocalTransform : null);
		TMP_Text val2 = TextPrefabRef.Invoke(chat);
		if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
		{
			return false;
		}
		TMP_Text val3 = Object.Instantiate<TMP_Text>(val2, val);
		Button component = ((Component)val3).GetComponent<Button>();
		if ((Object)(object)component != (Object)null)
		{
			((Selectable)component).interactable = false;
		}
		val3.text = text;
		List<GameObject> list = ((LocalMessagesRef != null) ? LocalMessagesRef.Invoke(chat) : null);
		if (list != null)
		{
			list.Add(((Component)val3).gameObject);
			int localMessageLimitCount = ScriptableSingleton<GameSettings>.I.LocalMessageLimitCount;
			while (list.Count > localMessageLimitCount && list.Count > 0)
			{
				GameObject val4 = list[0];
				list.RemoveAt(0);
				if ((Object)(object)val4 != (Object)null)
				{
					Object.Destroy((Object)(object)val4);
				}
			}
		}
		return true;
	}

	private static FieldRef<TextChannelManager, T> TryFieldRef<T>(string fieldName)
	{
		try
		{
			return AccessTools.FieldRefAccess<TextChannelManager, T>(fieldName);
		}
		catch (Exception)
		{
			return null;
		}
	}
}
internal static class Materials
{
	private const string InternalColored = "Hidden/Internal-Colored";

	private const string SpritesDefault = "Sprites/Default";

	private const string UrpUnlit = "Universal Render Pipeline/Unlit";

	public const int Queue = 3050;

	private static string _shaderInUse;

	public static string ShaderInUse => _shaderInUse ?? "none";

	public static Material Create(string name)
	{
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_007a: Expected O, but got Unknown
		Shader val = null;
		string[] array = new string[3] { "Hidden/Internal-Colored", "Sprites/Default", "Universal Render Pipeline/Unlit" };
		foreach (string text in array)
		{
			val = Shader.Find(text);
			if ((Object)(object)val != (Object)null)
			{
				_shaderInUse = text;
				break;
			}
		}
		if ((Object)(object)val == (Object)null)
		{
			return null;
		}
		Material val2 = new Material(val)
		{
			name = name,
			hideFlags = (HideFlags)61,
			renderQueue = 3050
		};
		if (_shaderInUse == "Hidden/Internal-Colored")
		{
			val2.SetInt("_SrcBlend", 5);
			val2.SetInt("_DstBlend", 10);
			val2.SetInt("_ZWrite", 0);
			val2.SetInt("_Cull", 0);
			val2.SetInt("_ZTest", 4);
			val2.SetFloat("_ZBias", -1f);
		}
		else if (_shaderInUse == "Universal Render Pipeline/Unlit")
		{
			val2.SetFloat("_Surface", 1f);
			val2.SetFloat("_Blend", 0f);
			val2.SetFloat("_SrcBlend", 5f);
			val2.SetFloat("_DstBlend", 10f);
			val2.SetFloat("_ZWrite", 0f);
			val2.SetFloat("_Cull", 0f);
			val2.EnableKeyword("_SURFACE_TYPE_TRANSPARENT");
		}
		return val2;
	}

	public static void SetColor(Material material, Color color)
	{
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)material != (Object)null)
		{
			material.color = color;
		}
	}

	public static void SetAlwaysOnTop(Material material, bool onTop)
	{
		if ((Object)(object)material != (Object)null && material.HasProperty("_ZTest"))
		{
			material.SetInt("_ZTest", onTop ? 8 : 4);
		}
	}

	public static void ConfigureRenderer(Renderer renderer)
	{
		renderer.shadowCastingMode = (ShadowCastingMode)0;
		renderer.receiveShadows = false;
		renderer.lightProbeUsage = (LightProbeUsage)0;
		renderer.reflectionProbeUsage = (ReflectionProbeUsage)0;
		renderer.motionVectorGenerationMode = (MotionVectorGenerationMode)2;
		renderer.allowOcclusionWhenDynamic = false;
	}
}
internal static class PlayersInRange
{
	private const float FallbackSearchInterval = 2f;

	private static PlayerController[] _fallbackPlayers = (PlayerController[])(object)new PlayerController[0];

	private static float _nextFallbackSearch;

	public static void Find(Transform localPlayer, float radius, List<Vector3> positions)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		positions.Clear();
		Vector3 position = localPlayer.position;
		float num = radius * radius;
		IList<PlayerController> players = GetPlayers();
		for (int i = 0; i < players.Count; i++)
		{
			PlayerController val = players[i];
			if ((Object)(object)val == (Object)null)
			{
				continue;
			}
			Transform transform = ((Component)val).transform;
			if (!((Object)(object)transform == (Object)(object)localPlayer))
			{
				Vector3 position2 = transform.position;
				Vector3 val2 = position2 - position;
				if (((Vector3)(ref val2)).sqrMagnitude <= num)
				{
					positions.Add(position2);
				}
			}
		}
	}

	private static IList<PlayerController> GetPlayers()
	{
		PlayerPanelController playerPanel = GameAccess.PlayerPanel;
		List<PlayerController> list = (((Object)(object)playerPanel != (Object)null) ? playerPanel.PlayerControllers : null);
		if (list != null && list.Count > 0)
		{
			return list;
		}
		if (Time.unscaledTime >= _nextFallbackSearch)
		{
			_nextFallbackSearch = Time.unscaledTime + 2f;
			_fallbackPlayers = Object.FindObjectsByType<PlayerController>((FindObjectsSortMode)0);
		}
		return _fallbackPlayers;
	}
}
internal sealed class PlayerMarkers
{
	private const float MarkerRadius = 0.45f;

	private const float RingWidth = 0.2f;

	private const int RingSegments = 40;

	private readonly GameObject _container;

	private readonly Mesh _ringMesh;

	private readonly Material _material;

	private readonly List<GameObject> _pool = new List<GameObject>();

	public bool IsAlive
	{
		get
		{
			if ((Object)(object)_container != (Object)null)
			{
				return (Object)(object)_ringMesh != (Object)null;
			}
			return false;
		}
	}

	public PlayerMarkers()
	{
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Expected O, but got Unknown
		_container = new GameObject("LocalChatRange.PlayerMarkers");
		Object.DontDestroyOnLoad((Object)(object)_container);
		_ringMesh = BuildRingMesh();
		_material = Materials.Create("LocalChatRange.Marker");
	}

	public void SetColor(Color color)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		Materials.SetColor(_material, color);
	}

	public void Show(List<Vector3> playerPositions, in AreaSettings s)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		for (int i = 0; i < playerPositions.Count; i++)
		{
			Place(GetMarker(i), playerPositions[i], in s);
		}
		for (int j = playerPositions.Count; j < _pool.Count; j++)
		{
			if ((Object)(object)_pool[j] != (Object)null && _pool[j].activeSelf)
			{
				_pool[j].SetActive(false);
			}
		}
	}

	public void HideAll()
	{
		foreach (GameObject item in _pool)
		{
			if ((Object)(object)item != (Object)null && item.activeSelf)
			{
				item.SetActive(false);
			}
		}
	}

	public void Destroy()
	{
		if ((Object)(object)_container != (Object)null)
		{
			Object.Destroy((Object)(object)_container);
		}
		if ((Object)(object)_ringMesh != (Object)null)
		{
			Object.Destroy((Object)(object)_ringMesh);
		}
		if ((Object)(object)_material != (Object)null)
		{
			Object.Destroy((Object)(object)_material);
		}
	}

	private static void Place(GameObject marker, Vector3 playerPosition, in AreaSettings s)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		Vector3 val = playerPosition;
		Quaternion val2 = Quaternion.identity;
		RaycastHit val3 = default(RaycastHit);
		if (Physics.Raycast(playerPosition + Vector3.up * 0.5f, Vector3.down, ref val3, 3f, s.LayerMask, (QueryTriggerInteraction)1))
		{
			val = ((RaycastHit)(ref val3)).point;
			val2 = Quaternion.FromToRotation(Vector3.up, ((RaycastHit)(ref val3)).normal);
		}
		marker.transform.SetPositionAndRotation(val + Vector3.up * (s.SurfaceOffset * 2f), val2);
		if (!marker.activeSelf)
		{
			marker.SetActive(true);
		}
	}

	private GameObject GetMarker(int index)
	{
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Expected O, but got Unknown
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		while (_pool.Count <= index)
		{
			_pool.Add(null);
		}
		if ((Object)(object)_pool[index] != (Object)null)
		{
			return _pool[index];
		}
		GameObject val = new GameObject("LocalChatRange.Marker");
		val.transform.SetParent(_container.transform, false);
		val.transform.localScale = Vector3.one * 0.45f;
		val.AddComponent<MeshFilter>().sharedMesh = _ringMesh;
		MeshRenderer obj = val.AddComponent<MeshRenderer>();
		((Renderer)obj).sharedMaterial = _material;
		Materials.ConfigureRenderer((Renderer)(object)obj);
		val.SetActive(false);
		_pool[index] = val;
		return val;
	}

	private static Mesh BuildRingMesh()
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0098: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_015c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0161: Unknown result type (might be due to invalid IL or missing references)
		//IL_016c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0174: Unknown result type (might be due to invalid IL or missing references)
		//IL_017b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0182: Unknown result type (might be due to invalid IL or missing references)
		//IL_018a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0191: Expected O, but got Unknown
		List<Vector3> list = new List<Vector3> { Vector3.zero };
		List<Color> list2 = new List<Color>
		{
			new Color(1f, 1f, 1f, 0.1f)
		};
		List<int> list3 = new List<int>();
		float num = 0.8f;
		Vector3 val = default(Vector3);
		for (int i = 0; i < 40; i++)
		{
			float num2 = (float)i * 2f * MathF.PI / 40f;
			((Vector3)(ref val))..ctor(Mathf.Cos(num2), 0f, Mathf.Sin(num2));
			list.Add(val * num);
			list.Add(val * num);
			list.Add(val);
			list2.Add(new Color(1f, 1f, 1f, 0.25f));
			list2.Add(Color.white);
			list2.Add(Color.white);
		}
		for (int j = 0; j < 40; j++)
		{
			int num3 = 1 + 3 * j;
			int num4 = 1 + 3 * ((j + 1) % 40);
			list3.Add(0);
			list3.Add(num3);
			list3.Add(num4);
			list3.Add(num3 + 1);
			list3.Add(num3 + 2);
			list3.Add(num4 + 2);
			list3.Add(num3 + 1);
			list3.Add(num4 + 2);
			list3.Add(num4 + 1);
		}
		Mesh val2 = new Mesh
		{
			name = "LocalChatRange.Marker",
			hideFlags = (HideFlags)61
		};
		val2.SetVertices(list);
		val2.SetColors(list2);
		val2.SetTriangles(list3, 0);
		val2.RecalculateBounds();
		return val2;
	}
}
public enum VisibilityMode
{
	Always,
	LocalTabOnly,
	WhileTypingLocal
}
[BepInPlugin("ontogether.localchatrange", "LocalChatRange", "1.0.1")]
[BepInProcess("OnTogether.exe")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class Plugin : BaseUnityPlugin
{
	public const string PluginGuid = "ontogether.localchatrange";

	public const string PluginName = "LocalChatRange";

	public const string PluginVersion = "1.0.1";

	internal ConfigEntry<bool> Enabled;

	internal ConfigEntry<KeyboardShortcut> ToggleKey;

	internal ConfigEntry<VisibilityMode> Mode;

	internal ConfigEntry<bool> HighlightPlayers;

	private ConfigEntry<bool> _autoDetectRadius;

	private ConfigEntry<float> _radius;

	private ConfigEntry<Color> _fillColor;

	private ConfigEntry<Color> _outlineColor;

	private ConfigEntry<float> _outlineWidth;

	private ConfigEntry<bool> _outlineOnTop;

	private ConfigEntry<Color> _markerColor;

	private ConfigEntry<int> _segments;

	private ConfigEntry<int> _rings;

	private ConfigEntry<int> _refineSteps;

	private ConfigEntry<float> _updateInterval;

	private ConfigEntry<float> _maxStepUp;

	private ConfigEntry<float> _surfaceOffset;

	private float? _detectedRadius;

	private Harmony _harmony;

	private RangeArea _area;

	private PlayerMarkers _markers;

	private int _layerMask;

	private readonly List<Vector3> _playersInRange = new List<Vector3>();

	private bool _visualsFailed;

	private string _lastError;

	private Transform _pivotOwner;

	private CharacterController _pivotController;

	private float _pivotHeight;

	internal static Plugin Instance { get; private set; }

	internal static ManualLogSource Log { get; private set; }

	internal float Radius
	{
		get
		{
			if (!_autoDetectRadius.Value || !_detectedRadius.HasValue)
			{
				return _radius.Value;
			}
			return _detectedRadius.Value;
		}
	}

	private void Awake()
	{
		//IL_010f: Unknown result type (might be due to invalid IL or missing references)
		Instance = this;
		Log = ((BaseUnityPlugin)this).Logger;
		BindConfig();
		try
		{
			_detectedRadius = GameAccess.DetectRadiusFromGameCode();
		}
		catch (Exception ex)
		{
			Log.LogWarning((object)("Radius auto-detection failed: " + ex.Message));
		}
		if (_detectedRadius.HasValue)
		{
			Log.LogInfo((object)$"Local chat radius read from the game code: {_detectedRadius.Value:0.##} m");
		}
		else
		{
			Log.LogWarning((object)$"Could not read the local chat radius from the game code; using Range.Radius = {_radius.Value} m");
		}
		try
		{
			_harmony = Harmony.CreateAndPatchAll(typeof(ChatCommandPatch), "ontogether.localchatrange");
		}
		catch (Exception ex2)
		{
			Log.LogError((object)("Could not patch the chat; /chatrange will not work: " + ex2));
		}
		ChatCommands.RegisterWithCommandApi();
		((BaseUnityPlugin)this).Config.SettingChanged += OnSettingChanged;
		Log.LogInfo((object)string.Format("{0} {1} loaded. Toggle with {2} or /chatrange", "LocalChatRange", "1.0.1", ToggleKey.Value));
	}

	private void BindConfig()
	{
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ec: Expected O, but got Unknown
		//IL_0116: Unknown result type (might be due to invalid IL or missing references)
		//IL_014f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0192: Unknown result type (might be due to invalid IL or missing references)
		//IL_019c: Expected O, but got Unknown
		//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0224: Unknown result type (might be due to invalid IL or missing references)
		//IL_022e: Expected O, but got Unknown
		//IL_0257: Unknown result type (might be due to invalid IL or missing references)
		//IL_0261: Expected O, but got Unknown
		//IL_0289: Unknown result type (might be due to invalid IL or missing references)
		//IL_0293: Expected O, but got Unknown
		//IL_02c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d1: Expected O, but got Unknown
		//IL_0305: Unknown result type (might be due to invalid IL or missing references)
		//IL_030f: Expected O, but got Unknown
		//IL_0343: Unknown result type (might be due to invalid IL or missing references)
		//IL_034d: Expected O, but got Unknown
		Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Show the local text chat range around your character.");
		ToggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "ToggleKey", new KeyboardShortcut((KeyCode)289, Array.Empty<KeyCode>()), "Hotkey that shows/hides the area (ignored while typing in a text field).");
		Mode = ((BaseUnityPlugin)this).Config.Bind<VisibilityMode>("General", "VisibilityMode", VisibilityMode.Always, "When the area is drawn:\nAlways - whenever it is enabled;\nLocalTabOnly - only while the chat is switched to the Local tab;\nWhileTypingLocal - only while you are typing a message in the Local tab.");
		HighlightPlayers = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "HighlightPlayersInRange", true, "Draw a ring under every player who would receive your local messages.");
		_autoDetectRadius = ((BaseUnityPlugin)this).Config.Bind<bool>("Range", "AutoDetectRadius", true, "Read the local chat distance from the game code at startup (recommended). If it cannot be read, Radius is used.");
		_radius = ((BaseUnityPlugin)this).Config.Bind<float>("Range", "Radius", 5f, new ConfigDescription("Local chat distance in metres, used when auto-detection is off or fails.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 100f), Array.Empty<object>()));
		_fillColor = ((BaseUnityPlugin)this).Config.Bind<Color>("Appearance", "FillColor", new Color(0.55f, 0.85f, 1f, 0.12f), "Colour of the area (RRGGBBAA). The fill fades towards the centre.");
		_outlineColor = ((BaseUnityPlugin)this).Config.Bind<Color>("Appearance", "OutlineColor", new Color(0.55f, 0.85f, 1f, 0.9f), "Colour of the area's edge (RRGGBBAA).");
		_outlineWidth = ((BaseUnityPlugin)this).Config.Bind<float>("Appearance", "OutlineWidth", 0.08f, new ConfigDescription("Width of the edge line in metres.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 1f), Array.Empty<object>()));
		_outlineOnTop = ((BaseUnityPlugin)this).Config.Bind<bool>("Appearance", "OutlineOnTop", false, "Draw the edge line on top of walls and furniture.");
		_markerColor = ((BaseUnityPlugin)this).Config.Bind<Color>("Appearance", "PlayerMarkerColor", new Color(0.55f, 1f, 0.55f, 0.9f), "Colour of the rings under players in range (RRGGBBAA).");
		_segments = ((BaseUnityPlugin)this).Config.Bind<int>("Quality", "Segments", 64, new ConfigDescription("Points around the circle.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(16, 256), Array.Empty<object>()));
		_rings = ((BaseUnityPlugin)this).Config.Bind<int>("Quality", "Rings", 8, new ConfigDescription("Surface samples from the centre to the edge. More rings follow stairs and bumps more closely.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(2, 32), Array.Empty<object>()));
		_refineSteps = ((BaseUnityPlugin)this).Config.Bind<int>("Quality", "EdgeRefineSteps", 4, new ConfigDescription("Extra samples used to place the edge precisely where the ground leaves the range.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 8), Array.Empty<object>()));
		_updateInterval = ((BaseUnityPlugin)this).Config.Bind<float>("Quality", "UpdateInterval", 0.05f, new ConfigDescription("Seconds between surface re-samples while moving. The area follows you every frame regardless.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
		_maxStepUp = ((BaseUnityPlugin)this).Config.Bind<float>("Quality", "MaxStepUp", 2f, new ConfigDescription("Ignore surfaces higher than this above your feet (ceilings, upper floors), in metres.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 10f), Array.Empty<object>()));
		_surfaceOffset = ((BaseUnityPlugin)this).Config.Bind<float>("Quality", "SurfaceOffset", 0.03f, new ConfigDescription("Lift above the surface to avoid flickering, in metres.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.5f), Array.Empty<object>()));
	}

	private void Update()
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		if (Pressed(ToggleKey.Value) && !GameAccess.IsAnyTextFieldFocused())
		{
			SetEnabled(!Enabled.Value, notify: false);
		}
	}

	private static bool Pressed(KeyboardShortcut shortcut)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		KeyCode mainKey = ((KeyboardShortcut)(ref shortcut)).MainKey;
		if ((int)mainKey == 0 || !Input.GetKeyDown(mainKey))
		{
			return false;
		}
		foreach (KeyCode modifier in ((KeyboardShortcut)(ref shortcut)).Modifiers)
		{
			if (!Input.GetKey(modifier))
			{
				return false;
			}
		}
		return true;
	}

	private void LateUpdate()
	{
		try
		{
			Tick();
		}
		catch (Exception ex)
		{
			string text = ex.GetType().Name + ": " + ex.Message;
			if (text != _lastError)
			{
				_lastError = text;
				Log.LogError((object)("Update failed: " + ex));
			}
			HideVisuals();
		}
	}

	private void Tick()
	{
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		TextChannelManager chat = GameAccess.Chat;
		Transform val = (((Object)(object)chat != (Object)null) ? chat.MainPlayer : null);
		if (!ShouldShow(chat, val) || !EnsureVisuals())
		{
			HideVisuals();
			return;
		}
		AreaSettings settings = CurrentSettings();
		Vector3 center = val.position + Vector3.down * PivotHeight(val);
		_area.SetVisible(visible: true);
		_area.Tick(center, in settings);
		if (HighlightPlayers.Value)
		{
			PlayersInRange.Find(val, settings.Radius, _playersInRange);
			_markers.Show(_playersInRange, in settings);
		}
		else
		{
			_markers.HideAll();
		}
	}

	private bool ShouldShow(TextChannelManager chat, Transform player)
	{
		if (!Enabled.Value || (Object)(object)chat == (Object)null || (Object)(object)player == (Object)null)
		{
			return false;
		}
		switch (Mode.Value)
		{
		case VisibilityMode.LocalTabOnly:
			return chat.Islocal;
		case VisibilityMode.WhileTypingLocal:
			if (chat.Islocal)
			{
				return GameAccess.IsChatInputFocused();
			}
			return false;
		default:
			return true;
		}
	}

	private float PivotHeight(Transform player)
	{
		//IL_005b: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)_pivotOwner != (Object)(object)player)
		{
			_pivotOwner = player;
			_pivotController = ((Component)player).GetComponentInChildren<CharacterController>(true);
			_pivotHeight = 0f;
		}
		if ((Object)(object)_pivotController != (Object)null && ((Collider)_pivotController).enabled && ((Component)_pivotController).gameObject.activeInHierarchy)
		{
			float y = player.position.y;
			Bounds bounds = ((Collider)_pivotController).bounds;
			float num = y - ((Bounds)(ref bounds)).min.y + _pivotController.skinWidth;
			_pivotHeight = Mathf.Clamp(num, 0f, 3f);
		}
		return _pivotHeight;
	}

	private AreaSettings CurrentSettings()
	{
		return new AreaSettings
		{
			Radius = Radius,
			Segments = _segments.Value,
			Rings = _rings.Value,
			RefineSteps = _refineSteps.Value,
			UpdateInterval = _updateInterval.Value,
			MaxStepUp = _maxStepUp.Value,
			SurfaceOffset = _surfaceOffset.Value,
			OutlineWidth = _outlineWidth.Value,
			LayerMask = _layerMask
		};
	}

	private bool EnsureVisuals()
	{
		if (_visualsFailed)
		{
			return false;
		}
		if (_area != null && _area.IsAlive && _markers != null && _markers.IsAlive)
		{
			return true;
		}
		DestroyVisuals();
		_layerMask = -5 & ~LayerMask.GetMask(new string[20]
		{
			"Player", "PlayerRender", "NPC", "Customization", "IsGroundedChecker", "Area", "AreaChecker", "AreaTrigger", "AntiPlayer", "IgnorePlayer",
			"BasketBall", "BasketBallPlayer", "BasketBoundaryLayer", "Umbrella", "Drawing", "UI", "Indicator", "Overlay", "PostProcess1", "PostProcess2"
		});
		_area = new RangeArea();
		_markers = new PlayerMarkers();
		if (!_area.HasMaterials)
		{
			_visualsFailed = true;
			Log.LogError((object)"No usable shader found; the area cannot be drawn.");
			DestroyVisuals();
			return false;
		}
		ApplyAppearance();
		Log.LogInfo((object)("Area visuals created (shader: " + Materials.ShaderInUse + ")"));
		return true;
	}

	private void ApplyAppearance()
	{
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		if (_area != null)
		{
			_area.ApplyAppearance(_fillColor.Value, _outlineColor.Value, _outlineOnTop.Value);
			_area.MarkDirty();
		}
		if (_markers != null)
		{
			_markers.SetColor(_markerColor.Value);
		}
	}

	private void HideVisuals()
	{
		if (_area != null && _area.IsAlive)
		{
			_area.SetVisible(visible: false);
		}
		if (_markers != null && _markers.IsAlive)
		{
			_markers.HideAll();
		}
	}

	private void DestroyVisuals()
	{
		if (_area != null)
		{
			_area.Destroy();
		}
		if (_markers != null)
		{
			_markers.Destroy();
		}
		_area = null;
		_markers = null;
	}

	private void OnSettingChanged(object sender, SettingChangedEventArgs e)
	{
		ApplyAppearance();
	}

	internal void SetEnabled(bool enabled, bool notify)
	{
		Enabled.Value = enabled;
		if (notify)
		{
			string text = (enabled ? "Local chat area: shown" : "Local chat area: hidden");
			if (enabled && Mode.Value != VisibilityMode.Always)
			{
				text = text + " (" + Describe(Mode.Value) + ")";
			}
			GameAccess.Notify(text);
		}
	}

	internal string DescribeStatus()
	{
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		string arg = ((_autoDetectRadius.Value && _detectedRadius.HasValue) ? "from game code" : "from config");
		string text = (Enabled.Value ? "shown" : "hidden") + ", mode: " + Describe(Mode.Value) + ", " + $"radius: {Radius:0.##} m ({arg}), hotkey: {ToggleKey.Value}";
		TextChannelManager chat = GameAccess.Chat;
		Transform val = (((Object)(object)chat != (Object)null) ? chat.MainPlayer : null);
		if ((Object)(object)val == (Object)null)
		{
			return text;
		}
		List<Vector3> list = new List<Vector3>();
		PlayersInRange.Find(val, Radius, list);
		return text + $", players in range: {list.Count}";
	}

	internal static string Describe(VisibilityMode mode)
	{
		return mode switch
		{
			VisibilityMode.LocalTabOnly => "only on the Local chat tab", 
			VisibilityMode.WhileTypingLocal => "only while typing in the Local tab", 
			_ => "always", 
		};
	}

	private void OnDestroy()
	{
		((BaseUnityPlugin)this).Config.SettingChanged -= OnSettingChanged;
		if (_harmony != null)
		{
			_harmony.UnpatchSelf();
		}
		DestroyVisuals();
	}
}
internal struct AreaSettings
{
	public float Radius;

	public int Segments;

	public int Rings;

	public int RefineSteps;

	public float UpdateInterval;

	public float MaxStepUp;

	public float SurfaceOffset;

	public float OutlineWidth;

	public int LayerMask;
}
internal sealed class RangeArea
{
	private const float VerticalTolerance = 0.05f;

	private const float IdleRefreshInterval = 0.5f;

	private const float MoveThresholdSqr = 0.0009f;

	private const float CenterAlpha = 0.35f;

	private const float TentMinHeight = 0.35f;

	private static readonly float TentMaxSlopeCos = Mathf.Cos(0.87266463f);

	private readonly GameObject _root;

	private readonly Mesh _mesh;

	private readonly Material _fillMaterial;

	private readonly Material _outlineMaterial;

	private readonly List<Vector3> _vertices = new List<Vector3>();

	private readonly List<Color> _colors = new List<Color>();

	private readonly List<int> _fillTriangles = new List<int>();

	private readonly List<int> _outlineTriangles = new List<int>();

	private Vector3[] _samples = (Vector3[])(object)new Vector3[0];

	private bool[] _sampleHit = new bool[0];

	private bool[] _vertexUsable = new bool[0];

	private float[] _boundaryRadius = new float[0];

	private Vector3[] _boundaryPoint = (Vector3[])(object)new Vector3[0];

	private Vector3[] _innerPoint = (Vector3[])(object)new Vector3[0];

	private int[] _outermostHit = new int[0];

	private Vector3 _builtCenter;

	private float _lastBuildTime = float.NegativeInfinity;

	private bool _dirty = true;

	public bool IsAlive
	{
		get
		{
			if ((Object)(object)_root != (Object)null)
			{
				return (Object)(object)_mesh != (Object)null;
			}
			return false;
		}
	}

	public bool HasMaterials
	{
		get
		{
			if ((Object)(object)_fillMaterial != (Object)null)
			{
				return (Object)(object)_outlineMaterial != (Object)null;
			}
			return false;
		}
	}

	public RangeArea()
	{
		//IL_009e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a8: Expected O, but got Unknown
		//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dd: Expected O, but got Unknown
		_root = new GameObject("LocalChatRange.Area");
		Object.DontDestroyOnLoad((Object)(object)_root);
		_root.SetActive(false);
		_mesh = new Mesh
		{
			name = "LocalChatRange.Area",
			hideFlags = (HideFlags)61
		};
		_mesh.MarkDynamic();
		_root.AddComponent<MeshFilter>().sharedMesh = _mesh;
		_fillMaterial = Materials.Create("LocalChatRange.Fill");
		_outlineMaterial = Materials.Create("LocalChatRange.Outline");
		MeshRenderer val = _root.AddComponent<MeshRenderer>();
		((Renderer)val).sharedMaterials = (Material[])(object)new Material[2] { _fillMaterial, _outlineMaterial };
		Materials.ConfigureRenderer((Renderer)(object)val);
	}

	public void SetVisible(bool visible)
	{
		if ((Object)(object)_root != (Object)null && _root.activeSelf != visible)
		{
			_root.SetActive(visible);
			if (visible)
			{
				_dirty = true;
			}
		}
	}

	public void MarkDirty()
	{
		_dirty = true;
	}

	public void ApplyAppearance(Color fill, Color outline, bool outlineOnTop)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		Materials.SetColor(_fillMaterial, fill);
		Materials.SetColor(_outlineMaterial, outline);
		Materials.SetAlwaysOnTop(_outlineMaterial, outlineOnTop);
	}

	public void Tick(Vector3 center, in AreaSettings settings)
	{
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		float unscaledTime = Time.unscaledTime;
		float num = unscaledTime - _lastBuildTime;
		Vector3 val = center - _builtCenter;
		bool flag = ((Vector3)(ref val)).sqrMagnitude > 0.0009f;
		if (_dirty || num >= 0.5f || (flag && num >= settings.UpdateInterval))
		{
			Build(center, in settings);
			_builtCenter = center;
			_lastBuildTime = unscaledTime;
			_dirty = false;
		}
		_root.transform.SetPositionAndRotation(center, Quaternion.identity);
	}

	public void Destroy()
	{
		if ((Object)(object)_root != (Object)null)
		{
			Object.Destroy((Object)(object)_root);
		}
		if ((Object)(object)_mesh != (Object)null)
		{
			Object.Destroy((Object)(object)_mesh);
		}
		if ((Object)(object)_fillMaterial != (Object)null)
		{
			Object.Destroy((Object)(object)_fillMaterial);
		}
		if ((Object)(object)_outlineMaterial != (Object)null)
		{
			Object.Destroy((Object)(object)_outlineMaterial);
		}
	}

	private void Build(Vector3 center, in AreaSettings s)
	{
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01da: Unknown result type (might be due to invalid IL or missing references)
		//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0200: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		//IL_0250: Unknown result type (might be due to invalid IL or missing references)
		//IL_0252: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_010a: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0174: Unknown result type (might be due to invalid IL or missing references)
		//IL_0176: Unknown result type (might be due to invalid IL or missing references)
		//IL_0458: Unknown result type (might be due to invalid IL or missing references)
		//IL_045d: Unknown result type (might be due to invalid IL or missing references)
		//IL_045f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0477: Unknown result type (might be due to invalid IL or missing references)
		//IL_047c: Unknown result type (might be due to invalid IL or missing references)
		//IL_047e: Unknown result type (might be due to invalid IL or missing references)
		//IL_048e: Unknown result type (might be due to invalid IL or missing references)
		//IL_049e: Unknown result type (might be due to invalid IL or missing references)
		//IL_010f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0294: Unknown result type (might be due to invalid IL or missing references)
		//IL_0299: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0300: Unknown result type (might be due to invalid IL or missing references)
		//IL_030c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0311: Unknown result type (might be due to invalid IL or missing references)
		//IL_0123: Unknown result type (might be due to invalid IL or missing references)
		//IL_013c: Unknown result type (might be due to invalid IL or missing references)
		//IL_013e: Unknown result type (might be due to invalid IL or missing references)
		//IL_034f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0354: Unknown result type (might be due to invalid IL or missing references)
		//IL_0356: Unknown result type (might be due to invalid IL or missing references)
		//IL_0366: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_0400: Unknown result type (might be due to invalid IL or missing references)
		//IL_0402: Unknown result type (might be due to invalid IL or missing references)
		//IL_0412: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_03b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_03e3: Unknown result type (might be due to invalid IL or missing references)
		int segments = s.Segments;
		int rings = s.Rings;
		float radius = s.Radius;
		float num = MathF.PI * 2f / (float)segments;
		EnsureCapacity(segments, rings);
		if (!Sample(center, 0f, 0f, 0f, in s, out var point))
		{
			point = center;
		}
		for (int i = 0; i < segments; i++)
		{
			float dx = Mathf.Cos((float)i * num);
			float dz = Mathf.Sin((float)i * num);
			int num2 = i * rings;
			int num3 = 0;
			for (int j = 1; j <= rings; j++)
			{
				int num4 = num2 + j - 1;
				_sampleHit[num4] = Sample(center, dx, dz, radius * (float)j / (float)rings, in s, out _samples[num4]);
				if (_sampleHit[num4])
				{
					num3 = j;
				}
			}
			float num5;
			Vector3 val;
			if (num3 == rings)
			{
				num5 = radius;
				val = _samples[num2 + rings - 1];
			}
			else
			{
				float num6 = radius * (float)num3 / (float)rings;
				float num7 = radius * (float)(num3 + 1) / (float)rings;
				num5 = num6;
				val = ((num3 > 0) ? _samples[num2 + num3 - 1] : point);
				for (int k = 0; k < s.RefineSteps; k++)
				{
					float num8 = 0.5f * (num6 + num7);
					if (Sample(center, dx, dz, num8, in s, out var point2))
					{
						num6 = num8;
						num5 = num8;
						val = point2;
					}
					else
					{
						num7 = num8;
					}
				}
			}
			_outermostHit[i] = num3;
			_boundaryRadius[i] = num5;
			_boundaryPoint[i] = val;
		}
		_vertices.Clear();
		_colors.Clear();
		_fillTriangles.Clear();
		_outlineTriangles.Clear();
		Vector3 val2 = new Vector3(0f, s.SurfaceOffset, 0f) - center;
		_vertices.Add(point + val2);
		_colors.Add(new Color(1f, 1f, 1f, 0.35f));
		for (int l = 0; l < segments; l++)
		{
			float num9 = Mathf.Cos((float)l * num);
			float num10 = Mathf.Sin((float)l * num);
			int num11 = l * rings;
			float num12 = _boundaryRadius[l];
			float num13 = Mathf.Max(0f, num12 - s.OutlineWidth);
			Vector3 val3 = point;
			float num14 = 0f;
			for (int num15 = _outermostHit[l]; num15 >= 1; num15--)
			{
				float num16 = radius * (float)num15 / (float)rings;
				int num17 = num11 + num15 - 1;
				if (num16 <= num13 && _sampleHit[num17])
				{
					val3 = _samples[num17];
					num14 = num16;
					break;
				}
			}
			float num18 = ((num12 - num14 > 0.0001f) ? ((num13 - num14) / (num12 - num14)) : 1f);
			_innerPoint[l] = new Vector3(center.x + num9 * num13, Mathf.Lerp(val3.y, _boundaryPoint[l].y, num18), center.z + num10 * num13);
			for (int m = 1; m <= rings; m++)
			{
				int num19 = num11 + m - 1;
				float num20 = radius * (float)m / (float)rings;
				if (num20 >= num13)
				{
					_vertexUsable[num19] = true;
					_vertices.Add(_innerPoint[l] + val2);
					_colors.Add(Color.white);
				}
				else if (_sampleHit[num19])
				{
					_vertexUsable[num19] = true;
					float num21 = num20 / Mathf.Max(num12, 0.0001f);
					_vertices.Add(_samples[num19] + val2);
					_colors.Add(new Color(1f, 1f, 1f, Mathf.Lerp(0.35f, 1f, num21 * num21)));
				}
				else
				{
					_vertexUsable[num19] = false;
					_vertices.Add(center + val2);
					_colors.Add(Color.clear);
				}
			}
		}
		int count = _vertices.Count;
		for (int n = 0; n < segments; n++)
		{
			_vertices.Add(_innerPoint[n] + val2);
			_vertices.Add(_boundaryPoint[n] + val2);
			_colors.Add(Color.white);
			_colors.Add(Color.white);
		}
		for (int num22 = 0; num22 < segments; num22++)
		{
			int num23 = (num22 + 1) % segments;
			int num24 = num22 * rings;
			int num25 = num23 * rings;
			if (_vertexUsable[num24] && _vertexUsable[num25])
			{
				AddFillTriangle(0, 1 + num24, 1 + num25);
			}
			for (int num26 = 0; num26 < rings - 1; num26++)
			{
				int num27 = num24 + num26;
				int num28 = num24 + num26 + 1;
				int num29 = num25 + num26;
				int num30 = num25 + num26 + 1;
				if (_vertexUsable[num27] && _vertexUsable[num28] && _vertexUsable[num29] && _vertexUsable[num30])
				{
					AddFillTriangle(1 + num27, 1 + num28, 1 + num30);
					AddFillTriangle(1 + num27, 1 + num30, 1 + num29);
				}
			}
			int num31 = count + 2 * num22;
			int num32 = count + 2 * num23;
			AddQuad(_outlineTriangles, num31, num31 + 1, num32 + 1, num32);
		}
		_mesh.Clear();
		_mesh.SetVertices(_vertices);
		_mesh.SetColors(_colors);
		_mesh.subMeshCount = 2;
		_mesh.SetTriangles(_fillTriangles, 0, false);
		_mesh.SetTriangles(_outlineTriangles, 1, false);
		_mesh.RecalculateBounds();
	}

	private static bool Sample(Vector3 center, float dx, float dz, float r, in AreaSettings s, out Vector3 point)
	{
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		float num = Mathf.Sqrt(Mathf.Max(0f, s.Radius * s.Radius - r * r)) + 0.05f;
		float num2 = Mathf.Min(num, s.MaxStepUp);
		RaycastHit val = default(RaycastHit);
		if (Physics.Raycast(new Vector3(center.x + dx * r, center.y + num2, center.z + dz * r), Vector3.down, ref val, num2 + num, s.LayerMask, (QueryTriggerInteraction)1))
		{
			point = ((RaycastHit)(ref val)).point;
			return true;
		}
		point = default(Vector3);
		return false;
	}

	private void EnsureCapacity(int segments, int rings)
	{
		int num = segments * rings;
		if (_samples.Length != num)
		{
			_samples = (Vector3[])(object)new Vector3[num];
			_sampleHit = new bool[num];
			_vertexUsable = new bool[num];
		}
		if (_boundaryRadius.Length != segments)
		{
			_boundaryRadius = new float[segments];
			_boundaryPoint = (Vector3[])(object)new Vector3[segments];
			_innerPoint = (Vector3[])(object)new Vector3[segments];
			_outermostHit = new int[segments];
		}
	}

	private void AddFillTriangle(int a, int b, int c)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: Unknown result type (might be due to invalid IL or missing references)
		Vector3 val = _vertices[a];
		Vector3 val2 = _vertices[b];
		Vector3 val3 = _vertices[c];
		if (Mathf.Max(val.y, Mathf.Max(val2.y, val3.y)) - Mathf.Min(val.y, Mathf.Min(val2.y, val3.y)) > 0.35f)
		{
			Vector3 val4 = Vector3.Cross(val2 - val, val3 - val);
			float magnitude = ((Vector3)(ref val4)).magnitude;
			if (magnitude > 1E-06f && Mathf.Abs(val4.y) < magnitude * TentMaxSlopeCos)
			{
				return;
			}
		}
		AddTriangle(_fillTriangles, a, b, c);
	}

	private static void AddTriangle(List<int> triangles, int a, int b, int c)
	{
		triangles.Add(a);
		triangles.Add(b);
		triangles.Add(c);
	}

	private static void AddQuad(List<int> triangles, int a, int b, int c, int d)
	{
		AddTriangle(triangles, a, b, c);
		AddTriangle(triangles, a, c, d);
	}
}