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<float> _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<float>("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<float>(0f, 1000f), Array.Empty<object>()));
((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>();
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>();
InputActionAsset[] array2 = array;
foreach (InputActionAsset val in array2)
{
Enumerator<InputActionMap> 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));
}
}
}
}