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<string> _log;
private readonly Action<string> _warn;
private readonly Color _menuColor;
private MelonPreferences_Category _preferences;
private MelonPreferences_Entry<int> _comboModePreference;
private MelonPreferences_Entry<int> _actionModePreference;
private MelonPreferences_Entry<float> _holdDurationPreference;
private MelonPreferences_Entry<int> _tapAmountPreference;
private MelonPreferences_Entry<int> _firstButtonPreference;
private MelonPreferences_Entry<int> _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<string> log, Action<string> 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<string>)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<float>)([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<int>("ComboMode", (int)_comboMode, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
_actionModePreference = _preferences.CreateEntry<int>("ActionMode", (int)_actionMode, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
_holdDurationPreference = _preferences.CreateEntry<float>("HoldDuration", _holdDuration, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
_tapAmountPreference = _preferences.CreateEntry<int>("TapAmount", _tapAmount, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
_firstButtonPreference = _preferences.CreateEntry<int>("FirstButton", (int)_firstButton, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
_secondButtonPreference = _preferences.CreateEntry<int>("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
{
}
}
}
}