Decompiled source of PeakToBeachReborn v1.1.1

BepInEx/plugins/Totodu4730.PeakToBeachReborn.dll

Decompiled 5 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Logging;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Totodu4730.PeakToBeachReborn")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0")]
[assembly: AssemblyProduct("Totodu4730.PeakToBeachReborn")]
[assembly: AssemblyTitle("PeakToBeachReborn")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace BepInEx
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	[Embedded]
	internal sealed class BepInAutoPluginAttribute : Attribute
	{
		public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace BepInEx.Preloader.Core.Patching
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	[Embedded]
	internal sealed class PatcherAutoPluginAttribute : Attribute
	{
		public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace Microsoft.CodeAnalysis
{
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace PeakToBeachReborn
{
	[BepInPlugin("Totodu4730.PeakToBeachReborn", "PeakToBeachReborn", "1.1.1")]
	public class Plugin : BaseUnityPlugin
	{
		private sealed class PhotonEventBridge<T>
		{
			private readonly Plugin owner;

			public PhotonEventBridge(Plugin owner)
			{
				this.owner = owner;
			}

			public void Handle(T eventData)
			{
				owner.HandlePhotonEventObject(eventData);
			}
		}

		internal static ManualLogSource Log = null;

		private static readonly Vector3 SavedHipStartPosition = new Vector3(16.8f, 1228.7f, 2240.45f);

		private bool descentModeReady;

		private bool isCampfireTransitionRunning;

		private float descentModeReadyAt;

		private float nextOrbFogKillAt;

		private bool beachFlareFinaleTriggered;

		private object? harmonyInstance;

		private static Plugin? Instance = null;

		private readonly HashSet<int> triggeredCampfires = new HashSet<int>();

		private readonly Dictionary<string, float> nextFarLitCampfireLogAt = new Dictionary<string, float>(StringComparer.Ordinal);

		private readonly HashSet<string> completedCampfirePaths = new HashSet<string>(StringComparer.Ordinal);

		private bool initialCampfireResetDone;

		private bool summitBackpackRelocated;

		private bool summitStartConfirmed;

		private float nextSummitRecoveryCheckAt;

		private int summitRecoveryAttempts;

		private float nextMultiStateLogAt;

		private float multiStateLogUntil;

		private bool routeWasActiveAtCharacterLoss;

		private float localCharacterLostAt = -9999f;

		private bool respawnRecoveryPending;

		private float respawnRecoveryAt;

		private int respawnRecoveryAttempts;

		private const byte NetworkEventStartDescent = 170;

		private const byte NetworkEventSegmentChange = 171;

		private const byte NetworkEventHelicopterRequest = 172;

		private const byte NetworkEventHelicopterPrepare = 173;

		private const byte NetworkEventHelicopterActivate = 174;

		private const byte NetworkEventStartRequest = 175;

		private const byte NetworkEventKilnSceneStateChunk = 176;

		private bool photonEventBridgeInstalled;

		private object? photonEventSource;

		private EventInfo? photonEventInfo;

		private object? photonEventBridge;

		private Delegate? photonEventDelegate;

		private float nextPhotonBridgeRetryAt;

		private string photonBridgeLastWaitReason = "";

		private bool networkStartSequenceRunning;

		private bool helicopterNetworkSequenceRunning;

		private bool peakSequencePreparedForNetwork;

		private bool autoStartTriggered;

		private bool hadLocalCharacterLastFrame;

		private bool transitionBlackout;

		private float localCharacterReadyAt;

		private float nextStartRequestAt;

		private bool descentNetworkStarted;

		private int networkRunEpoch;

		private int lastHandledNetworkStartEpoch;

		private float nextFlareVanillaBlockLogAt;

		private readonly Dictionary<int, string> kilnSceneStateChunks = new Dictionary<int, string>();

		private int kilnSceneStateExpectedChunks;

		private int kilnSceneStateChunkEpoch = -1;

		private int lastAppliedKilnSceneStateEpoch = -1;

		private bool forcePhotonMasterForLocalCalderaJump;

		private bool joinerHostLikeCalderaJumpSucceeded;

		private bool joinerHostLikeTropicsJumpSucceeded;

		private bool joinerHostLikeBeachJumpSucceeded;

		private bool photonMasterGetterPatchInstalled;

		private readonly Dictionary<Behaviour, bool> kilnSoftSuppressedBehaviours = new Dictionary<Behaviour, bool>();

		private readonly Dictionary<Renderer, bool> kilnSoftSuppressedRenderers = new Dictionary<Renderer, bool>();

		private readonly Dictionary<Collider, bool> kilnSoftSuppressedColliders = new Dictionary<Collider, bool>();

		private readonly Dictionary<ParticleSystem, bool> kilnSoftSuppressedParticles = new Dictionary<ParticleSystem, bool>();

		private bool kilnSoftSuppressionActive;

		private void Awake()
		{
			Log = ((BaseUnityPlugin)this).Logger;
			Instance = this;
			Log.LogInfo((object)"PeakToBeachReborn chargé !");
			PatchFlareActionForBeachFinale();
			TryInstallPhotonEventBridge();
		}

		private void OnDestroy()
		{
			try
			{
				if (photonEventInfo != null && photonEventSource != null && (object)photonEventDelegate != null)
				{
					photonEventInfo.GetRemoveMethod(nonPublic: true)?.Invoke(photonEventSource, new object[1] { photonEventDelegate });
				}
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Désabonnement EventReceived impossible : " + ex.Message));
			}
			photonEventBridgeInstalled = false;
			photonEventSource = null;
			photonEventInfo = null;
			photonEventBridge = null;
			photonEventDelegate = null;
			if (Instance == this)
			{
				Instance = null;
			}
		}

		private void OnGUI()
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			if (transitionBlackout)
			{
				int depth = GUI.depth;
				GUI.depth = -10000;
				GUI.DrawTexture(new Rect(0f, 0f, (float)Screen.width, (float)Screen.height), (Texture)(object)Texture2D.blackTexture, (ScaleMode)0);
				GUI.depth = depth;
			}
		}

		private void Update()
		{
			TryInstallPhotonEventBridgeTick();
			TrackRunLifecycleForAutoStart();
			AutoStartDescentTick();
			LogCompactMultiplayerStateTick();
			KeepLocalPlayerAtSummitUntilRouteStartsTick();
			RecoverLocalRespawnTick();
			WatchLitCampfiresForDescentTransition();
			KeepOrbFogDisabledTick();
		}

		private void TryInstallPhotonEventBridgeTick()
		{
			if (!photonEventBridgeInstalled && !(Time.time < nextPhotonBridgeRetryAt))
			{
				nextPhotonBridgeRetryAt = Time.time + 1f;
				TryInstallPhotonEventBridge();
			}
		}

		private void TryInstallPhotonEventBridge()
		{
			if (photonEventBridgeInstalled)
			{
				return;
			}
			try
			{
				Type type = FindLoadedType("Photon.Pun.PhotonNetwork");
				if (type == null)
				{
					LogPhotonBridgeWaitReason("Photon.Pun.PhotonNetwork introuvable");
					return;
				}
				PropertyInfo property = type.GetProperty("NetworkingClient", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				FieldInfo field = type.GetField("NetworkingClient", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				object obj = null;
				if (property != null)
				{
					obj = property.GetValue(null);
				}
				else if (field != null)
				{
					obj = field.GetValue(null);
				}
				if (obj == null)
				{
					string text = string.Join(", ", (from member in type.GetMembers(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)
						where member.Name.IndexOf("client", StringComparison.OrdinalIgnoreCase) >= 0 || member.Name.IndexOf("network", StringComparison.OrdinalIgnoreCase) >= 0
						select $"{member.MemberType}:{member.Name}").Take(20));
					LogPhotonBridgeWaitReason("PhotonNetwork.NetworkingClient introuvable/null | candidats=[" + text + "]");
					return;
				}
				EventInfo eventInfo = FindInstanceEventInHierarchy(obj.GetType(), "EventReceived");
				if (eventInfo == null)
				{
					LogPhotonBridgeWaitReason("EventReceived introuvable sur " + obj.GetType().FullName);
					return;
				}
				Type eventHandlerType = eventInfo.EventHandlerType;
				Type type2 = (eventHandlerType?.GetMethod("Invoke"))?.GetParameters().FirstOrDefault()?.ParameterType;
				if (eventHandlerType == null || type2 == null)
				{
					string text2 = ((eventHandlerType != null) ? (eventHandlerType.FullName ?? eventHandlerType.Name) : "null");
					LogPhotonBridgeWaitReason("Signature EventReceived illisible | handler=" + text2);
					return;
				}
				Type type3 = typeof(PhotonEventBridge<>).MakeGenericType(type2);
				object obj2 = Activator.CreateInstance(type3, this);
				MethodInfo method = type3.GetMethod("Handle", BindingFlags.Instance | BindingFlags.Public);
				if (obj2 == null || method == null)
				{
					LogPhotonBridgeWaitReason("Création PhotonEventBridge runtime impossible");
					return;
				}
				Delegate obj3 = Delegate.CreateDelegate(eventHandlerType, obj2, method);
				MethodInfo addMethod = eventInfo.GetAddMethod(nonPublic: true);
				if (addMethod == null)
				{
					LogPhotonBridgeWaitReason("Accessor add_EventReceived introuvable");
					return;
				}
				addMethod.Invoke(obj, new object[1] { obj3 });
				photonEventSource = obj;
				photonEventInfo = eventInfo;
				photonEventBridge = obj2;
				photonEventDelegate = obj3;
				photonEventBridgeInstalled = true;
				photonBridgeLastWaitReason = "";
				Log.LogInfo((object)$"Photon EventReceived branché pour le mod | sourceType={obj.GetType().FullName} | eventData={type2.FullName} | inRoom={IsPhotonInRoom()} | master={IsPhotonMasterClient()}");
			}
			catch (Exception ex)
			{
				LogPhotonBridgeWaitReason("exception " + ex.GetType().Name + " - " + ex.Message);
			}
		}

		private EventInfo? FindInstanceEventInHierarchy(Type type, string eventName)
		{
			Type type2 = type;
			while (type2 != null)
			{
				EventInfo eventInfo = type2.GetEvent(eventName, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (eventInfo != null)
				{
					return eventInfo;
				}
				type2 = type2.BaseType;
			}
			return null;
		}

		private void LogPhotonBridgeWaitReason(string reason)
		{
			if (!(reason == photonBridgeLastWaitReason))
			{
				photonBridgeLastWaitReason = reason;
				Log.LogWarning((object)("PHOTON BRIDGE WAIT | " + reason));
			}
		}

		private bool IsPhotonInRoom()
		{
			try
			{
				object obj = (FindLoadedType("Photon.Pun.PhotonNetwork")?.GetProperty("InRoom", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))?.GetValue(null);
				bool flag = default(bool);
				int num;
				if (obj is bool)
				{
					flag = (bool)obj;
					num = 1;
				}
				else
				{
					num = 0;
				}
				return (byte)((uint)num & (flag ? 1u : 0u)) != 0;
			}
			catch
			{
				return false;
			}
		}

		private bool IsPhotonMasterClient()
		{
			try
			{
				if (!IsPhotonInRoom())
				{
					return true;
				}
				object obj = (FindLoadedType("Photon.Pun.PhotonNetwork")?.GetProperty("IsMasterClient", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))?.GetValue(null);
				bool flag = default(bool);
				int num;
				if (obj is bool)
				{
					flag = (bool)obj;
					num = 1;
				}
				else
				{
					num = 0;
				}
				return (byte)((uint)num & (flag ? 1u : 0u)) != 0;
			}
			catch
			{
				return false;
			}
		}

		private object? ReadReflectedMember(object instance, string memberName)
		{
			Type type = instance.GetType();
			PropertyInfo property = type.GetProperty(memberName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			if (property != null && property.GetIndexParameters().Length == 0)
			{
				return property.GetValue((property.GetMethod != null && property.GetMethod.IsStatic) ? null : instance);
			}
			FieldInfo field = type.GetField(memberName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			return field?.GetValue(field.IsStatic ? null : instance);
		}

		private bool SetReflectedMember(object instance, string memberName, object value)
		{
			try
			{
				Type type = instance.GetType();
				PropertyInfo property = type.GetProperty(memberName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if (property != null && property.CanWrite)
				{
					property.SetValue((property.SetMethod != null && property.SetMethod.IsStatic) ? null : instance, value);
					return true;
				}
				FieldInfo field = type.GetField(memberName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null)
				{
					field.SetValue(field.IsStatic ? null : instance, value);
					return true;
				}
			}
			catch
			{
			}
			return false;
		}

		private bool SendPhotonModEvent(byte eventCode, object content, string receiverGroupName)
		{
			if (!IsPhotonInRoom())
			{
				return false;
			}
			try
			{
				Type type = FindLoadedType("Photon.Pun.PhotonNetwork");
				if (type == null)
				{
					return false;
				}
				MethodInfo methodInfo = type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault(delegate(MethodInfo method)
				{
					if (method.Name != "RaiseEvent")
					{
						return false;
					}
					ParameterInfo[] parameters2 = method.GetParameters();
					return parameters2.Length == 4 && parameters2[0].ParameterType == typeof(byte);
				});
				if (methodInfo == null)
				{
					Log.LogWarning((object)"PhotonNetwork.RaiseEvent(byte, object, RaiseEventOptions, SendOptions) introuvable.");
					return false;
				}
				ParameterInfo[] parameters = methodInfo.GetParameters();
				Type parameterType = parameters[2].ParameterType;
				Type parameterType2 = parameters[3].ParameterType;
				object obj = Activator.CreateInstance(parameterType);
				if (obj == null)
				{
					return false;
				}
				Type type2 = parameterType.GetProperty("Receivers", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.PropertyType ?? parameterType.GetField("Receivers", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.FieldType;
				if (type2 == null || !type2.IsEnum)
				{
					return false;
				}
				object value = Enum.Parse(type2, receiverGroupName, ignoreCase: true);
				if (!SetReflectedMember(obj, "Receivers", value))
				{
					return false;
				}
				object obj2 = parameterType2.GetField("SendReliable", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(null) ?? parameterType2.GetProperty("SendReliable", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(null) ?? Activator.CreateInstance(parameterType2);
				if (obj2 == null)
				{
					return false;
				}
				SetReflectedMember(obj2, "Reliability", true);
				object obj3 = methodInfo.Invoke(null, new object[4] { eventCode, content, obj, obj2 });
				bool flag = default(bool);
				int num;
				if (obj3 is bool)
				{
					flag = (bool)obj3;
					num = ((1 == 0) ? 1 : 0);
				}
				else
				{
					num = 1;
				}
				bool flag2 = (byte)((uint)num | (flag ? 1u : 0u)) != 0;
				string text = ((eventCode == 176 && content is string text2) ? $"string[{text2.Length}]" : (content?.ToString() ?? "null"));
				Log.LogInfo((object)$"MOD NET SEND | code={eventCode} | receiver={receiverGroupName} | content={text} | sent={flag2}");
				return flag2;
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)$"SendPhotonModEvent impossible | code={eventCode} | receiver={receiverGroupName} | {ex.GetType().Name} - {ex.Message}");
				return false;
			}
		}

		private void HandlePhotonEventObject(object? eventData)
		{
			//IL_02b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b9: Unknown result type (might be due to invalid IL or missing references)
			if (eventData == null)
			{
				return;
			}
			try
			{
				object obj = ReadReflectedMember(eventData, "Code");
				if (obj == null)
				{
					return;
				}
				byte b = Convert.ToByte(obj);
				if (b < 170 || b > 176)
				{
					return;
				}
				object obj2 = ReadReflectedMember(eventData, "CustomData");
				string arg = ((b == 176 && obj2 is string text) ? $"string[{text.Length}]" : (obj2?.ToString() ?? "null"));
				Log.LogInfo((object)$"MOD NET RECEIVE | code={b} | content={arg} | master={IsPhotonMasterClient()}");
				switch (b)
				{
				case 170:
				{
					int num = ((obj2 == null) ? 1 : Convert.ToInt32(obj2));
					if (num <= lastHandledNetworkStartEpoch)
					{
						Log.LogInfo((object)$"START_DESCENT ignoré : epoch déjà traité | reçu={num} | dernier={lastHandledNetworkStartEpoch}");
						break;
					}
					lastHandledNetworkStartEpoch = num;
					networkRunEpoch = Math.Max(networkRunEpoch, num);
					if (networkStartSequenceRunning && !descentModeReady)
					{
						Log.LogInfo((object)$"START_DESCENT epoch={num} reçu pendant un auto-start local déjà en cours : la séquence existante continue.");
						descentNetworkStarted = true;
						autoStartTriggered = true;
						transitionBlackout = true;
						break;
					}
					descentModeReady = false;
					isCampfireTransitionRunning = false;
					beachFlareFinaleTriggered = false;
					peakSequencePreparedForNetwork = false;
					helicopterNetworkSequenceRunning = false;
					triggeredCampfires.Clear();
					completedCampfirePaths.Clear();
					nextFarLitCampfireLogAt.Clear();
					initialCampfireResetDone = false;
					summitBackpackRelocated = false;
					summitStartConfirmed = false;
					summitRecoveryAttempts = 0;
					respawnRecoveryPending = false;
					kilnSceneStateChunks.Clear();
					kilnSceneStateExpectedChunks = 0;
					kilnSceneStateChunkEpoch = -1;
					lastAppliedKilnSceneStateEpoch = -1;
					joinerHostLikeCalderaJumpSucceeded = false;
					joinerHostLikeTropicsJumpSucceeded = false;
					joinerHostLikeBeachJumpSucceeded = false;
					forcePhotonMasterForLocalCalderaJump = false;
					autoStartTriggered = true;
					descentNetworkStarted = true;
					transitionBlackout = true;
					networkStartSequenceRunning = false;
					Log.LogInfo((object)$"START_DESCENT NOUVELLE RUN RÉSEAU | epoch={num} | master={IsPhotonMasterClient()}");
					StartDescentModeSequenceLocal(IsPhotonMasterClient(), IsPhotonMasterClient() ? $"PHOTON START_DESCENT MASTER E{num}" : $"PHOTON START_DESCENT CLIENT WAIT VANILLA E{num}");
					break;
				}
				case 171:
					if (obj2 != null)
					{
						Segment targetSegment = (Segment)(byte)Convert.ToInt32(obj2);
						StartNetworkSegmentTransition(targetSegment);
					}
					break;
				case 172:
					if (IsPhotonMasterClient())
					{
						StartMasterHelicopterNetworkSequence("PHOTON HELI_REQUEST");
					}
					break;
				case 173:
					beachFlareFinaleTriggered = true;
					peakSequencePreparedForNetwork = TryPreparePeakSequenceAtBeachForNetwork();
					break;
				case 174:
					TrySummonPreparedPeakSequenceAtBeachForNetwork("PHOTON HELI_ACTIVATE");
					break;
				case 175:
					if (IsPhotonMasterClient() && descentNetworkStarted)
					{
						Log.LogInfo((object)"START_REQUEST reçu : le Master rediffuse START_DESCENT aux autres clients.");
						SendPhotonModEvent(170, Math.Max(1, networkRunEpoch), "Others");
					}
					break;
				case 176:
					if (!IsPhotonMasterClient())
					{
						HandleKilnSceneStateChunk(obj2);
					}
					break;
				}
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("HandlePhotonEventObject erreur : " + ex.Message));
			}
		}

		private void TrackRunLifecycleForAutoStart()
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Invalid comparison between Unknown and I4
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Invalid comparison between Unknown and I4
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			bool flag = (Object)(object)Character.localCharacter != (Object)null;
			if (flag && !hadLocalCharacterLastFrame)
			{
				bool flag2 = routeWasActiveAtCharacterLoss && (int)MapHandler.CurrentSegmentNumber == 0 && completedCampfirePaths.Count < 4;
				bool flag3 = routeWasActiveAtCharacterLoss && Time.time - localCharacterLostAt <= 15f && !flag2;
				if (flag2)
				{
					Log.LogWarning((object)$"NOUVELLE RUN MÊME LOBBY DÉTECTÉE | segment=Beach | completed={completedCampfirePaths.Count} | ancien état route ignoré");
				}
				if (flag3)
				{
					networkStartSequenceRunning = false;
					autoStartTriggered = true;
					transitionBlackout = true;
					respawnRecoveryPending = true;
					respawnRecoveryAt = Time.time + 0.75f;
					summitStartConfirmed = (int)MapHandler.CurrentSegmentNumber != 4;
					multiStateLogUntil = Time.time + 20f;
					nextMultiStateLogAt = 0f;
					Log.LogWarning((object)$"RESPAWN LOCAL DÉTECTÉ : progression descente conservée | segment={MapHandler.CurrentSegmentNumber} | completed={completedCampfirePaths.Count}");
				}
				else
				{
					autoStartTriggered = false;
					descentNetworkStarted = false;
					networkStartSequenceRunning = false;
					descentModeReady = false;
					beachFlareFinaleTriggered = false;
					peakSequencePreparedForNetwork = false;
					helicopterNetworkSequenceRunning = false;
					triggeredCampfires.Clear();
					completedCampfirePaths.Clear();
					nextFarLitCampfireLogAt.Clear();
					initialCampfireResetDone = false;
					summitBackpackRelocated = false;
					summitStartConfirmed = false;
					summitRecoveryAttempts = 0;
					respawnRecoveryPending = false;
					transitionBlackout = true;
					localCharacterReadyAt = Time.time + 1.25f;
					nextStartRequestAt = Time.time + 4f;
					multiStateLogUntil = Time.time + 25f;
					nextMultiStateLogAt = 0f;
					Log.LogInfo((object)$"RUN DÉTECTÉE : écran noir actif, auto-start prévu dans 1,25 s | inRoom={IsPhotonInRoom()} | master={IsPhotonMasterClient()} | bridgePhoton={photonEventBridgeInstalled}");
				}
				routeWasActiveAtCharacterLoss = false;
			}
			else if (!flag && hadLocalCharacterLastFrame)
			{
				bool flag4 = (routeWasActiveAtCharacterLoss = descentModeReady || isCampfireTransitionRunning || completedCampfirePaths.Count > 0 || (autoStartTriggered && (int)MapHandler.CurrentSegmentNumber > 0));
				localCharacterLostAt = Time.time;
				networkStartSequenceRunning = false;
				transitionBlackout = false;
				if (flag4)
				{
					Log.LogWarning((object)$"Character.localCharacter perdu pendant la route : état conservé pour un éventuel respawn | segment={MapHandler.CurrentSegmentNumber} | completed={completedCampfirePaths.Count}");
				}
				else
				{
					autoStartTriggered = false;
					descentNetworkStarted = false;
					descentModeReady = false;
					beachFlareFinaleTriggered = false;
					peakSequencePreparedForNetwork = false;
					helicopterNetworkSequenceRunning = false;
					triggeredCampfires.Clear();
					completedCampfirePaths.Clear();
					initialCampfireResetDone = false;
					summitBackpackRelocated = false;
					summitStartConfirmed = false;
					respawnRecoveryPending = false;
					joinerHostLikeCalderaJumpSucceeded = false;
					joinerHostLikeTropicsJumpSucceeded = false;
					joinerHostLikeBeachJumpSucceeded = false;
					forcePhotonMasterForLocalCalderaJump = false;
					Log.LogInfo((object)"Fin de run / Character.localCharacter disparu hors route : état auto-start réinitialisé.");
				}
			}
			hadLocalCharacterLastFrame = flag;
		}

		private void LogCompactMultiplayerStateTick()
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//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_0060: 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_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: 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_00b9: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Character.localCharacter == (Object)null || Time.time > multiStateLogUntil || Time.time < nextMultiStateLogAt)
			{
				return;
			}
			nextMultiStateLogAt = Time.time + 2f;
			try
			{
				Rigidbody val = FindBodyRigidbody("Hip");
				Vector3 position = ((Component)Character.localCharacter).transform.position;
				Vector3 val2 = (((Object)(object)val != (Object)null) ? val.position : position);
				Log.LogInfo((object)$"MULTI LOCAL STATE | master={IsPhotonMasterClient()} | bridge={photonEventBridgeInstalled} | segment={MapHandler.CurrentSegmentNumber} | root={position} | hip={val2} | rootHipDist={Vector3.Distance(position, val2):0.00} | ready={descentModeReady} | startRunning={networkStartSequenceRunning} | blackout={transitionBlackout} | completed={completedCampfirePaths.Count}");
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("MULTI LOCAL STATE impossible : " + ex.Message));
			}
		}

		private bool IsKilnCampfireLocallyReady()
		{
			try
			{
				return Resources.FindObjectsOfTypeAll<Campfire>().Any((Campfire campfire) => (Object)(object)campfire != (Object)null && ((Component)campfire).gameObject.activeInHierarchy && CampfireMatchesCurrentSegmentForDebug(campfire, (Segment)4));
			}
			catch
			{
				return false;
			}
		}

		private void KeepLocalPlayerAtSummitUntilRouteStartsTick()
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Invalid comparison between Unknown and I4
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Character.localCharacter == (Object)null || summitStartConfirmed || networkStartSequenceRunning || isCampfireTransitionRunning || respawnRecoveryPending || (!autoStartTriggered && !descentModeReady) || Time.time < nextSummitRecoveryCheckAt)
			{
				return;
			}
			nextSummitRecoveryCheckAt = Time.time + 0.75f;
			Segment currentSegmentNumber;
			try
			{
				currentSegmentNumber = MapHandler.CurrentSegmentNumber;
			}
			catch
			{
				return;
			}
			if ((int)currentSegmentNumber != 4 || !IsKilnCampfireLocallyReady())
			{
				return;
			}
			Rigidbody val = FindBodyRigidbody("Hip");
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			if (val.position.y >= 1100f)
			{
				summitStartConfirmed = true;
				Log.LogInfo((object)$"SUMMIT RECOVERY : sommet déjà confirmé localement | hip={val.position} | master={IsPhotonMasterClient()}");
				return;
			}
			summitRecoveryAttempts++;
			Log.LogWarning((object)$"SUMMIT RECOVERY #{summitRecoveryAttempts} : joueur local encore en bas du volcan | segment={currentSegmentNumber} | root={((Component)Character.localCharacter).transform.position} | hip={val.position} | master={IsPhotonMasterClient()}");
			if (MoveLocalCharacterBodyNetworkAligned(SavedHipStartPosition, $"SUMMIT RECOVERY #{summitRecoveryAttempts}"))
			{
				PatchCampfiresForDescent();
				if (!initialCampfireResetDone)
				{
					ForceResetCampfiresForDescent();
					initialCampfireResetDone = true;
				}
				DisableRisingHazard();
				descentModeReady = true;
				autoStartTriggered = true;
				networkStartSequenceRunning = false;
				summitStartConfirmed = true;
				transitionBlackout = false;
				descentModeReadyAt = Time.time;
				multiStateLogUntil = Time.time + 15f;
				Rigidbody val2 = FindBodyRigidbody("Hip");
				string arg = (((Object)(object)val2 != (Object)null) ? ((object)val2.position/*cast due to .constrained prefix*/).ToString() : "null");
				Log.LogInfo((object)$"SUMMIT RECOVERY OK | root={((Component)Character.localCharacter).transform.position} | hip={arg} | segment={MapHandler.CurrentSegmentNumber}");
			}
		}

		private void RecoverLocalRespawnTick()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: 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_0054: Invalid comparison between Unknown and I4
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: 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_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Invalid comparison between Unknown and I4
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: Unknown result type (might be due to invalid IL or missing references)
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			if (!respawnRecoveryPending || (Object)(object)Character.localCharacter == (Object)null || Time.time < respawnRecoveryAt)
			{
				return;
			}
			respawnRecoveryAttempts++;
			Segment currentSegmentNumber;
			try
			{
				currentSegmentNumber = MapHandler.CurrentSegmentNumber;
			}
			catch
			{
				respawnRecoveryAt = Time.time + 0.5f;
				return;
			}
			Vector3 val;
			string text;
			if ((int)currentSegmentNumber == 4)
			{
				val = SavedHipStartPosition;
				text = "sommet TheKiln";
			}
			else
			{
				Campfire val2 = FindDebugDescentCampfireForCurrentSegment(currentSegmentNumber);
				if ((Object)(object)val2 == (Object)null || !((Component)val2).gameObject.activeInHierarchy)
				{
					if (respawnRecoveryAttempts < 8)
					{
						Log.LogWarning((object)$"RESPAWN RECOVERY attente branche locale | tentative={respawnRecoveryAttempts} | segment={currentSegmentNumber}");
						respawnRecoveryAt = Time.time + 0.5f;
					}
					else
					{
						Log.LogWarning((object)$"RESPAWN RECOVERY abandonné : aucun campfire actif pour {currentSegmentNumber}.");
						respawnRecoveryPending = false;
						transitionBlackout = false;
					}
					return;
				}
				val = ((Component)val2).transform.position + GetSafeDebugOffsetForCampfire(val2);
				text = GetPath(((Component)val2).transform);
			}
			Log.LogWarning((object)$"RESPAWN RECOVERY | tentative={respawnRecoveryAttempts} | segment={currentSegmentNumber} | anchor={text} | targetHip={val}");
			if (!MoveLocalCharacterBodyNetworkAligned(val, $"RESPAWN RECOVERY {currentSegmentNumber}"))
			{
				respawnRecoveryAt = Time.time + 0.5f;
				return;
			}
			PatchCampfiresForDescent();
			if (!initialCampfireResetDone)
			{
				ForceResetCampfiresForDescent();
				initialCampfireResetDone = true;
			}
			DisableRisingHazard();
			descentModeReady = true;
			autoStartTriggered = true;
			networkStartSequenceRunning = false;
			respawnRecoveryPending = false;
			transitionBlackout = false;
			descentModeReadyAt = Time.time;
			summitStartConfirmed = (int)currentSegmentNumber == 4;
			multiStateLogUntil = Time.time + 15f;
			Rigidbody val3 = FindBodyRigidbody("Hip");
			string arg = (((Object)(object)val3 != (Object)null) ? ((object)val3.position/*cast due to .constrained prefix*/).ToString() : "null");
			Log.LogInfo((object)$"RESPAWN RECOVERY OK | segment={currentSegmentNumber} | root={((Component)Character.localCharacter).transform.position} | hip={arg}");
		}

		private void AutoStartDescentTick()
		{
			if ((Object)(object)Character.localCharacter == (Object)null || descentModeReady || networkStartSequenceRunning || autoStartTriggered || Time.time < localCharacterReadyAt)
			{
				return;
			}
			bool flag = IsPhotonInRoom();
			bool flag2 = IsPhotonMasterClient();
			autoStartTriggered = true;
			transitionBlackout = true;
			if (!flag)
			{
				Log.LogInfo((object)"AUTO START SOLO : lancement local direct vers TheKiln puis TP sommet.");
				StartDescentModeSequenceLocal(requestKilnJump: true, "AUTO START SOLO");
			}
			else if (flag2)
			{
				descentNetworkStarted = true;
				networkRunEpoch++;
				lastHandledNetworkStartEpoch = networkRunEpoch;
				Log.LogInfo((object)$"AUTO START MASTER LOCAL | bridgePhoton={photonEventBridgeInstalled} | epoch={networkRunEpoch} | lancement local immédiat.");
				if (photonEventBridgeInstalled)
				{
					SendPhotonModEvent(170, networkRunEpoch, "Others");
				}
				else
				{
					Log.LogWarning((object)"Bridge Photon absent au démarrage : fallback local actif sur chaque client.");
				}
				StartDescentModeSequenceLocal(requestKilnJump: true, "AUTO START MASTER LOCAL");
			}
			else
			{
				Log.LogInfo((object)$"AUTO START CLIENT LOCAL | bridgePhoton={photonEventBridgeInstalled} | attente de la réplication vanilla TheKiln, puis TP du joueur local.");
				StartDescentModeSequenceLocal(requestKilnJump: false, "AUTO START CLIENT WAIT VANILLA");
			}
		}

		private void StartDescentModeSequenceLocal(bool requestKilnJump, string source)
		{
			if (descentModeReady && source.IndexOf("PHOTON", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				Log.LogInfo((object)("START_DESCENT réseau ignoré : ce client est déjà prêt. source=" + source));
				return;
			}
			if (networkStartSequenceRunning)
			{
				Log.LogWarning((object)("Start descente ignoré : une séquence est déjà en cours. source=" + source));
				return;
			}
			transitionBlackout = true;
			if (IsPhotonInRoom() && !IsPhotonMasterClient())
			{
				RestoreJoinerKilnStateForNewRun("START DESCENT | source=" + source);
			}
			Log.LogInfo((object)$"Lancement local mode descente | source={source} | requestKilnJump={requestKilnJump}");
			descentModeReady = false;
			isCampfireTransitionRunning = false;
			beachFlareFinaleTriggered = false;
			peakSequencePreparedForNetwork = false;
			helicopterNetworkSequenceRunning = false;
			triggeredCampfires.Clear();
			summitStartConfirmed = false;
			summitRecoveryAttempts = 0;
			respawnRecoveryPending = false;
			networkStartSequenceRunning = true;
			((MonoBehaviour)this).StartCoroutine(StartDescentModeCoroutine(requestKilnJump, source));
		}

		private IEnumerator StartDescentModeCoroutine(bool requestKilnJump, string source)
		{
			if ((Object)(object)Character.localCharacter == (Object)null)
			{
				Log.LogWarning((object)("Aucun Character.localCharacter trouvé. source=" + source));
				networkStartSequenceRunning = false;
				yield break;
			}
			Segment currentSegmentNumber = MapHandler.CurrentSegmentNumber;
			bool inRoom = IsPhotonInRoom();
			bool isMaster = IsPhotonMasterClient();
			if (requestKilnJump && (int)currentSegmentNumber != 4)
			{
				if (inRoom && isMaster)
				{
					Log.LogInfo((object)$"MASTER : attente de sécurité 2,5 s avant JumpToSegment(TheKiln) | current={currentSegmentNumber}");
					yield return (object)new WaitForSeconds(2.5f);
					if ((Object)(object)Character.localCharacter == (Object)null)
					{
						Log.LogWarning((object)"MASTER : Character.localCharacter a disparu pendant le délai de sécurité. Séquence abandonnée.");
						networkStartSequenceRunning = false;
						yield break;
					}
				}
				Log.LogInfo((object)$"Chargement AUTHORITATIF de TheKiln | source={source} | current={MapHandler.CurrentSegmentNumber}");
				TryJumpToSegment("TheKiln");
				Log.LogInfo((object)"Écran noir maintenu pendant l'attente du segment TheKiln...");
				yield return ((MonoBehaviour)this).StartCoroutine(WaitForKilnReadyForTeleport(!inRoom || isMaster));
			}
			else if (!requestKilnJump && (int)currentSegmentNumber != 4)
			{
				Log.LogInfo((object)$"CLIENT : aucun JumpToSegment local. Attente de la réplication vanilla TheKiln | current={currentSegmentNumber}");
				yield return ((MonoBehaviour)this).StartCoroutine(WaitForKilnReadyForTeleport(allowLocalJumpFallback: false));
				if ((int)MapHandler.CurrentSegmentNumber != 4)
				{
					Log.LogWarning((object)$"CLIENT : TheKiln non reçu après attente. Pas de TP sommet pour éviter une mort/désynchro | current={MapHandler.CurrentSegmentNumber}");
					networkStartSequenceRunning = false;
					autoStartTriggered = false;
					localCharacterReadyAt = Time.time + 2f;
					yield break;
				}
			}
			else
			{
				Log.LogInfo((object)"Déjà sur TheKiln, courte stabilisation avant TP sommet.");
				yield return (object)new WaitForSeconds(0.35f);
			}
			if ((int)MapHandler.CurrentSegmentNumber != 4)
			{
				Log.LogWarning((object)$"TP SOMMET ANNULÉ : segment local={MapHandler.CurrentSegmentNumber}, attendu=TheKiln | source={source}");
				networkStartSequenceRunning = false;
				autoStartTriggered = false;
				localCharacterReadyAt = Time.time + 2f;
				yield break;
			}
			Log.LogInfo((object)$"TP SOMMET LOCAL SÉCURISÉ | source={source} | segmentAvantTP={MapHandler.CurrentSegmentNumber} | master={IsPhotonMasterClient()}");
			bool flag = (summitStartConfirmed = TeleportVisibleBodyToSavedHipPosition());
			if (!flag)
			{
				Log.LogWarning((object)"TP sommet initial non confirmé : le watchdog SUMMIT RECOVERY reste armé.");
			}
			if (flag && (!IsPhotonInRoom() || IsPhotonMasterClient()))
			{
				yield return ((MonoBehaviour)this).StartCoroutine(RelocateVanillaBackpackToSummitWhenReady());
			}
			yield return (object)new WaitForSeconds(0.5f);
			PatchCampfiresForDescent();
			yield return (object)new WaitForSeconds(0.2f);
			if (!initialCampfireResetDone)
			{
				ForceResetCampfiresForDescent();
				initialCampfireResetDone = true;
			}
			yield return (object)new WaitForSeconds(0.2f);
			DisableRisingHazard();
			descentModeReady = true;
			isCampfireTransitionRunning = false;
			triggeredCampfires.Clear();
			descentModeReadyAt = Time.time;
			networkStartSequenceRunning = false;
			Log.LogInfo((object)$"Mode descente prêt LOCAL | source={source} | segment={MapHandler.CurrentSegmentNumber} | inRoom={IsPhotonInRoom()} | master={IsPhotonMasterClient()}");
			Log.LogInfo((object)"En multi V2.5 : START_DESCENT est versionné par epoch ; une nouvelle run dans le même lobby purge l'ancien état.");
			Log.LogInfo((object)"Transitions V2.16 : correctifs V2.11 à V2.15 conservés. Tropics -> Beach utilise maintenant le même JumpToSegment host-like que le host au lieu de GoToSegment + currentSegment forcé.");
			Log.LogInfo((object)"Build release : raccourcis clavier de debug/test désactivés.");
			Log.LogInfo((object)"Finale multi : flare -> demande au Master -> préparation PeakSequence sur tous -> activation synchronisée quand le bridge Photon fonctionne.");
			yield return null;
			yield return (object)new WaitForSeconds(0.15f);
			transitionBlackout = false;
			Log.LogInfo((object)"ÉCRAN NOIR RETIRÉ : le joueur doit maintenant être directement visible au sommet.");
		}

		private IEnumerator WaitForKilnReadyForTeleport(bool allowLocalJumpFallback)
		{
			float timeoutAt = Time.time + 10f;
			while (Time.time < timeoutAt)
			{
				bool flag = false;
				try
				{
					flag = (int)MapHandler.CurrentSegmentNumber == 4;
				}
				catch
				{
				}
				if (flag && IsKilnCampfireLocallyReady())
				{
					Log.LogInfo((object)$"TheKiln prêt localement : segment + campfire Kiln actifs | master={IsPhotonMasterClient()}");
					yield return (object)new WaitForSeconds(0.15f);
					yield break;
				}
				yield return (object)new WaitForSeconds(0.1f);
			}
			if (allowLocalJumpFallback)
			{
				Log.LogWarning((object)$"Timeout attente TheKiln après 10s | current={MapHandler.CurrentSegmentNumber}. Le client autoritaire tente un dernier JumpToSegment local.");
			}
			else
			{
				Log.LogWarning((object)$"CLIENT FALLBACK RETARDÉ : TheKiln non reçu après 10s | current={MapHandler.CurrentSegmentNumber} | bridge={photonEventBridgeInstalled}. JumpToSegment(TheKiln) LOCAL maintenant.");
			}
			string fallbackLabel = (allowLocalJumpFallback ? "FALLBACK AUTORITATIF" : "CLIENT FALLBACK RETARDÉ");
			TryJumpToSegment("TheKiln");
			float fallbackTimeoutAt = Time.time + 5f;
			while (Time.time < fallbackTimeoutAt)
			{
				bool flag2 = false;
				try
				{
					flag2 = (int)MapHandler.CurrentSegmentNumber == 4;
				}
				catch
				{
				}
				if (flag2 && IsKilnCampfireLocallyReady())
				{
					Log.LogInfo((object)(fallbackLabel + " OK : TheKiln + campfire Kiln prêts localement."));
					yield return (object)new WaitForSeconds(0.1f);
					yield break;
				}
				yield return (object)new WaitForSeconds(0.1f);
			}
			Log.LogWarning((object)$"{fallbackLabel} ÉCHOUÉ | current={MapHandler.CurrentSegmentNumber} | kilnReady={IsKilnCampfireLocallyReady()}");
		}

		private IEnumerator RelocateVanillaBackpackToSummitWhenReady()
		{
			if (summitBackpackRelocated)
			{
				yield break;
			}
			if (IsPhotonInRoom() && !IsPhotonMasterClient())
			{
				Log.LogInfo((object)"SUMMIT BACKPACK : joiner local ignoré, le host déplace l'objet vanilla réseau.");
				yield break;
			}
			Log.LogInfo((object)"========== SUMMIT BACKPACK RELOCATE START ==========");
			for (int attempt = 1; attempt <= 8; attempt++)
			{
				if (TryRelocateVanillaBackpackToSummit(attempt))
				{
					summitBackpackRelocated = true;
					Log.LogInfo((object)"========== SUMMIT BACKPACK RELOCATE END : OK ==========");
					yield break;
				}
				if (attempt < 8)
				{
					yield return (object)new WaitForSeconds(0.25f);
				}
			}
			Log.LogWarning((object)"SUMMIT BACKPACK RELOCATE END : aucun Backpack(Clone) vanilla réseau trouvé après 8 tentatives.");
		}

		private bool TryRelocateVanillaBackpackToSummit(int attempt)
		{
			//IL_0016: 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)
			//IL_019f: 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_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: 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_022d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: 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_036c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0302: Unknown result type (might be due to invalid IL or missing references)
			//IL_0307: Unknown result type (might be due to invalid IL or missing references)
			//IL_0341: Unknown result type (might be due to invalid IL or missing references)
			//IL_034e: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_041b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0420: Unknown result type (might be due to invalid IL or missing references)
			//IL_0424: Unknown result type (might be due to invalid IL or missing references)
			//IL_0429: Unknown result type (might be due to invalid IL or missing references)
			//IL_042b: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0400: Unknown result type (might be due to invalid IL or missing references)
			//IL_0402: Unknown result type (might be due to invalid IL or missing references)
			//IL_0454: Unknown result type (might be due to invalid IL or missing references)
			//IL_0459: Unknown result type (might be due to invalid IL or missing references)
			//IL_045d: Unknown result type (might be due to invalid IL or missing references)
			//IL_046b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0474: Unknown result type (might be due to invalid IL or missing references)
			//IL_0480: Unknown result type (might be due to invalid IL or missing references)
			//IL_04bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0500: Unknown result type (might be due to invalid IL or missing references)
			//IL_050d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0517: Unknown result type (might be due to invalid IL or missing references)
			//IL_0521: Unknown result type (might be due to invalid IL or missing references)
			//IL_052b: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Vector3 vanillaBeachBackpackPosition = new Vector3(19.66f, -0.89f, -367.38f);
				Transform[] source = Resources.FindObjectsOfTypeAll<Transform>();
				List<Transform> list = (from transform in (from transform in source
						where (Object)(object)transform != (Object)null
						where ((Object)transform).name.Equals("Backpack(Clone)", StringComparison.Ordinal)
						select transform).Where(delegate(Transform transform)
					{
						//IL_0006: Unknown result type (might be due to invalid IL or missing references)
						//IL_000b: Unknown result type (might be due to invalid IL or missing references)
						Scene scene = ((Component)transform).gameObject.scene;
						return ((Scene)(ref scene)).IsValid();
					})
					where GetPath(transform).Equals("Backpack(Clone)", StringComparison.Ordinal)
					orderby HasPhotonViewComponent(transform) descending, ((Component)transform).gameObject.activeInHierarchy descending, Vector3.Distance(transform.position, vanillaBeachBackpackPosition)
					select transform).ToList();
				if (list.Count <= 0)
				{
					if (attempt == 1 || attempt == 8)
					{
						Log.LogWarning((object)$"SUMMIT BACKPACK introuvable | tentative={attempt}/8 | aucun root exact Backpack(Clone)");
					}
					return false;
				}
				Transform val = list[0];
				Component val2 = ((IEnumerable<Component>)((Component)val).GetComponents<Component>()).FirstOrDefault((Func<Component, bool>)((Component component) => (Object)(object)component != (Object)null && ((object)component).GetType().FullName == "Photon.Pun.PhotonView"));
				string text = TryReadBooleanPropertyText(val2, "IsMine");
				Log.LogInfo((object)$"SUMMIT BACKPACK FOUND | tentative={attempt}/8 | path={GetPath(val)} | active={((Component)val).gameObject.activeInHierarchy} | pos={val.position} | photonView={(Object)(object)val2 != (Object)null} | isMine={text} | candidats={list.Count}");
				Vector3 val3 = SavedHipStartPosition + new Vector3(2.5f, 0f, 1.5f);
				Vector3 val4 = val3 + new Vector3(0f, 12f, 0f);
				Vector3 val5 = SavedHipStartPosition + new Vector3(2.5f, -0.3f, 1.5f);
				RaycastHit[] source2 = Physics.RaycastAll(val4, Vector3.down, 40f);
				RaycastHit? val6 = (from hit in source2
					where (Object)(object)((RaycastHit)(ref hit)).collider != (Object)null
					where !((RaycastHit)(ref hit)).collider.isTrigger
					where GetPath(((Component)((RaycastHit)(ref hit)).collider).transform).StartsWith("Map/", StringComparison.Ordinal)
					orderby ((RaycastHit)(ref hit)).distance
					select hit).Cast<RaycastHit?>().FirstOrDefault();
				if (val6.HasValue)
				{
					RaycastHit value = val6.Value;
					val5 = ((RaycastHit)(ref value)).point + new Vector3(0f, 0.55f, 0f);
					Log.LogInfo((object)$"SUMMIT BACKPACK GROUND | hit='{((Object)((RaycastHit)(ref value)).collider).name}' | path={GetPath(((Component)((RaycastHit)(ref value)).collider).transform)} | point={((RaycastHit)(ref value)).point} | target={val5}");
				}
				else
				{
					Log.LogWarning((object)$"SUMMIT BACKPACK GROUND : aucun collider Map sous la cible. Fallback target={val5}");
				}
				Rigidbody[] componentsInChildren = ((Component)val).GetComponentsInChildren<Rigidbody>(true);
				Rigidbody val7 = ((IEnumerable<Rigidbody>)componentsInChildren).FirstOrDefault((Func<Rigidbody, bool>)((Rigidbody body) => (Object)(object)body != (Object)null));
				Vector3 val8 = (((Object)(object)val7 != (Object)null) ? val7.position : val.position);
				Vector3 val9 = val5 - val8;
				Dictionary<Rigidbody, Vector3> dictionary = new Dictionary<Rigidbody, Vector3>();
				Rigidbody[] array = componentsInChildren;
				foreach (Rigidbody val10 in array)
				{
					if (!((Object)(object)val10 == (Object)null))
					{
						dictionary[val10] = val10.position + val9;
					}
				}
				Vector3 position = val.position;
				val.position += val9;
				foreach (KeyValuePair<Rigidbody, Vector3> item in dictionary)
				{
					Rigidbody key = item.Key;
					Vector3 position2 = (key.position = item.Value);
					((Component)key).transform.position = position2;
					key.linearVelocity = Vector3.zero;
					key.angularVelocity = Vector3.zero;
				}
				Physics.SyncTransforms();
				Vector3 val11 = (((Object)(object)val7 != (Object)null) ? val7.position : val.position);
				bool flag = Vector3.Distance(val11, val5) <= 1.5f;
				Log.LogInfo((object)$"SUMMIT BACKPACK RELOCATED | ok={flag} | root={position}->{val.position} | anchor={val8}->{val11} | target={val5} | delta={val9} | rigidbodies={componentsInChildren.Length} | isMine={text}");
				return flag;
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)$"TryRelocateVanillaBackpackToSummit erreur | tentative={attempt}/8 | {ex.GetType().Name} - {ex.Message}");
				return false;
			}
		}

		private bool HasPhotonViewComponent(Transform transform)
		{
			try
			{
				return ((Component)transform).GetComponents<Component>().Any((Component component) => (Object)(object)component != (Object)null && ((object)component).GetType().FullName == "Photon.Pun.PhotonView");
			}
			catch
			{
				return false;
			}
		}

		private string TryReadBooleanPropertyText(object? instance, string propertyName)
		{
			if (instance == null)
			{
				return "null";
			}
			try
			{
				PropertyInfo property = instance.GetType().GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (property == null || property.PropertyType != typeof(bool))
				{
					return "unknown";
				}
				return property.GetValue(instance)?.ToString() ?? "null";
			}
			catch
			{
				return "error";
			}
		}

		private bool TeleportVisibleBodyToSavedHipPosition()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			Log.LogInfo((object)"Téléportation réseau-alignée du corps visible vers la position Hip sauvegardée.");
			return MoveLocalCharacterBodyNetworkAligned(SavedHipStartPosition, "TP SOMMET NETWORK-ALIGNED");
		}

		private bool MoveLocalCharacterBodyNetworkAligned(Vector3 desiredHip, string reason)
		{
			//IL_005f: 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_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_006d: 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_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Character.localCharacter == (Object)null)
			{
				Log.LogWarning((object)("NETWORK-ALIGNED TP annulé : Character.localCharacter null | reason=" + reason));
				return false;
			}
			Rigidbody val = FindBodyRigidbody("Hip");
			if ((Object)(object)val == (Object)null)
			{
				Log.LogWarning((object)("NETWORK-ALIGNED TP annulé : Rigidbody Hip introuvable | reason=" + reason));
				return false;
			}
			try
			{
				Character localCharacter = Character.localCharacter;
				Transform transform = ((Component)localCharacter).transform;
				Vector3 position = transform.position;
				Vector3 position2 = val.position;
				Vector3 val2 = desiredHip - position2;
				Rigidbody[] componentsInChildren = ((Component)localCharacter).GetComponentsInChildren<Rigidbody>(true);
				Dictionary<Rigidbody, Vector3> dictionary = new Dictionary<Rigidbody, Vector3>();
				Rigidbody[] array = componentsInChildren;
				foreach (Rigidbody val3 in array)
				{
					if (!((Object)(object)val3 == (Object)null))
					{
						dictionary[val3] = val3.position + val2;
					}
				}
				Vector3 position3 = desiredHip + new Vector3(0f, -0.8f, 0f);
				transform.position = position3;
				foreach (KeyValuePair<Rigidbody, Vector3> item in dictionary)
				{
					Rigidbody key = item.Key;
					Vector3 position4 = (key.position = item.Value);
					((Component)key).transform.position = position4;
					key.linearVelocity = Vector3.zero;
					key.angularVelocity = Vector3.zero;
				}
				Physics.SyncTransforms();
				Rigidbody val4 = FindBodyRigidbody("Hip");
				Vector3 val5 = (((Object)(object)val4 != (Object)null) ? val4.position : desiredHip);
				Log.LogInfo((object)$"NETWORK-ALIGNED TP | reason={reason} | root {position} -> {transform.position} | hip {position2} -> {val5} | rootHipDist={Vector3.Distance(transform.position, val5):0.00} | delta={val2}");
				return Vector3.Distance(val5, desiredHip) <= 1.5f;
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("NETWORK-ALIGNED TP erreur | reason=" + reason + " | " + ex.GetType().Name + " - " + ex.Message));
				return false;
			}
		}

		private void ForceResetCampfiresForDescent()
		{
			Log.LogInfo((object)"========== FORCE RESET CAMPFIRES DESCENTE ==========");
			try
			{
				Campfire[] array = Resources.FindObjectsOfTypeAll<Campfire>();
				FieldInfo field = typeof(Campfire).GetField("state", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				FieldInfo field2 = typeof(Campfire).GetField("fireHasStarted", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				FieldInfo field3 = typeof(Campfire).GetField("beenBurningFor", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				FieldInfo field4 = typeof(Campfire).GetField("logRoot", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				FieldInfo field5 = typeof(Campfire).GetField("enableWhenLit", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				FieldInfo field6 = typeof(Campfire).GetField("disableWhenLit", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field == null)
				{
					Log.LogWarning((object)"Champ Campfire.state introuvable.");
					Log.LogInfo((object)"========== FIN FORCE RESET CAMPFIRES DESCENTE ==========");
					return;
				}
				Type fieldType = field.FieldType;
				Array values = Enum.GetValues(fieldType);
				foreach (object item in values)
				{
					Log.LogInfo((object)$"FireState possible : {item}");
				}
				object bestCampfireResetState = GetBestCampfireResetState(fieldType);
				if (bestCampfireResetState == null)
				{
					Log.LogWarning((object)"Impossible de trouver un FireState de reset.");
					Log.LogInfo((object)"========== FIN FORCE RESET CAMPFIRES DESCENTE ==========");
					return;
				}
				int num = 0;
				Campfire[] array2 = array;
				foreach (Campfire val in array2)
				{
					if ((Object)(object)val == (Object)null)
					{
						continue;
					}
					string path = GetPath(((Component)val).transform);
					if (!path.StartsWith("Map/"))
					{
						continue;
					}
					if (completedCampfirePaths.Contains(path))
					{
						Log.LogInfo((object)("RESET CAMPFIRE SKIP COMPLETED | path=" + path));
						continue;
					}
					object value = field.GetValue(val);
					field.SetValue(val, bestCampfireResetState);
					if (field2 != null)
					{
						field2.SetValue(val, false);
					}
					if (field3 != null)
					{
						field3.SetValue(val, 0f);
					}
					if (field5 != null)
					{
						object? value2 = field5.GetValue(val);
						GameObject val2 = (GameObject)((value2 is GameObject) ? value2 : null);
						if ((Object)(object)val2 != (Object)null)
						{
							val2.SetActive(false);
						}
					}
					if (field6 != null)
					{
						object? value3 = field6.GetValue(val);
						GameObject val3 = (GameObject)((value3 is GameObject) ? value3 : null);
						if ((Object)(object)val3 != (Object)null)
						{
							val3.SetActive(true);
						}
					}
					if (field4 != null)
					{
						object? value4 = field4.GetValue(val);
						Transform val4 = (Transform)((value4 is Transform) ? value4 : null);
						if ((Object)(object)val4 != (Object)null)
						{
							((Component)val4).gameObject.SetActive(true);
							for (int j = 0; j < val4.childCount; j++)
							{
								((Component)val4.GetChild(j)).gameObject.SetActive(true);
							}
						}
					}
					num++;
					Log.LogInfo((object)$"RESET CAMPFIRE | name='{((Object)((Component)val).gameObject).name}' | {value} -> {bestCampfireResetState} | active={((Component)val).gameObject.activeInHierarchy} | path={path}");
				}
				Log.LogInfo((object)$"Nombre de campfires force reset : {num}");
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"Erreur ForceResetCampfiresForDescent : {arg}");
			}
			Log.LogInfo((object)"========== FIN FORCE RESET CAMPFIRES DESCENTE ==========");
		}

		private IEnumerator DumpCampfirePostLightState(Campfire campfire, string path)
		{
			yield return (object)new WaitForSeconds(0.2f);
			DumpSingleCampfireRuntimeState(campfire, path, "T+0.2s");
			yield return (object)new WaitForSeconds(0.8f);
			DumpSingleCampfireRuntimeState(campfire, path, "T+1s");
			yield return (object)new WaitForSeconds(2f);
			DumpSingleCampfireRuntimeState(campfire, path, "T+3s");
		}

		private void DumpSingleCampfireRuntimeState(Campfire campfire, string path, string label)
		{
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)campfire == (Object)null)
			{
				return;
			}
			try
			{
				FieldInfo field = typeof(Campfire).GetField("state", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				FieldInfo field2 = typeof(Campfire).GetField("fireHasStarted", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				FieldInfo field3 = typeof(Campfire).GetField("beenBurningFor", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				FieldInfo field4 = typeof(Campfire).GetField("enableWhenLit", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				FieldInfo field5 = typeof(Campfire).GetField("disableFogFakeMountain", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				object obj = field?.GetValue(campfire);
				object obj2 = field2?.GetValue(campfire);
				object obj3 = field3?.GetValue(campfire);
				object obj4 = field5?.GetValue(campfire);
				object? obj5 = field4?.GetValue(campfire);
				GameObject val = (GameObject)((obj5 is GameObject) ? obj5 : null);
				Transform val2 = null;
				if ((Object)(object)val != (Object)null)
				{
					Transform[] componentsInChildren = val.GetComponentsInChildren<Transform>(true);
					val2 = ((IEnumerable<Transform>)componentsInChildren).FirstOrDefault((Func<Transform, bool>)((Transform child) => (Object)(object)child != (Object)null && ((Object)child).name.Equals("CookRadius", StringComparison.OrdinalIgnoreCase)));
				}
				Log.LogInfo((object)$"CAMPFIRE VANILLA STATE {label} | state={obj} | fireHasStarted={obj2} | burningFor={obj3} | disableFogFakeMountain={obj4} | enableWhenLitSelf={((val != null) ? new bool?(val.activeSelf) : ((bool?)null))} | enableWhenLitHierarchy={((val != null) ? new bool?(val.activeInHierarchy) : ((bool?)null))} | cookRadiusSelf={((val2 != null) ? new bool?(((Component)val2).gameObject.activeSelf) : ((bool?)null))} | cookRadiusHierarchy={((val2 != null) ? new bool?(((Component)val2).gameObject.activeInHierarchy) : ((bool?)null))} | segment={MapHandler.CurrentSegmentNumber} | path={path}");
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("DumpSingleCampfireRuntimeState erreur | " + label + " | path=" + path + " | " + ex.Message));
			}
		}

		private object? GetBestCampfireResetState(Type fireStateType)
		{
			string[] array = new string[6] { "Unlit", "UnlitNoReveal", "Off", "Ready", "Idle", "None" };
			string[] array2 = array;
			foreach (string value in array2)
			{
				if (Enum.IsDefined(fireStateType, value))
				{
					return Enum.Parse(fireStateType, value);
				}
			}
			Array values = Enum.GetValues(fireStateType);
			foreach (object item in values)
			{
				string text = item.ToString() ?? "";
				if (text != "Spent" && text != "Lit" && text != "Burning")
				{
					return item;
				}
			}
			return null;
		}

		private Rigidbody? FindBodyRigidbody(string preferredName)
		{
			if ((Object)(object)Character.localCharacter == (Object)null)
			{
				return null;
			}
			Rigidbody[] componentsInChildren = ((Component)Character.localCharacter).GetComponentsInChildren<Rigidbody>(true);
			Rigidbody val = ((IEnumerable<Rigidbody>)componentsInChildren).FirstOrDefault((Func<Rigidbody, bool>)((Rigidbody rb) => (Object)(object)rb != (Object)null && ((Object)rb).name == preferredName));
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			Rigidbody val2 = ((IEnumerable<Rigidbody>)componentsInChildren).FirstOrDefault((Func<Rigidbody, bool>)((Rigidbody rb) => (Object)(object)rb != (Object)null && ((Object)rb).name.IndexOf(preferredName, StringComparison.OrdinalIgnoreCase) >= 0));
			if ((Object)(object)val2 != (Object)null)
			{
				return val2;
			}
			return ((IEnumerable<Rigidbody>)componentsInChildren).FirstOrDefault((Func<Rigidbody, bool>)((Rigidbody rb) => (Object)(object)rb != (Object)null));
		}

		private void ShiftWholeCharacter(Vector3 delta, string reason)
		{
			//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_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: 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_006a: 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_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Character.localCharacter == (Object)null)
			{
				Log.LogWarning((object)("Impossible de déplacer : Character.localCharacter null. Raison=" + reason));
				return;
			}
			Transform transform = ((Component)Character.localCharacter).transform;
			Vector3 position = transform.position;
			Rigidbody[] componentsInChildren = ((Component)Character.localCharacter).GetComponentsInChildren<Rigidbody>(true);
			Dictionary<Rigidbody, Vector3> dictionary = new Dictionary<Rigidbody, Vector3>();
			Rigidbody[] array = componentsInChildren;
			foreach (Rigidbody val in array)
			{
				if (!((Object)(object)val == (Object)null))
				{
					dictionary[val] = ((Component)val).transform.position;
				}
			}
			transform.position = position + delta;
			foreach (KeyValuePair<Rigidbody, Vector3> item in dictionary)
			{
				Rigidbody key = item.Key;
				Vector3 position2 = (key.position = item.Value + delta);
				((Component)key).transform.position = position2;
				key.linearVelocity = Vector3.zero;
				key.angularVelocity = Vector3.zero;
			}
			Physics.SyncTransforms();
			Log.LogInfo((object)$"{reason} : root {position} -> {transform.position}");
			LogPlayerPosition();
		}

		private void DisableRisingHazard()
		{
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			Log.LogInfo((object)"========== DISABLE RISING HAZARD ==========");
			try
			{
				Fog[] array = Resources.FindObjectsOfTypeAll<Fog>();
				Log.LogInfo((object)$"Nombre de Fog trouvés : {array.Length}");
				FieldInfo field = typeof(Fog).GetField("fogHeight", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				FieldInfo field2 = typeof(Fog).GetField("fogSpeed", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				FieldInfo field3 = typeof(Fog).GetField("FogHeight", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				Fog[] array2 = array;
				foreach (Fog val in array2)
				{
					if (!((Object)(object)val == (Object)null))
					{
						if (field != null)
						{
							field.SetValue(val, -9999f);
						}
						if (field2 != null)
						{
							field2.SetValue(val, 0f);
						}
						try
						{
							val.RPCA_SyncFog(-9999f);
						}
						catch (Exception ex)
						{
							Log.LogWarning((object)("RPCA_SyncFog impossible sur " + ((Object)val).name + " : " + ex.Message));
						}
						Log.LogInfo((object)$"Fog patché : name='{((Object)val).name}', active={((Component)val).gameObject.activeInHierarchy}, pos={((Component)val).transform.position}");
					}
				}
				if (field3 != null)
				{
					field3.SetValue(null, -9999);
					Log.LogInfo((object)"Fog.FogHeight statique mis à -9999.");
				}
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"Erreur DisableRisingHazard : {arg}");
			}
			DisableOrbFogHandler(verbose: true);
			Log.LogInfo((object)"========== FIN DISABLE RISING HAZARD ==========");
		}

		private void KeepOrbFogDisabledTick()
		{
			if (descentModeReady && !(Time.time < nextOrbFogKillAt))
			{
				nextOrbFogKillAt = Time.time + 0.5f;
				DisableOrbFogHandler(verbose: false);
			}
		}

		private void DisableOrbFogHandler(bool verbose)
		{
			try
			{
				Type type = typeof(Character).Assembly.GetType("OrbFogHandler");
				if (type == null)
				{
					if (verbose)
					{
						Log.LogWarning((object)"Type OrbFogHandler introuvable dans Assembly-CSharp.");
					}
					return;
				}
				Object[] array = Resources.FindObjectsOfTypeAll(type);
				if (verbose)
				{
					Log.LogInfo((object)$"OrbFogHandler trouvés : {array.Length}");
				}
				int num = 0;
				Object[] array2 = array;
				foreach (Object val in array2)
				{
					if (!(val == (Object)null))
					{
						Type type2 = ((object)val).GetType();
						Component val2 = (Component)(object)((val is Component) ? val : null);
						string path = ((val2 != null) ? GetPath(val2.transform) : val.name);
						num += SetFieldIfExists(type2, val, "speed", 0f, verbose, path);
						num += SetFieldIfExists(type2, val, "maxWaitTime", 999999f, verbose, path);
						num += SetFieldIfExists(type2, val, "currentWaitTime", 0f, verbose, path);
						num += SetFieldIfExists(type2, val, "currentSize", 999999f, verbose, path);
						num += SetFieldIfExists(type2, val, "isMoving", false, verbose, path);
						num += SetFieldIfExists(type2, val, "PlayersAreResting", false, verbose, path);
						num += ForceOrbFogOriginsSize(type2, val, 999999f, verbose, path);
						TryInvokeOrbFogSync(type2, val, 999999f, moving: false, verbose, path);
						if (verbose)
						{
							DumpOrbFogFields(type2, val, path);
						}
					}
				}
				if (verbose)
				{
					Log.LogInfo((object)$"OrbFogHandler anti-fog appliqué. Changements={num}");
				}
			}
			catch (Exception arg)
			{
				if (verbose)
				{
					Log.LogError((object)$"Erreur DisableOrbFogHandler : {arg}");
				}
			}
		}

		private int SetFieldIfExists(Type type, object instance, string fieldName, object value, bool verbose, string path)
		{
			FieldInfo field = type.GetField(fieldName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			if (field == null)
			{
				return 0;
			}
			try
			{
				object obj = (field.IsStatic ? null : instance);
				object value2 = field.GetValue(obj);
				object obj2 = value;
				if (field.FieldType == typeof(float) && value is int num)
				{
					obj2 = (float)num;
				}
				else if (field.FieldType == typeof(int) && value is float num2)
				{
					obj2 = (int)num2;
				}
				else if (field.FieldType == typeof(double) && value is float num3)
				{
					obj2 = (double)num3;
				}
				else
				{
					if (field.FieldType != value.GetType() && field.FieldType.IsEnum)
					{
						return 0;
					}
					if (field.FieldType != value.GetType() && !field.FieldType.IsAssignableFrom(value.GetType()))
					{
						return 0;
					}
				}
				field.SetValue(obj, obj2);
				if (verbose)
				{
					Log.LogInfo((object)$"OrbFog SET | {fieldName}: {value2} -> {obj2} | path={path}");
				}
				return 1;
			}
			catch (Exception ex)
			{
				if (verbose)
				{
					Log.LogWarning((object)("OrbFog SET impossible | " + fieldName + " | path=" + path + " | " + ex.Message));
				}
				return 0;
			}
		}

		private int ForceOrbFogOriginsSize(Type type, object instance, float size, bool verbose, string path)
		{
			FieldInfo field = type.GetField("origins", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			if (field == null)
			{
				return 0;
			}
			try
			{
				object value = field.GetValue(field.IsStatic ? null : instance);
				if (value == null)
				{
					return 0;
				}
				int num = 0;
				if (value is Array array)
				{
					for (int i = 0; i < array.Length; i++)
					{
						object value2 = array.GetValue(i);
						if (value2 == null)
						{
							continue;
						}
						FieldInfo field2 = value2.GetType().GetField("size", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
						if (!(field2 == null))
						{
							object value3 = field2.GetValue(field2.IsStatic ? null : value2);
							field2.SetValue(field2.IsStatic ? null : value2, size);
							array.SetValue(value2, i);
							num++;
							if (verbose)
							{
								Log.LogInfo((object)$"OrbFog origins[{i}].size : {value3} -> {size} | path={path}");
							}
						}
					}
				}
				else if (value is IList list)
				{
					for (int j = 0; j < list.Count; j++)
					{
						object obj = list[j];
						if (obj == null)
						{
							continue;
						}
						FieldInfo field3 = obj.GetType().GetField("size", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
						if (!(field3 == null))
						{
							object value4 = field3.GetValue(field3.IsStatic ? null : obj);
							field3.SetValue(field3.IsStatic ? null : obj, size);
							list[j] = obj;
							num++;
							if (verbose)
							{
								Log.LogInfo((object)$"OrbFog origins[{j}].size : {value4} -> {size} | path={path}");
							}
						}
					}
				}
				return num;
			}
			catch (Exception ex)
			{
				if (verbose)
				{
					Log.LogWarning((object)("OrbFog origins.size impossible | path=" + path + " | " + ex.Message));
				}
				return 0;
			}
		}

		private void TryInvokeOrbFogSync(Type type, object instance, float size, bool moving, bool verbose, string path)
		{
			try
			{
				MethodInfo method = type.GetMethod("RPCA_SyncFog", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if (method == null)
				{
					return;
				}
				ParameterInfo[] parameters = method.GetParameters();
				if (parameters.Length == 2)
				{
					method.Invoke(method.IsStatic ? null : instance, new object[2] { size, moving });
					if (verbose)
					{
						Log.LogInfo((object)$"OrbFog RPCA_SyncFog({size}, {moving}) invoqué | path={path}");
					}
				}
			}
			catch (Exception ex)
			{
				if (verbose)
				{
					Log.LogWarning((object)("OrbFog RPCA_SyncFog impossible | path=" + path + " | " + ex.Message));
				}
			}
		}

		private void DumpOrbFogFields(Type type, object instance, string path)
		{
			string[] array = new string[8] { "currentID", "currentSize", "speed", "maxWaitTime", "currentWaitTime", "isMoving", "PlayersAreResting", "syncCounter" };
			string[] array2 = array;
			foreach (string text in array2)
			{
				FieldInfo field = type.GetField(text, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if (!(field == null))
				{
					try
					{
						object value = field.GetValue(field.IsStatic ? null : instance);
						Log.LogInfo((object)$"OrbFog FIELD | {text}={value} | path={path}");
					}
					catch
					{
					}
				}
			}
		}

		private void PatchCampfiresForDescent()
		{
			//IL_00ad: 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)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: 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_0105: 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)
			Log.LogInfo((object)"========== PATCH CAMPFIRES DESCENTE ==========");
			try
			{
				Campfire[] array = Resources.FindObjectsOfTypeAll<Campfire>();
				FieldInfo field = typeof(Campfire).GetField("advanceToSegment", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field == null)
				{
					Log.LogWarning((object)"Champ Campfire.advanceToSegment introuvable.");
					Log.LogInfo((object)"========== FIN PATCH CAMPFIRES DESCENTE ==========");
					return;
				}
				int num = 0;
				Campfire[] array2 = array;
				foreach (Campfire val in array2)
				{
					if ((Object)(object)val == (Object)null)
					{
						continue;
					}
					Segment? forcedDescentTargetForCampfire = GetForcedDescentTargetForCampfire(val);
					if (forcedDescentTargetForCampfire.HasValue)
					{
						Segment val2 = ((field.GetValue(val) is Segment val3) ? val3 : forcedDescentTargetForCampfire.Value);
						Segment value = forcedDescentTargetForCampfire.Value;
						field.SetValue(val, value);
						if (val2 != value)
						{
							num++;
						}
						Log.LogInfo((object)$"PATCH | name='{((Object)((Component)val).gameObject).name}' | {val2} -> {value} | active={((Component)val).gameObject.activeInHierarchy} | pos={((Component)val).transform.position} | path={GetPath(((Component)val).transform)}");
					}
				}
				Log.LogInfo((object)$"Nombre de campfires patchés ou confirmés : {num}");
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"Erreur PatchCampfiresForDescent : {arg}");
			}
			Log.LogInfo((object)"========== FIN PATCH CAMPFIRES DESCENTE ==========");
		}

		private Segment? GetForcedDescentTargetForCampfire(Campfire campfire)
		{
			string path = GetPath(((Component)campfire).transform);
			if (!path.StartsWith("Map/"))
			{
				return null;
			}
			if (path.Contains("Biome_4") || path.Contains("Volcano_Campfire") || ((Object)((Component)campfire).gameObject).name.Contains("Kiln"))
			{
				return (Segment)3;
			}
			if (path.Contains("Biome_3") || path.Contains("Desert_Campfire") || path.Contains("Snow_Campfire") || path.Contains("Mesa"))
			{
				return (Segment)2;
			}
			if (path.Contains("Biome_2") || path.Contains("Roots_Campfire") || path.Contains("Roots"))
			{
				return (Segment)1;
			}
			if (path.Contains("Beach_Campfire") || path.Contains("crashed plane"))
			{
				return (Segment)0;
			}
			return null;
		}

		private float GetNearestActiveCharacterDistanceToPosition(Vector3 position, out string nearestCharacterName, out int activeCharacterCount)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			nearestCharacterName = "none";
			activeCharacterCount = 0;
			float num = float.PositiveInfinity;
			try
			{
				Character[] array = Resources.FindObjectsOfTypeAll<Character>();
				Character[] array2 = array;
				foreach (Character val in array2)
				{
					if ((Object)(object)val == (Object)null || !((Component)val).gameObject.activeInHierarchy)
					{
						continue;
					}
					activeCharacterCount++;
					Vector3 position2 = ((Component)val).transform.position;
					Rigidbody[] componentsInChildren = ((Component)val).GetComponentsInChildren<Rigidbody>(true);
					Rigidbody val2 = ((IEnumerable<Rigidbody>)componentsInChildren).FirstOrDefault((Func<Rigidbody, bool>)((Rigidbody rb) => (Object)(object)rb != (Object)null && ((Object)rb).name.Equals("Hip", StringComparison.Ordinal)));
					if ((Object)(object)val2 == (Object)null)
					{
						val2 = ((IEnumerable<Rigidbody>)componentsInChildren).FirstOrDefault((Func<Rigidbody, bool>)((Rigidbody rb) => (Object)(object)rb != (Object)null && ((Object)rb).name.IndexOf("Hip", StringComparison.OrdinalIgnoreCase) >= 0));
					}
					if ((Object)(object)val2 != (Object)null)
					{
						position2 = val2.position;
					}
					float num2 = Vector3.Distance(position2, position);
					if (!(num2 >= num))
					{
						num = num2;
						string text = ((val == Character.localCharacter) ? " LOCAL" : " REMOTE");
						nearestCharacterName = ((Object)((Component)val).gameObject).name + text;
					}
				}
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("GetNearestActiveCharacterDistanceToPosition erreur : " + ex.GetType().Name + " - " + ex.Message));
			}
			return num;
		}

		private void ResetExpectedCampfireForCurrentSegmentIfStale(string source)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: 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_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: 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_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_031e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0463: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Segment currentSegmentNumber = MapHandler.CurrentSegmentNumber;
				Campfire val = FindDebugDescentCampfireForCurrentSegment(currentSegmentNumber);
				if ((Object)(object)val == (Object)null)
				{
					Log.LogWarning((object)$"EXPECTED CAMPFIRE RESET SKIP | source={source} | current={currentSegmentNumber} | campfire=null");
					return;
				}
				string path = GetPath(((Component)val).transform);
				if (completedCampfirePaths.Contains(path))
				{
					Log.LogInfo((object)$"EXPECTED CAMPFIRE RESET SKIP COMPLETED | source={source} | current={currentSegmentNumber} | path={path}");
					return;
				}
				string nearestCharacterName;
				int activeCharacterCount;
				float nearestActiveCharacterDistanceToPosition = GetNearestActiveCharacterDistanceToPosition(((Component)val).transform.position, out nearestCharacterName, out activeCharacterCount);
				if (activeCharacterCount > 0 && nearestActiveCharacterDistanceToPosition <= 18f)
				{
					Log.LogInfo((object)$"EXPECTED CAMPFIRE RESET SKIP PLAYER NEAR | source={source} | current={currentSegmentNumber} | path={path} | nearestPlayer={nearestCharacterName} | distanceNearest={nearestActiveCharacterDistanceToPosition:0.00}");
					return;
				}
				FieldInfo field = typeof(Campfire).GetField("state", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				FieldInfo field2 = typeof(Campfire).GetField("fireHasStarted", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				FieldInfo field3 = typeof(Campfire).GetField("beenBurningFor", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				FieldInfo field4 = typeof(Campfire).GetField("logRoot", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				FieldInfo field5 = typeof(Campfire).GetField("enableWhenLit", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				FieldInfo field6 = typeof(Campfire).GetField("disableWhenLit", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field == null)
				{
					Log.LogWarning((object)$"EXPECTED CAMPFIRE RESET SKIP | source={source} | current={currentSegmentNumber} | path={path} | stateField=null");
					return;
				}
				string text = field.GetValue(val)?.ToString() ?? "null";
				object obj = field2?.GetValue(val);
				bool flag = default(bool);
				int num;
				if (obj is bool)
				{
					flag = (bool)obj;
					num = 1;
				}
				else
				{
					num = 0;
				}
				bool flag2 = (byte)((uint)num & (flag ? 1u : 0u)) != 0;
				float num2 = ((field3?.GetValue(val) is float num3) ? num3 : 0f);
				object? obj2 = field5?.GetValue(val);
				GameObject val2 = (GameObject)((obj2 is GameObject) ? obj2 : null);
				object? obj3 = field6?.GetValue(val);
				GameObject val3 = (GameObject)((obj3 is GameObject) ? obj3 : null);
				object? obj4 = field4?.GetValue(val);
				Transform val4 = (Transform)((obj4 is Transform) ? obj4 : null);
				bool flag3 = (Object)(object)val4 != (Object)null && ((Component)val4).gameObject.activeSelf;
				if (!(text == "Lit" || text == "Spent" || flag2) && !(num2 > 0f) && (!((Object)(object)val2 != (Object)null) || !val2.activeSelf) && flag3)
				{
					Log.LogInfo((object)$"EXPECTED CAMPFIRE READY | source={source} | current={currentSegmentNumber} | path={path} | state={text} | fireHasStarted={flag2} | logsVisible={flag3}");
					return;
				}
				object bestCampfireResetState = GetBestCampfireResetState(field.FieldType);
				if (bestCampfireResetState == null)
				{
					Log.LogWarning((object)$"EXPECTED CAMPFIRE RESET SKIP | source={source} | current={currentSegmentNumber} | path={path} | resetState=null");
					return;
				}
				field.SetValue(val, bestCampfireResetState);
				if (field2 != null)
				{
					field2.SetValue(val, false);
				}
				if (field3 != null)
				{
					field3.SetValue(val, 0f);
				}
				if ((Object)(object)val2 != (Object)null)
				{
					val2.SetActive(false);
				}
				if ((Object)(object)val3 != (Object)null)
				{
					val3.SetActive(true);
				}
				if ((Object)(object)val4 != (Object)null)
				{
					((Component)val4).gameObject.SetActive(true);
					for (int i = 0; i < val4.childCount; i++)
					{
						((Component)val4.GetChild(i)).gameObject.SetActive(true);
					}
				}
				triggeredCampfires.Remove(((Object)val).GetInstanceID());
				nextFarLitCampfireLogAt.Remove(path);
				Physics.SyncTransforms();
				object value = field.GetValue(val);
				obj = field2?.GetValue(val);
				bool flag4 = default(bool);
				int num4;
				if (obj is bool)
				{
					flag4 = (bool)obj;
					num4 = 1;
				}
				else
				{
					num4 = 0;
				}
				bool flag5 = (byte)((uint)num4 & (flag4 ? 1u : 0u)) != 0;
				bool flag6 = (Object)(object)val4 != (Object)null && ((Component)val4).gameObject.activeSelf;
				Log.LogWarning((object)string.Format("EXPECTED CAMPFIRE RESET | source={0} | current={1} | path={2} | state={3}->{4} | fireHasStarted={5}->{6} | burningFor={7:0.00}->0 | enableWhenLit={8} | disableWhenLit={9} | logsVisible={10}->{11} | nearestPlayer={12} | distanceNearest={13:0.00} | activeCharacters={14}", source, currentSegmentNumber, path, text, value, flag2, flag5, num2, ((Object)(object)val2 != (Object)null) ? val2.activeSelf.ToString() : "null", ((Object)(object)val3 != (Object)null) ? val3.activeSelf.ToString() : "null", flag3, flag6, nearestCharacterName, nearestActiveCharacterDistanceToPosition, activeCharacterCount));
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("ResetExpectedCampfireForCurrentSegmentIfStale erreur | source=" + source + " | " + ex.GetType().Name + " - " + ex.Message));
			}
		}

		private void WatchLitCampfiresForDescentTransition()
		{
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_025b: 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_0262: Unknown result type (might be due to invalid IL or missing references)
			//IL_0264: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03af: Unknown result type (might be due to invalid IL or missing references)
			//IL_0369: Unknown result type (might be due to invalid IL or missing references)
			//IL_039c: Unknown result type (might be due to invalid IL or missing references)
			if (!descentModeReady || isCampfireTransitionRunning || Time.time < descentModeReadyAt + 2f)
			{
				return;
			}
			bool flag = IsPhotonInRoom();
			bool flag2 = flag && photonEventBridgeInstalled;
			if ((flag2 && !IsPhotonMasterClient()) || (Object)(object)Character.localCharacter == (Object)null)
			{
				return;
			}
			FieldInfo field = typeof(Campfire).GetField("state", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			FieldInfo field2 = typeof(Campfire).GetField("advanceToSegment", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field == null || field2 == null)
			{
				return;
			}
			Rigidbody val = FindBodyRigidbody("Hip");
			Vector3 val2 = (((Object)(object)val != (Object)null) ? ((Component)val).transform.position : ((Component)Character.localCharacter).transform.position);
			Segment currentSegmentNumber = MapHandler.CurrentSegmentNumber;
			Campfire[] array = Resources.FindObjectsOfTypeAll<Campfire>();
			Campfire[] array2 = array;
			foreach (Campfire val3 in array2)
			{
				if ((Object)(object)val3 == (Object)null || !((Component)val3).gameObject.activeInHierarchy)
				{
					continue;
				}
				string path = GetPath(((Component)val3).transform);
				if (!path.StartsWith("Map/") || !CampfireMatchesCurrentSegmentForDebug(val3, currentSegmentNumber))
				{
					continue;
				}
				float num = Vector3.Distance(val2, ((Component)val3).transform.position);
				string text = field.GetValue(val3)?.ToString() ?? "null";
				if (text != "Lit")
				{
					continue;
				}
				string nearestCharacterName;
				int activeCharacterCount;
				float nearestActiveCharacterDistanceToPosition = GetNearestActiveCharacterDistanceToPosition(((Component)val3).transform.position, out nearestCharacterName, out activeCharacterCount);
				float num2 = (flag ? 18f : 15f);
				if (activeCharacterCount <= 0 || nearestActiveCharacterDistanceToPosition > num2)
				{
					if (!nextFarLitCampfireLogAt.TryGetValue(path, out var value) || Time.time >= value)
					{
						nextFarLitCampfireLogAt[path] = Time.time + 3f;
						Log.LogWarning((object)$"FEU LIT IGNORÉ : aucun joueur proche | path={path} | current={currentSegmentNumber} | distanceMaster={num:0.00} | nearestPlayer={nearestCharacterName} | distanceNearest={nearestActiveCharacterDistanceToPosition:0.00} | activeCharacters={activeCharacterCount} | limite={num2:0.00}");
					}
					continue;
				}
				object value2 = field2.GetValue(val3);
				if (value2 == null)
				{
					continue;
				}
				Segment val4 = (Segment)value2;
				if (val4 == currentSegmentNumber)
				{
					continue;
				}
				int instanceID = ((Object)val3).GetInstanceID();
				if (!completedCampfirePaths.Contains(path) && !triggeredCampfires.Contains(instanceID))
				{
					triggeredCampfires.Add(instanceID);
					completedCampfirePaths.Add(path);
					((MonoBehaviour)this).StartCoroutine(DumpCampfirePostLightState(val3, path));
					multiStateLogUntil = Time.time + 15f;
					Log.LogInfo((object)$"FEU ALLUMÉ DÉTECTÉ | path={path} | current={currentSegmentNumber} | target={val4} | distanceMaster={num:0.00} | nearestPlayer={nearestCharacterName} | distanceNearest={nearestActiveCharacterDistanceToPosition:0.00} | activeCharacters={activeCharacterCount} | inRoom={flag} | master={IsPhotonMasterClient()} | completed={completedCampfirePaths.Count}");
					if (flag2 && IsPhotonMasterClient())
					{
						SendPhotonModEvent(171, Convert.ToInt32(val4), "Others");
					}
					else if (flag && !photonEventBridgeInstalled)
					{
						Log.LogWarning((object)$"FALLBACK MULTI CAMPFIRE : bridge Photon absent, transition locale vers {val4}.");
					}
					((MonoBehaviour)this).StartCoroutine(DoCampfireDescentTransition(val4));
					break;
				}
			}
		}

		private void StartNetworkSegmentTransition(Segment targetSegment)
		{
			//IL_002d: 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)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Invalid comparison between Unknown and I4
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Invalid comparison between Unknown and I4
			//IL_0086: 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)
			if (isCampfireTransitionRunning)
			{
				Log.LogWarning((object)$"SEGMENT_CHANGE ignoré : transition locale déjà en cours | target={targetSegment}");
				return;
			}
			Log.LogInfo((object)$"SEGMENT_CHANGE réseau accepté | current={MapHandler.CurrentSegmentNumber} | target={targetSegment} | master={IsPhotonMasterClient()}");
			if (IsPhotonInRoom() && !IsPhotonMasterClient())
			{
				if ((int)targetSegment == 3)
				{
					((MonoBehaviour)this).StartCoroutine(ApplyRemoteCalderaHostLikeJump());
				}
				else if ((int)targetSegment == 1)
				{
					((MonoBehaviour)this).StartCoroutine(ApplyRemoteTropicsHostLikeJump());
				}
				else if ((int)targetSegment == 0)
				{
					((MonoBehaviour)this).StartCoroutine(ApplyRemoteBeachHostLikeJump());
				}
				else
				{
					((MonoBehaviour)this).StartCoroutine(ApplyRemoteSegmentTransitionWithLocalGoTo(targetSegment));
				}
			}
			else
			{
				((MonoBehaviour)this).StartCoroutine(DoCampfireDescentTransition(targetSegment));
			}
		}

		private IEnumerator ApplyRemoteCalderaHostLikeJump()
		{
			isCampfireTransitionRunning = true;
			transitionBlackout = true;
			Segment beforeSegment = MapHandler.CurrentSegmentNumber;
			Campfire val = FindSourceCampfireForTargetSegment((Segment)3);
			string text = (((Object)(object)val != (Object)null) ? GetPath(((Component)val).transform) : "null");
			if ((Object)(object)val != (Object)null)
			{
				completedCampfirePaths.Add(text);
			}
			Rigidbody val2 = FindBodyRigidbody("Hip");
			Vector3 hipBefore = (((Object)(object)val2 != (Object)null) ? val2.position : (((Object)(object)val != (Object)null) ? (((Component)val).transform.position + new Vector3(1.5f, 2.2f, 0f)) : Vector3.zero));
			bool realMasterBefore = IsPhotonMasterClient();
			joinerHostLikeCalderaJumpSucceeded = false;
			Log.LogWarning((object)$"REMOTE CALDERA HOST-LIKE START | before={beforeSegment} | source={text} | hipBefore={hipBefore} | masterRéel={realMasterBefore} | photonMasterPatch={photonMasterGetterPatchInstalled}");
			yield return (object)new WaitForSeconds(1f);
			bool jumpThrew = false;
			forcePhotonMasterForLocalCalderaJump = true;
			try
			{
				Log.LogWarning((object)$"REMOTE CALDERA HOST-LIKE JUMP | appel E