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);
}
}