Decompiled source of PEAK Skygear v1.0.0

tony4twentys-PEAK Skygear.dll

Decompiled 5 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using ExitGames.Client.Photon;
using HarmonyLib;
using Peak;
using Photon.Pun;
using Photon.Realtime;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: AssemblyTitle("PEAK Skygear")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("PEAK Skygear")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("4d0177cf-accf-427f-91a2-0e1309ac53fa")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}
namespace PeakSkygear
{
	[BepInPlugin("tony4twentys.PEAK_Skygear", "PEAK Skygear", "1.0.0")]
	public sealed class Plugin : BaseUnityPlugin
	{
		internal static Plugin Instance;

		internal static Harmony Harmony;

		private static bool s_loggedPatchError;

		internal const string PluginGuid = "tony4twentys.PEAK_Skygear";

		internal const string PluginName = "PEAK Skygear";

		internal const string PluginVersion = "1.0.0";

		private void Awake()
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			Instance = this;
			FlightConfig.Bind(((BaseUnityPlugin)this).Config, OnHostConfigChanged);
			FlightNet.Ensure();
			Harmony = new Harmony("tony4twentys.PEAK_Skygear");
			FlightPatches.PatchAll(Harmony);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[Skygear] PEAK Skygear ready (1.0.0).");
		}

		private void Update()
		{
			Flight.PollCameraSwap();
			ParachuteRepack.PollCancel();
			ParachuteRepack.Tick();
		}

		private void OnHostConfigChanged()
		{
			if (!PhotonNetwork.InRoom)
			{
				FlightConfig.Synced = FlightConfig.BuildFromHost();
			}
			else if (PhotonNetwork.IsMasterClient)
			{
				FlightNet.ScheduleBroadcast();
			}
		}

		internal static bool HandshakeActive()
		{
			if (!PhotonNetwork.InRoom)
			{
				return true;
			}
			if (PhotonNetwork.IsMasterClient)
			{
				return true;
			}
			return FlightNet.HostConfirmed;
		}

		internal static void LogInfo(string message)
		{
			Plugin instance = Instance;
			if (instance != null)
			{
				((BaseUnityPlugin)instance).Logger.LogInfo((object)message);
			}
		}

		internal static void LogWarning(string message)
		{
			Plugin instance = Instance;
			if (instance != null)
			{
				((BaseUnityPlugin)instance).Logger.LogWarning((object)message);
			}
		}

