using System; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using Microsoft.CodeAnalysis; using Pigeon.Movement; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Utilities; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("MycopunkModder")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyDescription("Always sprint by default - inverts the sprint input action")] [assembly: AssemblyFileVersion("1.3.0.0")] [assembly: AssemblyInformationalVersion("1.3.0.0")] [assembly: AssemblyProduct("AlwaysSprintMod")] [assembly: AssemblyTitle("AlwaysSprintMod")] [assembly: AssemblyVersion("1.3.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace AlwaysSprintMod { [BepInPlugin("coruscnium.alwayssprint", "AlwaysSprint", "1.4.0.0")] [BepInProcess("Mycopunk.exe")] [MycoMod(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { internal static ManualLogSource Logger; private static FieldInfo _isTryingToSprintField; private static FieldInfo _wantsToSprintField; private static bool _fieldsResolved; private static InputAction _sprintAction; private static InputAction _fireAction; private static bool _actionHooked; private static bool _walkToggled; private static bool _lastSprintButtonState; private static FieldInfo _gunDataField; private static FieldInfo _fireConstraintsField; private static FieldInfo _canFireWhileSprintingField; private static FieldInfo _gunOwnerField; private static object _canPerformDuringValue; private static bool _gunReflectionResolved; private static ConfigEntry _reSprintDelayMsConfig; private static bool _wasFiring; private static float _fireStoppedTime; private static FileSystemWatcher _configWatcher; private static volatile bool _pendingConfigReload; private void Awake() { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Expected O, but got Unknown Logger = ((BaseUnityPlugin)this).Logger; Logger.LogInfo((object)"AlwaysSprintMod loading..."); _reSprintDelayMsConfig = ((BaseUnityPlugin)this).Config.Bind("SprintSuppression", "ReSprintDelayMs", 300f, new ConfigDescription("Delay (ms) after releasing the fire button before sprint resumes.\nSet to 0 for instant re-sprint (v1.3 behavior).", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 1000f), Array.Empty())); ((BaseUnityPlugin)this).Config.Save(); _reSprintDelayMsConfig.SettingChanged += delegate { Logger.LogDebug((object)"ReSprintDelayMs config changed — applying immediately."); }; try { _configWatcher = new FileSystemWatcher(Paths.ConfigPath, "coruscnium.alwayssprint.cfg") { NotifyFilter = (NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite), EnableRaisingEvents = true }; _configWatcher.Changed += OnConfigFileChanged; _configWatcher.Created += OnConfigFileChanged; _configWatcher.Renamed += OnConfigFileChanged; Logger.LogInfo((object)"Config file watcher started."); } catch (Exception ex) { Logger.LogWarning((object)("Could not start config file watcher: " + ex.Message)); } ResolveFields(); ResolveGunReflection(); SceneManager.sceneLoaded += OnSceneLoaded; Logger.LogInfo((object)"AlwaysSprintMod initialized."); } private void OnConfigFileChanged(object sender, FileSystemEventArgs e) { _pendingConfigReload = true; } private void OnDestroy() { if (_configWatcher != null) { _configWatcher.EnableRaisingEvents = false; _configWatcher.Changed -= OnConfigFileChanged; _configWatcher.Created -= OnConfigFileChanged; _configWatcher.Renamed -= OnConfigFileChanged; _configWatcher.Dispose(); _configWatcher = null; } } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { _actionHooked = false; _sprintAction = null; _fireAction = null; _walkToggled = false; _lastSprintButtonState = false; _wasFiring = false; _fireStoppedTime = 0f; } private void Update() { if (_pendingConfigReload) { _pendingConfigReload = false; try { ((BaseUnityPlugin)this).Config.Reload(); Logger.LogInfo((object)"Config reloaded from disk."); } catch (Exception ex) { Logger.LogError((object)("Error reloading config: " + ex.Message)); } } if (!_fieldsResolved) { ResolveFields(); return; } if (!_actionHooked) { TryHookActions(); } Player localPlayer = Player.LocalPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } if (_sprintAction != null) { bool flag = false; try { flag = _sprintAction.IsPressed(); } catch { _sprintAction = null; return; } if (flag && !_lastSprintButtonState) { _walkToggled = !_walkToggled; } _lastSprintButtonState = flag; } bool flag2 = _fireAction != null && _fireAction.IsPressed(); if (!flag2 && _wasFiring) { _fireStoppedTime = Time.unscaledTime; } bool flag3; if (CheckCanFireWhileSprinting()) { flag3 = !_walkToggled; } else if (flag2) { flag3 = false; } else { float num = _reSprintDelayMsConfig.Value / 1000f; flag3 = !(Time.unscaledTime - _fireStoppedTime < num) && !_walkToggled; } if (_isTryingToSprintField != null) { _isTryingToSprintField.SetValue(localPlayer, flag3); } if (_wantsToSprintField != null) { _wantsToSprintField.SetValue(localPlayer, flag3); } _wasFiring = flag2; } private bool CheckCanFireWhileSprinting() { if (!_gunReflectionResolved || _gunDataField == null) { return false; } try { Player localPlayer = Player.LocalPlayer; if ((Object)(object)localPlayer == (Object)null) { return false; } Gun[] array = Object.FindObjectsOfType(); Gun[] array2 = array; foreach (Gun val in array2) { if ((Object)(object)val == (Object)null) { continue; } if (_gunOwnerField != null) { object value = _gunOwnerField.GetValue(val); Player val2 = (Player)((value is Player) ? value : null); if (val2 != null && (Object)(object)val2 != (Object)(object)localPlayer) { continue; } } object value2 = _gunDataField.GetValue(val); if (value2 == null) { continue; } object value3 = _fireConstraintsField.GetValue(value2); if (value3 != null) { object value4 = _canFireWhileSprintingField.GetValue(value3); if (value4 != null && value4.Equals(_canPerformDuringValue)) { return true; } } } } catch (Exception ex) { Logger.LogWarning((object)("CheckCanFireWhileSprinting error: " + ex.Message)); } return false; } private void ResolveFields() { Type typeFromHandle = typeof(Player); _isTryingToSprintField = typeFromHandle.GetField("isTryingToSprint", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _wantsToSprintField = typeFromHandle.GetField("wantsToSprint", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); Logger.LogInfo((object)$"AlwaysSprintMod - isTryingToSprint: {_isTryingToSprintField != null}"); Logger.LogInfo((object)$"AlwaysSprintMod - wantsToSprint: {_wantsToSprintField != null}"); _fieldsResolved = _isTryingToSprintField != null && _wantsToSprintField != null; if (_fieldsResolved) { Logger.LogInfo((object)"AlwaysSprintMod - fields resolved successfully."); } else { Logger.LogWarning((object)"AlwaysSprintMod - failed to resolve one or more sprint fields!"); } } private void ResolveGunReflection() { try { Type typeFromHandle = typeof(Gun); _gunDataField = typeFromHandle.GetField("gunData", BindingFlags.Instance | BindingFlags.NonPublic); if (_gunDataField == null) { Logger.LogWarning((object)"AlwaysSprintMod - gunData field not found on Gun."); return; } Type fieldType = _gunDataField.FieldType; _fireConstraintsField = fieldType.GetField("fireConstraints", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (_fireConstraintsField == null) { Logger.LogWarning((object)"AlwaysSprintMod - fireConstraints field not found on GunData."); return; } Type fieldType2 = _fireConstraintsField.FieldType; _canFireWhileSprintingField = fieldType2.GetField("canFireWhileSprinting", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (_canFireWhileSprintingField == null) { Logger.LogWarning((object)"AlwaysSprintMod - canFireWhileSprinting field not found on FireConstraints."); return; } Type fieldType3 = _canFireWhileSprintingField.FieldType; if (fieldType3.IsEnum) { _canPerformDuringValue = Enum.Parse(fieldType3, "CanPerformDuring"); _gunOwnerField = typeFromHandle.GetField("_owner", BindingFlags.Instance | BindingFlags.NonPublic) ?? typeFromHandle.GetField("owner", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? typeFromHandle.GetField("player", BindingFlags.Instance | BindingFlags.NonPublic) ?? typeFromHandle.GetField("_player", BindingFlags.Instance | BindingFlags.NonPublic) ?? typeFromHandle.GetField("m_Owner", BindingFlags.Instance | BindingFlags.NonPublic); if (_gunOwnerField != null && _gunOwnerField.FieldType != typeof(Player)) { Logger.LogWarning((object)("AlwaysSprintMod - gun owner field '" + _gunOwnerField.Name + "' is not Player type (got " + _gunOwnerField.FieldType.Name + "), will check all guns.")); _gunOwnerField = null; } _gunReflectionResolved = true; Logger.LogInfo((object)("AlwaysSprintMod - gun fire-constraint reflection resolved. Owner field: " + ((_gunOwnerField != null) ? _gunOwnerField.Name : "none (checks all guns)"))); } else { Logger.LogWarning((object)"AlwaysSprintMod - canFireWhileSprinting is not an enum type."); } } catch (Exception ex) { Logger.LogWarning((object)("AlwaysSprintMod - error resolving gun reflection: " + ex.Message)); _gunReflectionResolved = false; } } private void TryHookActions() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0022: 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) try { InputActionAsset[] array = Resources.FindObjectsOfTypeAll(); InputActionAsset[] array2 = array; foreach (InputActionAsset val in array2) { Enumerator enumerator = val.actionMaps.GetEnumerator(); try { while (enumerator.MoveNext()) { InputActionMap current = enumerator.Current; if (_sprintAction == null) { _sprintAction = current.FindAction("Sprint", false); if (_sprintAction != null) { _sprintAction.Enable(); Logger.LogInfo((object)("Hooked Sprint from '" + ((Object)val).name + "/" + current.name + "'")); } } if (_fireAction == null) { _fireAction = current.FindAction("Fire", false); if (_fireAction != null) { _fireAction.Enable(); Logger.LogInfo((object)("Hooked Fire from '" + ((Object)val).name + "/" + current.name + "'")); } } } } finally { ((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose(); } } if (_sprintAction != null && _fireAction != null) { _actionHooked = true; } } catch (Exception ex) { Logger.LogWarning((object)("Error hooking actions: " + ex.Message)); } } } }