using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BetterJump;
using BetterJump.Config;
using BetterJump.Runtime;
using HarmonyLib;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using Mimic.Actors;
using MimicAPI.GameAPI;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(Core), "BetterJump", "1.3.0", "DooDesch", null)]
[assembly: MelonGame("ReLUGames", "MIMESIS")]
[assembly: MelonOptionalDependencies(new string[] { "MimicAPI" })]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("BetterJump")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.3.0.0")]
[assembly: AssemblyInformationalVersion("1.3.0+c8a6c3c7b4df01573a14fbcab17c58ef3306f53a")]
[assembly: AssemblyProduct("BetterJump")]
[assembly: AssemblyTitle("BetterJump")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.3.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.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 BetterJump
{
public sealed class Core : MelonMod
{
public override void OnInitializeMelon()
{
BetterJumpPreferences.Initialize();
((MelonBase)this).HarmonyInstance.PatchAll();
MelonLogger.Msg("BetterJump initialized. JumpVelocity={0:F2}, ForceUngroundTime={1:F2}", new object[2]
{
BetterJumpPreferences.JumpVelocity,
BetterJumpPreferences.ForceUngroundTime
});
}
}
}
namespace BetterJump.Patches
{
[HarmonyPatch(typeof(FakeJumper), "StartJump")]
internal static class FakeJumperPatches
{
private static void Postfix(FakeJumper __instance)
{
JumpRuntimeState.OnJumpStarted(__instance);
}
}
[HarmonyPatch(typeof(ProtoActor), "CheckGrounded")]
internal static class ProtoActorGroundedPatch
{
private static void Postfix(ProtoActor __instance)
{
JumpRuntimeState.OnGroundCheck(__instance);
}
}
[HarmonyPatch(typeof(ProtoActor), "OnDestroy")]
internal static class ProtoActorDestroyPatch
{
private static void Postfix(ProtoActor __instance)
{
JumpRuntimeState.OnActorDestroyed(__instance);
}
}
}
namespace BetterJump.Runtime
{
internal static class JumpRuntimeState
{
private sealed class ActorState
{
public float ForceUngroundUntil;
}
private static readonly Dictionary<ProtoActor, ActorState> States = new Dictionary<ProtoActor, ActorState>();
internal static void OnJumpStarted(FakeJumper fakeJumper)
{
if (!BetterJumpPreferences.Enabled || fakeJumper == null)
{
return;
}
ProtoActor fieldValue = ReflectionHelper.GetFieldValue<ProtoActor>((object)fakeJumper, "owner");
if (!((Object)(object)fieldValue == (Object)null) && fieldValue.AmIAvatar() && GetGrounded(fieldValue))
{
SetFalling(fieldValue, BetterJumpPreferences.JumpVelocity);
SetGrounded(fieldValue, value: false);
if (!States.TryGetValue(fieldValue, out var value) || value == null)
{
value = new ActorState();
States[fieldValue] = value;
}
value.ForceUngroundUntil = Time.time + Mathf.Max(0.02f, BetterJumpPreferences.ForceUngroundTime);
}
}
internal static void OnGroundCheck(ProtoActor actor)
{
if (BetterJumpPreferences.Enabled && States.TryGetValue(actor, out var value))
{
if (Time.time < value.ForceUngroundUntil)
{
SetGrounded(actor, value: false);
}
else
{
States.Remove(actor);
}
}
}
internal static void OnActorDestroyed(ProtoActor actor)
{
States.Remove(actor);
}
private static bool GetGrounded(ProtoActor actor)
{
object propertyValue = ReflectionHelper.GetPropertyValue((object)actor, "grounded");
if (propertyValue != null && propertyValue is bool)
{
return (bool)propertyValue;
}
propertyValue = ReflectionHelper.GetFieldValue((object)actor, "<grounded>k__BackingField");
if (propertyValue != null && propertyValue is bool)
{
return (bool)propertyValue;
}
return false;
}
private static void SetGrounded(ProtoActor actor, bool value)
{
ReflectionHelper.SetFieldValue((object)actor, "<grounded>k__BackingField", (object)value);
}
private static void SetFalling(ProtoActor actor, float value)
{
ReflectionHelper.SetFieldValue((object)actor, "falling", (object)value);
}
}
}
namespace BetterJump.Config
{
internal static class BetterJumpPreferences
{
private const string CategoryId = "BetterJump";
private static MelonPreferences_Category _category;
private static MelonPreferences_Entry<bool> _enabled;
private static MelonPreferences_Entry<float> _jumpVelocity;
private static MelonPreferences_Entry<float> _forceUngroundTime;
private static MelonPreferences_Entry<bool> _debugLogs;
internal static bool Enabled => _enabled.Value;
internal static float JumpVelocity => Mathf.Max(0f, _jumpVelocity.Value);
internal static float ForceUngroundTime => Mathf.Max(0.01f, _forceUngroundTime.Value);
internal static bool DebugLogs => _debugLogs.Value;
internal static void Initialize()
{
if (_category == null)
{
_category = MelonPreferences.CreateCategory("BetterJump", "BetterJump");
_enabled = CreateEntry("Enabled", defaultValue: true, "Enabled", "Enable BetterJump functionality. When disabled, the mod will not modify jump behavior.");
_jumpVelocity = CreateEntry("JumpVelocity", 5.2f, "Jump Velocity", "Upward speed applied when a jump starts (units/second). Higher values result in stronger jumps. Default: 5.2");
_forceUngroundTime = CreateEntry("ForceUngroundTime", 0.08f, "Force Unground Time", "Seconds to keep avatar airborne before the next ground check can succeed. This prevents the game from immediately detecting the ground after a jump, allowing for better jump responsiveness. Default: 0.08");
_debugLogs = CreateEntry("DebugLogs", defaultValue: false, "Debug Logs", "Enable detailed debug logging for troubleshooting jump behavior.");
}
}
private static MelonPreferences_Entry<T> CreateEntry<T>(string identifier, T defaultValue, string displayName, string description = null)
{
if (_category == null)
{
throw new InvalidOperationException("Preference category not initialized.");
}
return _category.CreateEntry<T>(identifier, defaultValue, displayName, description, false, false, (ValueValidator)null, (string)null);
}
}
}