Decompiled source of ArrowExpanders v1.0.2

plugins/ArrowExpanders.dll

Decompiled 2 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using BepInEx.NET.Common;
using BepInExResoniteShim;
using Elements.Core;
using FrooxEngine;
using FrooxEngine.UIX;
using HarmonyLib;
using Renderite.Shared;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(/*Could not decode attribute arguments.*/)]
[assembly: TargetFramework(".NETCoreApp,Version=v9.0", FrameworkDisplayName = ".NET 9.0")]
[assembly: AssemblyCompany("eia485")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.2.0")]
[assembly: AssemblyInformationalVersion("1.0.2+e0aeb2e89a815887c633c38d5f5714f3f3c6858d")]
[assembly: AssemblyProduct("ArrowExpanders")]
[assembly: AssemblyTitle("ArrowExpanders")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/EIA485/NeosArrowExpanders")]
[assembly: AssemblyVersion("1.0.2.0")]
[module: RefSafetyRules(11)]
namespace ArrowExpanders;

[ResonitePlugin("net.eia485.ArrowExpanders", "ArrowExpanders", "1.0.2", "eia485", "https://github.com/EIA485/NeosArrowExpanders")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class ArrowExpanders : BasePlugin
{
	[HarmonyPatch(typeof(Userspace), "OnCommonUpdate")]
	private class ArrowExpandersPatch
	{
		private static void Postfix(Userspace __instance)
		{
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0319: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: 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_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_0280: Unknown result type (might be due to invalid IL or missing references)
			//IL_0285: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: Unknown result type (might be due to invalid IL or missing references)
			//IL_0295: 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_0343: Unknown result type (might be due to invalid IL or missing references)
			//IL_0348: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_0398: 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_022f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d6: Expected O, but got Unknown
			//IL_03ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f1: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				InputInterface inputInterface = ((Worker)__instance).InputInterface;
				Key? key = null;
				if (inputInterface.GetKeyDown((Key)276))
				{
					key = (Key)276;
					pressedAt[(Key)276] = global::System.DateTime.Now;
				}
				else if (inputInterface.GetKeyDown((Key)275))
				{
					key = (Key)275;
				}
				else if (inputInterface.GetKeyDown((Key)273))
				{
					key = (Key)273;
				}
				else if (inputInterface.GetKeyDown((Key)274))
				{
					key = (Key)274;
				}
				else if (inputInterface.GetKey(EnterBind.Value))
				{
					key = (Key)13;
				}
				if (inputInterface.GetKeyDown((Key)275))
				{
					pressedAt[(Key)275] = global::System.DateTime.Now;
				}
				if (inputInterface.GetKeyDown((Key)273))
				{
					pressedAt[(Key)273] = global::System.DateTime.Now;
				}
				if (inputInterface.GetKeyDown((Key)274))
				{
					pressedAt[(Key)274] = global::System.DateTime.Now;
				}
				if (!key.HasValue)
				{
					TimeSpan val;
					if (HoldRateMinMS.Value != 0 && LastHoldTriger.HasValue)
					{
						val = global::System.DateTime.Now - LastHoldTriger.Value;
						if (!(((TimeSpan)(ref val)).TotalMilliseconds >= (double)HoldRateMinMS.Value))
						{
							goto IL_02d7;
						}
					}
					KeyValuePair<Key, global::System.DateTime>? val2 = null;
					KeyValuePair<Key, global::System.DateTime>? val3 = null;
					int value = HoldMilliseconds.Value;
					Enumerator<Key, global::System.DateTime> enumerator = pressedAt.GetEnumerator();
					try
					{
						while (enumerator.MoveNext())
						{
							KeyValuePair<Key, global::System.DateTime> current = enumerator.Current;
							if (!val3.HasValue)
							{
								val3 = current;
							}
							else if (current.Value.CompareTo(val3.Value.Value) > 0)
							{
								val3 = current;
							}
							if (inputInterface.GetKey(current.Key))
							{
								val = global::System.DateTime.Now - current.Value;
								if (((TimeSpan)(ref val)).TotalMilliseconds > (double)value && (!val2.HasValue || val2.Value.Value.CompareTo(current.Value) != 1))
								{
									val2 = current;
								}
							}
						}
					}
					finally
					{
						((global::System.IDisposable)enumerator).Dispose();
					}
					if (val2.HasValue && val2.Value.Key == val3.Value.Key)
					{
						key = val2.Value.Key;
						LastHoldTriger = global::System.DateTime.Now;
					}
					else
					{
						LastHoldTriger = null;
					}
				}
				goto IL_02d7;
				IL_02d7:
				if (!key.HasValue || Userspace.HasFocus)
				{
					return;
				}
				World focusedWorld = ((Worker)__instance).Engine.WorldManager.FocusedWorld;
				if (focusedWorld != null && FocusManagerExtensions.HasActiveFocus(focusedWorld.LocalUser))
				{
					return;
				}
				ControllerData controllerData = Userspace.GetControllerData(inputInterface.PrimaryHand);
				InteractionHandler tool = controllerData.userspaceController;
				bool flag = controllerData.userspaceLaserHitTarget;
				if (!flag && inputInterface.VR_Active)
				{
					ControllerData controllerData2 = Userspace.GetControllerData(GetOther(inputInterface.PrimaryHand));
					if (controllerData2.userspaceLaserHitTarget)
					{
						tool = controllerData2.userspaceController;
						flag = true;
					}
				}
				if (!flag)
				{
					World focusedWorld2 = ((Worker)__instance).Engine.WorldManager.FocusedWorld;
					UserRoot userRoot = ((focusedWorld2 != null) ? focusedWorld2.LocalUser.Root : null);
					InteractionHandler commonTool = GetCommonTool(userRoot, inputInterface.PrimaryHand);
					if (commonTool.Laser.CurrentInteractionTarget != null && typeof(Canvas).IsAssignableFrom(((object)commonTool.Laser.CurrentInteractionTarget).GetType()))
					{
						tool = commonTool;
					}
					else
					{
						if (!inputInterface.VR_Active)
						{
							return;
						}
						InteractionHandler commonTool2 = GetCommonTool(userRoot, GetOther(inputInterface.PrimaryHand));
						if (commonTool2.Laser.CurrentInteractionTarget == null || !typeof(Canvas).IsAssignableFrom(((object)commonTool2.Laser.CurrentInteractionTarget).GetType()))
						{
							return;
						}
						tool = commonTool2;
					}
				}
				Expander firstRoot = ((IComponent)tool.Laser.CurrentInteractionTarget).Slot.GetComponentInChildren<Expander>((Predicate<Expander>)null, false, false);
				Expander currentSelection = ((IComponent)tool.Laser.CurrentInteractionTarget).Slot.GetComponentInChildren<Expander>((Predicate<Expander>)((Expander e) => ((SyncField<bool>)(object)((InteractionElement)(((ContainerWorker<Component>)(object)((Component)e).Slot).GetComponent<Button>((Predicate<Button>)null, false)?)).IsHovering).Value ?? false), false, true) ?? firstRoot;
				if (currentSelection == null)
				{
					return;
				}
				((Worker)currentSelection).World.RunSynchronously((Action)delegate
				{
					//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_001d: Unknown result type (might be due to invalid IL or missing references)
					//IL_0021: Invalid comparison between Unknown and I4
					//IL_03d5: Unknown result type (might be due to invalid IL or missing references)
					//IL_03da: Unknown result type (might be due to invalid IL or missing references)
					//IL_03de: 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)
					//IL_0418: 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_002d: Unknown result type (might be due to invalid IL or missing references)
					//IL_0043: Expected I4, but got Unknown
					//IL_01fb: 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_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)
					if (key.HasValue)
					{
						Key valueOrDefault = key.GetValueOrDefault();
						if ((int)valueOrDefault != 13)
						{
							switch (valueOrDefault - 273)
							{
							case 3:
								if (currentSelection.SectionRoot.Target != null && currentSelection.IsExpanded)
								{
									currentSelection.IsExpanded = false;
								}
								else
								{
									Expander val8 = (PreferParent.Value ? parentExp(((Component)currentSelection).Slot) : null);
									if (val8 == null)
									{
										List<Expander> componentsInChildren3 = ((IComponent)tool.Laser.CurrentInteractionTarget).Slot.GetComponentsInChildren<Expander>((Predicate<Expander>)null, false, false, (Predicate<Slot>)null);
										int num3 = -1;
										List<Expander> val9 = new List<Expander>();
										Enumerator<Expander> enumerator2 = componentsInChildren3.GetEnumerator();
										try
										{
											while (enumerator2.MoveNext())
											{
												Expander current3 = enumerator2.Current;
												if (current3 == currentSelection)
												{
													num3 = val9.Count - 1;
												}
												else if (((Component)current3).Slot.IsActive && current3.SectionRoot.Target != null && current3.IsExpanded)
												{
													val9.Add(current3);
												}
											}
										}
										finally
										{
											((global::System.IDisposable)enumerator2).Dispose();
										}
										if (val9.Count > 0)
										{
											if (num3 < 0 && num3 + 1 < val9.Count)
											{
												num3++;
											}
											val8 = val9[num3];
										}
										else
										{
											val8 = currentSelection;
										}
									}
									if (val8 != null)
									{
										((SyncField<bool>)(object)((InteractionElement)((ContainerWorker<Component>)(object)((Component)currentSelection).Slot).GetComponent<Button>((Predicate<Button>)null, false)).IsHovering).Value = false;
										if (InstantAction.Value)
										{
											val8.IsExpanded = false;
										}
										((SyncField<bool>)(object)((InteractionElement)((ContainerWorker<Component>)(object)((Component)val8).Slot).GetComponent<Button>((Predicate<Button>)null, false)).IsHovering).Value = true;
									}
								}
								break;
							case 2:
								if (!currentSelection.IsExpanded)
								{
									currentSelection.IsExpanded = true;
								}
								else
								{
									List<Expander> componentsInChildren = ((IComponent)tool.Laser.CurrentInteractionTarget).Slot.GetComponentsInChildren<Expander>((Predicate<Expander>)null, false, false, (Predicate<Slot>)null);
									int num = -1;
									List<Expander> val5 = new List<Expander>();
									Enumerator<Expander> enumerator2 = componentsInChildren.GetEnumerator();
									try
									{
										while (enumerator2.MoveNext())
										{
											Expander current2 = enumerator2.Current;
											if (current2 == currentSelection)
											{
												num = val5.Count;
											}
											else if (((Component)current2).Slot.IsActive && current2.SectionRoot.Target != null && !current2.IsExpanded)
											{
												val5.Add(current2);
											}
										}
									}
									finally
									{
										((global::System.IDisposable)enumerator2).Dispose();
									}
									Expander val6 = null;
									if (val5.Count > 0)
									{
										if (num > val5.Count - 1 && num - 1 > -1)
										{
											num--;
										}
										val6 = val5[num];
									}
									else
									{
										val6 = currentSelection;
									}
									if (val6 != null)
									{
										((SyncField<bool>)(object)((InteractionElement)((ContainerWorker<Component>)(object)((Component)currentSelection).Slot).GetComponent<Button>((Predicate<Button>)null, false)).IsHovering).Value = false;
										if (InstantAction.Value)
										{
											val6.IsExpanded = true;
										}
										((SyncField<bool>)(object)((InteractionElement)((ContainerWorker<Component>)(object)((Component)val6).Slot).GetComponent<Button>((Predicate<Button>)null, false)).IsHovering).Value = true;
									}
								}
								break;
							case 0:
							{
								((SyncField<bool>)(object)((InteractionElement)((ContainerWorker<Component>)(object)((Component)currentSelection).Slot).GetComponent<Button>((Predicate<Button>)null, false)).IsHovering).Value = false;
								List<Expander> componentsInChildren2 = ((IComponent)tool.Laser.CurrentInteractionTarget).Slot.GetComponentsInChildren<Expander>((Predicate<Expander>)null, true, false, (Predicate<Slot>)null);
								int num2 = componentsInChildren2.IndexOf(currentSelection) - 1;
								if (num2 < 0)
								{
									num2 = componentsInChildren2.Count - 1;
								}
								Expander val7 = componentsInChildren2[num2];
								if (val7 != null)
								{
									((SyncField<bool>)(object)((InteractionElement)((ContainerWorker<Component>)(object)((Component)val7).Slot).GetComponent<Button>((Predicate<Button>)null, false)).IsHovering).Value = true;
								}
								break;
							}
							case 1:
							{
								((SyncField<bool>)(object)((InteractionElement)((ContainerWorker<Component>)(object)((Component)currentSelection).Slot).GetComponent<Button>((Predicate<Button>)null, false)).IsHovering).Value = false;
								Expander val4 = ArrowExpanders.searchAfter<Expander>(((Component)currentSelection).Slot) ?? firstRoot;
								if (val4 != null)
								{
									((SyncField<bool>)(object)((InteractionElement)((ContainerWorker<Component>)(object)((Component)val4).Slot).GetComponent<Button>((Predicate<Button>)null, false)).IsHovering).Value = true;
								}
								break;
							}
							}
						}
						else
						{
							Slot slot = ((Component)currentSelection).Slot;
							float3 zero = float3.Zero;
							float3 val10 = slot.LocalPointToGlobal(ref zero);
							float2 val11 = default(float2);
							((float2)(ref val11))..ctor(0.5f, 0.5f);
							ArrowExpanders.searchInParentsWithSiblings<Button>(((Component)currentSelection).Slot, (Predicate<Button>)null).SimulatePress(0.1f, new ButtonEventData((Component)(object)currentSelection, ref val10, ref val11, ref val11));
						}
					}
				}, false, (IUpdatable)null, false);
			}
			catch (global::System.Exception ex)
			{
				log.LogError((object)ex);
			}
		}
	}

	private static ConfigEntry<bool> PreferParent;

	private static ConfigEntry<bool> InstantAction;

	private static ConfigEntry<int> HoldMilliseconds;

	private static ConfigEntry<int> HoldRateMinMS;

	private static ConfigEntry<Key> EnterBind;

	private static ManualLogSource log;

	private static Dictionary<Key, global::System.DateTime> pressedAt = new Dictionary<Key, global::System.DateTime>();

	private static global::System.DateTime? LastHoldTriger;

	public override void Load()
	{
		PreferParent = ((BasePlugin)this).Config.Bind<bool>("ArrowExpanders", "PreferParentLeft", true, "only applies when the current expander is closed, when true the left arrow will prefer the parent of the current expander otherwise it will attempt to find the closest open expander");
		InstantAction = ((BasePlugin)this).Config.Bind<bool>("ArrowExpanders", "InstantAction", true, "when true if the left or right key are pressed and the selected expander is in it's target state then it will jump a new expander and run the keys action on that expander. when false it will only jump to the new expander but not preform an action till the action.");
		HoldMilliseconds = ((BasePlugin)this).Config.Bind<int>("ArrowExpanders", "HoldMilliseconds", 500, "number of milliseconds to wait before starting hold behavior");
		HoldRateMinMS = ((BasePlugin)this).Config.Bind<int>("ArrowExpanders", "HoldRateMinMS", 0, "minimum number of milliseconds between hold actions");
		EnterBind = ((BasePlugin)this).Config.Bind<Key>("ArrowExpanders", "EnterBind", (Key)13, "what key if any should trigger an attempt to press the closest button?");
		((BasePlugin)this).HarmonyInstance.PatchAll();
	}

	private static InteractionHandler GetCommonTool(UserRoot userRoot, Chirality side)
	{
		//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)
		return userRoot.GetRegisteredComponent<InteractionHandler>((Predicate<InteractionHandler>)((InteractionHandler t) => ((SyncField<Chirality>)(object)t.Side).Value == side));
	}

	private static Chirality GetOther(Chirality cur)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0002: Invalid comparison between Unknown and I4
		if ((int)cur == 1)
		{
			return (Chirality)0;
		}
		return (Chirality)1;
	}

	private static T searchBefore<T>(Slot cur) where T : Component
	{
		return searchBefore<T>(cur.Parent, cur.Parent.IndexOfChild(cur) - 1);
	}

	private static T searchBefore<T>(Slot root, int index) where T : Component
	{
		for (int num = index; num >= 0; num--)
		{
			T componentInChildren = root[num].GetComponentInChildren<T>((Predicate<T>)((T f) => ((Component)f).Slot.IsActive), false, false);
			if (componentInChildren != null)
			{
				return componentInChildren;
			}
		}
		if (root.Parent == ((Worker)root).World.RootSlot)
		{
			return default(T);
		}
		return searchBefore<T>(root);
	}

	private static T searchAfter<T>(Slot cur) where T : Component
	{
		return searchAfter<T>(cur.Parent, cur.Parent.IndexOfChild(cur) + 1);
	}

	private static T searchAfter<T>(Slot root, int index) where T : Component
	{
		for (int i = index; i < root.ChildrenCount; i++)
		{
			T componentInChildren = root[i].GetComponentInChildren<T>((Predicate<T>)((T f) => ((Component)f).Slot.IsActive), false, false);
			if (componentInChildren != null)
			{
				return componentInChildren;
			}
		}
		if (root.Parent == ((Worker)root).World.RootSlot)
		{
			return default(T);
		}
		return searchAfter<T>(root);
	}

	private static T searchInParentsWithSiblings<T>(Slot cur, Predicate<T> filter = null) where T : Component
	{
		return searchInParentsWithSiblings<T>(cur.Parent, cur, filter);
	}

	private static T searchInParentsWithSiblings<T>(Slot cur, Slot last, Predicate<T> filter = null) where T : Component
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: 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_000e: Unknown result type (might be due to invalid IL or missing references)
		Enumerator<Slot> enumerator = cur.Children.GetEnumerator();
		try
		{
			while (enumerator.MoveNext())
			{
				Slot current = enumerator.Current;
				if (current != last)
				{
					T componentInChildren = current.GetComponentInChildren<T>(filter, false, true);
					if (componentInChildren != null)
					{
						return componentInChildren;
					}
				}
			}
		}
		finally
		{
			((global::System.IDisposable)enumerator).Dispose();
		}
		if (last.Parent == ((Worker)last).World.RootSlot)
		{
			return default(T);
		}
		return searchInParentsWithSiblings<T>(cur, filter);
	}

	private static Expander parentExp(Slot cur)
	{
		Slot cur2 = cur;
		return searchInParentsWithSiblings<Expander>(cur2, (Predicate<Expander>)((Expander e) => cur2.IsChildOf(e.SectionRoot.Target ?? cur2, false) && ((Component)e).Slot.IsActive));
	}

	private static string parentString(Slot slot)
	{
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		Slot val = slot;
		string text = "";
		while (val.Parent != null)
		{
			string[] obj = new string[6] { text, "/", val.Name, "(", null, null };
			RefID referenceID = ((Worker)val).ReferenceID;
			obj[4] = ((object)(RefID)(ref referenceID)).ToString();
			obj[5] = ")";
			text = string.Concat(obj);
			val = val.Parent;
		}
		return text;
	}
}
public static class PluginMetadata
{
	public const string GUID = "net.eia485.ArrowExpanders";

	public const string NAME = "ArrowExpanders";

	public const string VERSION = "1.0.2";

	public const string AUTHORS = "eia485";

	public const string REPOSITORY_URL = "https://github.com/EIA485/NeosArrowExpanders";
}