using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Threading.Tasks; using BepInEx; using BepInEx.Configuration; using BepInEx.Core.Logging.Interpolation; using BepInEx.Logging; using BepInEx.NET.Common; using BepInExResoniteShim; using Elements.Core; using FrooxEngine; using HarmonyLib; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(/*Could not decode attribute arguments.*/)] [assembly: TargetFramework(".NETCoreApp,Version=v10.0", FrameworkDisplayName = ".NET 10.0")] [assembly: AssemblyCompany("IHaveAName2653")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright (c) 2026 IHaveAName2653")] [assembly: AssemblyDescription("No Description Provided")] [assembly: AssemblyFileVersion("1.1.0.0")] [assembly: AssemblyInformationalVersion("1.1.0+2d1701ce2aa54dac539275e07d6abfbea8c248ef")] [assembly: AssemblyProduct("ResoniteInputControl")] [assembly: AssemblyTitle("ResoniteInputControl")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/Gyztor/BepisResoniteInputControl")] [assembly: AssemblyVersion("1.1.0.0")] [module: RefSafetyRules(11)] namespace ResoniteInputControl; public class NullInputNode(T defaultValue) : IInputNode, IInputNode where T : struct { private readonly T value = defaultValue; public T? Evaluate(in InputEvaluationContext context) { return value; } public void ResetNode() { } T? IInputNode.Evaluate(in InputEvaluationContext context) { return Evaluate(in context); } } [HarmonyPatch] public static class Patches { [CompilerGenerated] private sealed class <>c__DisplayClass14_0 { [StructLayout((LayoutKind)3)] private struct <b__1>d : IAsyncStateMachine { public int <>1__state; public AsyncTaskMethodBuilder <>t__builder; public <>c__DisplayClass14_0 <>4__this; private Updates <>u__1; private void MoveNext() { //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_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0020: 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) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) int num = <>1__state; <>c__DisplayClass14_0 <>c__DisplayClass14_ = <>4__this; try { if (num != 0) { goto IL_00b3; } Updates val = <>u__1; <>u__1 = default(Updates); num = (<>1__state = -1); goto IL_006e; IL_006e: ((Updates)(ref val)).GetResult(); bool flag = default(bool); if (!<>c__DisplayClass14_.manager.TryReadValue(<>c__DisplayClass14_.varName, ref flag)) { flag = true; } if (flag != <>c__DisplayClass14_.last) { <>c__DisplayClass14_.OnChange.Invoke(flag, ((Worker)<>c__DisplayClass14_.root).World); <>c__DisplayClass14_.last = flag; } goto IL_00b3; IL_00b3: if (!((ContainerWorker)(object)<>c__DisplayClass14_.root).IsDestroyed) { Updates val2 = new Updates(3); val = ((Updates)(ref val2)).GetAwaiter(); if (!((Updates)(ref val)).IsCompleted) { num = (<>1__state = 0); <>u__1 = val; ((AsyncTaskMethodBuilder)(ref <>t__builder)).AwaitOnCompletedb__1>d>(ref val, ref this); return; } goto IL_006e; } } catch (global::System.Exception exception) { <>1__state = -2; ((AsyncTaskMethodBuilder)(ref <>t__builder)).SetException(exception); return; } <>1__state = -2; ((AsyncTaskMethodBuilder)(ref <>t__builder)).SetResult(); } [DebuggerHidden] private void SetStateMachine(IAsyncStateMachine stateMachine) { ((AsyncTaskMethodBuilder)(ref <>t__builder)).SetStateMachine(stateMachine); } } public DynamicVariableSpace manager; public string varName; public bool last; public Action OnChange; public Slot root; [AsyncStateMachine(typeof(<b__1>d))] internal global::System.Threading.Tasks.Task b__1() { //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) <b__1>d <b__1>d = default(<b__1>d); <b__1>d.<>t__builder = AsyncTaskMethodBuilder.Create(); <b__1>d.<>4__this = this; <b__1>d.<>1__state = -1; ((AsyncTaskMethodBuilder)(ref <b__1>d.<>t__builder)).Start<<b__1>d>(ref <b__1>d); return ((AsyncTaskMethodBuilder)(ref <b__1>d.<>t__builder)).Task; } } private const string VariableBase = "User/InputControl.{0}.{1}"; private static World? currentWorld = null; private static NullInputNode nullJump = new NullInputNode(defaultValue: false); private static NullInputNode nullSpeed = new NullInputNode(0f); private static NullInputNode nullAxis = new NullInputNode(float2.Zero); public static Dictionary currentStates = new Dictionary(); public static List storedMoveData = new List(); public static List storedTurnData = new List(); public static List storedTurn3AxisData = new List(); public static List storedJumpData = new List(); [HarmonyPatch(typeof(DualControllerBindingGenerator), "BindLocomotionDirection")] [HarmonyPostfix] public static void FindControllerMoveInputPatch(VR_LocomotionDirection __result) { storedMoveData.Add(new MoveInputData { controller = __result, leftAxis = __result.LeftAxis, rightAxis = __result.RightAxis, leftSpeed = __result.LeftSpeed, rightSpeed = __result.RightSpeed }); } [HarmonyPatch(typeof(DualControllerBindingGenerator), "BindLocomotionTurn")] [HarmonyPostfix] public static void FindControllerTurnInputPatch(VR_LocomotionTurn __result) { storedTurnData.Add(new TurnInputData { controller = __result, leftAxis = ((VR_DualInputTurnBase)(object)__result).LeftAxis, rightAxis = ((VR_DualInputTurnBase)(object)__result).RightAxis }); } [HarmonyPatch(typeof(DualControllerBindingGenerator), "BindThreeAxisTurn")] [HarmonyPostfix] public static void FindControllerTurn3AxisInputPatch(VR_LocomotionThreeAxisTurn __result) { storedTurn3AxisData.Add(new Turn3AxisInputData { controller = __result, leftAxis = ((VR_DualInputTurnBase)(object)__result).LeftAxis, rightAxis = ((VR_DualInputTurnBase)(object)__result).RightAxis }); } [HarmonyPatch(typeof(DualControllerBindingGenerator), "BindJump")] [HarmonyPostfix] public static void FindControllerJumpInputPatch(AnyInput __result) { List> inputs = __result.Inputs; Func, bool> obj = delegate(IInputNode r) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown //IL_0021: Unknown result type (might be due to invalid IL or missing references) if (typeof(ControllerDigitalSource).IsAssignableFrom(((object)r).GetType())) { return false; } ControllerDigitalSource val4 = (ControllerDigitalSource)r; if ((int)((ControllerPropertySource)(object)val4).Side != 0) { return false; } return !(((DevicePropertySource)(object)val4).PropertyName != "Jump"); }; IInputNode obj2; if (__result.Inputs.Count < 1) { IInputNode val = nullJump; obj2 = val; } else { obj2 = __result.Inputs[0]; } IInputNode val2 = Enumerable.FirstOrDefault>((global::System.Collections.Generic.IEnumerable>)inputs, obj, obj2); List> inputs2 = __result.Inputs; Func, bool> obj3 = delegate(IInputNode r) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Invalid comparison between Unknown and I4 if (typeof(ControllerDigitalSource).IsAssignableFrom(((object)r).GetType())) { return false; } ControllerDigitalSource val4 = (ControllerDigitalSource)r; if ((int)((ControllerPropertySource)(object)val4).Side != 1) { return false; } return !(((DevicePropertySource)(object)val4).PropertyName != "Jump"); }; IInputNode obj4; if (__result.Inputs.Count < 2) { IInputNode val = nullJump; obj4 = val; } else { obj4 = __result.Inputs[1]; } IInputNode val3 = Enumerable.FirstOrDefault>((global::System.Collections.Generic.IEnumerable>)inputs2, obj3, obj4); storedJumpData.Add(new JumpInputData { controller = __result, LeftButton = val2, RightButton = val3, LeftIndex = __result.Inputs.IndexOf(val2), RightIndex = __result.Inputs.IndexOf(val3) }); } private static void InitReadVariable(Slot root, string VariableName, Action OnChange) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown <>c__DisplayClass14_0 CS$<>8__locals10 = new <>c__DisplayClass14_0(); CS$<>8__locals10.OnChange = OnChange; CS$<>8__locals10.root = root; string text = default(string); DynamicVariableHelper.ParsePath(VariableName, ref text, ref CS$<>8__locals10.varName); CS$<>8__locals10.manager = ((ContainerWorker)(object)CS$<>8__locals10.root).GetComponent((Predicate)((DynamicVariableSpace x) => ((SyncField)(object)x.SpaceName).Value == "User"), false); ManualLogSource log = ResoniteInputControl.Log; bool flag = default(bool); BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(21, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Space Manager on "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(VariableName); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" is "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(CS$<>8__locals10.manager); } log.LogWarning(val); CS$<>8__locals10.last = true; if (ResoniteInputControl.GenerateDynamicVarsOnUser.Value) { DynamicValueVariable obj = ((ContainerWorker)(object)CS$<>8__locals10.root).AttachComponent>(true, (Action>)null); ((ComponentBase)(object)obj).Persistent = false; ((SyncField)(object)((DynamicVariableBase)(object)obj).VariableName).Value = VariableName; ((SyncField)(object)obj.Value).Value = true; } ((Worker)CS$<>8__locals10.root).StartTask((Func)([AsyncStateMachine(typeof(<>c__DisplayClass14_0.<b__1>d))] () => { //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) <>c__DisplayClass14_0.<b__1>d <b__1>d = default(<>c__DisplayClass14_0.<b__1>d); <b__1>d.<>t__builder = AsyncTaskMethodBuilder.Create(); <b__1>d.<>4__this = CS$<>8__locals10; <b__1>d.<>1__state = -1; ((AsyncTaskMethodBuilder)(ref <b__1>d.<>t__builder)).Start<<>c__DisplayClass14_0.<b__1>d>(ref <b__1>d); return ((AsyncTaskMethodBuilder)(ref <b__1>d.<>t__builder)).Task; })); } [HarmonyPostfix] [HarmonyPatch(typeof(UserRoot), "OnStart")] public static void OnUserRootInitialize(UserRoot __instance) { if (!ResoniteInputControl.shouldBeActive.Value || __instance != ((Worker)__instance).LocalUserRoot) { return; } World world = ((Worker)__instance).World; if (!WorldExtensions.IsUserspace(world)) { Slot slot = ((Component)__instance).Slot; if (ResoniteInputControl.AddMovementVars.Value) { InitReadVariable(slot, string.Format("User/InputControl.{0}.{1}", (object)"Left", (object)"Move"), LeftMoveChangedEvent); InitReadVariable(slot, string.Format("User/InputControl.{0}.{1}", (object)"Right", (object)"Move"), RightMoveChangedEvent); } if (ResoniteInputControl.AddRotationVars.Value) { InitReadVariable(slot, string.Format("User/InputControl.{0}.{1}", (object)"Left", (object)"Turn"), LeftTurnChangedEvent); InitReadVariable(slot, string.Format("User/InputControl.{0}.{1}", (object)"Right", (object)"Turn"), RightTurnChangedEvent); } if (ResoniteInputControl.AddJumpVars.Value) { InitReadVariable(slot, string.Format("User/InputControl.{0}.{1}", (object)"Left", (object)"Jump"), LeftJumpChangedEvent); InitReadVariable(slot, string.Format("User/InputControl.{0}.{1}", (object)"Right", (object)"Jump"), RightJumpChangedEvent); } UpdateForWorld(world); } } [HarmonyPostfix] [HarmonyPatch(typeof(WorldManager), "FocusWorld")] public static void OnWorldFocus(World world) { UpdateForWorld(world); } public static void LeftMoveChangedEvent(bool value, World world) { StateData stateData = default(StateData); if (!currentStates.TryGetValue(world, ref stateData)) { stateData = new StateData(); } stateData.Left.Move = value; if (currentStates.ContainsKey(world)) { currentStates[world] = stateData; } else { currentStates.Add(world, stateData); } RegisterControllerModifications(); } public static void RightMoveChangedEvent(bool value, World world) { StateData stateData = default(StateData); if (!currentStates.TryGetValue(world, ref stateData)) { stateData = new StateData(); } stateData.Right.Move = value; if (currentStates.ContainsKey(world)) { currentStates[world] = stateData; } else { currentStates.Add(world, stateData); } RegisterControllerModifications(); } public static void LeftTurnChangedEvent(bool value, World world) { StateData stateData = default(StateData); if (!currentStates.TryGetValue(world, ref stateData)) { stateData = new StateData(); } stateData.Left.Turn = value; if (currentStates.ContainsKey(world)) { currentStates[world] = stateData; } else { currentStates.Add(world, stateData); } RegisterControllerModifications(); } public static void RightTurnChangedEvent(bool value, World world) { StateData stateData = default(StateData); if (!currentStates.TryGetValue(world, ref stateData)) { stateData = new StateData(); } stateData.Right.Turn = value; if (currentStates.ContainsKey(world)) { currentStates[world] = stateData; } else { currentStates.Add(world, stateData); } RegisterControllerModifications(); } public static void LeftJumpChangedEvent(bool value, World world) { StateData stateData = default(StateData); if (!currentStates.TryGetValue(world, ref stateData)) { stateData = new StateData(); } stateData.Left.Jump = value; if (currentStates.ContainsKey(world)) { currentStates[world] = stateData; } else { currentStates.Add(world, stateData); } RegisterControllerModifications(); } public static void RightJumpChangedEvent(bool value, World world) { StateData stateData = default(StateData); if (!currentStates.TryGetValue(world, ref stateData)) { stateData = new StateData(); } stateData.Right.Jump = value; if (currentStates.ContainsKey(world)) { currentStates[world] = stateData; } else { currentStates.Add(world, stateData); } RegisterControllerModifications(); } public static void RegisterControllerModifications() { if (currentWorld == null || !currentWorld.LocalUser.VR_Active) { return; } StateData vals = default(StateData); if (!currentStates.TryGetValue(currentWorld, ref vals)) { vals = new StateData(); } if (ResoniteInputControl.AddMovementVars.Value) { storedMoveData.ForEach((Action)delegate(MoveInputData v) { VR_LocomotionDirection controller = v.controller; IInputNode leftAxis; if (!vals.Left.Move) { IInputNode val = nullAxis; leftAxis = val; } else { leftAxis = v.leftAxis; } controller.LeftAxis = leftAxis; IInputNode leftSpeed; if (!vals.Left.Move) { IInputNode val2 = nullSpeed; leftSpeed = val2; } else { leftSpeed = v.leftSpeed; } controller.LeftSpeed = leftSpeed; IInputNode rightAxis; if (!vals.Right.Move) { IInputNode val = nullAxis; rightAxis = val; } else { rightAxis = v.rightAxis; } controller.RightAxis = rightAxis; IInputNode rightSpeed; if (!vals.Right.Move) { IInputNode val2 = nullSpeed; rightSpeed = val2; } else { rightSpeed = v.rightSpeed; } controller.RightSpeed = rightSpeed; }); } if (ResoniteInputControl.AddRotationVars.Value) { storedTurnData.ForEach((Action)delegate(TurnInputData v) { VR_LocomotionTurn controller = v.controller; IInputNode leftAxis; if (!vals.Left.Turn) { IInputNode val = nullAxis; leftAxis = val; } else { leftAxis = v.leftAxis; } ((VR_DualInputTurnBase)(object)controller).LeftAxis = leftAxis; IInputNode rightAxis; if (!vals.Right.Turn) { IInputNode val = nullAxis; rightAxis = val; } else { rightAxis = v.rightAxis; } ((VR_DualInputTurnBase)(object)controller).RightAxis = rightAxis; }); storedTurn3AxisData.ForEach((Action)delegate(Turn3AxisInputData v) { VR_LocomotionThreeAxisTurn controller = v.controller; IInputNode leftAxis; if (!vals.Left.Turn) { IInputNode val = nullAxis; leftAxis = val; } else { leftAxis = v.leftAxis; } ((VR_DualInputTurnBase)(object)controller).LeftAxis = leftAxis; IInputNode rightAxis; if (!vals.Right.Turn) { IInputNode val = nullAxis; rightAxis = val; } else { rightAxis = v.rightAxis; } ((VR_DualInputTurnBase)(object)controller).RightAxis = rightAxis; }); } if (!ResoniteInputControl.AddJumpVars.Value) { return; } storedJumpData.ForEach((Action)delegate(JumpInputData v) { AnyInput controller = v.controller; List> inputs = controller.Inputs; int leftIndex = v.LeftIndex; IInputNode obj; if (!vals.Left.Jump) { IInputNode val = nullJump; obj = val; } else { obj = v.LeftButton; } inputs[leftIndex] = obj; List> inputs2 = controller.Inputs; int rightIndex = v.RightIndex; IInputNode obj2; if (!vals.Right.Jump) { IInputNode val = nullJump; obj2 = val; } else { obj2 = v.RightButton; } inputs2[rightIndex] = obj2; }); } public static void UpdateForWorld(World world) { if (ResoniteInputControl.shouldBeActive.Value) { currentWorld = world; RegisterControllerModifications(); } } } [ResonitePlugin("com.IHaveAName2653.ResoniteInputControl", "ResoniteInputControl", "1.1.0", "IHaveAName2653", "https://github.com/Gyztor/BepisResoniteInputControl")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class ResoniteInputControl : BasePlugin { internal static ManualLogSource Log; internal static ConfigEntry shouldBeActive; internal static ConfigEntry GenerateDynamicVarsOnUser; internal static ConfigEntry AddMovementVars; internal static ConfigEntry AddRotationVars; internal static ConfigEntry AddJumpVars; public override void Load() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Expected O, but got Unknown //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Expected O, but got Unknown //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Expected O, but got Unknown //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Expected O, but got Unknown Log = ((BasePlugin)this).Log; shouldBeActive = ((BasePlugin)this).Config.Bind("General", "Enabled", true, new ConfigDescription("Enables the mod.", (AcceptableValueBase)null, global::System.Array.Empty())); GenerateDynamicVarsOnUser = ((BasePlugin)this).Config.Bind("General", "Generate Variables", true, new ConfigDescription("Generates the needed Dyanmic Variables on User Root. If this is off it will instead attempt to find the component with the correct space name and subscribe to that.", (AcceptableValueBase)null, global::System.Array.Empty())); AddMovementVars = ((BasePlugin)this).Config.Bind("Variable Toggles", "Position Variables", true, new ConfigDescription("Enables if it actually cares about checking for the variable for movement.", (AcceptableValueBase)null, global::System.Array.Empty())); AddRotationVars = ((BasePlugin)this).Config.Bind("Variable Toggles", "Rotation Variables", true, new ConfigDescription("Enables if it actually cares about checking for the variable for rotation.", (AcceptableValueBase)null, global::System.Array.Empty())); AddJumpVars = ((BasePlugin)this).Config.Bind("Variable Toggles", "Jump Variables", true, new ConfigDescription("Enables if it actually cares about checking for the variable for jumping.", (AcceptableValueBase)null, global::System.Array.Empty())); try { ((BasePlugin)this).HarmonyInstance.PatchAll(); Log.LogInfo((object)"Resonite Input Control has successfully loaded!"); } catch (global::System.Exception ex) { ManualLogSource log = Log; bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(40, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Resonite Input Control failed to patch: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(ex); } log.LogError(val); } } } public struct MoveInputData { public VR_LocomotionDirection controller; public IInputNode leftAxis; public IInputNode rightAxis; public IInputNode leftSpeed; public IInputNode rightSpeed; } public struct TurnInputData { public VR_LocomotionTurn controller; public IInputNode leftAxis; public IInputNode rightAxis; } public struct Turn3AxisInputData { public VR_LocomotionThreeAxisTurn controller; public IInputNode leftAxis; public IInputNode rightAxis; } public struct JumpInputData { public AnyInput controller; public IInputNode LeftButton; public IInputNode RightButton; public int LeftIndex; public int RightIndex; } public struct ControllerState { public bool Move; public bool Turn; public bool Jump; public ControllerState(bool move = true, bool turn = true, bool jump = true) { Move = move; Turn = turn; Jump = jump; } } public struct StateData { public ControllerState Left; public ControllerState Right; public StateData() { Left = new ControllerState(move: true, turn: true, jump: true); Right = new ControllerState(move: true, turn: true, jump: true); } } public static class PluginMetadata { public const string GUID = "com.IHaveAName2653.ResoniteInputControl"; public const string NAME = "ResoniteInputControl"; public const string VERSION = "1.1.0"; public const string AUTHORS = "IHaveAName2653"; public const string REPOSITORY_URL = "https://github.com/Gyztor/BepisResoniteInputControl"; }