		internal static void LogPatchErrorOnce(string where, Exception e)
		{
			if (!s_loggedPatchError)
			{
				s_loggedPatchError = true;
				Plugin instance = Instance;
				if (instance != null)
				{
					((BaseUnityPlugin)instance).Logger.LogError((object)$"[Skygear] {where} failed (further errors suppressed): {e}");
				}
			}
		}
	}
	internal enum AerialKind
	{
		None,
		Balloon,
		Parasol,
		Parachute,
		Glider,
		Jetpack,
		Rocket
	}
	internal static class Flight
	{
		internal static bool ManualParachuteOpen;

		internal static bool ManualBalloonPop;

		internal static bool? LocalFirstPersonOverride;

		private static bool s_jetpackRocketCam;

		private const float LookSteerBaseTorque = 200f;

		private const float FirstPersonLookScale = 0.65f;

		private const float LookSteerAntiRoll = 0.1f;

		private static readonly Dictionary<Character, bool> s_nearGround = new Dictionary<Character, bool>();

		private const int BalloonMoveCap = 6;

		internal static Character GetCharacter(CharacterMovement move)
		{
			if ((Object)(object)move == (Object)null)
			{
				return null;
			}
			return ((Object)(object)move.character != (Object)null) ? move.character : ((Component)move).GetComponent<Character>();
		}

		internal static Item CurrentItem(Character c)
		{
			return ((Object)(object)c != (Object)null && (Object)(object)c.data != (Object)null) ? c.data.currentItem : null;
		}

		internal static Parasol GetHeldParasol(Character c)
		{
			Item val = CurrentItem(c);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			Parasol result = default(Parasol);
			if (((Component)val).TryGetComponent<Parasol>(ref result))
			{
				return result;
			}
			return ((Component)val).GetComponentInChildren<Parasol>(true);
		}

		internal static Action_Parasol GetHeldParasolAction(Character c)
		{
			Item val = CurrentItem(c);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			Action_Parasol result = default(Action_Parasol);
			if (((Component)val).TryGetComponent<Action_Parasol>(ref result))
			{
				return result;
			}
			return ((Component)val).GetComponentInChildren<Action_Parasol>(true);
		}

		internal static Glider GetHeldGlider(Character c)
		{
			Item val = CurrentItem(c);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			Glider result = default(Glider);
			if (((Component)val).TryGetComponent<Glider>(ref result))
			{
				return result;
			}
			return ((Component)val).GetComponentInChildren<Glider>(true);
		}

		internal static bool IsHoldingParachute(Character c)
		{
			Item val = CurrentItem(c);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			if (((Component)val).CompareTag("Parachute"))
			{
				return true;
			}
			if ((Object)(object)((Component)val).GetComponent<ParachuteItem>() != (Object)null)
			{
				return true;
			}
			if ((Object)(object)((Component)val).GetComponent<Parachute>() != (Object)null)
			{
				return true;
			}
			return (Object)(object)c.data != (Object)null && (Object)(object)val == (Object)(object)c.data.currentParachuteItem;
		}

		internal static bool HasParachute(Character c)
		{
			if ((Object)(object)c == (Object)null || (Object)(object)c.data == (Object)null)
			{
				return false;
			}
			if (c.data.hasParachute)
			{
				return true;
			}
			if ((Object)(object)c.data.currentParachuteItem != (Object)null)
			{
				return true;
			}
			if (c.data.currentParachuteSlot != null && !c.data.currentParachuteSlot.IsEmpty())
			{
				return true;
			}
			return IsHoldingParachute(c);
		}

		internal static bool RocketLookSteerActive()
		{
			FlightConfig.HostCfg synced = FlightConfig.Synced;
			if (!synced.rocketLookSteerEnabled)
			{
				return false;
			}
			return synced.rocketLookPitchSens > 0.001f || synced.rocketLookYawSens > 0.001f;
		}

		internal static bool WantFirstPerson()
		{
			if (LocalFirstPersonOverride.HasValue)
			{
				return LocalFirstPersonOverride.Value;
			}
			return FlightConfig.RocketFirstPerson != null && FlightConfig.RocketFirstPerson.Value;
		}

		internal static bool JetpackUsesRocketFlight()
		{
			return FlightConfig.Synced.jetpackUseRocketFlight;
		}

		internal static bool JetpackUsesCustomRocketSettings()
		{
			return FlightConfig.Synced.jetpackUseRocketFlight && FlightConfig.Synced.jetpackUseCustomRocketSettings;
		}

		private static bool IsRocketStyleFlight(CharacterMovement move, Character c)
		{
			if (IsRocketing(move))
			{
				return true;
			}
			return JetpackUsesRocketFlight() && IsJetpacking(c);
		}

		internal static bool CustomRocketControlsActive(CharacterMovement move, Character c)
		{
			if (IsRocketing(move))
			{
				return RocketLookSteerActive();
			}
			return JetpackUsesCustomRocketSettings() && IsJetpacking(c) && RocketLookSteerActive();
		}

		internal static void PollCameraSwap()
		{
			if (!Plugin.HandshakeActive())
			{
				return;
			}
			ConfigEntry<KeyCode> swapRocketCameraKey = FlightConfig.SwapRocketCameraKey;
			if (FlightConfig.KeyDown(swapRocketCameraKey))
			{
				Character localCharacter = Character.localCharacter;
				if (!((Object)(object)localCharacter == (Object)null) && localCharacter.refs != null && IsRocketStyleFlight(localCharacter.refs.movement, localCharacter))
				{
					LocalFirstPersonOverride = !WantFirstPerson();
				}
			}
		}

		private static MainCameraMovement GetCamMove()
		{
			if ((Object)(object)MainCamera.instance == (Object)null)
			{
				return null;
			}
			return ((Component)MainCamera.instance).GetComponent<MainCameraMovement>();
		}

		internal static void EnsureRocketCam(Character c)
		{
			if (!((Object)(object)c == (Object)null) && !((Object)(object)c != (Object)(object)Character.localCharacter))
			{
				MainCameraMovement camMove = GetCamMove();
				if (!((Object)(object)camMove == (Object)null) && !camMove.isRocketing)
				{
					camMove.StartRocketing();
					s_jetpackRocketCam = true;
				}
			}
		}

		internal static void StopJetpackRocketCam()
		{
			if (!s_jetpackRocketCam)
			{
				return;
			}
			s_jetpackRocketCam = false;
			Character localCharacter = Character.localCharacter;
			if (!((Object)(object)localCharacter != (Object)null) || localCharacter.refs == null || !((Object)(object)localCharacter.refs.movement != (Object)null) || !localCharacter.refs.movement.rocketActive)
			{
				MainCameraMovement camMove = GetCamMove();
				if ((Object)(object)camMove != (Object)null && camMove.isRocketing)
				{
					camMove.StopRocketing();
				}
			}
		}

		internal static void ApplyRocketStylePhysics(Character c, CharacterMovement move, bool useCustom)
		{
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_022f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_0245: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_0260: Unknown result type (might be due to invalid IL or missing references)
			//IL_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0276: Unknown result type (might be due to invalid IL or missing references)
			//IL_0283: Unknown result type (might be due to invalid IL or missing references)
			//IL_028a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0292: Unknown result type (might be due to invalid IL or missing references)
			//IL_0299: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)c == (Object)null || (Object)(object)move == (Object)null || c.refs == null || (Object)(object)c.refs.ragdoll == (Object)null)
			{
				return;
			}
			Rigidbody bodypartRig = c.GetBodypartRig((BodypartType)2);
			Rigidbody bodypartRig2 = c.GetBodypartRig((BodypartType)0);
			if ((Object)(object)bodypartRig == (Object)null || (Object)(object)bodypartRig2 == (Object)null)
			{
				return;
			}
			float num = move.rocketForce;
			if (useCustom)
			{
				num *= Mathf.Clamp(FlightConfig.Synced.rocketMove, 0.25f, 5f);
			}
			if (WantsSprint(c))
			{
				num *= Mathf.Clamp(FlightConfig.Synced.jetpackSprintMove, 1f, 2f);
			}
			c.data.sinceGrounded = 0f;
			c.Fall(0.1f, 0f);
			Vector3 val = ((Component)bodypartRig).transform.up + ((Component)bodypartRig).transform.forward * 0.25f;
			for (int i = 0; i < c.refs.ragdoll.partList.Count; i++)
			{
				Bodypart val2 = c.refs.ragdoll.partList[i];
				if (!((Object)(object)val2 == (Object)null))
				{
					val2.AddForce(val * num, (ForceMode)5);
					val2.Drag(move.rocketDrag, true);
				}
			}
			bool flag = useCustom && RocketLookSteerActive();
			if ((!flag || !FlightConfig.Synced.rocketBlockWasdWhenLook) && (Object)(object)c.input != (Object)null && (Object)(object)MainCamera.instance != (Object)null && (Object)(object)MainCamera.instance.cam != (Object)null)
			{
				Vector2 movementInput = c.input.movementInput;
				Vector3 right = ((Component)MainCamera.instance.cam).transform.right;
				Vector3 forward = ((Component)bodypartRig2).transform.forward;
				right.y = 0f;
				((Vector3)(ref right)).Normalize();
				((Vector3)(ref forward)).Normalize();
				float rocketTorque = move.rocketTorque;
				bodypartRig.AddTorque(right * movementInput.y * rocketTorque, (ForceMode)5);
				bodypartRig2.AddTorque(right * movementInput.y * rocketTorque, (ForceMode)5);
				bodypartRig.AddTorque(forward * (0f - movementInput.x) * rocketTorque, (ForceMode)5);
				bodypartRig2.AddTorque(forward * (0f - movementInput.x) * rocketTorque, (ForceMode)5);
			}
			if (flag)
			{
				ApplyLookSteer(c);
			}
		}

		internal static void ApplyLookSteer(Character c)
		{
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)c == (Object)null || (Object)(object)c.data == (Object)null)
			{
				return;
			}
			Rigidbody bodypartRig = c.GetBodypartRig((BodypartType)2);
			Rigidbody bodypartRig2 = c.GetBodypartRig((BodypartType)0);
			if ((Object)(object)bodypartRig == (Object)null || (Object)(object)bodypartRig2 == (Object)null)
			{
				return;
			}
			StabilizeLookSteerRoll(bodypartRig, bodypartRig2);
			FlightConfig.HostCfg synced = FlightConfig.Synced;
			Vector3 lookDirection = c.data.lookDirection;
			if (!(((Vector3)(ref lookDirection)).sqrMagnitude < 0.0001f))
			{
				if (synced.rocketInvertVertical)
				{
					lookDirection.y = 0f - lookDirection.y;
				}
				((Vector3)(ref lookDirection)).Normalize();
				Vector3 val = Vector3.Cross(((Component)bodypartRig).transform.up, lookDirection);
				Vector3 val2 = c.data.lookDirection_Right;
				val2.y = 0f;
				if (((Vector3)(ref val2)).sqrMagnitude < 0.0001f)
				{
					val2 = Vector3.right;
				}
				((Vector3)(ref val2)).Normalize();
				float num = ((c.IsLocal && WantFirstPerson()) ? 0.65f : 1f);
				float num2 = Vector3.Dot(val, val2) * synced.rocketLookPitchSens * num;
				float num3 = Vector3.Dot(val, Vector3.up) * synced.rocketLookYawSens * num;
				Vector3 val3 = (val2 * num2 + Vector3.up * num3) * 200f;
				bodypartRig.AddTorque(val3, (ForceMode)5);
				bodypartRig2.AddTorque(val3, (ForceMode)5);
			}
		}

		private static void StabilizeLookSteerRoll(Rigidbody torso, Rigidbody hip)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: 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)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			Vector3 up = ((Component)torso).transform.up;
			if (!(((Vector3)(ref up)).sqrMagnitude < 0.0001f))
			{
				((Vector3)(ref up)).Normalize();
				Vector3 val = Vector3.Cross(up, Vector3.up);
				if (!(((Vector3)(ref val)).sqrMagnitude < 0.04f))
				{
					((Vector3)(ref val)).Normalize();
					float num = Vector3.SignedAngle(((Component)torso).transform.right, val, up);
					Vector3 val2 = up * ((0f - num) / 90f) * 200f * 2.5f * 0.1f;
					torso.AddTorque(val2, (ForceMode)5);
					hip.AddTorque(val2, (ForceMode)5);
				}
			}
		}

		internal static float JetpackMaxFuel()
		{
			return Mathf.Max(1f, FlightConfig.Synced.jetpackMaxFuel);
		}

		internal static float JetpackSprintThrustMult(Character c)
		{
			if (!WantsSprint(c))
			{
				return 1f;
			}
			return Mathf.Clamp(FlightConfig.Synced.jetpackSprintMove, 1f, 2f);
		}

		internal static void SyncJetpackFuelPercent(FloatItemData fuel, FloatItemData percent)
		{
			if (fuel != null)
			{
				float num = JetpackMaxFuel();
				if (fuel.Value > num)
				{
					fuel.Value = num;
				}
				if (percent != null)
				{
					percent.Value = Mathf.Clamp01(fuel.Value / num);
				}
			}
		}

		internal static void SyncWornJetpackFuel(Character c)
		{
			FloatItemData fuel = default(FloatItemData);
			if (!((Object)(object)c == (Object)null) && !((Object)(object)c.player == (Object)null) && c.player.backpackSlot != null && ((ItemSlot)c.player.backpackSlot).data != null && ((ItemSlot)c.player.backpackSlot).data.TryGetDataEntry<FloatItemData>((DataEntryKey)10, ref fuel))
			{
				FloatItemData percent = null;
				((ItemSlot)c.player.backpackSlot).data.TryGetDataEntry<FloatItemData>((DataEntryKey)11, ref percent);
				SyncJetpackFuelPercent(fuel, percent);
			}
		}

		internal static bool WantsSprint(Character c)
		{
			return (Object)(object)c != (Object)null && (Object)(object)c.data != (Object)null && c.data.isSprinting;
		}

		internal static bool IsParasolGliding(Character c)
		{
			if ((Object)(object)c == (Object)null || (Object)(object)c.data == (Object)null || c.data.isGrounded)
			{
				return false;
			}
			Parasol heldParasol = GetHeldParasol(c);
			return (Object)(object)heldParasol != (Object)null && heldParasol.isOpen;
		}

		internal static bool IsParachuteOpen(Character c)
		{
			return (Object)(object)c != (Object)null && c.refs != null && (Object)(object)c.refs.balloons != (Object)null && c.refs.balloons._isParachuteOpen;
		}

		internal static bool IsGliding(Character c)
		{
			Glider heldGlider = GetHeldGlider(c);
			return (Object)(object)heldGlider != (Object)null && heldGlider._gliding;
		}

		internal static bool IsJetpacking(Character c)
		{
			if ((Object)(object)c == (Object)null || c.refs == null || (Object)(object)c.refs.backpackHandler == (Object)null)
			{
				return false;
			}
			Jetpack jetpack = c.refs.backpackHandler.jetpack;
			return (Object)(object)jetpack != (Object)null && jetpack._active;
		}

		internal static bool IsRocketing(CharacterMovement move)
		{
			return (Object)(object)move != (Object)null && move.rocketActive;
		}

		internal static bool HasRocketpack(Character c)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Invalid comparison between Unknown and I4
			if ((Object)(object)c == (Object)null || (Object)(object)c.player == (Object)null)
			{
				return false;
			}
			BackpackSlot backpackSlot = c.player.GetBackpackSlot();
			if (backpackSlot == null || ((ItemSlot)backpackSlot).IsEmpty())
			{
				return false;
			}
			return (int)backpackSlot.backpackType == 4;
		}

		internal static bool IsAirborne(Character c)
		{
			return (Object)(object)c != (Object)null && (Object)(object)c.data != (Object)null && !c.data.isGrounded;
		}

		private static int BalloonCount(Character c)
		{
			if ((Object)(object)c == (Object)null || c.refs == null || (Object)(object)c.refs.balloons == (Object)null)
			{
				return 0;
			}
			return c.refs.balloons.currentBalloonCount;
		}

		internal static void TickFalling(Character c)
		{
			if (!((Object)(object)c == (Object)null) && !((Object)(object)c.data == (Object)null))
			{
				s_nearGround[c] = ProbeNearGround(c);
			}
		}

		private static bool ProbeNearGround(Character c)
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			if (c.data.isGrounded)
			{
				return true;
			}
			Rigidbody bodypartRig = c.GetBodypartRig((BodypartType)0);
			if ((Object)(object)bodypartRig == (Object)null)
			{
				return true;
			}
			float num = c.data.targetHipHeight + FlightConfig.Synced.groundProbeExtra;
			RaycastHit val = HelperFunctions.LineCheck(bodypartRig.position, bodypartRig.position + Vector3.down * num, (LayerType)1, 0f, (QueryTriggerInteraction)1);
			return (Object)(object)((RaycastHit)(ref val)).transform != (Object)null;
		}

		internal static bool NearGround(Character c)
		{
			if ((Object)(object)c == (Object)null || (Object)(object)c.data == (Object)null || c.data.isGrounded)
			{
				return true;
			}
			if (!s_nearGround.TryGetValue(c, out var value))
			{
				return true;
			}
			return value;
		}

		internal static bool CanDeployParachute(Character c)
		{
			if (!FlightConfig.Synced.parachuteManual)
			{
				return false;
			}
			return HasParachute(c) && IsAirborne(c) && !NearGround(c) && !IsParachuteOpen(c) && !ParachuteRepack.IsUnpacked(CurrentItem(c));
		}

		internal static bool IsParachuteItem(Item item)
		{
			if ((Object)(object)item == (Object)null)
			{
				return false;
			}
			if (((Component)item).CompareTag("Parachute"))
			{
				return true;
			}
			return (Object)(object)((Component)item).GetComponent<ParachuteItem>() != (Object)null || (Object)(object)((Component)item).GetComponent<Parachute>() != (Object)null;
		}

		internal static AerialKind GetKind(CharacterMovement move, Character c)
		{
			if ((Object)(object)c == (Object)null || (Object)(object)c.data == (Object)null)
			{
				return AerialKind.None;
			}
			if (IsRocketing(move))
			{
				return AerialKind.Rocket;
			}
			if (IsJetpacking(c))
			{
				return AerialKind.Jetpack;
			}
			if (c.data.isGrounded)
			{
				return AerialKind.None;
			}
			if (IsGliding(c))
			{
				return AerialKind.Glider;
			}
			if (IsParachuteOpen(c))
			{
				return AerialKind.Parachute;
			}
			if (IsParasolGliding(c))
			{
				return AerialKind.Parasol;
			}
			if (BalloonCount(c) > 0)
			{
				return AerialKind.Balloon;
			}
			return AerialKind.None;
		}

		internal static bool TryGetMoveMult(CharacterMovement move, Character c, out float mult)
		{
			mult = 1f;
			if ((Object)(object)c == (Object)null || (Object)(object)c.data == (Object)null || c.data.isGrounded)
			{
				return false;
			}
			AerialKind kind = GetKind(move, c);
			if (kind == AerialKind.None || kind == AerialKind.Rocket)
			{
				return false;
			}
			if ((kind == AerialKind.Balloon || kind == AerialKind.Glider || kind == AerialKind.Parasol) && NearGround(c))
			{
				return false;
			}
			FlightConfig.HostCfg synced = FlightConfig.Synced;
			bool sprint = c.data.isSprinting && !c.OutOfRegularStamina();
			switch (kind)
			{
			case AerialKind.Balloon:
				mult = ScaleBalloonMove(StackSprint(synced.balloonMove, synced.balloonSprintMove, sprint), c);
				return true;
			case AerialKind.Parasol:
				mult = StackSprint(synced.parasolMove, synced.parasolSprintMove, sprint);
				return true;
			case AerialKind.Parachute:
				mult = StackSprint(synced.parachuteMove, synced.parachuteSprintMove, sprint);
				return true;
			case AerialKind.Glider:
				mult = StackSprint(synced.gliderMove, synced.gliderSprintMove, sprint);
				return true;
			case AerialKind.Jetpack:
				if (JetpackUsesRocketFlight())
				{
					return false;
				}
				mult = StackSprint(synced.jetpackMove, synced.jetpackSprintMove, sprint);
				return true;
			default:
				return false;
			}
		}

		private static float StackSprint(float moveMult, float sprintMult, bool sprint)
		{
			float num = (sprint ? (moveMult * sprintMult) : moveMult);
			return Mathf.Clamp(num, 0.25f, 10f);
		}

		private static float ScaleBalloonMove(float fullMult, Character c)
		{
			int num = Mathf.Clamp(BalloonCount(c), 0, 6);
			if (num <= 1)
			{
				return 1f;
			}
			return 1f + (fullMult - 1f) * ((float)(num - 1) / 5f);
		}

		internal static bool TryGetSprintStamina(CharacterMovement move, Character c, out float drainPerSecond)
		{
			drainPerSecond = 0f;
			if ((Object)(object)c == (Object)null || !c.data.isSprinting || c.OutOfRegularStamina())
			{
				return false;
			}
			AerialKind kind = GetKind(move, c);
			if ((kind == AerialKind.Balloon || kind == AerialKind.Glider || kind == AerialKind.Parasol) && NearGround(c))
			{
				return false;
			}
			FlightConfig.HostCfg synced = FlightConfig.Synced;
			switch (kind)
			{
			case AerialKind.Balloon:
				if (!synced.balloonSprintUsesStamina)
				{
					return false;
				}
				drainPerSecond = synced.balloonSprintStaminaDrain;
				return drainPerSecond > 0f;
			case AerialKind.Parasol:
				if (!synced.parasolSprintUsesStamina)
				{
					return false;
				}
				drainPerSecond = synced.parasolSprintStaminaDrain;
				return drainPerSecond > 0f;
			case AerialKind.Parachute:
				if (!synced.parachuteSprintUsesStamina)
				{
					return false;
				}
				drainPerSecond = synced.parachuteSprintStaminaDrain;
				return drainPerSecond > 0f;
			case AerialKind.Glider:
				if (!synced.gliderSprintUsesStamina)
				{
					return false;
				}
				drainPerSecond = synced.gliderSprintStaminaDrain;
				return drainPerSecond > 0f;
			default:
				return false;
			}
		}

		internal static bool TryPopOneTiedBalloon(Character c)
		{
			List<TiedBalloon> list = (((Object)(object)c != (Object)null && c.refs != null && (Object)(object)c.refs.balloons != (Object)null) ? c.refs.balloons.tiedBalloons : null);
			if (list == null || list.Count == 0)
			{
				return false;
			}
			TiedBalloon val = list[list.Count - 1];
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			ManualBalloonPop = true;
			try
			{
				val.Pop();
			}
			finally
			{
				ManualBalloonPop = false;
			}
			return true;
		}

		internal static void OpenParachute(Character c)
		{
			if (!((Object)(object)c == (Object)null) && c.refs != null && !((Object)(object)c.refs.balloons == (Object)null) && !((Object)(object)c.data == (Object)null) && CanDeployParachute(c))
			{
				ParachuteRepack.MarkDeployed();
				ManualParachuteOpen = true;
				try
				{
					c.refs.balloons.SetParachute(true);
				}
				finally
				{
					ManualParachuteOpen = false;
				}
				ConsumeHeldParachute(c);
			}
		}

		private static void ConsumeHeldParachute(Character c)
		{
			if (!((Object)(object)c == (Object)null) && !((Object)(object)c.data == (Object)null))
			{
				Item val = (((Object)(object)c.data.currentParachuteItem != (Object)null) ? c.data.currentParachuteItem : CurrentItem(c));
				if ((Object)(object)val != (Object)null)
				{
					val.ClearDataFromBackpack();
					((MonoBehaviour)val).StartCoroutine(val.ConsumeDelayed(false));
				}
				if (c.data.currentParachuteSlot != null)
				{
					c.data.currentParachuteSlot.EmptyOut();
				}
			}
		}

		internal static void CloseParachute(Character c)
		{
			if (!((Object)(object)c == (Object)null) && c.refs != null && !((Object)(object)c.refs.balloons == (Object)null))
			{
				ParachuteRepack.MarkCut();
				c.refs.balloons.SetParachute(false);
			}
		}

		internal static void LightWornRocket(Character c)
		{
			if (!((Object)(object)c == (Object)null) && c.refs != null && !((Object)(object)c.refs.backpackHandler == (Object)null) && !((Object)(object)c.refs.movement == (Object)null) && HasRocketpack(c) && !c.refs.movement.rocketLit && !c.refs.movement.rocketActive)
			{
				c.refs.movement.rocketTime = FlightConfig.Synced.rocketFlightSeconds;
				c.refs.backpackHandler.LightRocket(FlightConfig.Synced.rocketFuseSeconds);
			}
		}

		internal static void CutRocket(Character c)
		{
			if (!((Object)(object)c == (Object)null) && c.refs != null && !((Object)(object)c.refs.movement == (Object)null) && c.refs.movement.rocketActive)
			{
				FlightNet.BroadcastCutRocket(c);
			}
		}

		internal static void StopRocket(Character c)
		{
			if (!((Object)(object)c == (Object)null) && c.refs != null && !((Object)(object)c.refs.movement == (Object)null))
			{
				c.refs.movement.rocketActive = false;
			}
		}
	}
	internal static class FlightConfig
	{
		[Serializable]
		public struct HostCfg
		{
			public float balloonMove;

			public float balloonSprintMove;

			public bool balloonSprintUsesStamina;

			public float balloonSprintStaminaDrain;

			public bool balloonNeverPopUnlessManual;

			public float balloonPopHeight;

			public float balloonPopTimeSeconds;

			public bool balloonCactusPops;

			public float parasolMove;

			public float parasolSprintMove;

			public bool parasolSprintUsesStamina;

			public float parasolSprintStaminaDrain;

			public float gliderMove;

			public float gliderSprintMove;

			public bool gliderUsesStamina;

			public float gliderStaminaDrain;

			public bool gliderSprintUsesStamina;

			public float gliderSprintStaminaDrain;

			public float parachuteMove;

			public float parachuteSprintMove;

			public bool parachuteSprintUsesStamina;

			public float parachuteSprintStaminaDrain;

			public float jetpackMove;

			public float jetpackSprintMove;

			public float jetpackFuelDrainPerSecond;

			public float jetpackFuelPerItemMult;

			public float jetpackSprintFuelDrain;

			public float jetpackMaxFuel;

			public bool jetpackUseRocketFlight;

			public bool jetpackUseCustomRocketSettings;

			public float rocketMove;

			public float rocketFlightSeconds;

			public float rocketFuseSeconds;

			public bool rocketLookSteerEnabled;

			public float rocketLookPitchSens;

			public float rocketLookYawSens;

			public bool rocketInvertVertical;

			public bool rocketFirstPerson;

			public bool rocketBlockWasdWhenLook;

			public bool rocketCrouchCuts;

			public bool parachuteManual;

			public bool parachuteCrouchCuts;

			public bool parachuteRepack;

			public float parachuteRepackSeconds;

			public bool parachutePackBlocksClimb;

			public bool parachutePackPreventRun;

			public bool parachutePackPreventMove;

			public float jumpSpamDelay;

			public float groundProbeExtra;
		}

		public const float MoveMin = 0.25f;

		public const float MoveMax = 5f;

		public const float SprintMoveMin = 1f;

		public const float SprintMoveMax = 2f;

		public const float MoveProductMax = 10f;

		public const float VanillaSprintStaminaDrain = 0.025f;

		public const float StamDrainMax = 1f;

		internal static HostCfg Synced = Defaults();

		internal static ConfigEntry<float> BalloonMove;

		internal static ConfigEntry<float> BalloonSprintMove;

		internal static ConfigEntry<bool> BalloonSprintUsesStamina;

		internal static ConfigEntry<float> BalloonSprintStaminaDrain;

		internal static ConfigEntry<bool> BalloonNeverPopUnlessManual;

		internal static ConfigEntry<float> BalloonPopHeight;

		internal static ConfigEntry<float> BalloonPopTimeSeconds;

		internal static ConfigEntry<bool> BalloonCactusPops;

		internal static ConfigEntry<float> ParasolMove;

		internal static ConfigEntry<float> ParasolSprintMove;

		internal static ConfigEntry<bool> ParasolSprintUsesStamina;

		internal static ConfigEntry<float> ParasolSprintStaminaDrain;

		internal static ConfigEntry<float> GliderMove;

		internal static ConfigEntry<float> GliderSprintMove;

		internal static ConfigEntry<bool> GliderUsesStamina;

		internal static ConfigEntry<float> GliderStaminaDrain;

		internal static ConfigEntry<bool> GliderSprintUsesStamina;

		internal static ConfigEntry<float> GliderSprintStaminaDrain;

		internal static ConfigEntry<float> ParachuteMove;

		internal static ConfigEntry<float> ParachuteSprintMove;

		internal static ConfigEntry<bool> ParachuteSprintUsesStamina;

		internal static ConfigEntry<float> ParachuteSprintStaminaDrain;

		internal static ConfigEntry<float> JetpackMove;

		internal static ConfigEntry<float> JetpackSprintMove;

		internal static ConfigEntry<float> JetpackFuelDrainPerSecond;

		internal static ConfigEntry<float> JetpackFuelPerItemMult;

		internal static ConfigEntry<float> JetpackSprintFuelDrain;

		internal static ConfigEntry<float> JetpackMaxFuel;

		internal static ConfigEntry<bool> JetpackUseRocketFlight;

		internal static ConfigEntry<bool> JetpackUseCustomRocketSettings;

		internal static ConfigEntry<KeyCode> SwapRocketCameraKey;

		internal static ConfigEntry<float> RocketMove;

		internal static ConfigEntry<float> RocketFlightSeconds;

		internal static ConfigEntry<float> RocketFuseSeconds;

		internal static ConfigEntry<bool> RocketLookSteerEnabled;

		internal static ConfigEntry<float> RocketLookPitchSens;

		internal static ConfigEntry<float> RocketLookYawSens;

		internal static ConfigEntry<bool> RocketInvertVertical;

		internal static ConfigEntry<bool> RocketFirstPerson;

		internal static ConfigEntry<bool> RocketBlockWasdWhenLook;

		internal static ConfigEntry<bool> RocketCrouchCuts;

		internal static ConfigEntry<bool> ParachuteManual;

		internal static ConfigEntry<bool> ParachuteCrouchCuts;

		internal static ConfigEntry<bool> ParachuteRepack;

		internal static ConfigEntry<float> ParachuteRepackSeconds;

		internal static ConfigEntry<bool> ParachutePackBlocksClimb;

		internal static ConfigEntry<bool> ParachutePackPreventRun;

		internal static ConfigEntry<bool> ParachutePackPreventMove;

		internal static ConfigEntry<KeyCode> CancelRepackKey;

		internal static ConfigEntry<float> JumpSpamDelay;

		internal static ConfigEntry<float> GroundProbeExtra;

		internal static HostCfg Defaults()
		{
			return new HostCfg
			{
				balloonMove = 1.5f,
				balloonSprintMove = 1.5f,
				balloonSprintUsesStamina = true,
				balloonSprintStaminaDrain = 0.025f,
				balloonNeverPopUnlessManual = false,
				balloonPopHeight = 100f,
				balloonPopTimeSeconds = 120f,
				balloonCactusPops = true,
				parasolMove = 1.5f,
				parasolSprintMove = 1.5f,
				parasolSprintUsesStamina = true,
				parasolSprintStaminaDrain = 0.025f,
				gliderMove = 1.5f,
				gliderSprintMove = 1.5f,
				gliderUsesStamina = true,
				gliderStaminaDrain = 0.025f,
				gliderSprintUsesStamina = true,
				gliderSprintStaminaDrain = 0.025f,
				parachuteMove = 1.5f,
				parachuteSprintMove = 1.5f,
				parachuteSprintUsesStamina = true,
				parachuteSprintStaminaDrain = 0.025f,
				jetpackMove = 1.5f,
				jetpackSprintMove = 1.5f,
				jetpackFuelDrainPerSecond = 20f,
				jetpackFuelPerItemMult = 1f,
				jetpackSprintFuelDrain = 20f,
				jetpackMaxFuel = 100f,
				jetpackUseRocketFlight = false,
				jetpackUseCustomRocketSettings = false,
				rocketMove = 1.5f,
				rocketFlightSeconds = 3f,
				rocketFuseSeconds = 3f,
				rocketLookSteerEnabled = false,
				rocketLookPitchSens = 3f,
				rocketLookYawSens = 3f,
				rocketInvertVertical = false,
				rocketFirstPerson = false,
				rocketBlockWasdWhenLook = true,
				rocketCrouchCuts = true,
				parachuteManual = true,
				parachuteCrouchCuts = false,
				parachuteRepack = true,
				parachuteRepackSeconds = 8f,
				parachutePackBlocksClimb = true,
				parachutePackPreventRun = false,
				parachutePackPreventMove = false,
				jumpSpamDelay = 1.5f,
				groundProbeExtra = 6f
			};
		}

		internal static void Bind(ConfigFile cfg, Action onHostChanged)
		{
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Expected O, but got Unknown
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Expected O, but got Unknown
			//IL_0370: Unknown result type (might be due to invalid IL or missing references)
			//IL_037a: Expected O, but got Unknown
			//IL_03a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b3: Expected O, but got Unknown
			//IL_03e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ec: Expected O, but got Unknown
			//IL_041b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0425: Expected O, but got Unknown
			//IL_051c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0526: Expected O, but got Unknown
			//IL_0555: Unknown result type (might be due to invalid IL or missing references)
			//IL_055f: Expected O, but got Unknown
			//IL_05ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b8: Expected O, but got Unknown
			//IL_05e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f1: Expected O, but got Unknown
			//IL_0700: Unknown result type (might be due to invalid IL or missing references)
			//IL_070a: Expected O, but got Unknown
			//IL_07b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_07bf: Expected O, but got Unknown
			//IL_07ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_07f8: Expected O, but got Unknown
			HostCfg hostCfg = Defaults();
			BalloonMove = Move(cfg, "Balloon", "MovementMultiplier", hostCfg.balloonMove, "Full extra air move at 6 tied balloons. 1 balloon is vanilla air move. Each balloon from 2 to 6 adds 1/5 of this extra. 7+ does not go faster. 1 = vanilla, 2 = 2x at 6 balloons.");
			BalloonSprintMove = SprintMove(cfg, "Balloon", "SprintMovementMultiplier", hostCfg.balloonSprintMove, "While sprinting, multiplies MovementMultiplier. Default 1.5. 2 move and 1.5 sprint = 3x vanilla air move.");
			BalloonSprintUsesStamina = cfg.Bind<bool>("Balloon", "SprintUsesStamina", hostCfg.balloonSprintUsesStamina, "If true, the balloon sprint-move boost costs stamina.");
			BalloonSprintStaminaDrain = Drain(cfg, "Balloon", "SprintStaminaDrainPerSecond", hostCfg.balloonSprintStaminaDrain, "Stamina drained per second while sprinting with balloons. Stamina bar is 0-1. Vanilla ground sprint is 0.025. 0 = no drain. Only used if SprintUsesStamina is on.");
			BalloonNeverPopUnlessManual = cfg.Bind<bool>("Balloon", "NeverPopUnlessManual", hostCfg.balloonNeverPopUnlessManual, "If true, tied balloons never pop from lifetime, height, or cactus. Crouch still pops one balloon at a time.");
			BalloonPopHeight = cfg.Bind<float>("Balloon", "PopHeight", hostCfg.balloonPopHeight, new ConfigDescription("How many world units above the tie height a balloon can rise before it pops. Vanilla C# default is 100. 0 = never pop from height. Ignored if NeverPopUnlessManual is on.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2000f), Array.Empty<object>()));
			BalloonPopTimeSeconds = cfg.Bind<float>("Balloon", "PopTimeSeconds", hostCfg.balloonPopTimeSeconds, new ConfigDescription("How many seconds a tied balloon lasts before it pops. Vanilla is 120 (2 minutes). 0 = never pop from time. Ignored if NeverPopUnlessManual is on.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 600f), Array.Empty<object>()));
			BalloonCactusPops = cfg.Bind<bool>("Balloon", "CactusPops", hostCfg.balloonCactusPops, "If false, sticky cactus collision will not pop tied balloons. Ignored if NeverPopUnlessManual is on.");
			ParasolMove = Move(cfg, "Parasol", "MovementMultiplier", hostCfg.parasolMove, "Lateral movement while an open parasol is gliding. Multiplies vanilla air move. 1 = vanilla.");
			ParasolSprintMove = SprintMove(cfg, "Parasol", "SprintMovementMultiplier", hostCfg.parasolSprintMove, "While sprinting, multiplies MovementMultiplier. Default 1.5.");
			ParasolSprintUsesStamina = cfg.Bind<bool>("Parasol", "SprintUsesStamina", hostCfg.parasolSprintUsesStamina, "If true, the parasol sprint-move boost costs stamina.");
			ParasolSprintStaminaDrain = Drain(cfg, "Parasol", "SprintStaminaDrainPerSecond", hostCfg.parasolSprintStaminaDrain, "Stamina drained per second while sprinting with an open parasol. Stamina bar is 0-1. Vanilla ground sprint is 0.025. 0 = no drain. Only used if SprintUsesStamina is on.");
			GliderMove = Move(cfg, "Glider", "MovementMultiplier", hostCfg.gliderMove, "Lateral movement while gliding. Multiplies vanilla air move. 1 = vanilla.");
			GliderSprintMove = SprintMove(cfg, "Glider", "SprintMovementMultiplier", hostCfg.gliderSprintMove, "While sprinting, multiplies MovementMultiplier. Default 1.5. Vanilla blocks sprint on the glider; this mod unblocks it.");
			GliderUsesStamina = cfg.Bind<bool>("Glider", "UsesStamina", hostCfg.gliderUsesStamina, "If false, regular gliding does not drain stamina and still works at 0 stamina. Independent from SprintUsesStamina.");
			GliderStaminaDrain = Drain(cfg, "Glider", "StaminaDrainPerSecond", hostCfg.gliderStaminaDrain, "Stamina drained per second while gliding. Stamina bar is 0-1. Vanilla ground sprint is 0.025. 0 = no drain. Only used if UsesStamina is on.");
			GliderSprintUsesStamina = cfg.Bind<bool>("Glider", "SprintUsesStamina", hostCfg.gliderSprintUsesStamina, "If true, sprinting on the glider costs stamina. Independent from UsesStamina: regular glide can be free while sprint still costs.");
			GliderSprintStaminaDrain = Drain(cfg, "Glider", "SprintStaminaDrainPerSecond", hostCfg.gliderSprintStaminaDrain, "Stamina drained per second while sprinting on the glider, on top of StaminaDrainPerSecond. Vanilla ground sprint is 0.025. 0 = no extra drain. Only used if SprintUsesStamina is on.");
			ParachuteMove = Move(cfg, "Parachute", "MovementMultiplier", hostCfg.parachuteMove, "Lateral movement while a parachute is open. Multiplies vanilla air move. 1 = vanilla.");
			ParachuteSprintMove = SprintMove(cfg, "Parachute", "SprintMovementMultiplier", hostCfg.parachuteSprintMove, "While sprinting, multiplies MovementMultiplier. Default 1.5.");
			ParachuteSprintUsesStamina = cfg.Bind<bool>("Parachute", "SprintUsesStamina", hostCfg.parachuteSprintUsesStamina, "If true, the parachute sprint-move boost costs stamina.");
			ParachuteSprintStaminaDrain = Drain(cfg, "Parachute", "SprintStaminaDrainPerSecond", hostCfg.parachuteSprintStaminaDrain, "Stamina drained per second while sprinting under an open parachute. Stamina bar is 0-1. Vanilla ground sprint is 0.025. 0 = no drain. Only used if SprintUsesStamina is on.");
			JetpackMove = Move(cfg, "Jetpack", "MovementMultiplier", hostCfg.jetpackMove, "Lateral movement while the jetpack is firing. 1 = vanilla, 2 = 2x.");
			JetpackSprintMove = SprintMove(cfg, "Jetpack", "SprintMovementMultiplier", hostCfg.jetpackSprintMove, "While sprinting, multiplies MovementMultiplier and vanilla jetpack thrust. Default 1.5.");
			JetpackFuelDrainPerSecond = cfg.Bind<float>("Jetpack", "FuelDrainPerSecond", hostCfg.jetpackFuelDrainPerSecond, new ConfigDescription("Fuel drained per second while the jetpack is firing. Vanilla is 20. 0 = infinite fuel.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>()));
			JetpackMaxFuel = cfg.Bind<float>("Jetpack", "MaxFuel", hostCfg.jetpackMaxFuel, new ConfigDescription("Maximum jetpack fuel. Vanilla is 100.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 1000f), Array.Empty<object>()));
			JetpackFuelPerItemMult = cfg.Bind<float>("Jetpack", "FuelPerItemMultiplier", hostCfg.jetpackFuelPerItemMult, new ConfigDescription("Global multiplier for fuel gained from sacrificed items. 1 = vanilla.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 5f), Array.Empty<object>()));
			JetpackSprintFuelDrain = cfg.Bind<float>("Jetpack", "SprintFuelDrainPerSecond", hostCfg.jetpackSprintFuelDrain, new ConfigDescription("Fuel drained per second while the jetpack is firing AND you are sprinting. Vanilla jetpack drain is 20 (sprint does not change it). Does not change thrust; use SprintMovementMultiplier for that.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>()));
			bool value = hostCfg.jetpackUseRocketFlight;
			bool value2 = hostCfg.jetpackUseCustomRocketSettings;
			TryReadCfgBool(cfg.ConfigFilePath, "Jetpack", "UseRocketPackFlight", ref value);
			TryReadCfgBool(cfg.ConfigFilePath, "Jetpack", "UseCustomRocketPackFlightMovementSettings", ref value2);
			TryReadCfgBool(cfg.ConfigFilePath, "Jetpack", "UseCustomRocketPackSettings", ref value2);
			JetpackUseRocketFlight = cfg.Bind<bool>("Experimental", "UseRocketPackFlight", value, "EXPERIMENTAL. Jetpack rocket-style flight is unfinished. If true, the jetpack uses rocketpack-style body thrust and WASD steering. Fuel and jetpack flames/audio stay the same.");
			JetpackUseCustomRocketSettings = cfg.Bind<bool>("Experimental", "UseCustomRocketPackSettings", value2, "EXPERIMENTAL. Unfinished. If true (and UseRocketPackFlight is on), the jetpack also uses this mod's rocket settings: look-steer, invert, first/third person, camera hotkey, block WASD, anti-roll, and rocket MovementMultiplier.");
			SwapRocketCameraKey = cfg.Bind<KeyCode>("Rocket", "SwapCameraHotkey", (KeyCode)99, "Local hotkey to swap first/third person during rocketpack flight (and experimental jetpack rocket-flight). None = unbound. Not host-synced.");
			RocketMove = Move(cfg, "Rocket", "MovementMultiplier", hostCfg.rocketMove, "Scales vanilla rocket thrust only. WASD steering stays vanilla. 1 = vanilla, 2 = 2x thrust.");
			RocketFlightSeconds = cfg.Bind<float>("Rocket", "FlightSeconds", hostCfg.rocketFlightSeconds, new ConfigDescription("How long the worn rocketpack thrusts after the fuse. Vanilla is 3 seconds.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 15f), Array.Empty<object>()));
			RocketFuseSeconds = cfg.Bind<float>("Rocket", "FuseSeconds", hostCfg.rocketFuseSeconds, new ConfigDescription("Fuse time after crouch-lighting a worn rocketpack. Vanilla is 3 seconds.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 10f), Array.Empty<object>()));
			RocketLookSteerEnabled = cfg.Bind<bool>("Rocket", "EnableLookSteer", hostCfg.rocketLookSteerEnabled, "Master toggle for mouse look-steer. Off by default. Turn this on to steer with the mouse instead of vanilla WASD.");
			RocketLookPitchSens = cfg.Bind<float>("Rocket", "LookPitchSensitivity", hostCfg.rocketLookPitchSens, new ConfigDescription("Mouse up/down steering strength while rocketing. Only used if EnableLookSteer is on.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 3f), Array.Empty<object>()));
			RocketLookYawSens = cfg.Bind<float>("Rocket", "LookYawSensitivity", hostCfg.rocketLookYawSens, new ConfigDescription("Mouse left/right steering strength while rocketing. Only used if EnableLookSteer is on.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 3f), Array.Empty<object>()));
			RocketInvertVertical = cfg.Bind<bool>("Rocket", "InvertLookVertical", hostCfg.rocketInvertVertical, "If true, looking down pitches the rocket up and looking up pitches it down. Off by default. Left/right are unchanged.");
			RocketFirstPerson = cfg.Bind<bool>("Rocket", "FirstPerson", hostCfg.rocketFirstPerson, "If true, rocket flight uses the normal first-person camera instead of vanilla third-person spectate. Off by default. Look-steer is auto-scaled so first person matches third person.");
			RocketBlockWasdWhenLook = cfg.Bind<bool>("Rocket", "BlockWasdWhenLookSteer", hostCfg.rocketBlockWasdWhenLook, "If true, vanilla WASD rocket steering is disabled while EnableLookSteer is on. The two steering systems do not share torque.");
			RocketCrouchCuts = cfg.Bind<bool>("Rocket", "CrouchCutsOff", hostCfg.rocketCrouchCuts, "If true, crouch during rocketpack flight ends the rocket early. Uses the vanilla burnout: flames out, spent rocket drops, backpack is consumed.");
			ParachuteManual = cfg.Bind<bool>("Parachute", "ManualParachutes", hostCfg.parachuteManual, "If true, parachutes only open when you crouch or use the item. If false, vanilla auto-open is kept. Speed and repack settings still apply.");
			ParachuteCrouchCuts = cfg.Bind<bool>("Parachute", "CrouchCutsOff", hostCfg.parachuteCrouchCuts, "If true, crouch cuts an already-open parachute. A cut chute cannot be repacked. Only used if ManualParachutes is on.");
			ParachuteRepack = cfg.Bind<bool>("Parachute", "RepackParachute", hostCfg.parachuteRepack, "If true, landing with an open parachute (not cut) starts a repack timer and returns a new parachute.");
			ParachuteRepackSeconds = cfg.Bind<float>("Parachute", "RepackSeconds", hostCfg.parachuteRepackSeconds, new ConfigDescription("How long the repack progress bar takes before the parachute is returned.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 60f), Array.Empty<object>()));
			ParachutePackBlocksClimb = cfg.Bind<bool>("Parachute", "PackingParachuteBlocksClimb", hostCfg.parachutePackBlocksClimb, "If true, the player cannot climb walls, ropes, or vines while repacking. Walk and run are still allowed unless the other packing toggles are on.");
			ParachutePackPreventRun = cfg.Bind<bool>("Parachute", "PackingParachutePreventRun", hostCfg.parachutePackPreventRun, "If true, sprinting is blocked while repacking. Walking is still allowed.");
			ParachutePackPreventMove = cfg.Bind<bool>("Parachute", "PackingParachutePreventMovement", hostCfg.parachutePackPreventMove, "If true, all WASD movement is blocked while repacking.");
			CancelRepackKey = cfg.Bind<KeyCode>("Parachute", "CancelRepackHotkey", (KeyCode)120, "Local hotkey to cancel parachute repacking. Drops an UNPACKED PARACHUTE on the ground. Picking it up starts repack again. None = unbound. Not host-synced.");
			JumpSpamDelay = cfg.Bind<float>("Movement", "JumpSpamDelay", hostCfg.jumpSpamDelay, new ConfigDescription("Unused. Extra movement and manual parachute deploy are gated by GroundProbeExtra. Kept so older configs still load.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 3f), Array.Empty<object>()));
			GroundProbeExtra = cfg.Bind<float>("Movement", "GroundProbeExtra", hostCfg.groundProbeExtra, new ConfigDescription("Extra meters below the hip that must be clear of terrain before balloon/glider/parasol extra movement (and manual parachute deploy) can apply. Total check is hip height + this value. Default 6. Cap 10 — higher often hits mountain terrain and never arms the boost.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10f), Array.Empty<object>()));
			BalloonMove.SettingChanged += delegate
			{
				onHostChanged();
			};
			BalloonSprintMove.SettingChanged += delegate
			{
				onHostChanged();
			};
			BalloonSprintUsesStamina.SettingChanged += delegate
			{
				onHostChanged();
			};
			BalloonSprintStaminaDrain.SettingChanged += delegate
			{
				onHostChanged();
			};
			BalloonNeverPopUnlessManual.SettingChanged += delegate
			{
				onHostChanged();
			};
			BalloonPopHeight.SettingChanged += delegate
			{
				onHostChanged();
			};
			BalloonPopTimeSeconds.SettingChanged += delegate
			{
				onHostChanged();
			};
			BalloonCactusPops.SettingChanged += delegate
			{
				onHostChanged();
			};
			ParasolMove.SettingChanged += delegate
			{
				onHostChanged();
			};
			ParasolSprintMove.SettingChanged += delegate
			{
				onHostChanged();
			};
			ParasolSprintUsesStamina.SettingChanged += delegate
			{
				onHostChanged();
			};
			ParasolSprintStaminaDrain.SettingChanged += delegate
			{
				onHostChanged();
			};
			GliderMove.SettingChanged += delegate
			{
				onHostChanged();
			};
			GliderSprintMove.SettingChanged += delegate
			{
				onHostChanged();
			};
			GliderUsesStamina.SettingChanged += delegate
			{
				onHostChanged();
			};
			GliderStaminaDrain.SettingChanged += delegate
			{
				onHostChanged();
			};
			GliderSprintUsesStamina.SettingChanged += delegate
			{
				onHostChanged();
			};
			GliderSprintStaminaDrain.SettingChanged += delegate
			{
				onHostChanged();
			};
			ParachuteMove.SettingChanged += delegate
			{
				onHostChanged();
			};
			ParachuteSprintMove.SettingChanged += delegate
			{
				onHostChanged();
			};
			ParachuteSprintUsesStamina.SettingChanged += delegate
			{
				onHostChanged();
			};
			ParachuteSprintStaminaDrain.SettingChanged += delegate
			{
				onHostChanged();
			};
			JetpackMove.SettingChanged += delegate
			{
				onHostChanged();
			};
			JetpackSprintMove.SettingChanged += delegate
			{
				onHostChanged();
			};
			JetpackFuelDrainPerSecond.SettingChanged += delegate
			{
				onHostChanged();
			};
			JetpackMaxFuel.SettingChanged += delegate
			{
				onHostChanged();
			};
			JetpackFuelPerItemMult.SettingChanged += delegate
			{
				onHostChanged();
			};
			JetpackSprintFuelDrain.SettingChanged += delegate
			{
				onHostChanged();
			};
			JetpackUseRocketFlight.SettingChanged += delegate
			{
				onHostChanged();
			};
			JetpackUseCustomRocketSettings.SettingChanged += delegate
			{
				onHostChanged();
			};
			RocketMove.SettingChanged += delegate
			{
				onHostChanged();
			};
			RocketFlightSeconds.SettingChanged += delegate
			{
				onHostChanged();
			};
			RocketFuseSeconds.SettingChanged += delegate
			{
				onHostChanged();
			};
			RocketLookSteerEnabled.SettingChanged += delegate
			{
				onHostChanged();
			};
			RocketLookPitchSens.SettingChanged += delegate
			{
				onHostChanged();
			};
			RocketLookYawSens.SettingChanged += delegate
			{
				onHostChanged();
			};
			RocketInvertVertical.SettingChanged += delegate
			{
				onHostChanged();
			};
			RocketBlockWasdWhenLook.SettingChanged += delegate
			{
				onHostChanged();
			};
			RocketCrouchCuts.SettingChanged += delegate
			{
				onHostChanged();
			};
			ParachuteManual.SettingChanged += delegate
			{
				onHostChanged();
			};
			ParachuteCrouchCuts.SettingChanged += delegate
			{
				onHostChanged();
			};
			ParachuteRepack.SettingChanged += delegate
			{
				onHostChanged();
			};
			ParachuteRepackSeconds.SettingChanged += delegate
			{
				onHostChanged();
			};
			ParachutePackBlocksClimb.SettingChanged += delegate
			{
				onHostChanged();
			};
			ParachutePackPreventRun.SettingChanged += delegate
			{
				onHostChanged();
			};
			ParachutePackPreventMove.SettingChanged += delegate
			{
				onHostChanged();
			};
			JumpSpamDelay.SettingChanged += delegate
			{
				onHostChanged();
			};
			GroundProbeExtra.SettingChanged += delegate
			{
				onHostChanged();
			};
			Synced = BuildFromHost();
		}

		private static ConfigEntry<float> Move(ConfigFile cfg, string section, string key, float def, string desc)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			return cfg.Bind<float>(section, key, def, new ConfigDescription(desc, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 5f), Array.Empty<object>()));
		}

		private static ConfigEntry<float> SprintMove(ConfigFile cfg, string section, string key, float def, string desc)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			return cfg.Bind<float>(section, key, def, new ConfigDescription(desc, (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 2f), Array.Empty<object>()));
		}

		private static ConfigEntry<float> Drain(ConfigFile cfg, string section, string key, float def, string desc)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			return cfg.Bind<float>(section, key, def, new ConfigDescription(desc, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
		}

		internal static bool KeyDown(ConfigEntry<KeyCode> entry)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			if (entry == null)
			{
				return false;
			}
			KeyCode value = entry.Value;
			return (int)value != 0 && Input.GetKeyDown(value);
		}

		private static void TryReadCfgBool(string path, string section, string key, ref bool value)
		{
			if (string.IsNullOrEmpty(path) || !File.Exists(path))
			{
				return;
			}
			string a = null;
			string[] array = File.ReadAllLines(path);
			foreach (string text in array)
			{
				string text2 = text.Trim();
				if (text2.StartsWith("[") && text2.EndsWith("]"))
				{
					a = text2.Substring(1, text2.Length - 2);
					continue;
				}
				int num = text2.IndexOf('=');
				if (num > 0 && string.Equals(a, section, StringComparison.OrdinalIgnoreCase) && string.Equals(text2.Substring(0, num).Trim(), key, StringComparison.OrdinalIgnoreCase))
				{
					if (bool.TryParse(text2.Substring(num + 1).Trim(), out var result))
					{
						value = result;
					}
					break;
				}
			}
		}

		internal static HostCfg BuildFromHost()
		{
			return new HostCfg
			{
				balloonMove = BalloonMove.Value,
				balloonSprintMove = BalloonSprintMove.Value,
				balloonSprintUsesStamina = BalloonSprintUsesStamina.Value,
				balloonSprintStaminaDrain = BalloonSprintStaminaDrain.Value,
				balloonNeverPopUnlessManual = BalloonNeverPopUnlessManual.Value,
				balloonPopHeight = BalloonPopHeight.Value,
				balloonPopTimeSeconds = BalloonPopTimeSeconds.Value,
				balloonCactusPops = BalloonCactusPops.Value,
				parasolMove = ParasolMove.Value,
				parasolSprintMove = ParasolSprintMove.Value,
				parasolSprintUsesStamina = ParasolSprintUsesStamina.Value,
				parasolSprintStaminaDrain = ParasolSprintStaminaDrain.Value,
				gliderMove = GliderMove.Value,
				gliderSprintMove = GliderSprintMove.Value,
				gliderUsesStamina = GliderUsesStamina.Value,
				gliderStaminaDrain = GliderStaminaDrain.Value,
				gliderSprintUsesStamina = GliderSprintUsesStamina.Value,
				gliderSprintStaminaDrain = GliderSprintStaminaDrain.Value,
				parachuteMove = ParachuteMove.Value,
				parachuteSprintMove = ParachuteSprintMove.Value,
				parachuteSprintUsesStamina = ParachuteSprintUsesStamina.Value,
				parachuteSprintStaminaDrain = ParachuteSprintStaminaDrain.Value,
				jetpackMove = JetpackMove.Value,
				jetpackSprintMove = JetpackSprintMove.Value,
				jetpackFuelDrainPerSecond = JetpackFuelDrainPerSecond.Value,
				jetpackFuelPerItemMult = JetpackFuelPerItemMult.Value,
				jetpackSprintFuelDrain = JetpackSprintFuelDrain.Value,
				jetpackMaxFuel = JetpackMaxFuel.Value,
				jetpackUseRocketFlight = JetpackUseRocketFlight.Value,
				jetpackUseCustomRocketSettings = JetpackUseCustomRocketSettings.Value,
				rocketMove = RocketMove.Value,
				rocketFlightSeconds = RocketFlightSeconds.Value,
				rocketFuseSeconds = RocketFuseSeconds.Value,
				rocketLookSteerEnabled = RocketLookSteerEnabled.Value,
				rocketLookPitchSens = RocketLookPitchSens.Value,
				rocketLookYawSens = RocketLookYawSens.Value,
				rocketInvertVertical = RocketInvertVertical.Value,
				rocketFirstPerson = RocketFirstPerson.Value,
				rocketBlockWasdWhenLook = RocketBlockWasdWhenLook.Value,
				rocketCrouchCuts = RocketCrouchCuts.Value,
				parachuteManual = ParachuteManual.Value,
				parachuteCrouchCuts = ParachuteCrouchCuts.Value,
				parachuteRepack = ParachuteRepack.Value,
				parachuteRepackSeconds = ParachuteRepackSeconds.Value,
				parachutePackBlocksClimb = ParachutePackBlocksClimb.Value,
				parachutePackPreventRun = ParachutePackPreventRun.Value,
				parachutePackPreventMove = ParachutePackPreventMove.Value,
				jumpSpamDelay = JumpSpamDelay.Value,
				groundProbeExtra = GroundProbeExtra.Value
			};
		}

		internal static string Pack(HostCfg c)
		{
			CultureInfo invariantCulture = CultureInfo.InvariantCulture;
			return string.Join("|", F(c.balloonMove), F(c.balloonSprintMove), B(c.balloonSprintUsesStamina), F(c.balloonSprintStaminaDrain), F(c.parasolMove), F(c.parasolSprintMove), B(c.parasolSprintUsesStamina), F(c.parasolSprintStaminaDrain), F(c.gliderMove), F(c.gliderSprintMove), B(c.gliderUsesStamina), F(c.gliderStaminaDrain), B(c.gliderSprintUsesStamina), F(c.gliderSprintStaminaDrain), F(c.parachuteMove), F(c.parachuteSprintMove), B(c.parachuteSprintUsesStamina), F(c.parachuteSprintStaminaDrain), F(c.jetpackMove), F(c.jetpackFuelDrainPerSecond), F(c.jetpackFuelPerItemMult), F(c.jetpackSprintFuelDrain), B(c.jetpackUseRocketFlight), B(c.jetpackUseCustomRocketSettings), F(c.rocketMove), F(c.rocketFlightSeconds), F(c.rocketFuseSeconds), B(c.rocketLookSteerEnabled), F(c.rocketLookPitchSens), F(c.rocketLookYawSens), B(c.rocketInvertVertical), B(c.rocketFirstPerson), B(c.rocketBlockWasdWhenLook), B(c.parachuteCrouchCuts), B(c.parachuteRepack), F(c.parachuteRepackSeconds), F(c.jumpSpamDelay), B(c.balloonNeverPopUnlessManual), F(c.balloonPopHeight), F(c.balloonPopTimeSeconds), B(c.balloonCactusPops), B(c.parachutePackBlocksClimb), B(c.parachutePackPreventRun), B(c.parachutePackPreventMove), F(c.jetpackSprintMove), F(c.jetpackMaxFuel), B(c.parachuteManual), F(c.groundProbeExtra), B(c.rocketCrouchCuts));
		}

		internal static HostCfg Unpack(string s)
		{
			CultureInfo invariantCulture = CultureInfo.InvariantCulture;
			HostCfg c = Defaults();
			string[] array = (s ?? string.Empty).Split(new char[1] { '|' });
			if (array.Length < 46)
			{
				return Clamp(c);
			}
			Parse(array[0], invariantCulture, ref c.balloonMove);
			Parse(array[1], invariantCulture, ref c.balloonSprintMove);
			c.balloonSprintUsesStamina = array[2] == "1";
			Parse(array[3], invariantCulture, ref c.balloonSprintStaminaDrain);
			Parse(array[4], invariantCulture, ref c.parasolMove);
			Parse(array[5], invariantCulture, ref c.parasolSprintMove);
			c.parasolSprintUsesStamina = array[6] == "1";
			Parse(array[7], invariantCulture, ref c.parasolSprintStaminaDrain);
			Parse(array[8], invariantCulture, ref c.gliderMove);
			Parse(array[9], invariantCulture, ref c.gliderSprintMove);
			c.gliderUsesStamina = array[10] == "1";
			Parse(array[11], invariantCulture, ref c.gliderStaminaDrain);
			c.gliderSprintUsesStamina = array[12] == "1";
			Parse(array[13], invariantCulture, ref c.gliderSprintStaminaDrain);
			Parse(array[14], invariantCulture, ref c.parachuteMove);
			Parse(array[15], invariantCulture, ref c.parachuteSprintMove);
			c.parachuteSprintUsesStamina = array[16] == "1";
			Parse(array[17], invariantCulture, ref c.parachuteSprintStaminaDrain);
			Parse(array[18], invariantCulture, ref c.jetpackMove);
			Parse(array[19], invariantCulture, ref c.jetpackFuelDrainPerSecond);
			Parse(array[20], invariantCulture, ref c.jetpackFuelPerItemMult);
			Parse(array[21], invariantCulture, ref c.jetpackSprintFuelDrain);
			c.jetpackUseRocketFlight = array[22] == "1";
			c.jetpackUseCustomRocketSettings = array[23] == "1";
			Parse(array[24], invariantCulture, ref c.rocketMove);
			Parse(array[25], invariantCulture, ref c.rocketFlightSeconds);
			Parse(array[26], invariantCulture, ref c.rocketFuseSeconds);
			c.rocketLookSteerEnabled = array[27] == "1";
			Parse(array[28], invariantCulture, ref c.rocketLookPitchSens);
			Parse(array[29], invariantCulture, ref c.rocketLookYawSens);
			c.rocketInvertVertical = array[30] == "1";
			c.rocketFirstPerson = array[31] == "1";
			c.rocketBlockWasdWhenLook = array[32] == "1";
			c.parachuteCrouchCuts = array[33] == "1";
			c.parachuteRepack = array[34] == "1";
			Parse(array[35], invariantCulture, ref c.parachuteRepackSeconds);
			Parse(array[36], invariantCulture, ref c.jumpSpamDelay);
			c.balloonNeverPopUnlessManual = array[37] == "1";
			Parse(array[38], invariantCulture, ref c.balloonPopHeight);
			Parse(array[39], invariantCulture, ref c.balloonPopTimeSeconds);
			c.balloonCactusPops = array[40] == "1";
			c.parachutePackBlocksClimb = array[41] == "1";
			c.parachutePackPreventRun = array[42] == "1";
			c.parachutePackPreventMove = array[43] == "1";
			Parse(array[44], invariantCulture, ref c.jetpackSprintMove);
			Parse(array[45], invariantCulture, ref c.jetpackMaxFuel);
			if (array.Length >= 47)
			{
				c.parachuteManual = array[46] == "1";
			}
			if (array.Length >= 48)
			{
				Parse(array[47], invariantCulture, ref c.groundProbeExtra);
			}
			if (array.Length >= 49)
			{
				c.rocketCrouchCuts = array[48] == "1";
			}
			return Clamp(c);
		}

		private static string F(float v)
		{
			return v.ToString(CultureInfo.InvariantCulture);
		}

		private static string B(bool v)
		{
			return v ? "1" : "0";
		}

		private static void Parse(string s, CultureInfo ic, ref float dest)
		{
			float.TryParse(s, NumberStyles.Float, ic, out dest);
		}

		private static HostCfg Clamp(HostCfg c)
		{
			c.balloonMove = Mathf.Clamp(c.balloonMove, 0.25f, 5f);
			c.balloonSprintMove = Mathf.Clamp(c.balloonSprintMove, 1f, 2f);
			c.balloonSprintStaminaDrain = Mathf.Clamp(c.balloonSprintStaminaDrain, 0f, 1f);
			c.parasolMove = Mathf.Clamp(c.parasolMove, 0.25f, 5f);
			c.parasolSprintMove = Mathf.Clamp(c.parasolSprintMove, 1f, 2f);
			c.parasolSprintStaminaDrain = Mathf.Clamp(c.parasolSprintStaminaDrain, 0f, 1f);
			c.gliderMove = Mathf.Clamp(c.gliderMove, 0.25f, 5f);
			c.gliderSprintMove = Mathf.Clamp(c.gliderSprintMove, 1f, 2f);
			c.gliderStaminaDrain = Mathf.Clamp(c.gliderStaminaDrain, 0f, 1f);
			c.gliderSprintStaminaDrain = Mathf.Clamp(c.gliderSprintStaminaDrain, 0f, 1f);
			c.parachuteMove = Mathf.Clamp(c.parachuteMove, 0.25f, 5f);
			c.parachuteSprintMove = Mathf.Clamp(c.parachuteSprintMove, 1f, 2f);
			c.parachuteSprintStaminaDrain = Mathf.Clamp(c.parachuteSprintStaminaDrain, 0f, 1f);
			c.jetpackMove = Mathf.Clamp(c.jetpackMove, 0.25f, 5f);
			c.jetpackSprintMove = Mathf.Clamp(c.jetpackSprintMove, 1f, 2f);
			c.jetpackFuelDrainPerSecond = Mathf.Clamp(c.jetpackFuelDrainPerSecond, 0f, 100f);
			c.jetpackFuelPerItemMult = Mathf.Clamp(c.jetpackFuelPerItemMult, 0.25f, 5f);
			c.jetpackSprintFuelDrain = Mathf.Clamp(c.jetpackSprintFuelDrain, 0f, 100f);
			c.jetpackMaxFuel = Mathf.Clamp(c.jetpackMaxFuel, 10f, 1000f);
			c.rocketMove = Mathf.Clamp(c.rocketMove, 0.25f, 5f);
			c.rocketFlightSeconds = Mathf.Clamp(c.rocketFlightSeconds, 0.5f, 15f);
			c.rocketFuseSeconds = Mathf.Clamp(c.rocketFuseSeconds, 0.1f, 10f);
			c.rocketLookPitchSens = Mathf.Clamp(c.rocketLookPitchSens, 0f, 3f);
			c.rocketLookYawSens = Mathf.Clamp(c.rocketLookYawSens, 0f, 3f);
			c.parachuteRepackSeconds = Mathf.Clamp(c.parachuteRepackSeconds, 1f, 60f);
			c.jumpSpamDelay = Mathf.Clamp(c.jumpSpamDelay, 0.1f, 3f);
			c.groundProbeExtra = Mathf.Clamp(c.groundProbeExtra, 1f, 10f);
			c.balloonPopHeight = Mathf.Clamp(c.balloonPopHeight, 0f, 2000f);
			c.balloonPopTimeSeconds = Mathf.Clamp(c.balloonPopTimeSeconds, 0f, 600f);
			return c;
		}
	}
	internal sealed class FlightNet : MonoBehaviour, IOnEventCallback, IInRoomCallbacks, IMatchmakingCallbacks
	{
		internal const byte EventCode = 172;

		internal const int ProtocolVersion = 117;

		private const byte SubConfig = 1;

		private const byte SubConfigRequest = 2;

		private const byte SubCutRocket = 3;

		private const byte SubDropUnpacked = 4;

		private const float HostSyncTimeoutSeconds = 12f;

		private const float HostSyncRetrySeconds = 2f;

		internal static FlightNet Instance;

		internal static bool HostConfirmed;

		private Coroutine _debounce;

		private Coroutine _hostSyncWatch;

		internal static void Ensure()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			if (!((Object)(object)Instance != (Object)null))
			{
				GameObject val = new GameObject("PEAK_Skygear_Net");
				Object.DontDestroyOnLoad((Object)(object)val);
				Instance = val.AddComponent<FlightNet>();
				if (PhotonNetwork.InRoom)
				{
					Instance.HandleJoinedRoom();
				}
			}
		}

		private void OnEnable()
		{
			PhotonNetwork.AddCallbackTarget((object)this);
		}

		private void OnDisable()
		{
			PhotonNetwork.RemoveCallbackTarget((object)this);
		}

		public void OnJoinedRoom()
		{
			HandleJoinedRoom();
		}

		public void OnLeftRoom()
		{
			StopHostSyncWatch();
			HostConfirmed = false;
			FlightConfig.Synced = FlightConfig.BuildFromHost();
		}

		public void OnCreatedRoom()
		{
		}

		public void OnCreateRoomFailed(short returnCode, string message)
		{
		}

		public void OnFriendListUpdate(List<FriendInfo> friendList)
		{
		}

		public void OnJoinRandomFailed(short returnCode, string message)
		{
		}

		public void OnJoinRoomFailed(short returnCode, string message)
		{
		}

		public void OnMasterClientSwitched(Player newMasterClient)
		{
			if (PhotonNetwork.IsMasterClient)
			{
				HostConfirmed = true;
				FlightConfig.Synced = FlightConfig.BuildFromHost();
				BroadcastNow();
				StopHostSyncWatch();
			}
			else
			{
				HostConfirmed = false;
				RequestHostSync();
				RestartHostSyncWatch();
			}
		}

		public void OnPlayerEnteredRoom(Player newPlayer)
		{
			if (PhotonNetwork.IsMasterClient)
			{
				((MonoBehaviour)this).StartCoroutine(BroadcastAfterDelay(0.5f));
			}
		}

		public void OnPlayerLeftRoom(Player otherPlayer)
		{
		}

		public void OnRoomPropertiesUpdate(Hashtable propertiesThatChanged)
		{
		}

		public void OnPlayerPropertiesUpdate(Player targetPlayer, Hashtable changedProps)
		{
		}

		private void HandleJoinedRoom()
		{
			if (PhotonNetwork.InRoom)
			{
				if (PhotonNetwork.IsMasterClient)
				{
					HostConfirmed = true;
					FlightConfig.Synced = FlightConfig.BuildFromHost();
					BroadcastNow();
					StopHostSyncWatch();
				}
				else
				{
					HostConfirmed = false;
					RequestHostSync();
					RestartHostSyncWatch();
				}
			}
		}

		public void OnEvent(EventData e)
		{
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			if (e == null || e.Code != 172 || !(e.CustomData is object[] array) || array.Length < 2 || Convert.ToInt32(array[0]) != 117)
			{
				return;
			}
			byte b = Convert.ToByte(array[1]);
			if (b == 2 && PhotonNetwork.IsMasterClient)
			{
				BroadcastNow();
			}
			else if (b == 3 && array.Length >= 3)
			{
				if (Plugin.HandshakeActive())
				{
					ApplyCutRocket(Convert.ToInt32(array[2]));
				}
			}
			else if (b == 4 && array.Length >= 5 && PhotonNetwork.IsMasterClient)
			{
				Vector3 pos = default(Vector3);
				((Vector3)(ref pos))..ctor(Convert.ToSingle(array[2]), Convert.ToSingle(array[3]), Convert.ToSingle(array[4]));
				ParachuteRepack.MasterSpawnUnpacked(pos);
			}
			else
			{
				if (b != 1 || array.Length < 3 || PhotonNetwork.IsMasterClient)
				{
					return;
				}
				Player masterClient = PhotonNetwork.MasterClient;
				if (masterClient != null && e.Sender == masterClient.ActorNumber)
				{
					string text = array[2] as string;
					if (!string.IsNullOrEmpty(text))
					{
						FlightConfig.Synced = FlightConfig.Unpack(text);
						HostConfirmed = true;
						StopHostSyncWatch();
						Plugin.LogInfo("[Skygear] Host config sync applied.");
					}
				}
			}
		}

		internal static void BroadcastSpawnUnpacked(Vector3 pos)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Expected O, but got Unknown
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			if (!PhotonNetwork.InRoom || Plugin.HandshakeActive())
			{
				if (!PhotonNetwork.InRoom || PhotonNetwork.IsMasterClient)
				{
					ParachuteRepack.MasterSpawnUnpacked(pos);
					return;
				}
				PhotonNetwork.RaiseEvent((byte)172, (object)new object[5]
				{
					117,
					(byte)4,
					pos.x,
					pos.y,
					pos.z
				}, new RaiseEventOptions
				{
					Receivers = (ReceiverGroup)2
				}, SendOptions.SendReliable);
			}
		}

		internal static void BroadcastCutRocket(Character c)
		{
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Expected O, but got Unknown
			if (!((Object)(object)c == (Object)null) && c.refs != null && !((Object)(object)c.refs.view == (Object)null))
			{
				Flight.StopRocket(c);
				if (PhotonNetwork.InRoom && Plugin.HandshakeActive())
				{
					PhotonNetwork.RaiseEvent((byte)172, (object)new object[3]
					{
						117,
						(byte)3,
						c.refs.view.ViewID
					}, new RaiseEventOptions
					{
						Receivers = (ReceiverGroup)0
					}, SendOptions.SendReliable);
				}
			}
		}

		private static void ApplyCutRocket(int viewId)
		{
			PhotonView val = PhotonView.Find(viewId);
			if (!((Object)(object)val == (Object)null))
			{
				Character val2 = ((Component)val).GetComponent<Character>();
				if ((Object)(object)val2 == (Object)null)
				{
					val2 = ((Component)val).GetComponentInParent<Character>();
				}
				Flight.StopRocket(val2);
			}
		}

		internal static void ScheduleBroadcast()
		{
			if (!((Object)(object)Instance == (Object)null) && PhotonNetwork.InRoom && PhotonNetwork.IsMasterClient)
			{
				if (Instance._debounce != null)
				{
					((MonoBehaviour)Instance).StopCoroutine(Instance._debounce);
				}
				Instance._debounce = ((MonoBehaviour)Instance).StartCoroutine(Instance.DebounceBroadcast());
			}
		}

		private static void RequestHostSync()
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			if (PhotonNetwork.InRoom && !PhotonNetwork.IsMasterClient)
			{
				PhotonNetwork.RaiseEvent((byte)172, (object)new object[2]
				{
					117,
					(byte)2
				}, new RaiseEventOptions
				{
					Receivers = (ReceiverGroup)2
				}, SendOptions.SendReliable);
			}
		}

		private void RestartHostSyncWatch()
		{
			StopHostSyncWatch();
			if (PhotonNetwork.InRoom && !PhotonNetwork.IsMasterClient)
			{
				_hostSyncWatch = ((MonoBehaviour)this).StartCoroutine(WatchForHostSync());
			}
		}

		private void StopHostSyncWatch()
		{
			if (_hostSyncWatch != null)
			{
				((MonoBehaviour)this).StopCoroutine(_hostSyncWatch);
				_hostSyncWatch = null;
			}
		}

		private IEnumerator WatchForHostSync()
		{
			float elapsed = 0f;
			float nextRetry = 2f;
			while (elapsed < 12f)
			{
				if (!PhotonNetwork.InRoom || PhotonNetwork.IsMasterClient || HostConfirmed)
				{
					yield break;
				}
				elapsed += Time.unscaledDeltaTime;
				if (elapsed >= nextRetry)
				{
					RequestHostSync();
					nextRetry += 2f;
				}
				yield return null;
			}
			if (PhotonNetwork.InRoom && !PhotonNetwork.IsMasterClient && !HostConfirmed)
			{
				Plugin.LogWarning("[Skygear] Host does not appear to have this mod — using vanilla flight.");
			}
			_hostSyncWatch = null;
		}

		private IEnumerator DebounceBroadcast()
		{
			yield return (object)new WaitForSeconds(0.25f);
			BroadcastNow();
			_debounce = null;
		}

		private IEnumerator BroadcastAfterDelay(float seconds)
		{
			yield return (object)new WaitForSeconds(seconds);
			BroadcastNow();
		}

		private static void BroadcastNow()
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Expected O, but got Unknown
			if (PhotonNetwork.InRoom && PhotonNetwork.IsMasterClient)
			{
				FlightConfig.Synced = FlightConfig.BuildFromHost();
				string text = FlightConfig.Pack(FlightConfig.Synced);
				PhotonNetwork.RaiseEvent((byte)172, (object)new object[3]
				{
					117,
					(byte)1,
					text
				}, new RaiseEventOptions
				{
					Receivers = (ReceiverGroup)0
				}, SendOptions.SendReliable);
			}
		}
	}
	internal static class FlightPatches
	{
		[HarmonyPatch(typeof(CharacterMovement), "SetMovementState")]
		private static class Patch_SetMovementState
		{
			private static void Postfix(CharacterMovement __instance)
			{
				try
				{
					if (!Plugin.HandshakeActive())
					{
						return;
					}
					CrouchEdgeAction(__instance);
					Character character = Flight.GetCharacter(__instance);
					if (!((Object)(object)character == (Object)null) && character.IsLocal)
					{
						ParachuteRepack.ApplyLocomotion(character);
						if (Flight.TryGetSprintStamina(__instance, character, out var drainPerSecond))
						{
							character.UseStamina(drainPerSecond * Time.deltaTime, false, true);
						}
					}
				}
				catch (Exception e)
				{
					Plugin.LogPatchErrorOnce("SetMovementState", e);
				}
			}
		}

		[HarmonyPatch(typeof(CharacterMovement), "GetMovementForce")]
		private static class Patch_GetMovementForce
		{
			private static void Postfix(CharacterMovement __instance, ref float __result)
			{
				try
				{
					if (Plugin.HandshakeActive())
					{
						Character character = Flight.GetCharacter(__instance);
						float mult;
						if ((Object)(object)character != (Object)null && character.IsLocal && ParachuteRepack.IsRepacking && FlightConfig.Synced.parachutePackPreventMove)
						{
							__result = 0f;
						}
						else if (!((Object)(object)character == (Object)null) && Flight.TryGetMoveMult(__instance, character, out mult))
						{
							__result *= mult;
						}
					}
				}
				catch (Exception e)
				{
					Plugin.LogPatchErrorOnce("GetMovementForce", e);
				}
			}
		}

		[HarmonyPatch(typeof(Glider), "FixedUpdate")]
		private static class Patch_GliderFixedUpdate
		{
			private static void Prefix(Glider __instance, out float[] __state)
			{
				__state = new float[2] { __instance.stamUse, __instance.extraOpeningCost };
				if (Plugin.HandshakeActive())
				{
					FlightConfig.HostCfg synced = FlightConfig.Synced;
					if (!synced.gliderUsesStamina)
					{
						__instance.stamUse = 0f;
						__instance.extraOpeningCost = 0f;
					}
					else
					{
						__instance.stamUse = synced.gliderStaminaDrain;
					}
				}
			}

			private static void Postfix(Glider __instance, float[] __state)
			{
				if (__state != null && __state.Length >= 2)
				{
					__instance.stamUse = __state[0];
					__instance.extraOpeningCost = __state[1];
				}
				if (!Plugin.HandshakeActive())
				{
					return;
				}
				if ((Object)(object)__instance.item != (Object)null)
				{
					__instance.item.blocksSprint = false;
				}
				if (!FlightConfig.Synced.gliderUsesStamina && !__instance._gliding)
				{
					Character val = (((Object)(object)__instance.item != (Object)null) ? __instance.item.holderCharacter : null);
					if (!((Object)(object)val == (Object)null) && val.IsLocal && !((Object)(object)val.data == (Object)null) && val.data.fullyConscious && !val.data.isGrounded && val.refs != null && !((Object)(object)val.refs.movement == (Object)null))
					{
						val.refs.movement.ApplyGlider(__instance.extraYDrag, __instance.extraXZDrag, __instance.soarForwardForce * val.data.sinceGrounded);
						__instance._gliding = true;
					}
				}
			}
		}

		[HarmonyPatch(typeof(CharacterMovement), "TryJetpack")]
		private static class Patch_TryJetpack
		{
			private static void Prefix(CharacterMovement __instance, out float __state)
			{
				__state = __instance.jetpackFuelDecaySpeed;
				if (Plugin.HandshakeActive())
				{
					float jetpackFuelDecaySpeed = FlightConfig.Synced.jetpackFuelDrainPerSecond;
					Character character = Flight.GetCharacter(__instance);
					if (Flight.WantsSprint(character))
					{
						jetpackFuelDecaySpeed = FlightConfig.Synced.jetpackSprintFuelDrain;
					}
					__instance.jetpackFuelDecaySpeed = jetpackFuelDecaySpeed;
				}
			}

			private static void Postfix(CharacterMovement __instance, float __state)
			{
				__instance.jetpackFuelDecaySpeed = __state;
				if (Plugin.HandshakeActive())
				{
					Flight.SyncWornJetpackFuel(Flight.GetCharacter(__instance));
				}
			}
		}

		[HarmonyPatch(typeof(CharacterMovement), "JetpackRPC")]
		private static class Patch_JetpackRpcThrust
		{
			private static void Prefix(CharacterMovement __instance, out float __state)
			{
				__state = __instance.jetpackForce;
				if (Plugin.HandshakeActive())
				{
					Character character = Flight.GetCharacter(__instance);
					__instance.jetpackForce = __state * Flight.JetpackSprintThrustMult(character);
				}
			}

			private static void Postfix(CharacterMovement __instance, float __state)
			{
				__instance.jetpackForce = __state;
				if (Plugin.HandshakeActive())
				{
					Flight.SyncWornJetpackFuel(Flight.GetCharacter(__instance));
				}
			}
		}

		[HarmonyPatch(typeof(CharacterMovement), "JetpackRPC")]
		private static class Patch_JetpackRocketStyle
		{
			private static bool Prefix(CharacterMovement __instance, float fuel)
			{
				if (!Plugin.HandshakeActive() || !Flight.JetpackUsesRocketFlight())
				{
					return true;
				}
				Character character = Flight.GetCharacter(__instance);
				if ((Object)(object)character == (Object)null || (Object)(object)character.player == (Object)null)
				{
					return true;
				}
				FloatItemData val = default(FloatItemData);
				if (!character.IsLocal && character.player.backpackSlot != null && ((ItemSlot)character.player.backpackSlot).data != null && ((ItemSlot)character.player.backpackSlot).data.TryGetDataEntry<FloatItemData>((DataEntryKey)10, ref val))
				{
					val.Value = fuel;
					Flight.SyncWornJetpackFuel(character);
				}
				if (fuel <= 0f)
				{
					return false;
				}
				if (character.refs != null && (Object)(object)character.refs.backpackHandler != (Object)null && (Object)(object)character.refs.backpackHandler.jetpack != (Object)null)
				{
					character.refs.backpackHandler.jetpack.ActivateJetpack();
				}
				character.data.isJumping = true;
				Flight.EnsureRocketCam(character);
				return false;
			}
		}

		[HarmonyPatch(typeof(Jetpack), "ForceStopJetpack")]
		private static class Patch_JetpackStopCam
		{
			private static void Postfix()
			{
				Flight.StopJetpackRocketCam();
			}
		}

		[HarmonyPatch(typeof(JetpackItem), "RPCAddFuel")]
		private static class Patch_JetpackRpcAddFuel
		{
			private static void Prefix(JetpackItem __instance, ref float addedFuel)
			{
				if (Plugin.HandshakeActive())
				{
					addedFuel *= FlightConfig.Synced.jetpackFuelPerItemMult;
					__instance.startingFuel = Flight.JetpackMaxFuel();
				}
			}

			private static void Postfix(JetpackItem __instance)
			{
				ClampHeldJetpack(__instance);
			}
		}

		[HarmonyPatch(typeof(JetpackItem), "Start")]
		[HarmonyPatch(typeof(JetpackItem), "OnInstanceDataSet")]
		private static class Patch_JetpackItemFuelCap
		{
			private static void Prefix(JetpackItem __instance)
			{
				if (Plugin.HandshakeActive())
				{
					__instance.startingFuel = Flight.JetpackMaxFuel();
				}
			}

			private static void Postfix(JetpackItem __instance)
			{
				ClampHeldJetpack(__instance);
			}
		}

		[HarmonyPatch(typeof(CharacterBackpackHandler), "RPCAddFuelToJetpack")]
		private static class Patch_WearJetpackRpcAddFuel
		{
			private static bool Prefix(CharacterBackpackHandler __instance, float addedFuel)
			{
				//IL_0118: Unknown result type (might be due to invalid IL or missing references)
				if (!Plugin.HandshakeActive())
				{
					return true;
				}
				if ((Object)(object)__instance == (Object)null || (Object)(object)__instance.character == (Object)null || (Object)(object)__instance.character.player == (Object)null)
				{
					return true;
				}
				BackpackSlot backpackSlot = __instance.character.player.backpackSlot;
				if (backpackSlot == null || ((ItemSlot)backpackSlot).data == null)
				{
					return true;
				}
				FloatItemData val = default(FloatItemData);
				if (!((ItemSlot)backpackSlot).data.TryGetDataEntry<FloatItemData>((DataEntryKey)10, ref val))
				{
					return true;
				}
				addedFuel *= FlightConfig.Synced.jetpackFuelPerItemMult;
				val.Value = Mathf.Min(val.Value + addedFuel, Flight.JetpackMaxFuel());
				FloatItemData percent = null;
				((ItemSlot)backpackSlot).data.TryGetDataEntry<FloatItemData>((DataEntryKey)11, ref percent);
				Flight.SyncJetpackFuelPercent(val, percent);
				if ((Object)(object)__instance.fuelFlame != (Object)null)
				{
					__instance.fuelFlame.Play();
				}
				if ((Object)(object)__instance.fuelFlameSFX != (Object)null)
				{
					__instance.fuelFlameSFX.Play(((Component)__instance).transform.position);
				}
				return false;
			}
		}

		[HarmonyPatch(typeof(Backpack), "GetFuel")]
		private static class Patch_BackpackGetFuel
		{
			private static void Postfix(Backpack __instance, ref float __result)
			{
				if (Plugin.HandshakeActive() && !((Object)(object)__instance == (Object)null))
				{
					FloatItemData data = ((Item)__instance).GetData<FloatItemData>((DataEntryKey)10);
					if (data != null)
					{
						__result = Mathf.Clamp01(data.Value / Flight.JetpackMaxFuel());
					}
				}
			}
		}

		[HarmonyPatch(typeof(CharacterMovement), "TryRocket")]
		private static class Patch_TryRocket
		{
			private static void Prefix(CharacterMovement __instance)
			{
				if (Plugin.HandshakeActive())
				{
					__instance.rocketTime = FlightConfig.Synced.rocketFlightSeconds;
				}
			}
		}

		[HarmonyPatch(typeof(CharacterBackpackHandler), "RPCA_Fire")]
		private static class Patch_RocketFireVisual
		{
			private static bool Prefix(CharacterBackpackHandler __instance)
			{
				if (!Plugin.HandshakeActive())
				{
					return true;
				}
				((MonoBehaviour)__instance).StartCoroutine(FireForConfiguredTime(__instance));
				return false;
			}

			private static IEnumerator FireForConfiguredTime(CharacterBackpackHandler handler)
			{
				if ((Object)(object)handler == (Object)null || (Object)(object)handler.character == (Object)null || handler.character.refs == null)
				{
					yield break;
				}
				CharacterMovement move = handler.character.refs.movement;
				if (!((Object)(object)move == (Object)null) && !((Object)(object)handler.rocketpackVisuals == (Object)null) && !((Object)(object)handler.rocketpackVisuals.rocketFX == (Object)null))
				{
					RocketFX fx = handler.rocketpackVisuals.rocketFX;
					move.rocketLit = false;
					move.rocketActive = true;
					move.rocketTime = FlightConfig.Synced.rocketFlightSeconds;
					fx.RocketFire();
					KeepRocketFireVfx(fx, loop: true);
					handler.rocketpackVisuals.rocketColl.enabled = false;
					float t = 0f;
					float duration = Mathf.Max(0.1f, FlightConfig.Synced.rocketFlightSeconds);
					while (t < duration && move.rocketActive)
					{
						t += Time.fixedDeltaTime;
						KeepRocketFireVfx(fx, loop: true);
						yield return (object)new WaitForFixedUpdate();
					}
					KeepRocketFireVfx(fx, loop: false);
					fx.RocketExtinguish();
					handler.rocketpackVisuals.rocketColl.enabled = true;
					if ((Object)(object)handler.photonView != (Object)null && handler.photonView.IsMine && (Object)(object)handler.character.refs.items != (Object)null)
					{
						handler.character.refs.items.DeleteMyBackpack();
					}
				}
			}

			private static void KeepRocketFireVfx(RocketFX fx, bool loop)
			{
				//IL_0032: Unknown result type (might be due to invalid IL or missing references)
				//IL_0037: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)fx == (Object)null)
				{
					return;
				}
				ParticleSystem[] componentsInChildren = ((Component)fx).GetComponentsInChildren<ParticleSystem>(true);
				foreach (ParticleSystem val in componentsInChildren)
				{
					if (!((Object)(object)val == (Object)null))
					{
						MainModule main = val.main;
						((MainModule)(ref main)).loop = loop;
						if (loop && !val.isPlaying)
						{
							val.Play();
						}
					}
				}
				if (loop && (Object)(object)fx.fireSFX != (Object)null && !fx.fireSFX.activeSelf)
				{
					fx.fireSFX.SetActive(true);
				}
			}
		}

		[HarmonyPatch(typeof(CharacterMovement), "FixedUpdate")]
		private static class Patch_RocketPhysics
		{
			private static readonly Dictionary<CharacterMovement, Vector2> s_vanillaRocket = new Dictionary<CharacterMovement, Vector2>();

			private static void Prefix(CharacterMovement __instance)
			{
				//IL_0067: Unknown result type (might be due to invalid IL or missing references)
				//IL_006c: Unknown result type (might be due to invalid IL or missing references)
				try
				{
					ApplyRocketMoveScale(__instance);
					if (Plugin.HandshakeActive())
					{
						Character character = Flight.GetCharacter(__instance);
						if (!((Object)(object)character == (Object)null) && !((Object)(object)character.input == (Object)null) && Flight.CustomRocketControlsActive(__instance, character) && FlightConfig.Synced.rocketBlockWasdWhenLook)
						{
							character.input.movementInput = Vector2.zero;
						}
					}
				}
				catch (Exception e)
				{
					Plugin.LogPatchErrorOnce("RocketPhysicsPrefix", e);
				}
			}

			private static void Postfix(CharacterMovement __instance)
			{
				try
				{
					if (!Plugin.HandshakeActive())
					{
						return;
					}
					Character character = Flight.GetCharacter(__instance);
					if (!((Object)(object)character == (Object)null))
					{
						if (Flight.JetpackUsesRocketFlight() && Flight.IsJetpacking(character))
						{
							Flight.ApplyRocketStylePhysics(character, __instance, Flight.JetpackUsesCustomRocketSettings());
						}
						else if (Flight.CustomRocketControlsActive(__instance, character))
						{
							Flight.ApplyLookSteer(character);
						}
					}
				}
				catch (Exception e)
				{
					Plugin.LogPatchErrorOnce("RocketLookSteer", e);
				}
			}

			private static void ApplyRocketMoveScale(CharacterMovement move)
			{
				//IL_0069: Unknown result type (might be due to invalid IL or missing references)
				//IL_006e: Unknown result type (might be due to invalid IL or missing references)
				//IL_008a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0098: Unknown result type (might be due to invalid IL or missing references)
				//IL_0058: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)move == (Object)null)
				{
					return;
				}
				if (!Plugin.HandshakeActive() || !move.rocketActive)
				{
					RestoreRocketMoveScale(move);
					return;
				}
				if (!s_vanillaRocket.ContainsKey(move))
				{
					s_vanillaRocket[move] = new Vector2(move.rocketForce, move.rocketTorque);
				}
				Vector2 val = s_vanillaRocket[move];
				float num = Mathf.Clamp(FlightConfig.Synced.rocketMove, 0.25f, 5f);
				move.rocketForce = val.x * num;
				move.rocketTorque = val.y;
			}

			private static void RestoreRocketMoveScale(CharacterMovement move)
			{
				//IL_0024: Unknown result type (might be due to invalid IL or missing references)
				//IL_0030: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)move == (Object)null) && s_vanillaRocket.TryGetValue(move, out var value))
				{
					move.rocketForce = value.x;
					move.rocketTorque = value.y;
					s_vanillaRocket.Remove(move);
				}
			}
		}

		[HarmonyPatch(typeof(MainCameraMovement), "LateUpdate")]
		private static class Patch_RocketFirstPerson
		{
			private static void Prefix(MainCameraMovement __instance, out bool __state)
			{
				__state = false;
				try
				{
					if (Plugin.HandshakeActive() && __instance.isRocketing && Flight.WantFirstPerson())
					{
						__state = true;
						__instance.isRocketing = false;
						__instance.ragdollCam = 0f;
					}
				}
				catch (Exception e)
				{
					Plugin.LogPatchErrorOnce("RocketFirstPerson", e);
				}
			}

			private static void Postfix(MainCameraMovement __instance, bool __state)
			{
				if (__state)
				{
					__instance.isRocketing = true;
				}
			}
		}

		[HarmonyPatch(typeof(Character), "UpdateVariablesFixed")]
		private static class Patch_BlockAutoParachute
		{
			private static void Prefix(Character __instance, out bool __state)
			{
				__state = false;
				if (Plugin.HandshakeActive() && FlightConfig.Synced.parachuteManual && !((Object)(object)__instance == (Object)null) && __instance.IsLocal && !((Object)(object)__instance.data == (Object)null) && __instance.data.hasParachute)
				{
					__state = true;
					__instance.data.hasParachute = false;
				}
			}

			private static void Postfix(Character __instance, bool __state)
			{
				try
				{
					Flight.TickFalling(__instance);
				}
				catch (Exception e)
				{
					Plugin.LogPatchErrorOnce("TickFalling", e);
				}
				if (__state && (Object)(object)__instance != (Object)null && (Object)(object)__instance.data != (Object)null)
				{
					__instance.data.hasParachute = true;
				}
			}
		}

		[HarmonyPatch(typeof(CharacterBalloons), "SetParachute")]
		private static class Patch_SetParachute
		{
			private static bool Prefix(CharacterBalloons __instance, bool shouldOpen, out bool __state)
			{
				__state = !shouldOpen && (Object)(object)__instance != (Object)null && __instance._isParachuteOpen;
				if (!shouldOpen)
				{
					return true;
				}
				if (!Plugin.HandshakeActive())
				{
					return true;
				}
				if (!FlightConfig.Synced.parachuteManual)
				{
					return true;
				}
				return Flight.ManualParachuteOpen;
			}

			private static void Postfix(CharacterBalloons __instance, bool shouldOpen, bool __state)
			{
				if (!Plugin.HandshakeActive())
				{
					return;
				}
				Character val = (((Object)(object)__instance != (Object)null) ? __instance.character : null);
				if (!((Object)(object)val == (Object)null) && val.IsLocal)
				{
					if (shouldOpen && __instance._isParachuteOpen)
					{
						ParachuteRepack.MarkDeployed();
					}
					if (__state)
					{
						ParachuteRepack.OnParachuteClosed(val);
					}
				}
			}
		}

		[HarmonyPatch(typeof(Item), "GetItemName")]
		private static class Patch_ParachuteItemName
		{
			private static void Postfix(Item __instance, ItemInstanceData data, ref string __result)
			{
				if (Flight.IsParachuteItem(__instance))
				{
					if (ParachuteRepack.IsUnpacked(__instance, data))
					{
						__result = "UNPACKED PARACHUTE";
					}
					else if (Plugin.HandshakeActive() && FlightConfig.Synced.parachuteManual)
					{
						__result = "PARACHUTE";
					}
				}
			}
		}

		[HarmonyPatch(typeof(CharacterItems), "OnPickupAccepted")]
		private static class Patch_PickupAccepted
		{
			private static void Postfix(CharacterItems __instance, byte slotID)
			{
				if (!((Object)(object)__instance == (Object)null) && !((Object)(object)__instance.character == (Object)null) && __instance.character.IsLocal)
				{
					ParachuteRepack.OnPickedUpSlot(__instance.character, slotID);
				}
			}
		}

		[HarmonyPatch(typeof(Item), "FinishCastPrimary")]
		private static class Patch_FinishCastPrimary
		{
			private static void Postfix(Item __instance)
			{
				if (Plugin.HandshakeActive())
				{
					Character val = (((Object)(object)__instance != (Object)null) ? __instance.holderCharacter : null);
					if (!((Object)(object)val == (Object)null) && val.IsLocal && Flight.IsHoldingParachute(val) && Flight.CanDeployParachute(val))
					{
						Flight.OpenParachute(val);
					}
				}
			}
		}

		[HarmonyPatch(typeof(TiedBalloon), "Pop")]
		private static class Patch_TiedBalloonPop
		{
			private static bool Prefix()
			{
				if (!Plugin.HandshakeActive())
				{
					return true;
				}
				if (!FlightConfig.Synced.balloonNeverPopUnlessManual)
				{
					return true;
				}
				return Flight.ManualBalloonPop;
			}
		}

		[HarmonyPatch(typeof(TiedBalloon), "FixedUpdate")]
		private static class Patch_TiedBalloonLimits
		{
			private static bool s_loggedPrefab;

			private static void Prefix(TiedBalloon __instance, out Vector2 __state)
			{
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				//IL_0029: Unknown result type (might be due to invalid IL or missing references)
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				__state = Vector2.zero;
				if (!((Object)(object)__instance == (Object)null))
				{
					__state = new Vector2(__instance.popHeight, __instance.popTime);
					if (!s_loggedPrefab)
					{
						s_loggedPrefab = true;
						Plugin.LogInfo($"[Skygear] TiedBalloon prefab popTime={__instance.popTime:0.##}s popHeight={__instance.popHeight:0.##}");
					}
					if (Plugin.HandshakeActive())
					{
						FlightConfig.HostCfg synced = FlightConfig.Synced;
						__instance.popHeight = Mathf.Max(0f, synced.balloonPopHeight);
						__instance.popTime = Mathf.Max(0f, synced.balloonPopTimeSeconds);
					}
				}
			}

			private static void Postfix(TiedBalloon __instance, Vector2 __state)
			{
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				//IL_001b: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)__instance == (Object)null))
				{
					__instance.popHeight = __state.x;
					__instance.popTime = __state.y;
				}
			}
		}

		[HarmonyPatch(typeof(TiedBalloonCollision), "OnCollisionEnter")]
		private static class Patch_TiedBalloonCactus
		{
			private static bool Prefix()
			{
				if (!Plugin.HandshakeActive())
				{
					return true;
				}
				if (FlightConfig.Synced.balloonNeverPopUnlessManual)
				{
					return fal