using System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BoneLib; using BoneLib.BoneMenu; using BonemenuRefreshShared; using BonemenuRefreshStandalone; using Il2CppSLZ.Marrow; using MelonLoader; using MelonLoader.Preferences; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(/*Could not decode attribute arguments.*/)] [assembly: MelonInfo(typeof(BonemenuRefreshMod), "Bonemenu Refresh", "1.0.0", "Codex", null)] [assembly: TargetFramework(".NETCoreApp,Version=v8.0", FrameworkDisplayName = ".NET 8.0")] [assembly: AssemblyCompany("BonemenuRefresh")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("BonemenuRefresh")] [assembly: AssemblyTitle("BonemenuRefresh")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace BonemenuRefreshStandalone { public sealed class BonemenuRefreshMod : MelonMod { private static readonly Color MenuColor = Color.cyan; private BonemenuRefreshCore _refreshCore; public override void OnLateInitializeMelon() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) _refreshCore = new BonemenuRefreshCore(((MelonBase)this).LoggerInstance.Msg, ((MelonBase)this).LoggerInstance.Warning, MenuColor); _refreshCore.Initialize(); if (Page.Root == null) { Menu.Initialize(); } _refreshCore.CreateMenu(Page.Root); ((MelonBase)this).LoggerInstance.Msg("Bonemenu Refresh loaded."); } public override void OnUpdate() { _refreshCore?.OnUpdate(); } } } namespace BonemenuRefreshShared { public sealed class BonemenuRefreshCore { private enum ComboMode { Double, Single } private enum ActionMode { Hold, Tap } private enum RefreshButton { LeftThumbstick, RightThumbstick, Y, B } private const string PreferenceCategory = "BonemenuRefresh"; private const float TapWindowSeconds = 1.25f; private const float ResetCooldownSeconds = 1f; private readonly Action _log; private readonly Action _warn; private readonly Color _menuColor; private MelonPreferences_Category _preferences; private MelonPreferences_Entry _comboModePreference; private MelonPreferences_Entry _actionModePreference; private MelonPreferences_Entry _holdDurationPreference; private MelonPreferences_Entry _tapAmountPreference; private MelonPreferences_Entry _firstButtonPreference; private MelonPreferences_Entry _secondButtonPreference; private FunctionElement _comboModeElement; private FunctionElement _actionModeElement; private FunctionElement _tapAmountElement; private FunctionElement _firstButtonElement; private FunctionElement _secondButtonElement; private ComboMode _comboMode; private ActionMode _actionMode; private float _holdDuration = 5f; private int _tapAmount = 1; private RefreshButton _firstButton; private RefreshButton _secondButton = RefreshButton.RightThumbstick; private float _holdTimer; private int _tapCount; private float _tapWindowEnd; private float _nextResetTime; private bool _createdPreferences; public BonemenuRefreshCore(Action log, Action warn, Color? menuColor = null) { //IL_006f: 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_0074: Unknown result type (might be due to invalid IL or missing references) _log = log ?? ((Action)delegate { }); _warn = warn ?? _log; _menuColor = (Color)(((??)menuColor) ?? Color.cyan); } public void Initialize() { CreatePreferences(); } public void CreateMenu(Page parent) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0044: 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_005a: Expected O, but got Unknown //IL_0064: 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_007a: Expected O, but got Unknown //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Expected O, but got Unknown //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Expected O, but got Unknown //IL_0103: 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_0119: Expected O, but got Unknown //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Expected O, but got Unknown CreatePreferences(); if (parent == null) { EnsureMenuInitialized(); parent = Page.Root; } if (parent == null) { _warn.Invoke("Bonemenu refresh: BoneMenu root was not ready; settings page was not created."); return; } Page val = parent.CreatePage("Bonemenu refresh", _menuColor, 0, true); val.CreateFunction("Reset now", _menuColor, new Action(ForceReset)); _comboModeElement = val.CreateFunction(GetComboModeLabel(), _menuColor, new Action(CycleComboMode)); _actionModeElement = val.CreateFunction(GetActionModeLabel(), _menuColor, new Action(CycleActionMode)); val.CreateFloat("Hold duration", _menuColor, _holdDuration, 0.5f, 1f, 15f, (Action)([CompilerGenerated] (float value) => { _holdDuration = Mathf.Clamp(value, 1f, 15f); _holdDurationPreference.Value = _holdDuration; SavePreferences(); })); _tapAmountElement = val.CreateFunction(GetTapAmountLabel(), _menuColor, new Action(CycleTapAmount)); _firstButtonElement = val.CreateFunction(GetFirstButtonLabel(), _menuColor, new Action(CycleFirstButton)); _secondButtonElement = val.CreateFunction(GetSecondButtonLabel(), _menuColor, new Action(CycleSecondButton)); } public void OnUpdate() { if (Input.GetKeyDown((KeyCode)286)) { ForceReset(); return; } BaseController leftController = Player.LeftController; BaseController rightController = Player.RightController; if ((Object)(object)leftController == (Object)null || (Object)(object)rightController == (Object)null) { ResetInputState(); } else if (_actionMode == ActionMode.Hold) { UpdateHoldInput(leftController, rightController); } else { UpdateTapInput(leftController, rightController); } } public void ForceReset() { if (Time.time < _nextResetTime) { return; } _nextResetTime = Time.time + 1f; ResetInputState(); try { EnsureMenuInitialized(); Page root = Page.Root; if (root == null) { _warn.Invoke("Bonemenu refresh: reset skipped because BoneMenu root is not ready."); return; } TrySetCurrentPage(root); TryInvokeStaticMenuMethod("OpenPage", root); Menu.OpenPage(root); TrySetCurrentPage(root); _log.Invoke("Bonemenu refresh: reset to root."); } catch (global::System.Exception ex) { _warn.Invoke("Bonemenu refresh: reset failed safely: " + ex.Message); } } private void CreatePreferences() { if (!_createdPreferences) { _preferences = MelonPreferences.CreateCategory("BonemenuRefresh", "Bonemenu Refresh"); _comboModePreference = _preferences.CreateEntry("ComboMode", (int)_comboMode, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); _actionModePreference = _preferences.CreateEntry("ActionMode", (int)_actionMode, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); _holdDurationPreference = _preferences.CreateEntry("HoldDuration", _holdDuration, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); _tapAmountPreference = _preferences.CreateEntry("TapAmount", _tapAmount, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); _firstButtonPreference = _preferences.CreateEntry("FirstButton", (int)_firstButton, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); _secondButtonPreference = _preferences.CreateEntry("SecondButton", (int)_secondButton, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); _comboMode = ClampComboMode(_comboModePreference.Value); _actionMode = ClampActionMode(_actionModePreference.Value); _holdDuration = Mathf.Clamp(_holdDurationPreference.Value, 1f, 15f); _tapAmount = Mathf.Clamp(_tapAmountPreference.Value, 1, 5); _firstButton = ClampRefreshButton(_firstButtonPreference.Value); _secondButton = ClampRefreshButton(_secondButtonPreference.Value); _createdPreferences = true; } } private void UpdateHoldInput(BaseController left, BaseController right) { if (!IsComboHeld(left, right)) { _holdTimer = 0f; return; } _holdTimer += Time.deltaTime; if (_holdTimer >= _holdDuration) { ForceReset(); } } private void UpdateTapInput(BaseController left, BaseController right) { if (!IsComboPressedThisFrame(left, right)) { if (Time.time > _tapWindowEnd) { _tapCount = 0; } return; } if (Time.time > _tapWindowEnd) { _tapCount = 0; _tapWindowEnd = Time.time + 1.25f; } _tapCount++; if (_tapCount >= _tapAmount) { ForceReset(); } } private bool IsComboHeld(BaseController left, BaseController right) { if (!IsButtonHeld(_firstButton, left, right)) { return false; } if (_comboMode != ComboMode.Single) { return IsButtonHeld(_secondButton, left, right); } return true; } private bool IsComboPressedThisFrame(BaseController left, BaseController right) { if (_comboMode == ComboMode.Single) { return IsButtonDown(_firstButton, left, right); } bool num = IsButtonHeld(_firstButton, left, right); bool flag = IsButtonHeld(_secondButton, left, right); if (!num || !flag) { return false; } if (!IsButtonDown(_firstButton, left, right)) { return IsButtonDown(_secondButton, left, right); } return true; } private static bool IsButtonDown(RefreshButton button, BaseController left, BaseController right) { return button switch { RefreshButton.RightThumbstick => InvokeBool(right, "GetThumbStickDown", "GetThumbstickDown", "GetThumbStickButtonDown"), RefreshButton.Y => InvokeBool(left, "GetBButtonDown", "GetYButtonDown"), RefreshButton.B => InvokeBool(right, "GetBButtonDown"), _ => InvokeBool(left, "GetThumbStickDown", "GetThumbstickDown", "GetThumbStickButtonDown"), }; } private static bool IsButtonHeld(RefreshButton button, BaseController left, BaseController right) { return button switch { RefreshButton.RightThumbstick => InvokeBool(right, "GetThumbStick", "GetThumbstick", "GetThumbStickButton"), RefreshButton.Y => InvokeBool(left, "GetBButton", "GetYButton"), RefreshButton.B => InvokeBool(right, "GetBButton"), _ => InvokeBool(left, "GetThumbStick", "GetThumbstick", "GetThumbStickButton"), }; } private static bool InvokeBool(object target, params string[] methodNames) { if (target == null) { return false; } global::System.Type type = target.GetType(); foreach (string text in methodNames) { MethodInfo method = type.GetMethod(text, (BindingFlags)52); if (!(method == (MethodInfo)null) && ((MethodBase)method).GetParameters().Length == 0) { object obj = ((MethodBase)method).Invoke(target, (object[])null); if (obj is bool) { return (bool)obj; } } } return false; } private static void EnsureMenuInitialized() { if (Page.Root == null) { Menu.Initialize(); } } private static void TrySetCurrentPage(Page root) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown global::System.Type pageType = typeof(Page); Try((Action)delegate { PropertyInfo property = pageType.GetProperty("CurrentPage", (BindingFlags)56); if (property != null) { property.SetValue((object)null, (object)root); } }); Try((Action)delegate { FieldInfo field = pageType.GetField("_currentPage", (BindingFlags)56); if (field != null) { field.SetValue((object)null, (object)root); } }); } private static void TryInvokeStaticMenuMethod(string methodName, Page root) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown Try((Action)delegate { MethodInfo method = typeof(Menu).GetMethod(methodName, (BindingFlags)56, (Binder)null, new global::System.Type[1] { typeof(Page) }, (ParameterModifier[])null); if (method != null) { ((MethodBase)method).Invoke((object)null, new object[1] { root }); } }); } private void CycleComboMode() { _comboMode = ((_comboMode == ComboMode.Double) ? ComboMode.Single : ComboMode.Double); _comboModePreference.Value = (int)_comboMode; SavePreferences(); ResetInputState(); UpdateLabels(); } private void CycleActionMode() { _actionMode = ((_actionMode == ActionMode.Hold) ? ActionMode.Tap : ActionMode.Hold); _actionModePreference.Value = (int)_actionMode; SavePreferences(); ResetInputState(); UpdateLabels(); } private void CycleTapAmount() { _tapAmount++; if (_tapAmount > 5) { _tapAmount = 1; } _tapAmountPreference.Value = _tapAmount; SavePreferences(); ResetInputState(); UpdateLabels(); } private void CycleFirstButton() { _firstButton = NextButton(_firstButton); _firstButtonPreference.Value = (int)_firstButton; SavePreferences(); ResetInputState(); UpdateLabels(); } private void CycleSecondButton() { _secondButton = NextButton(_secondButton); _secondButtonPreference.Value = (int)_secondButton; SavePreferences(); ResetInputState(); UpdateLabels(); } private void UpdateLabels() { SetElementName(_comboModeElement, GetComboModeLabel()); SetElementName(_actionModeElement, GetActionModeLabel()); SetElementName(_tapAmountElement, GetTapAmountLabel()); SetElementName(_firstButtonElement, GetFirstButtonLabel()); SetElementName(_secondButtonElement, GetSecondButtonLabel()); } private string GetComboModeLabel() { return "Keybind mode: " + ((_comboMode == ComboMode.Double) ? "Double" : "Single"); } private string GetActionModeLabel() { return "Action mode: " + ((_actionMode == ActionMode.Hold) ? "Hold" : "Tap"); } private string GetTapAmountLabel() { return $"Tap amount: {_tapAmount}"; } private string GetFirstButtonLabel() { return "First keybind: " + GetButtonName(_firstButton); } private string GetSecondButtonLabel() { return "Second keybind: " + GetButtonName(_secondButton); } private static string GetButtonName(RefreshButton button) { return button switch { RefreshButton.RightThumbstick => "right thumbstick press", RefreshButton.Y => "Y", RefreshButton.B => "B", _ => "left thumbstick press", }; } private static RefreshButton NextButton(RefreshButton button) { return button switch { RefreshButton.LeftThumbstick => RefreshButton.RightThumbstick, RefreshButton.RightThumbstick => RefreshButton.Y, RefreshButton.Y => RefreshButton.B, _ => RefreshButton.LeftThumbstick, }; } private static ComboMode ClampComboMode(int value) { if (value != 1) { return ComboMode.Double; } return ComboMode.Single; } private static ActionMode ClampActionMode(int value) { if (value != 1) { return ActionMode.Hold; } return ActionMode.Tap; } private static RefreshButton ClampRefreshButton(int value) { if (value < 0 || value > 3) { return RefreshButton.LeftThumbstick; } return (RefreshButton)value; } private static void SavePreferences() { MelonPreferences.Save(); } private void ResetInputState() { _holdTimer = 0f; _tapCount = 0; _tapWindowEnd = 0f; } private static void SetElementName(FunctionElement element, string name) { if (element != null) { ((Element)element).ElementName = name; } } private static void Try(Action action) { try { action.Invoke(); } catch { } } } }