Decompiled source of Campfire Building v2.0.0

tony4twentys-Campfire Building.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;
using UnityEngine.SceneManagement;
using Zorro.Core;
using Zorro.Core.Serizalization;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: AssemblyTitle("Campfire Building")]
[assembly: AssemblyDescription("BepInEx plugin for PEAK that requires firewood before lighting campfires")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("tony4twentys")]
[assembly: AssemblyProduct("Campfire Building")]
[assembly: AssemblyCopyright("Copyright © tony4twentys 2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("69efbd55-05ad-4c68-8483-6d8e9db0b1c9")]
[assembly: AssemblyFileVersion("2.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.0.0.0")]
[module: UnverifiableCode]
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}
namespace tony4twentys.Campfire_Building
{
	[BepInPlugin("tony4twentys.Campfire_Building", "Campfire Building", "2.0.0")]
	[BepInProcess("PEAK.exe")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "tony4twentys.Campfire_Building";

		public const string PluginName = "Campfire Building";

		public const string PluginVersion = "2.0.0";

		internal const string SummitToShoreGuid = "tony4twentys.Summit_to_Shore";

		internal const byte EventCode = 159;

		internal const int ProtocolVersion = 7;

		internal const string EventMagic = "tony4twentys.Campfire_Building";

		internal const int ConfigPayloadLength = 9;

		internal const string FirewoodPrefabName = "FireWood";

		internal const string StonePrefabName = "Stone";

		internal const ushort FirewoodItemId = 28;

		internal const ushort StoneItemId = 72;

		internal const int DefaultRequiredFirewood = 3;

		internal const int HighAscentRequiredFirewood = 6;

		internal const int HighAscentMinimum = 5;

		internal const string AddFirewoodPrompt = "ADD FIREWOOD ({current}/{required})";

		internal const string NeedFirewoodPrompt = "NEED FIREWOOD ({current}/{required})";

		internal const string AddStonesPrompt = "ADD STONES ({current}/{required})";

		internal const string NeedStonesPrompt = "NEED STONES ({current}/{required})";

		internal static ConfigEntry<bool> EnableSpawning;

		internal static ConfigEntry<bool> EnableDebugLogging;

		internal static ConfigEntry<bool> Stacking;

		internal static ConfigEntry<KeyCode> DropOneFromStack;

		internal static ConfigEntry<int> SpawnsPerSegment;

		internal static ConfigEntry<float> SpawnCooldown;

		internal static ConfigEntry<bool> SpawnsInKilnCitadel;

		internal static ConfigEntry<bool> EnableStones;

		internal static bool syncedEnableSpawning = true;

		internal static int syncedSpawnsPerSegment = 60;

		internal static float syncedSpawnCooldown = 15f;

		internal static bool syncedSpawnsInKilnCitadel = false;

		internal static bool syncedEnableStones = true;

		internal static bool syncedStacking = true;

		internal static bool SummitToShorePresent;

		internal static bool isHandshakeValid = true;

		private Harmony _harmony;

		internal static Plugin Instance { get; private set; }

		internal static ManualLogSource Log { get; private set; }

		internal static bool IsGameplayEnabled
		{
			get
			{
				try
				{
					if (!PhotonNetwork.InRoom || PhotonNetwork.IsMasterClient)
					{
						return true;
					}
				}
				catch
				{
					return isHandshakeValid;
				}
				return isHandshakeValid;
			}
		}

		internal static int ItemCap
		{
			get
			{
				int num = Mathf.Clamp(syncedSpawnsPerSegment, 0, 200);
				if (!syncedEnableStones)
				{
					return num;
				}
				return num / 2;
			}
		}

		internal static int CurrentAscent
		{
			get
			{
				try
				{
					return Ascents.currentAscent;
				}
				catch
				{
					return 0;
				}
			}
		}

		internal static int RequiredFirewoodCount
		{
			get
			{
				if (CurrentAscent < 5)
				{
					return 3;
				}
				return 6;
			}
		}

		internal static int RequiredStoneCount => RequiredFirewoodCount;

		internal static bool StonesEnabled
		{
			get
			{
				if (syncedEnableStones)
				{
					return IsGameplayEnabled;
				}
				return false;
			}
		}

		internal static bool DebugLogs
		{
			get
			{
				try
				{
					return EnableDebugLogging != null && EnableDebugLogging.Value;
				}
				catch
				{
					return false;
				}
			}
		}

		private void Awake()
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			BindConfig();
			SummitToShorePresent = DetectSummitToShore();
			if (SummitToShorePresent)
			{
				DebugLog("[Campfire Building] Summit to Shore detected — Kiln/Citadel ping spawns enabled.");
			}
			ApplyLocalConfig();
			if (!PhotonNetwork.InRoom || PhotonNetwork.IsMasterClient)
			{
				isHandshakeValid = true;
			}
			_harmony = new Harmony("tony4twentys.Campfire_Building");
			PatchAllSafe();
			BuildFireNet.Ensure();
			((MonoBehaviour)this).StartCoroutine(FirewoodStack.WatchDropOne());
			((BaseUnityPlugin)this).Config.SettingChanged += delegate
			{
				BuildFireNet.OnLocalSettingChanged();
			};
			Log.LogInfo((object)string.Format("{0} v{1} loaded. Photon {2}.", "Campfire Building", "2.0.0", (byte)159));
		}

		private void BindConfig()
		{
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Expected O, but got Unknown
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Expected O, but got Unknown
			EnableDebugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableDebugLogging", false, "Local only. Log ping spawns, biome stingers, and handshake details.");
			Stacking = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Stacking", true, "Host only. Stack sticks and stones in one inventory slot (count on the name, extra carry weight). Off = vanilla inventory, one item per slot, no name/count changes.");
			DropOneFromStack = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("General", "DropOneFromStack", (KeyCode)122, "Local only. Drop one stick or stone from the held stack. Vanilla drop still throws the whole stack. Does nothing if you are holding a single item.");
			EnableSpawning = ((BaseUnityPlugin)this).Config.Bind<bool>("Spawning", "EnableSpawning", true, "Host only. Players ping nearby plants and the host drops sticks and stones beside them, up to SpawnsPerSegment per biome. Turn off if another mod already spawns sticks.");
			int num = 60;
			ConfigDefinition val = new ConfigDefinition("Spawning", "FirewoodPerSegment");
			if (((BaseUnityPlugin)this).Config.ContainsKey(val))
			{
				try
				{
					num = Convert.ToInt32(((BaseUnityPlugin)this).Config[val].BoxedValue);
				}
				catch
				{
				}
				((BaseUnityPlugin)this).Config.Remove(val);
			}
			SpawnsPerSegment = ((BaseUnityPlugin)this).Config.Bind<int>("Spawning", "SpawnsPerSegment", num, "Host only. Max ping-spawns per biome. Split 50/50 when stones are on (60 → 30 stones + 30 sticks). Sticks use the full value if stones are off.");
			SpawnCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("Spawning", "SpawnCooldown", 15f, "Host only. Seconds between ping-spawns. Host value is synced to the room.");
			bool flag = false;
			ConfigDefinition val2 = new ConfigDefinition("Spawning", "SpawnSticksKilnCitadel");
			if (((BaseUnityPlugin)this).Config.ContainsKey(val2))
			{
				try
				{
					flag = Convert.ToBoolean(((BaseUnityPlugin)this).Config[val2].BoxedValue);
				}
				catch
				{
				}
				((BaseUnityPlugin)this).Config.Remove(val2);
			}
			SpawnsInKilnCitadel = ((BaseUnityPlugin)this).Config.Bind<bool>("Spawning", "SpawnsInKilnCitadel", flag, "Host only. Also ping-spawn sticks and stones in Kiln/Citadel. Leave off for a normal climb. Turned on automatically when Summit to Shore is loaded.");
			EnableStones = ((BaseUnityPlugin)this).Config.Bind<bool>("Spawning", "EnableStones", true, "Host only. Spawn stones and require a stone ring (hologram) before firewood. Turn off to skip stones, holograms, and VFX_Smoke_Off changes.");
		}

		internal static void ApplyLocalConfig()
		{
			syncedEnableSpawning = EnableSpawning.Value;
			syncedSpawnsPerSegment = Mathf.Clamp(SpawnsPerSegment.Value, 0, 200);
			syncedSpawnCooldown = Mathf.Clamp(SpawnCooldown.Value, 0f, 300f);
			syncedSpawnsInKilnCitadel = SpawnsInKilnCitadel.Value || SummitToShorePresent;
			syncedEnableStones = EnableStones.Value;
			syncedStacking = Stacking.Value;
			CampfireStones.RefreshAll();
		}

		internal static object[] BuildConfigPayload(byte sub)
		{
			return new object[9]
			{
				"tony4twentys.Campfire_Building",
				7,
				sub,
				EnableSpawning.Value,
				SpawnsPerSegment.Value,
				SpawnsInKilnCitadel.Value || SummitToShorePresent,
				EnableStones.Value,
				SpawnCooldown.Value,
				Stacking.Value
			};
		}

		internal static void ApplyRemoteConfig(object[] arr)
		{
			if (arr == null || arr.Length < 9)
			{
				throw new InvalidOperationException("Campfire Building config payload too short.");
			}
			syncedEnableSpawning = Convert.ToBoolean(arr[3]);
			syncedSpawnsPerSegment = Mathf.Clamp(Convert.ToInt32(arr[4]), 0, 200);
			syncedSpawnsInKilnCitadel = Convert.ToBoolean(arr[5]);
			syncedEnableStones = Convert.ToBoolean(arr[6]);
			syncedSpawnCooldown = Mathf.Clamp(Convert.ToSingle(arr[7]), 0f, 300f);
			syncedStacking = Convert.ToBoolean(arr[8]);
			CampfireStones.RefreshAll();
		}

		internal static string FormatPrompt(bool holdingFirewood, int current, int required)
		{
			return (holdingFirewood ? "ADD FIREWOOD ({current}/{required})" : "NEED FIREWOOD ({current}/{required})").Replace("{current}", current.ToString()).Replace("{required}", required.ToString());
		}

		internal static string FormatStonePrompt(bool holdingStone, int current, int required)
		{
			return (holdingStone ? "ADD STONES ({current}/{required})" : "NEED STONES ({current}/{required})").Replace("{current}", current.ToString()).Replace("{required}", required.ToString());
		}

		internal static bool IsFirewoodItemId(ushort itemId)
		{
			return itemId == 28;
		}

		internal static bool IsStoneItemId(ushort itemId)
		{
			return itemId == 72;
		}

		internal static void DebugLog(string message)
		{
			if (DebugLogs)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogInfo((object)message);
				}
			}
		}

		internal static void LogOnce(ref bool flag, string message, Exception ex)
		{
			if (flag)
			{
				return;
			}
			flag = true;
			if (ex != null)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogError((object)(message + " " + ex));
				}
			}
			else
			{
				ManualLogSource log2 = Log;
				if (log2 != null)
				{
					log2.LogError((object)message);
				}
			}
		}

		private static bool DetectSummitToShore()
		{
			try
			{
				return Chainloader.PluginInfos != null && Chainloader.PluginInfos.ContainsKey("tony4twentys.Summit_to_Shore");
			}
			catch
			{
				return false;
			}
		}

		private void PatchAllSafe()
		{
			Type[] types = typeof(Plugin).Assembly.GetTypes();
			foreach (Type type in types)
			{
				if (!(type == null) && type.GetCustomAttributes(typeof(HarmonyPatch), inherit: false).Length != 0)
				{
					try
					{
						_harmony.CreateClassProcessor(type).Patch();
					}
					catch (Exception ex)
					{
						Log.LogError((object)("[Campfire Building] Patch failed on " + type.Name + ": " + ex.Message));
					}
				}
			}
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
		}
	}
	internal sealed class BuildFireNet : MonoBehaviourPunCallbacks, IOnEventCallback
	{
		internal const byte SubConfig = 1;

		internal const byte SubConfigRequest = 2;

		internal const byte SubFirewood = 3;

		internal const byte SubSnapshot = 4;

		internal const byte SubSnapshotRequest = 5;

		internal const byte SubPingSpawn = 6;

		internal const byte SubPingCount = 7;

		internal const byte SubStones = 8;

		internal const byte SubStoneSnapshot = 9;

		internal const byte SubDropOne = 10;

		private const float HostSyncTimeoutSeconds = 12f;

		private const float HostSyncRetrySeconds = 2f;

		internal static bool HostModConfirmed;

		private Coroutine _debounce;

		private Coroutine _hostSyncWatch;

		private bool _syncingFromNet;

		internal static BuildFireNet Instance { get; private set; }

		internal static void Ensure()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			if ((Object)(object)Instance != (Object)null)
			{
				return;
			}
			GameObject val = new GameObject("CampfireBuilding_Net");
			Object.DontDestroyOnLoad((Object)val);
			Instance = val.AddComponent<BuildFireNet>();
			try
			{
				if (PhotonNetwork.InRoom)
				{
					Instance.HandleJoinedRoom();
				}
			}
			catch
			{
			}
		}

		private void Awake()
		{
			Instance = this;
		}

		public override void OnEnable()
		{
			((MonoBehaviourPunCallbacks)this).OnEnable();
			PhotonNetwork.AddCallbackTarget((object)this);
		}

		public override void OnDisable()
		{
			PhotonNetwork.RemoveCallbackTarget((object)this);
			((MonoBehaviourPunCallbacks)this).OnDisable();
		}

		public override void OnJoinedRoom()
		{
			HandleJoinedRoom();
		}

		public override void OnLeftRoom()
		{
			StopHostSyncWatch();
			HostModConfirmed = false;
			Plugin.isHandshakeValid = true;
			Plugin.ApplyLocalConfig();
			CampfireWood.ResetAll();
			CampfireStones.ResetAll();
			FirewoodSpawner.ResetRun();
		}

		public override void OnMasterClientSwitched(Player newMasterClient)
		{
			if (PhotonNetwork.IsMasterClient)
			{
				HostModConfirmed = true;
				Plugin.isHandshakeValid = true;
				Plugin.ApplyLocalConfig();
				BroadcastNow();
				BroadcastWoodSnapshot();
				BroadcastStoneSnapshot();
				FirewoodPing.BroadcastAllCounts();
				FirewoodPing.Ensure();
				StopHostSyncWatch();
			}
			else
			{
				HostModConfirmed = false;
				Plugin.isHandshakeValid = false;
				RequestHostSync();
				RestartHostSyncWatch();
			}
		}

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

		public void OnEvent(EventData photonEvent)
		{
			//IL_0210: 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_0217: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			if (photonEvent == null || photonEvent.Code != 159 || !(photonEvent.CustomData is object[] array) || array.Length < 3 || !(array[0] is string text) || text != "tony4twentys.Campfire_Building" || ToInt(array[1]) != 7)
			{
				return;
			}
			byte b = ToByte(array[2]);
			if (b == 2 && PhotonNetwork.IsMasterClient)
			{
				BroadcastNow();
				BroadcastWoodSnapshot();
				BroadcastStoneSnapshot();
				FirewoodPing.BroadcastAllCounts();
				return;
			}
			if (b == 5 && PhotonNetwork.IsMasterClient)
			{
				BroadcastWoodSnapshot();
				BroadcastStoneSnapshot();
				return;
			}
			switch (b)
			{
			case 3:
				if (array.Length >= 5)
				{
					CampfireWood.ApplyNetworkCount(ToInt(array[3]), ToInt(array[4]));
				}
				break;
			case 4:
				if (array.Length >= 5)
				{
					CampfireWood.ApplySnapshot(array[3] as int[], array[4] as int[]);
				}
				break;
			case 8:
				if (array.Length >= 5)
				{
					CampfireStones.ApplyNetworkCount(ToInt(array[3]), ToInt(array[4]));
				}
				break;
			case 9:
				if (array.Length >= 5)
				{
					CampfireStones.ApplySnapshot(array[3] as int[], array[4] as int[]);
				}
				break;
			case 6:
				if (PhotonNetwork.IsMasterClient && array.Length >= 8)
				{
					int segment = ToInt(array[3]);
					Vector3 pos2 = default(Vector3);
					((Vector3)(ref pos2))..ctor(ToFloat(array[4]), ToFloat(array[5]), ToFloat(array[6]));
					bool cactus = Convert.ToBoolean(array[7]);
					bool flag = array.Length > 8 && Convert.ToBoolean(array[8]);
					FirewoodPing.TryHonorRequest(stick: (array.Length > 9) ? Convert.ToBoolean(array[9]) : (!flag), segment: segment, pos: pos2, cactus: cactus, stone: flag);
				}
				break;
			case 7:
				if (array.Length >= 5)
				{
					bool stone = array.Length > 5 && Convert.ToBoolean(array[5]);
					FirewoodPing.ApplyHostCount(ToInt(array[3]), ToInt(array[4]), stone);
				}
				break;
			case 10:
				if (PhotonNetwork.IsMasterClient && array.Length >= 8)
				{
					ushort itemId = (ushort)ToInt(array[3]);
					Vector3 pos = default(Vector3);
					((Vector3)(ref pos))..ctor(ToFloat(array[4]), ToFloat(array[5]), ToFloat(array[6]));
					FirewoodStack.HonorWorldDrop(rot: Quaternion.Euler(0f, ToFloat(array[7]), 0f), itemId: itemId, pos: pos);
				}
				break;
			case 1:
				if (PhotonNetwork.IsMasterClient)
				{
					break;
				}
				try
				{
					_syncingFromNet = true;
					StopHostSyncWatch();
					HostModConfirmed = true;
					Plugin.isHandshakeValid = true;
					Plugin.ApplyRemoteConfig(array);
					Plugin.DebugLog("[Campfire Building] Host config sync applied. Ascent " + Plugin.CurrentAscent + " — campfires need " + (Plugin.syncedEnableStones ? (Plugin.RequiredStoneCount + " stones then ") : "") + Plugin.RequiredFirewoodCount + " firewood.");
					break;
				}
				catch (Exception ex)
				{
					Plugin.Log.LogError((object)("[Campfire Building] Config sync failed: " + ex.Message));
					break;
				}
				finally
				{
					_syncingFromNet = false;
				}
			}
		}

		internal static void OnLocalSettingChanged()
		{
			if (!((Object)(object)Instance != (Object)null) || !Instance._syncingFromNet)
			{
				if (!PhotonNetwork.InRoom || PhotonNetwork.IsMasterClient)
				{
					Plugin.ApplyLocalConfig();
				}
				ScheduleBroadcast();
			}
		}

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

		internal static void BroadcastStones(int viewId, int count)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Expected O, but got Unknown
			if (!PhotonNetwork.InRoom || viewId <= 0)
			{
				return;
			}
			try
			{
				PhotonNetwork.RaiseEvent((byte)159, (object)new object[5]
				{
					"tony4twentys.Campfire_Building",
					7,
					(byte)8,
					viewId,
					count
				}, new RaiseEventOptions
				{
					Receivers = (ReceiverGroup)0
				}, SendOptions.SendReliable);
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[Campfire Building] Stone RaiseEvent failed: " + ex.Message));
				}
			}
		}

		internal static void BroadcastStoneSnapshot()
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Expected O, but got Unknown
			if (!PhotonNetwork.InRoom || !PhotonNetwork.IsMasterClient)
			{
				return;
			}
			CampfireStones.CopySnapshot(out var viewIds, out var counts);
			if (viewIds.Length == 0)
			{
				return;
			}
			try
			{
				PhotonNetwork.RaiseEvent((byte)159, (object)new object[5]
				{
					"tony4twentys.Campfire_Building",
					7,
					(byte)9,
					viewIds,
					counts
				}, new RaiseEventOptions
				{
					Receivers = (ReceiverGroup)0
				}, SendOptions.SendReliable);
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[Campfire Building] Stone snapshot RaiseEvent failed: " + ex.Message));
				}
			}
		}

		internal static void BroadcastWood(int viewId, int count)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Expected O, but got Unknown
			if (!PhotonNetwork.InRoom || viewId <= 0)
			{
				return;
			}
			try
			{
				PhotonNetwork.RaiseEvent((byte)159, (object)new object[5]
				{
					"tony4twentys.Campfire_Building",
					7,
					(byte)3,
					viewId,
					count
				}, new RaiseEventOptions
				{
					Receivers = (ReceiverGroup)0
				}, SendOptions.SendReliable);
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[Campfire Building] Firewood RaiseEvent failed: " + ex.Message));
				}
			}
		}

		internal static void BroadcastWoodSnapshot()
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: 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_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Expected O, but got Unknown
			if (!PhotonNetwork.InRoom || !PhotonNetwork.IsMasterClient)
			{
				return;
			}
			CampfireWood.CopySnapshot(out var viewIds, out var counts);
			if (viewIds.Length == 0)
			{
				return;
			}
			try
			{
				PhotonNetwork.RaiseEvent((byte)159, (object)new object[5]
				{
					"tony4twentys.Campfire_Building",
					7,
					(byte)4,
					viewIds,
					counts
				}, new RaiseEventOptions
				{
					Receivers = (ReceiverGroup)0
				}, SendOptions.SendReliable);
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[Campfire Building] Snapshot RaiseEvent failed: " + ex.Message));
				}
			}
		}

		private void HandleJoinedRoom()
		{
			FirewoodSpawner.ResetRun();
			FirewoodPing.Ensure();
			if (PhotonNetwork.IsMasterClient)
			{
				HostModConfirmed = true;
				Plugin.isHandshakeValid = true;
				Plugin.ApplyLocalConfig();
				Plugin.DebugLog("[Campfire Building] Ascent " + Plugin.CurrentAscent + " — campfires need " + (Plugin.syncedEnableStones ? (Plugin.RequiredStoneCount + " stones then ") : "") + Plugin.RequiredFirewoodCount + " firewood.");
				BroadcastNow();
				StopHostSyncWatch();
				FirewoodSpawner.ScheduleCurrentSegment();
			}
			else
			{
				HostModConfirmed = false;
				Plugin.isHandshakeValid = false;
				RequestHostSync();
				RestartHostSyncWatch();
			}
		}

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

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

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

		private IEnumerator WatchForHostSync()
		{
			WaitForSecondsRealtime tick = new WaitForSecondsRealtime(2f);
			float elapsed = 0f;
			while (elapsed < 12f)
			{
				if (!PhotonNetwork.InRoom || PhotonNetwork.IsMasterClient || HostModConfirmed)
				{
					yield break;
				}
				yield return tick;
				elapsed += 2f;
				if (!PhotonNetwork.InRoom || PhotonNetwork.IsMasterClient || HostModConfirmed)
				{
					yield break;
				}
				RequestHostSync();
			}
			if (PhotonNetwork.InRoom && !PhotonNetwork.IsMasterClient && !HostModConfirmed)
			{
				Plugin.isHandshakeValid = false;
				Plugin.Log.LogWarning((object)"[Campfire Building] Host does not appear to have Campfire Building — vanilla lighting left enabled.");
			}
			_hostSyncWatch = null;
		}

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

		private IEnumerator BroadcastAfterDelay(float seconds)
		{
			yield return (object)new WaitForSeconds(seconds);
			BroadcastNow();
			BroadcastWoodSnapshot();
			BroadcastStoneSnapshot();
			FirewoodPing.BroadcastAllCounts();
		}

		internal static void RequestStickSpawn(int segment, Vector3 pos, bool cactus, bool stone, bool stick)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: 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_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Expected O, but got Unknown
			if (!PhotonNetwork.InRoom || PhotonNetwork.IsMasterClient)
			{
				return;
			}
			try
			{
				PhotonNetwork.RaiseEvent((byte)159, (object)new object[10]
				{
					"tony4twentys.Campfire_Building",
					7,
					(byte)6,
					segment,
					pos.x,
					pos.y,
					pos.z,
					cactus,
					stone,
					stick
				}, new RaiseEventOptions
				{
					Receivers = (ReceiverGroup)2
				}, SendOptions.SendReliable);
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[Campfire Building] Ping spawn request failed: " + ex.Message));
				}
			}
		}

		internal static void RequestDropOne(ushort itemId, Vector3 pos, Quaternion rot)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Expected O, but got Unknown
			if (!PhotonNetwork.InRoom || PhotonNetwork.IsMasterClient || (itemId != 28 && itemId != 72))
			{
				return;
			}
			try
			{
				PhotonNetwork.RaiseEvent((byte)159, (object)new object[8]
				{
					"tony4twentys.Campfire_Building",
					7,
					(byte)10,
					(int)itemId,
					pos.x,
					pos.y,
					pos.z,
					((Quaternion)(ref rot)).eulerAngles.y
				}, new RaiseEventOptions
				{
					Receivers = (ReceiverGroup)2
				}, SendOptions.SendReliable);
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[Campfire Building] Drop-one request failed: " + ex.Message));
				}
			}
		}

		internal static void BroadcastSpawnCount(int segment, int spawned, bool stone)
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Expected O, but got Unknown
			if (!PhotonNetwork.InRoom || !PhotonNetwork.IsMasterClient)
			{
				return;
			}
			try
			{
				PhotonNetwork.RaiseEvent((byte)159, (object)new object[6]
				{
					"tony4twentys.Campfire_Building",
					7,
					(byte)7,
					segment,
					spawned,
					stone
				}, new RaiseEventOptions
				{
					Receivers = (ReceiverGroup)0
				}, SendOptions.SendReliable);
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[Campfire Building] Ping count broadcast failed: " + ex.Message));
				}
			}
		}

		private static void BroadcastNow()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			if (PhotonNetwork.InRoom && PhotonNetwork.IsMasterClient)
			{
				PhotonNetwork.RaiseEvent((byte)159, (object)Plugin.BuildConfigPayload(1), new RaiseEventOptions
				{
					Receivers = (ReceiverGroup)0
				}, SendOptions.SendReliable);
			}
		}

		private static int ToInt(object value)
		{
			return Convert.ToInt32(value);
		}

		private static float ToFloat(object value)
		{
			return Convert.ToSingle(value);
		}

		private static byte ToByte(object value)
		{
			return Convert.ToByte(value);
		}
	}
	internal static class CampfireWood
	{
		private static readonly Dictionary<int, int> CountsByViewId = new Dictionary<int, int>();

		private static bool _loggedVisualError;

		internal static void ResetAll()
		{
			CountsByViewId.Clear();
			CampfireStones.ResetAll();
		}

		internal static bool NeedsBuild(Campfire campfire)
		{
			if (!CampfireStones.NeedsStones(campfire))
			{
				return NeedsWood(campfire);
			}
			return true;
		}

		internal static bool ShouldModify(Campfire campfire)
		{
			if ((Object)(object)campfire == (Object)null || !Plugin.IsGameplayEnabled)
			{
				return false;
			}
			if (campfire.forceLit)
			{
				return false;
			}
			if (IsPortableStove(campfire))
			{
				return false;
			}
			return true;
		}

		internal static bool NeedsWood(Campfire campfire)
		{
			if (!ShouldModify(campfire) || campfire.Lit)
			{
				return false;
			}
			if (CampfireStones.NeedsStones(campfire))
			{
				return false;
			}
			return GetCount(campfire) < Plugin.RequiredFirewoodCount;
		}

		internal static int GetCount(Campfire campfire)
		{
			int viewId = GetViewId(campfire);
			if (viewId > 0 && CountsByViewId.TryGetValue(viewId, out var value))
			{
				return value;
			}
			return 0;
		}

		internal static void EnsureInitialized(Campfire campfire)
		{
			if ((Object)(object)campfire == (Object)null)
			{
				return;
			}
			CampfireStones.Ensure(campfire);
			if (!ShouldModify(campfire))
			{
				return;
			}
			int viewId = GetViewId(campfire);
			int value = 0;
			if (viewId > 0 && CountsByViewId.TryGetValue(viewId, out value))
			{
				ApplyLogVisuals(campfire, value);
			}
			else if (!campfire.Lit)
			{
				if (viewId > 0)
				{
					CountsByViewId[viewId] = 0;
				}
				ApplyLogVisuals(campfire, 0);
			}
		}

		internal static bool TryAddFirewood(Campfire campfire, Character interactor)
		{
			if ((Object)(object)campfire == (Object)null || (Object)(object)interactor == (Object)null || !interactor.IsLocal)
			{
				return false;
			}
			if (!NeedsWood(campfire))
			{
				return false;
			}
			if (!IsFirewoodItem(((Object)(object)interactor.data != (Object)null) ? interactor.data.currentItem : null))
			{
				return false;
			}
			int count = GetCount(campfire) + 1;
			SetCount(campfire, count, broadcast: true);
			FirewoodStack.ConsumeOne(interactor);
			return true;
		}

		internal static void SetCount(Campfire campfire, int count, bool broadcast)
		{
			if (!((Object)(object)campfire == (Object)null))
			{
				int num = Mathf.Max(0, count);
				int viewId = GetViewId(campfire);
				if (viewId > 0)
				{
					CountsByViewId[viewId] = num;
				}
				ApplyLogVisuals(campfire, num);
				RefreshPrompt(campfire);
				if (broadcast && viewId > 0)
				{
					BuildFireNet.BroadcastWood(viewId, num);
				}
			}
		}

		internal static void ApplyNetworkCount(int viewId, int count)
		{
			if (viewId > 0)
			{
				CountsByViewId[viewId] = Mathf.Max(0, count);
				Campfire val = FindCampfire(viewId);
				if ((Object)(object)val != (Object)null)
				{
					ApplyLogVisuals(val, CountsByViewId[viewId]);
					RefreshPrompt(val);
				}
			}
		}

		internal static void ApplySnapshot(int[] viewIds, int[] counts)
		{
			if (viewIds != null && counts != null)
			{
				int num = Math.Min(viewIds.Length, counts.Length);
				for (int i = 0; i < num; i++)
				{
					ApplyNetworkCount(viewIds[i], counts[i]);
				}
			}
		}

		internal static void CopySnapshot(out int[] viewIds, out int[] counts)
		{
			viewIds = new int[CountsByViewId.Count];
			counts = new int[CountsByViewId.Count];
			int num = 0;
			foreach (KeyValuePair<int, int> item in CountsByViewId)
			{
				viewIds[num] = item.Key;
				counts[num] = item.Value;
				num++;
			}
		}

		internal static string GetPrompt(Campfire campfire)
		{
			if (!ShouldModify(campfire) || campfire.Lit)
			{
				return null;
			}
			int count = GetCount(campfire);
			int requiredFirewoodCount = Plugin.RequiredFirewoodCount;
			if (count >= requiredFirewoodCount)
			{
				return null;
			}
			return Plugin.FormatPrompt(IsFirewoodItem(((Object)(object)Character.localCharacter != (Object)null && (Object)(object)Character.localCharacter.data != (Object)null) ? Character.localCharacter.data.currentItem : null), count, requiredFirewoodCount);
		}

		internal static bool IsFirewoodItem(Item item)
		{
			if ((Object)(object)item == (Object)null)
			{
				return false;
			}
			if (Plugin.IsFirewoodItemId(item.itemID))
			{
				return true;
			}
			try
			{
				return (Object)(object)((Component)item).GetComponent<FireWoodItem>() != (Object)null;
			}
			catch
			{
				return false;
			}
		}

		internal static bool IsPortableStove(Campfire fire)
		{
			if ((Object)(object)fire == (Object)null)
			{
				return false;
			}
			if (LooksLikePortableStove(fire.nameOverride))
			{
				return true;
			}
			Transform val = ((Component)fire).transform;
			int num = 0;
			while ((Object)(object)val != (Object)null && num < 8)
			{
				if (LooksLikePortableStove(((Object)val).name))
				{
					return true;
				}
				val = val.parent;
				num++;
			}
			try
			{
				string name = fire.GetName();
				if (!string.IsNullOrEmpty(name) && name.Replace(" ", string.Empty).IndexOf("PORTABLESTOVE", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return true;
				}
			}
			catch
			{
			}
			return false;
		}

		internal static int GetViewId(Campfire campfire)
		{
			if ((Object)(object)campfire == (Object)null)
			{
				return 0;
			}
			PhotonView val = campfire.view;
			if ((Object)(object)val == (Object)null)
			{
				val = ((Component)campfire).GetComponent<PhotonView>();
			}
			if (!((Object)(object)val != (Object)null))
			{
				return 0;
			}
			return val.ViewID;
		}

		internal static void ApplyLogVisuals(Campfire campfire, int count)
		{
			if ((Object)(object)campfire == (Object)null)
			{
				return;
			}
			try
			{
				Transform val = campfire.logRoot;
				if ((Object)(object)val == (Object)null)
				{
					val = FindLogsRecursive(((Component)campfire).transform, 0);
				}
				if ((Object)(object)val == (Object)null)
				{
					return;
				}
				int childCount = val.childCount;
				for (int i = 0; i < childCount; i++)
				{
					Transform child = val.GetChild(i);
					if ((Object)(object)child != (Object)null)
					{
						((Component)child).gameObject.SetActive(false);
					}
				}
				if (count <= 0)
				{
					return;
				}
				if (childCount >= 6 && Plugin.RequiredFirewoodCount >= 6)
				{
					int num = Mathf.Min(count, childCount);
					for (int j = 0; j < num; j++)
					{
						SetChildActive(val, j, active: true);
					}
				}
				else if (childCount >= 6)
				{
					if (count >= 1)
					{
						SetChildActive(val, 0, active: true);
						SetChildActive(val, 5, active: true);
					}
					if (count >= 2)
					{
						SetChildActive(val, 2, active: true);
						SetChildActive(val, 3, active: true);
					}
					if (count >= 3)
					{
						SetChildActive(val, 1, active: true);
						SetChildActive(val, 4, active: true);
					}
				}
				else
				{
					int num2 = Mathf.Min(count * 2, childCount);
					for (int k = 0; k < num2; k++)
					{
						SetChildActive(val, k, active: true);
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.LogOnce(ref _loggedVisualError, "[Campfire Building] Log visuals failed.", ex);
			}
		}

		private static Campfire FindCampfire(int viewId)
		{
			PhotonView val = PhotonView.Find(viewId);
			if ((Object)(object)val != (Object)null)
			{
				Campfire component = ((Component)val).GetComponent<Campfire>();
				if ((Object)(object)component != (Object)null)
				{
					return component;
				}
			}
			List<Campfire> aLL_CAMPFIRES = Campfire.ALL_CAMPFIRES;
			if (aLL_CAMPFIRES == null)
			{
				return null;
			}
			for (int i = 0; i < aLL_CAMPFIRES.Count; i++)
			{
				Campfire val2 = aLL_CAMPFIRES[i];
				if ((Object)(object)val2 != (Object)null && GetViewId(val2) == viewId)
				{
					return val2;
				}
			}
			return null;
		}

		private static void RefreshPrompt(Campfire campfire)
		{
			try
			{
				if ((Object)(object)GUIManager.instance != (Object)null && (object)GUIManager.instance.currentInteractable == campfire)
				{
					GUIManager.instance.RefreshInteractablePrompt();
				}
			}
			catch
			{
			}
		}

		private static bool LooksLikePortableStove(string token)
		{
			if (string.IsNullOrEmpty(token))
			{
				return false;
			}
			string text = token.Replace(" ", string.Empty);
			if (text.IndexOf("PORTABLESTOVE", StringComparison.OrdinalIgnoreCase) < 0)
			{
				return text.IndexOf("PortableStove", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return true;
		}

		private static Transform FindLogsRecursive(Transform parent, int depth)
		{
			if ((Object)(object)parent == (Object)null || depth > 3)
			{
				return null;
			}
			for (int i = 0; i < parent.childCount; i++)
			{
				Transform child = parent.GetChild(i);
				if ((Object)(object)child != (Object)null && ((Object)child).name.IndexOf("Logs", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return child;
				}
				Transform val = FindLogsRecursive(child, depth + 1);
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			return null;
		}

		private static void SetChildActive(Transform logRoot, int index, bool active)
		{
			if (index >= 0 && index < logRoot.childCount)
			{
				Transform child = logRoot.GetChild(index);
				if ((Object)(object)child != (Object)null)
				{
					((Component)child).gameObject.SetActive(active);
				}
			}
		}
	}
	internal static class CampfireStones
	{
		private const string HologramName = "CB_StoneHologram";

		private static readonly Dictionary<int, int> CountsByViewId = new Dictionary<int, int>();

		private static bool _loggedHolo;

		internal static void ResetAll()
		{
			CountsByViewId.Clear();
			List<Campfire> aLL_CAMPFIRES = Campfire.ALL_CAMPFIRES;
			if (aLL_CAMPFIRES != null)
			{
				for (int i = 0; i < aLL_CAMPFIRES.Count; i++)
				{
					RestoreVisuals(aLL_CAMPFIRES[i]);
				}
			}
		}

		internal static void RefreshAll()
		{
			List<Campfire> aLL_CAMPFIRES = Campfire.ALL_CAMPFIRES;
			if (aLL_CAMPFIRES != null)
			{
				for (int i = 0; i < aLL_CAMPFIRES.Count; i++)
				{
					Ensure(aLL_CAMPFIRES[i]);
				}
			}
		}

		internal static bool NeedsStones(Campfire campfire)
		{
			if (!ShouldUse(campfire) || campfire.Lit)
			{
				return false;
			}
			return GetCount(campfire) < Plugin.RequiredStoneCount;
		}

		internal static bool ShouldUse(Campfire campfire)
		{
			if ((Object)(object)campfire == (Object)null || !Plugin.StonesEnabled)
			{
				return false;
			}
			if (campfire.forceLit || CampfireWood.IsPortableStove(campfire))
			{
				return false;
			}
			if (FirewoodSpawner.IsPlaneWreckCampfire(((Component)campfire).transform))
			{
				return false;
			}
			return true;
		}

		internal static int GetCount(Campfire campfire)
		{
			int viewId = CampfireWood.GetViewId(campfire);
			if (viewId > 0 && CountsByViewId.TryGetValue(viewId, out var value))
			{
				return value;
			}
			return 0;
		}

		internal static void Ensure(Campfire campfire)
		{
			if ((Object)(object)campfire == (Object)null)
			{
				return;
			}
			if (!ShouldUse(campfire) || campfire.Lit)
			{
				RestoreVisuals(campfire);
				return;
			}
			int viewId = CampfireWood.GetViewId(campfire);
			if (viewId > 0 && !CountsByViewId.ContainsKey(viewId))
			{
				CountsByViewId[viewId] = 0;
			}
			DisableSmokeOff(((Component)campfire).transform);
			if (NeedsStones(campfire))
			{
				ShowHologram(campfire);
			}
			else
			{
				RestoreVisuals(campfire);
			}
		}

		internal static bool TryPlace(Campfire campfire, Character interactor)
		{
			if ((Object)(object)campfire == (Object)null || (Object)(object)interactor == (Object)null || !interactor.IsLocal)
			{
				return false;
			}
			if (!NeedsStones(campfire))
			{
				return false;
			}
			if (!IsStoneItem(((Object)(object)interactor.data != (Object)null) ? interactor.data.currentItem : null))
			{
				return false;
			}
			if (!FirewoodStack.ConsumeOne(interactor, 72))
			{
				return false;
			}
			SetCount(campfire, GetCount(campfire) + 1, broadcast: true);
			return true;
		}

		internal static void SetCount(Campfire campfire, int count, bool broadcast)
		{
			if (!((Object)(object)campfire == (Object)null))
			{
				int num = Mathf.Max(0, count);
				int viewId = CampfireWood.GetViewId(campfire);
				if (viewId > 0)
				{
					CountsByViewId[viewId] = num;
				}
				Ensure(campfire);
				RefreshPrompt(campfire);
				if (broadcast && viewId > 0)
				{
					BuildFireNet.BroadcastStones(viewId, num);
				}
			}
		}

		internal static void ApplyNetworkCount(int viewId, int count)
		{
			if (viewId > 0)
			{
				CountsByViewId[viewId] = Mathf.Max(0, count);
				Campfire val = FindCampfire(viewId);
				if ((Object)(object)val != (Object)null)
				{
					Ensure(val);
					RefreshPrompt(val);
				}
			}
		}

		internal static void ApplySnapshot(int[] viewIds, int[] counts)
		{
			if (viewIds != null && counts != null)
			{
				int num = Math.Min(viewIds.Length, counts.Length);
				for (int i = 0; i < num; i++)
				{
					ApplyNetworkCount(viewIds[i], counts[i]);
				}
			}
		}

		internal static void CopySnapshot(out int[] viewIds, out int[] counts)
		{
			viewIds = new int[CountsByViewId.Count];
			counts = new int[CountsByViewId.Count];
			int num = 0;
			foreach (KeyValuePair<int, int> item in CountsByViewId)
			{
				viewIds[num] = item.Key;
				counts[num] = item.Value;
				num++;
			}
		}

		internal static string GetPrompt(Campfire campfire)
		{
			if (!NeedsStones(campfire))
			{
				return null;
			}
			int count = GetCount(campfire);
			int requiredStoneCount = Plugin.RequiredStoneCount;
			return Plugin.FormatStonePrompt(IsStoneItem(((Object)(object)Character.localCharacter != (Object)null && (Object)(object)Character.localCharacter.data != (Object)null) ? Character.localCharacter.data.currentItem : null), count, requiredStoneCount);
		}

		internal static bool IsStoneItem(Item item)
		{
			if ((Object)(object)item != (Object)null)
			{
				return Plugin.IsStoneItemId(item.itemID);
			}
			return false;
		}

		private static void ShowHologram(Campfire campfire)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = ((Component)campfire).transform;
			DisableSmokeOff(transform);
			TintAsHologram(campfire);
			if ((Object)(object)FindHologram(transform) == (Object)null)
			{
				new GameObject("CB_StoneHologram").transform.SetParent(transform, false);
			}
		}

		private static void RestoreVisuals(Campfire campfire)
		{
			if (!((Object)(object)campfire == (Object)null))
			{
				Transform val = FindHologram(((Component)campfire).transform);
				if ((Object)(object)val != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)val).gameObject);
				}
				CampfireHoloState component = ((Component)campfire).GetComponent<CampfireHoloState>();
				if ((Object)(object)component != (Object)null)
				{
					component.Restore();
					Object.Destroy((Object)(object)component);
				}
				if (ShouldUse(campfire))
				{
					DisableSmokeOff(((Component)campfire).transform);
				}
				CampfireWood.ApplyLogVisuals(campfire, CampfireWood.GetCount(campfire));
			}
		}

		private static void TintAsHologram(Campfire campfire)
		{
			CampfireHoloState campfireHoloState = ((Component)campfire).GetComponent<CampfireHoloState>();
			if ((Object)(object)campfireHoloState != (Object)null && campfireHoloState.Applied)
			{
				return;
			}
			List<Renderer> list = new List<Renderer>(16);
			CollectRenderers(((Component)campfire).transform, list, 0);
			if (list.Count == 0)
			{
				Plugin.LogOnce(ref _loggedHolo, "[Campfire Building] Stone hologram found no campfire meshes.", null);
				return;
			}
			if ((Object)(object)campfireHoloState == (Object)null)
			{
				campfireHoloState = ((Component)campfire).gameObject.AddComponent<CampfireHoloState>();
			}
			if (!campfireHoloState.Apply(list))
			{
				Plugin.LogOnce(ref _loggedHolo, "[Campfire Building] Stone hologram material missing.", null);
			}
		}

		private static void CollectRenderers(Transform t, List<Renderer> list, int depth)
		{
			if ((Object)(object)t == (Object)null || depth > 6 || ((Object)t).name == "CB_StoneHologram" || IsVfxName(((Object)t).name) || ((Object)t).name.IndexOf("Logs", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return;
			}
			Renderer[] components = ((Component)t).GetComponents<Renderer>();
			foreach (Renderer val in components)
			{
				if ((Object)(object)val != (Object)null)
				{
					list.Add(val);
				}
			}
			int childCount = t.childCount;
			for (int j = 0; j < childCount; j++)
			{
				CollectRenderers(t.GetChild(j), list, depth + 1);
			}
		}

		private static void DisableSmokeOff(Transform root)
		{
			if (!((Object)(object)root == (Object)null))
			{
				Transform val = FindNamed(root, "VFX_Smoke_Off", 6);
				if ((Object)(object)val != (Object)null)
				{
					((Component)val).gameObject.SetActive(false);
				}
			}
		}

		private static Transform FindHologram(Transform root)
		{
			if ((Object)(object)root == (Object)null)
			{
				return null;
			}
			return root.Find("CB_StoneHologram");
		}

		private static Transform FindNamed(Transform root, string token, int depth)
		{
			if ((Object)(object)root == (Object)null || depth < 0)
			{
				return null;
			}
			if (((Object)root).name.IndexOf(token, StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return root;
			}
			int childCount = root.childCount;
			for (int i = 0; i < childCount; i++)
			{
				Transform val = FindNamed(root.GetChild(i), token, depth - 1);
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			return null;
		}

		private static bool IsVfxName(string name)
		{
			if (string.IsNullOrEmpty(name))
			{
				return false;
			}
			if (name.IndexOf("VFX", StringComparison.OrdinalIgnoreCase) < 0 && name.IndexOf("Smoke", StringComparison.OrdinalIgnoreCase) < 0)
			{
				return name.IndexOf("Particle", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return true;
		}

		private static Campfire FindCampfire(int viewId)
		{
			PhotonView val = PhotonView.Find(viewId);
			if ((Object)(object)val != (Object)null)
			{
				Campfire component = ((Component)val).GetComponent<Campfire>();
				if ((Object)(object)component != (Object)null)
				{
					return component;
				}
			}
			List<Campfire> aLL_CAMPFIRES = Campfire.ALL_CAMPFIRES;
			if (aLL_CAMPFIRES == null)
			{
				return null;
			}
			for (int i = 0; i < aLL_CAMPFIRES.Count; i++)
			{
				Campfire val2 = aLL_CAMPFIRES[i];
				if ((Object)(object)val2 != (Object)null && CampfireWood.GetViewId(val2) == viewId)
				{
					return val2;
				}
			}
			return null;
		}

		private static void RefreshPrompt(Campfire campfire)
		{
			try
			{
				if ((Object)(object)GUIManager.instance != (Object)null && (object)GUIManager.instance.currentInteractable == campfire)
				{
					GUIManager.instance.RefreshInteractablePrompt();
				}
			}
			catch
			{
			}
		}
	}
	internal sealed class CampfireHoloState : MonoBehaviour
	{
		private Renderer[] _renderers;

		private Material[][] _originals;

		private readonly List<Material> _ghosts = new List<Material>(8);

		internal bool Applied => _renderers != null;

		internal bool Apply(List<Renderer> renderers)
		{
			if (Applied || renderers == null || renderers.Count == 0)
			{
				return Applied;
			}
			_renderers = (Renderer[])(object)new Renderer[renderers.Count];
			_originals = new Material[renderers.Count][];
			bool flag = false;
			for (int i = 0; i < renderers.Count; i++)
			{
				Renderer val = renderers[i];
				_renderers[i] = val;
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				Material[] sharedMaterials = val.sharedMaterials;
				_originals[i] = CopyMaterials(sharedMaterials);
				Material[] array = (Material[])(object)new Material[(sharedMaterials == null || sharedMaterials.Length == 0) ? 1 : sharedMaterials.Length];
				for (int j = 0; j < array.Length; j++)
				{
					Material source = ((sharedMaterials != null && j < sharedMaterials.Length) ? sharedMaterials[j] : null);
					array[j] = MakeGhost(source);
					if ((Object)(object)array[j] != (Object)null)
					{
						_ghosts.Add(array[j]);
						flag = true;
					}
				}
				val.sharedMaterials = array;
				val.enabled = true;
			}
			if (!flag)
			{
				Restore();
				return false;
			}
			return true;
		}

		internal void Restore()
		{
			if (_renderers != null && _originals != null)
			{
				int num = Math.Min(_renderers.Length, _originals.Length);
				for (int i = 0; i < num; i++)
				{
					Renderer val = _renderers[i];
					if ((Object)(object)val != (Object)null && _originals[i] != null)
					{
						val.sharedMaterials = _originals[i];
					}
				}
			}
			for (int j = 0; j < _ghosts.Count; j++)
			{
				if ((Object)(object)_ghosts[j] != (Object)null)
				{
					Object.Destroy((Object)(object)_ghosts[j]);
				}
			}
			_ghosts.Clear();
			_renderers = null;
			_originals = null;
		}

		private void OnDestroy()
		{
			Restore();
		}

		private static Material[] CopyMaterials(Material[] src)
		{
			if (src == null || src.Length == 0)
			{
				return src;
			}
			Material[] array = (Material[])(object)new Material[src.Length];
			Array.Copy(src, array, src.Length);
			return array;
		}

		private static Material MakeGhost(Material source)
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			Shader val = Shader.Find("Universal Render Pipeline/Unlit");
			if ((Object)(object)val == (Object)null)
			{
				val = Shader.Find("Unlit/Transparent");
			}
			if ((Object)(object)val == (Object)null)
			{
				val = Shader.Find("Standard");
			}
			if ((Object)(object)val == (Object)null && (Object)(object)source != (Object)null)
			{
				val = source.shader;
			}
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			Material val2 = new Material(val);
			if ((Object)(object)source != (Object)null)
			{
				if (source.HasProperty("_BaseMap") && val2.HasProperty("_BaseMap"))
				{
					val2.SetTexture("_BaseMap", source.GetTexture("_BaseMap"));
				}
				if (source.HasProperty("_MainTex") && val2.HasProperty("_MainTex"))
				{
					val2.SetTexture("_MainTex", source.GetTexture("_MainTex"));
				}
			}
			Color tint = default(Color);
			((Color)(ref tint))..ctor(0.35f, 0.9f, 1f, 0.4f);
			MakeTransparent(val2, tint);
			return val2;
		}

		private static void MakeTransparent(Material mat, Color tint)
		{
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: 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_014d: 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_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			if (mat.HasProperty("_Surface"))
			{
				mat.SetFloat("_Surface", 1f);
			}
			if (mat.HasProperty("_Blend"))
			{
				mat.SetFloat("_Blend", 0f);
			}
			if (mat.HasProperty("_Mode"))
			{
				mat.SetFloat("_Mode", 3f);
			}
			if (mat.HasProperty("_SrcBlend"))
			{
				mat.SetFloat("_SrcBlend", 5f);
			}
			if (mat.HasProperty("_DstBlend"))
			{
				mat.SetFloat("_DstBlend", 10f);
			}
			if (mat.HasProperty("_ZWrite"))
			{
				mat.SetFloat("_ZWrite", 0f);
			}
			mat.DisableKeyword("_ALPHATEST_ON");
			mat.DisableKeyword("_ALPHAPREMULTIPLY_ON");
			mat.EnableKeyword("_ALPHABLEND_ON");
			mat.EnableKeyword("_SURFACE_TYPE_TRANSPARENT");
			mat.SetOverrideTag("RenderType", "Transparent");
			mat.renderQueue = 3000;
			if (mat.HasProperty("_BaseColor"))
			{
				Color color = mat.GetColor("_BaseColor");
				color.a = tint.a;
				mat.SetColor("_BaseColor", Color.Lerp(color, tint, 0.55f));
			}
			if (mat.HasProperty("_Color"))
			{
				Color color2 = mat.GetColor("_Color");
				color2.a = tint.a;
				mat.SetColor("_Color", Color.Lerp(color2, tint, 0.55f));
			}
			mat.color = tint;
			if (mat.HasProperty("_EmissionColor"))
			{
				mat.EnableKeyword("_EMISSION");
				mat.SetColor("_EmissionColor", new Color(0.08f, 0.35f, 0.5f, 1f));
			}
		}
	}
	internal static class FirewoodSpawner
	{
		private struct ClimbSurface
		{
			public Vector3 origin;

			public Vector3 topCenter;

			public Vector3 xzExtents;

			public float topY;
		}

		internal struct BiomeVeg
		{
			public string[] folders;

			public string[] tokens;

			public bool berry;

			public bool tumble;

			public bool cactus;

			public bool climbSurfaces;
		}

		private const float MaxDropBelowOrigin = 14f;

		private const float MaxDropThroughCanopy = 72f;

		private const int NoSegment = int.MinValue;

		private static readonly List<Vector3> PlacedPoints = new List<Vector3>(80);

		private static readonly List<Vector3> PlacedStonePoints = new List<Vector3>(80);

		private static readonly RaycastHit[] RayHits = (RaycastHit[])(object)new RaycastHit[96];

		private static readonly List<Renderer> ClimbRenderers = new List<Renderer>(24);

		private static readonly BiomeVeg VegCaldera = new BiomeVeg
		{
			climbSurfaces = true
		};

		private static readonly BiomeVeg VegKiln = new BiomeVeg
		{
			folders = new string[4] { "Edges", "Start", "Bridges", "Foundation" },
			tokens = new string[4] { "RockFinal", "Rock_Round", "Cliff", "LavaBridge" },
			climbSurfaces = true
		};

		private static readonly BiomeVeg VegCitadel = new BiomeVeg
		{
			folders = new string[6] { "Spawners", "Floor Small", "Small Architecture", "Loose Bricks", "Floors", "Bridges" },
			tokens = new string[6] { "Temple Floor Chunk", "Loose Brick", "Floor Bridge", "Bridge Structure", "Floor partial Bridge", "Bridge Stairs" },
			climbSurfaces = true
		};

		private static readonly BiomeVeg VegShore = new BiomeVeg
		{
			folders = new string[4] { "PlateauProps", "Palms", "Oasis Palms", "Bushes" },
			tokens = new string[1] { "Jungle_PalmTree" },
			berry = true
		};

		private static readonly BiomeVeg VegTropics = new BiomeVeg
		{
			folders = new string[6] { "Thorny", "Pops_Plat", "Props_Wall", "Palms", "Trees", "Bushes" },
			tokens = new string[2] { "Jungle_PalmTree", "Jungle_Willow" },
			berry = true
		};

		private static readonly BiomeVeg VegRoots = new BiomeVeg
		{
			folders = new string[4] { "PlateauProps", "WallProps", "redwoods", "base Stumps" },
			tokens = new string[1] { "Redwood" }
		};

		private static readonly BiomeVeg VegAlpine = new BiomeVeg
		{
			folders = new string[5] { "PlateauProps", "WallProps", "Pine", "Trees", "Shrub" },
			tokens = new string[3] { "Ice_Pine", "Ice_DeadTree", "Ice_DeadShrub" }
		};

		private static readonly BiomeVeg VegMesa = new BiomeVeg
		{
			folders = new string[3] { "Oasis", "Spawns", "Tumblers" },
			tokens = new string[2] { "Jungle_PalmTree", "TumbleWeed" },
			berry = true,
			tumble = true,
			cactus = true
		};

		private static readonly BiomeVeg VegGloom = new BiomeVeg
		{
			folders = new string[3] { "Rocks", "Big Rocks", "Small Rocks" },
			tokens = new string[3] { "RockFinal_Desert", "Rock_Lil", "RockFinalSmall" },
			climbSurfaces = true
		};

		private static int _terrainMask = int.MinValue;

		private static int _groundMask = int.MinValue;

		private static Transform _gloomWater;

		private static float _gloomWaterY = float.MinValue;

		private static int _gloomWaterSearchFrame = -999;

		internal static void ResetRun()
		{
			PlacedPoints.Clear();
			PlacedStonePoints.Clear();
			_gloomWater = null;
			_gloomWaterY = float.MinValue;
			_gloomWaterSearchFrame = -999;
			FirewoodPing.Reset();
		}

		internal static void ScheduleCurrentSegment()
		{
			FirewoodPing.Ensure();
		}

		internal static void OnBiomeStinger()
		{
			FirewoodPing.Ensure();
			if (InGameplayLevel())
			{
				int num = CurrentSegmentIndex();
				if (num >= 0)
				{
					Plugin.DebugLog("[Campfire Building] Stinger — ping biome segment " + num + " (" + DescribeSegment(num) + ").");
				}
			}
		}

		internal static int GetCurrentSegment()
		{
			return CurrentSegmentIndex();
		}

		internal static bool SkipKiln(int segment)
		{
			return ShouldSkipKilnCitadel(segment);
		}

		internal static bool GameplayReady()
		{
			if (InGameplayLevel())
			{
				return !IsLoading();
			}
			return false;
		}

		internal static string SegmentLabel(int segment)
		{
			return DescribeSegment(segment);
		}

		internal static BiomeVeg GetVeg(int segment)
		{
			return GetBiomeVeg(segment);
		}

		internal static bool IsLodOrMesh(string name)
		{
			return IsMeshOrLodName(name);
		}

		internal static bool PingTooClose(Vector3 pos, float spacing, bool stone)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			return TooClose(stone ? PlacedStonePoints : PlacedPoints, pos, spacing);
		}

		internal static void PingRemember(Vector3 pos, bool stone)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			if (stone)
			{
				PlacedStonePoints.Add(pos);
			}
			else
			{
				PlacedPoints.Add(pos);
			}
		}

		internal static bool IsPingPlant(Transform t, BiomeVeg veg, out bool cactus, out bool climb, out string key)
		{
			cactus = false;
			climb = false;
			key = null;
			if ((Object)(object)t == (Object)null || string.IsNullOrEmpty(((Object)t).name))
			{
				return false;
			}
			string name = ((Object)t).name;
			if (NameContains(name, "FireWood") || NameContains(name, "Campfire") || NameContains(name, "crashed plane") || NameContains(name, "WaterHazard"))
			{
				return false;
			}
			cactus = veg.cactus && IsMesaCactusName(name);
			if (cactus)
			{
				key = NormalizePrefabName(name);
				return true;
			}
			if (veg.berry && (Object)(object)((Component)t).GetComponent<BerryBush>() != (Object)null)
			{
				key = "BerryBush";
				return true;
			}
			if (veg.tumble && (Object)(object)((Component)t).GetComponent<TumbleWeed>() != (Object)null)
			{
				key = "TumbleWeed";
				return true;
			}
			climb = veg.climbSurfaces && (IsWalkableSurfaceName(name) || IsNestName(name) || (veg.tokens != null && MatchesToken(name, veg.tokens)));
			if (climb)
			{
				if (IsCalderaMiddleGround(t))
				{
					return false;
				}
				key = NormalizePrefabName(name);
				return true;
			}
			if (MatchesToken(name, veg.tokens) && !IsBiomeFolder(name, veg.folders))
			{
				key = NormalizePrefabName(name);
				return true;
			}
			if (veg.berry && NameContains(name, "berrybush"))
			{
				key = "BerryBush";
				return true;
			}
			return false;
		}

		internal static bool TrySnapPing(Transform root, bool cactus, bool climb, out Vector3 pos)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			pos = Vector3.zero;
			if ((Object)(object)root == (Object)null)
			{
				return false;
			}
			if (cactus)
			{
				if (!TrySnapBesideCactus(root.position, out pos))
				{
					return false;
				}
			}
			else if (climb)
			{
				if (!TrySnapClimbTop(PreferClimbSnapRoot(root), out pos))
				{
					return false;
				}
			}
			else if (!TrySnapBesidePlant(root.position, out pos))
			{
				return false;
			}
			if (IsBelowGloomWater(pos))
			{
				pos = Vector3.zero;
				return false;
			}
			return true;
		}

		internal static bool SpawnStickNow(Vector3 position)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			return SpawnLootNow("FireWood", position);
		}

		internal static bool SpawnStoneNow(Vector3 position)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			return SpawnLootNow("Stone", position);
		}

		internal static bool IsPlaneWreckCampfire(Transform t)
		{
			if (!HasNamedAncestor(t, "crashed plane"))
			{
				return NameContains(((Object)t).name, "crashed plane");
			}
			return true;
		}

		internal static bool IsCalderaMiddleGround(Transform t)
		{
			bool flag = false;
			int num = 0;
			Transform val = t;
			while ((Object)(object)val != (Object)null && num < 14)
			{
				string name = ((Object)val).name;
				if (!string.IsNullOrEmpty(name))
				{
					if (name.Equals("Middle", StringComparison.OrdinalIgnoreCase))
					{
						flag = true;
					}
					if (flag && NameContains(name, "Caldera_Segment"))
					{
						return true;
					}
				}
				val = val.parent;
				num++;
			}
			return false;
		}

		private static bool IsGloomWaterCollider(Collider col)
		{
			if ((Object)(object)col == (Object)null)
			{
				return false;
			}
			if (!HasNamedAncestor(((Component)col).transform, "WaterHazard"))
			{
				return NameContains(((Object)col).name, "WaterHazard");
			}
			return true;
		}

		private static bool IsBelowGloomWater(Vector3 pos)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: 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_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			EnsureGloomWater();
			if ((Object)(object)_gloomWater == (Object)null)
			{
				return false;
			}
			Collider componentInChildren = ((Component)_gloomWater).GetComponentInChildren<Collider>();
			if ((Object)(object)componentInChildren != (Object)null)
			{
				Bounds bounds = componentInChildren.bounds;
				if (((Bounds)(ref bounds)).size.y > 4f)
				{
					return pos.y <= ((Bounds)(ref bounds)).min.y + 0.5f;
				}
				return pos.y <= ((Bounds)(ref bounds)).max.y + 0.75f;
			}
			if (_gloomWaterY <= -1000f)
			{
				return false;
			}
			return pos.y <= _gloomWater.position.y + 0.75f;
		}

		private static void EnsureGloomWater()
		{
			if ((Object)(object)_gloomWater != (Object)null)
			{
				_gloomWaterY = WaterSurfaceY(_gloomWater);
			}
			else if (Time.frameCount - _gloomWaterSearchFrame >= 90)
			{
				_gloomWaterSearchFrame = Time.frameCount;
				GameObject val = GameObject.Find("WaterHazard_Swamp");
				if (!((Object)(object)val == (Object)null))
				{
					_gloomWater = val.transform;
					_gloomWaterY = WaterSurfaceY(_gloomWater);
				}
			}
		}

		private static float WaterSurfaceY(Transform water)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)water == (Object)null)
			{
				return float.MinValue;
			}
			Collider componentInChildren = ((Component)water).GetComponentInChildren<Collider>();
			Bounds bounds;
			if ((Object)(object)componentInChildren != (Object)null)
			{
				bounds = componentInChildren.bounds;
				return ((Bounds)(ref bounds)).max.y;
			}
			Renderer componentInChildren2 = ((Component)water).GetComponentInChildren<Renderer>();
			if ((Object)(object)componentInChildren2 != (Object)null)
			{
				bounds = componentInChildren2.bounds;
				return ((Bounds)(ref bounds)).max.y;
			}
			return water.position.y;
		}

		private static bool SpawnLootNow(string prefabName, Vector3 position)
		{
			//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_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			Quaternion identity = Quaternion.identity;
			GameObject val = TryInstantiateItemRoom(prefabName, position, identity);
			if ((Object)(object)val == (Object)null)
			{
				val = TryInstantiateRoomObject("0_Items/" + prefabName, position, identity);
			}
			return (Object)(object)val != (Object)null;
		}

		private static BiomeVeg GetBiomeVeg(int segment)
		{
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Invalid comparison between Unknown and I4
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Invalid comparison between Unknown and I4
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Invalid comparison between Unknown and I4
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Invalid comparison between Unknown and I4
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Invalid comparison between Unknown and I4
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Invalid comparison between Unknown and I4
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Invalid comparison between Unknown and I4
			string segmentParentName = GetSegmentParentName(segment);
			if (NameContains(segmentParentName, "Temple_Segment") || NameContains(segmentParentName, "Gloom Temple") || NameContains(segmentParentName, "Citadel") || NameContains(segmentParentName, "Peak_Segment"))
			{
				return VegCitadel;
			}
			if (NameContains(segmentParentName, "Volcano_Segment") || NameContains(segmentParentName, "Peak_Kiln"))
			{
				return VegKiln;
			}
			BiomeType val = ResolveBiome(segment);
			if ((int)val == 3)
			{
				return VegCaldera;
			}
			if ((int)val == 0)
			{
				return VegShore;
			}
			if ((int)val == 1)
			{
				return VegTropics;
			}
			if ((int)val == 7)
			{
				return VegRoots;
			}
			if ((int)val == 2)
			{
				return VegAlpine;
			}
			if ((int)val == 6)
			{
				return VegMesa;
			}
			if ((int)val == 8)
			{
				return VegGloom;
			}
			if ((int)val == 9)
			{
				return VegCitadel;
			}
			return default(BiomeVeg);
		}

		private static string GetSegmentParentName(int segment)
		{
			try
			{
				MapHandler instance = Singleton<MapHandler>.Instance;
				if ((Object)(object)instance != (Object)null && instance.segments != null && segment >= 0 && segment < instance.segments.Length && instance.segments[segment] != null && (Object)(object)instance.segments[segment].segmentParent != (Object)null)
				{
					return ((Object)instance.segments[segment].segmentParent).name;
				}
			}
			catch
			{
			}
			return "";
		}

		private static BiomeType ResolveBiome(int segment)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			BiomeType result = (BiomeType)0;
			string name = "";
			try
			{
				MapHandler instance = Singleton<MapHandler>.Instance;
				if ((Object)(object)instance != (Object)null && instance.segments != null && segment >= 0 && segment < instance.segments.Length && instance.segments[segment] != null)
				{
					MapSegment val = instance.segments[segment];
					result = val._biome;
					if ((Object)(object)val.segmentParent != (Object)null)
					{
						name = ((Object)val.segmentParent).name;
					}
				}
			}
			catch
			{
			}
			if (NameContains(name, "Beach") || NameContains(name, "Beach_Segment"))
			{
				return (BiomeType)0;
			}
			if (NameContains(name, "Jungle") || NameContains(name, "Tropics"))
			{
				return (BiomeType)1;
			}
			if (NameContains(name, "Roots"))
			{
				return (BiomeType)7;
			}
			if (NameContains(name, "Snow") || NameContains(name, "Alpine"))
			{
				return (BiomeType)2;
			}
			if (NameContains(name, "Desert") || NameContains(name, "Mesa"))
			{
				return (BiomeType)6;
			}
			if (NameContains(name, "Caldera") || NameContains(name, "Volcano_Segment"))
			{
				return (BiomeType)3;
			}
			if (NameContains(name, "Swamp") || (NameContains(name, "Gloom") && !NameContains(name, "Gloom Temple")))
			{
				return (BiomeType)8;
			}
			return result;
		}

		private static bool MatchesToken(string name, string[] tokens)
		{
			if (tokens == null)
			{
				return false;
			}
			for (int i = 0; i < tokens.Length; i++)
			{
				if (NameContains(name, tokens[i]))
				{
					return true;
				}
			}
			return false;
		}

		private static bool IsBiomeFolder(string name, string[] folders)
		{
			if (folders == null)
			{
				return false;
			}
			string text = StripInstanceSuffix(name);
			for (int i = 0; i < folders.Length; i++)
			{
				if (text.Equals(folders[i], StringComparison.OrdinalIgnoreCase))
				{
					return true;
				}
			}
			return false;
		}

		private static bool TrySnapBesidePlant(Vector3 origin, out Vector3 pos)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: 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)
			pos = origin;
			for (int i = 0; i < 6; i++)
			{
				float num = Random.Range(0f, (float)Math.PI * 2f);
				float num2 = Random.Range(3.5f, 9f);
				if (TrySnapToGround(origin + new Vector3(Mathf.Cos(num) * num2, 0f, Mathf.Sin(num) * num2), origin.y, 72f, out pos))
				{
					return true;
				}
			}
			return TrySnapToGround(origin, origin.y, 72f, out pos);
		}

		private static bool TrySnapBesideCactus(Vector3 origin, out Vector3 pos)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: 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_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: 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_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			pos = origin;
			for (int i = 0; i < 2; i++)
			{
				float num = Random.Range(0f, (float)Math.PI * 2f);
				float num2 = Random.Range(6.5f, 11f);
				if (TrySnapToGround(origin + new Vector3(Mathf.Cos(num) * num2, 0f, Mathf.Sin(num) * num2), origin.y, out var pos2))
				{
					float num3 = pos2.x - origin.x;
					float num4 = pos2.z - origin.z;
					if (!(num3 * num3 + num4 * num4 < 30.25f))
					{
						pos = pos2;
						return true;
					}
				}
			}
			return TrySnapToGround(JitterXz(origin, 8f), origin.y, out pos);
		}

		private static Vector3 JitterXz(Vector3 origin, float spread)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//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)
			return origin + new Vector3(Random.Range(0f - spread, spread), 0f, Random.Range(0f - spread, spread));
		}

		private static bool TooClose(List<Vector3> points, Vector3 pos, float minSpacing)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: 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)
			if (points == null || minSpacing <= 0f)
			{
				return false;
			}
			float num = minSpacing * minSpacing;
			for (int i = 0; i < points.Count; i++)
			{
				Vector3 val = points[i] - pos;
				if (((Vector3)(ref val)).sqrMagnitude < num)
				{
					return true;
				}
			}
			return false;
		}

		private static Transform PreferClimbSnapRoot(Transform t)
		{
			if ((Object)(object)t == (Object)null)
			{
				return null;
			}
			if (NameContains(((Object)t).name, "Plartform") || NameContains(((Object)t).name, "Cliff") || NameContains(((Object)t).name, "Bridge Structure") || NameContains(((Object)t).name, "Bridge Stairs") || NameContains(((Object)t).name, "Floor partial Bridge") || ((Object)t).name.Equals("Floor", StringComparison.OrdinalIgnoreCase))
			{
				return t;
			}
			Transform val = FindNamedDescendant(t, "Plartform", 3);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			Transform val2 = FindNamedDescendant(t, "Cliff", 2);
			if ((Object)(object)val2 != (Object)null)
			{
				return val2;
			}
			Transform val3 = FindNamedDescendant(t, "Bridge Structure", 3);
			if ((Object)(object)val3 != (Object)null)
			{
				return val3;
			}
			Transform val4 = FindNamedDescendant(t, "Bridge Stairs", 3);
			if ((Object)(object)val4 != (Object)null)
			{
				return val4;
			}
			Transform val5 = FindNamedDescendant(t, "Floor", 2);
			if ((Object)(object)val5 != (Object)null && !NameContains(((Object)val5).name, "Floor Small") && !NameContains(((Object)val5).name, "Floors"))
			{
				return val5;
			}
			return t;
		}

		private static Transform FindNamedDescendant(Transform t, string token, int depth)
		{
			if ((Object)(object)t == (Object)null || depth < 0)
			{
				return null;
			}
			int childCount = t.childCount;
			for (int i = 0; i < childCount; i++)
			{
				Transform child = t.GetChild(i);
				if (!((Object)(object)child == (Object)null))
				{
					if (NameContains(((Object)child).name, token))
					{
						return child;
					}
					Transform val = FindNamedDescendant(child, token, depth - 1);
					if ((Object)(object)val != (Object)null)
					{
						return val;
					}
				}
			}
			return null;
		}

		private static bool TrySnapClimbTop(Transform t, out Vector3 pos)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: 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_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: 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_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			pos = t.position;
			if (!TryGetClimbBounds(t, out var bounds))
			{
				return false;
			}
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(((Bounds)(ref bounds)).center.x, ((Bounds)(ref bounds)).max.y, ((Bounds)(ref bounds)).center.z);
			return TrySnapOnTop(new ClimbSurface
			{
				origin = val,
				topCenter = val,
				xzExtents = new Vector3(((Bounds)(ref bounds)).extents.x, 0f, ((Bounds)(ref bounds)).extents.z),
				topY = ((Bounds)(ref bounds)).max.y
			}, NameContains(((Object)t).name, "Ring"), out pos);
		}

		private static bool TryGetClimbBounds(Transform t, out Bounds bounds)
		{
			//IL_0001: 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_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			bounds = default(Bounds);
			if ((Object)(object)t == (Object)null)
			{
				return false;
			}
			ClimbRenderers.Clear();
			((Component)t).GetComponentsInChildren<Renderer>(false, ClimbRenderers);
			bool flag = false;
			for (int i = 0; i < ClimbRenderers.Count; i++)
			{
				Renderer val = ClimbRenderers[i];
				if ((Object)(object)val == (Object)null || !val.enabled)
				{
					continue;
				}
				string name = ((Object)val).name;
				if (!NameContains(name, "lava") && !NameContains(name, "Water") && !NameContains(name, "WaterHazard"))
				{
					if (!flag)
					{
						bounds = val.bounds;
						flag = true;
					}
					else
					{
						((Bounds)(ref bounds)).Encapsulate(val.bounds);
					}
				}
			}
			ClimbRenderers.Clear();
			if (flag)
			{
				if (!(((Bounds)(ref bounds)).size.x > 0.4f))
				{
					return ((Bounds)(ref bounds)).size.z > 0.4f;
				}
				return true;
			}
			return false;
		}

		private static bool TrySnapOnTop(ClimbSurface spot, bool ring, out Vector3 pos)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: 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_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			pos = spot.topCenter;
			float num = Mathf.Max(0.55f, spot.xzExtents.x * 0.62f);
			float num2 = Mathf.Max(0.55f, spot.xzExtents.z * 0.62f);
			int num3 = GroundMask();
			RaycastHit hit = default(RaycastHit);
			for (int i = 0; i < 5; i++)
			{
				float num4;
				float num5;
				if (ring)
				{
					switch (i)
					{
					case 0:
						num4 = num;
						num5 = 0f;
						break;
					case 1:
						num4 = 0f - num;
						num5 = 0f;
						break;
					case 2:
						num4 = 0f;
						num5 = num2;
						break;
					case 3:
						num4 = 0f;
						num5 = 0f - num2;
						break;
					default:
						num4 = num * 0.7f;
						num5 = num2 * 0.7f;
						break;
					}
				}
				else
				{
					float num6 = Mathf.Max(0.45f, spot.xzExtents.x * 0.28f);
					float num7 = Mathf.Max(0.45f, spot.xzExtents.z * 0.28f);
					switch (i)
					{
					case 0:
						num4 = 0f;
						num5 = 0f;
						break;
					case 1:
						num4 = num6;
						num5 = 0f;
						break;
					case 2:
						num4 = 0f - num6;
						num5 = 0f;
						break;
					case 3:
						num4 = 0f;
						num5 = num7;
						break;
					default:
						num4 = 0f;
						num5 = 0f - num7;
						break;
					}
				}
				if (Physics.Raycast(new Vector3(spot.topCenter.x + num4, spot.topY + 10f, spot.topCenter.z + num5), Vector3.down, ref hit, 24f, num3, (QueryTriggerInteraction)1) && IsStandableHit(hit, spot.topY + 1f, 3.5f) && !IsBelowGloomWater(((RaycastHit)(ref hit)).point) && !(((RaycastHit)(ref hit)).point.y < spot.topY - 2.2f) && !(Vector3.Angle(Vector3.up, ((RaycastHit)(ref hit)).normal) > 48f))
				{
					pos = ((RaycastHit)(ref hit)).point + Vector3.up * 0.18f;
					return true;
				}
			}
			return false;
		}

		private static string NormalizePrefabName(string name)
		{
			string text = StripInstanceSuffix(name);
			if (text.Length != 0)
			{
				return string.Intern(text);
			}
			return "Plant";
		}

		private static string StripInstanceSuffix(string name)
		{
			if (string.IsNullOrEmpty(name))
			{
				return "Plant";
			}
			int num = name.IndexOf("(Clone)", StringComparison.OrdinalIgnoreCase);
			if (num >= 0)
			{
				name = name.Substring(0, num);
			}
			name = name.Trim();
			int length = name.Length;
			if (length >= 4 && name[length - 1] == ')')
			{
				int num2 = name.LastIndexOf('(');
				if (num2 > 0 && num2 < length - 2)
				{
					bool flag = true;
					for (int i = num2 + 1; i < length - 1; i++)
					{
						if (name[i] < '0' || name[i] > '9')
						{
							flag = false;
							break;
						}
					}
					if (flag)
					{
						name = name.Substring(0, num2).TrimEnd(Array.Empty<char>());
					}
				}
			}
			return name;
		}

		private static bool IsMeshOrLodName(string name)
		{
			if (!NameContains(name, "AutoLOD") && !NameContains(name, "TreeBark") && !NameContains(name, "PalmMesh") && !NameContains(name, "PalmLeaf") && !NameContains(name, "BushLeaves") && !NameContains(name, "TreeCrown") && !NameContains(name, "_Leaves"))
			{
				return name.StartsWith("Spine", StringComparison.OrdinalIgnoreCase);
			}
			return true;
		}

		private static bool IsMesaCactusName(string name)
		{
			if (string.IsNullOrEmpty(name) || IsMeshOrLodName(name))
			{
				return false;
			}
			if (NameContains(name, "Tall Cactus") || NameContains(name, "Cactus Ball Base") || NameContains(name, "Cactus Ball Big"))
			{
				return true;
			}
			if (!NameContains(name, "cactus"))
			{
				return false;
			}
			if (!NameContains(name, "Props") && !NameContains(name, "Bushes") && !NameContains(name, "Spawns"))
			{
				return !NameContains(name, "Oasis");
			}
			return false;
		}

		private static bool IsWalkableSurfaceName(string name)
		{
			if (!NameContains(name, "LavaPillar") && !NameContains(name, "rock_Ring"))
			{
				return NameContains(name, "Plartform");
			}
			return true;
		}

		private static bool IsNestName(string name)
		{
			if (!NameContains(name, "EggNest") && !NameContains(name, "BirdNest"))
			{
				return NameContains(name, "EggNestRaven");
			}
			return true;
		}

		private static bool HasNamedAncestor(Transform t, string token)
		{
			Transform val = (((Object)(object)t != (Object)null) ? t.parent : null);
			int num = 0;
			while ((Object)(object)val != (Object)null && num < 8)
			{
				if (!string.IsNullOrEmpty(((Object)val).name) && NameContains(((Object)val).name, token))
				{
					return true;
				}
				val = val.parent;
				num++;
			}
			return false;
		}

		private static bool ShouldSkipKilnCitadel(int segment)
		{
			if (Plugin.syncedSpawnsInKilnCitadel)
			{
				return false;
			}
			return IsKilnOrCitadelSegment(segment);
		}

		private static bool IsKilnOrCitadelSegment(int segment)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Invalid comparison between Unknown and I4
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Invalid comparison between Unknown and I4
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Invalid comparison between Unknown and I4
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Invalid comparison between Unknown and I4
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Invalid comparison between Unknown and I4
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Invalid comparison between Unknown and I4
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Invalid comparison between Unknown and I4
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Invalid comparison between Unknown and I4
			if (segment < 0)
			{
				return false;
			}
			try
			{
				Segment val = (Segment)(byte)segment;
				if ((int)val == 5)
				{
					return true;
				}
				MapHandler instance = Singleton<MapHandler>.Instance;
				Transform val2 = null;
				BiomeType val3 = (BiomeType)0;
				if ((Object)(object)instance != (Object)null && instance.segments != null && segment < instance.segments.Length)
				{
					MapSegment val4 = instance.segments[segment];
					if (val4 != null)
					{
						val3 = val4._biome;
						if ((Object)(object)val4.segmentParent != (Object)null)
						{
							val2 = val4.segmentParent.transform;
						}
					}
				}
				string name = (((Object)(object)val2 != (Object)null) ? ((Object)val2).name : "");
				if ((IsCalderaOrGloomName(name) || (int)val3 == 3 || (int)val3 == 8) && (int)val != 4 && (int)val != 5)
				{
					return false;
				}
				if ((int)val == 4)
				{
					return true;
				}
				if (IsKilnCitadelSubtree(name))
				{
					return true;
				}
				return (int)val3 == 5 || (int)val3 == 9;
			}
			catch
			{
				return false;
			}
		}

		private static bool IsKilnCitadelSubtree(string name)
		{
			if (string.IsNullOrEmpty(name) || IsCalderaOrGloomName(name))
			{
				return false;
			}
			if (!NameContains(name, "Peak_Kiln") && !NameContains(name, "Peak_Segment") && !NameContains(name, "Temple_Segment") && !NameContains(name, "Gloom Temple") && !name.Equals("Peak", StringComparison.OrdinalIgnoreCase) && !name.Equals("Citadel", StringComparison.OrdinalIgnoreCase))
			{
				return name.Equals("Kiln", StringComparison.OrdinalIgnoreCase);
			}
			return true;
		}

		private static bool IsCalderaOrGloomName(string name)
		{
			if (!NameContains(name, "Caldera") && !NameContains(name, "Volcano_Segment") && !NameContains(name, "Swamp_Segment"))
			{
				if (NameContains(name, "Gloom"))
				{
					return !NameContains(name, "Gloom Temple");
				}
				return false;
			}
			return true;
		}

		private static string DescribeSegment(int segment)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: 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_0067: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				MapHandler instance = Singleton<MapHandler>.Instance;
				if ((Object)(object)instance == (Object)null || instance.segments == null || segment < 0 || segment >= instance.segments.Length)
				{
					return ((object)(Segment)(byte)segment/*cast due to .constrained prefix*/).ToString();
				}
				MapSegment val = instance.segments[segment];
				string text = ((object)(Segment)(byte)segment/*cast due to .constrained prefix*/).ToString();
				if (val == null)
				{
					return text;
				}
				string text2 = ((object)ResolveBiome(segment)/*cast due to .constrained prefix*/).ToString();
				string text3 = (((Object)(object)val.segmentParent != (Object)null) ? ((Object)val.segmentParent).name : "none");
				return text + " " + text2 + " / " + text3;
			}
			catch
			{
				return "segment " + segment;
			}
		}

		private static GameObject TryInstantiateItemRoom(string prefabName, Vector3 pos, Quaternion rot)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				return PhotonNetwork.InstantiateItemRoom(prefabName, pos, rot, true);
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[Campfire Building] InstantiateItemRoom('" + prefabName + "') failed: " + ex.Message));
				}
				return null;
			}
		}

		private static GameObject TryInstantiateRoomObject(string prefabName, Vector3 pos, Quaternion rot)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				return PhotonNetwork.InstantiateRoomObject(prefabName, pos, rot, (byte)0, (object[])null);
			}
			catch
			{
				return null;
			}
		}

		private static bool TrySnapToGround(Vector3 origin, float minY, out Vector3 pos)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return TrySnapToGround(origin, minY, 14f, out pos);
		}

		private static bool TrySnapToGround(Vector3 origin, float minY, float maxDrop, out Vector3 pos)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//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_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			pos = origin;
			Vector3[] array = (Vector3[])(object)new Vector3[3]
			{
				origin + Vector3.up * 6f,
				origin + Vector3.up * 25f,
				new Vector3(origin.x, origin.y + 80f, origin.z)
			};
			int num = TerrainMask();
			for (int i = 0; i < array.Length; i++)
			{
				if (TryPickGroundHit(array[i], 160f, minY, maxDrop, num, out pos))
				{
					return true;
				}
			}
			int num2 = GroundMask();
			if (num2 != num)
			{
				for (int j = 0; j < array.Length; j++)
				{
					if (TryPickGroundHit(array[j], 160f, minY, maxDrop, num2, out pos))
					{
						return true;
					}
				}
			}
			return false;
		}

		private static bool TryPickGroundHit(Vector3 from, float rayLength, float minY, float maxDrop, int mask, out Vector3 pos)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: 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_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: 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_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			pos = from;
			int num = Physics.RaycastNonAlloc(from, Vector3.down, RayHits, rayLength, mask, (QueryTriggerInteraction)1);
			bool flag = mask == GroundMask();
			int num2 = -1;
			float num3 = float.MinValue;
			for (int i = 0; i < num; i++)
			{
				RaycastHit hit = RayHits[i];
				if ((!flag || !IsCanopyHit(hit)) && IsStandableHit(hit, minY, maxDrop) && !IsBelowGloomWater(((RaycastHit)(ref hit)).point) && !IsGloomWaterCollider(((RaycastHit)(ref hit)).collider) && !(Vector3.Angle(Vector3.up, ((RaycastHit)(ref hit)).normal) > 55f) && ((RaycastHit)(ref hit)).point.y > num3)
				{
					num3 = ((RaycastHit)(ref hit)).point.y;
					num2 = i;
				}
			}
			if (num2 < 0)
			{
				return false;
			}
			pos = ((RaycastHit)(ref RayHits[num2])).point + Vector3.up * 0.12f;
			return true;
		}

		private static bool IsCanopyHit(RaycastHit hit)
		{
			Transform val = (((Object)(object)((RaycastHit)(ref hit)).collider != (Object)null) ? ((Component)((RaycastHit)(ref hit)).collider).transform : null);
			int num = 0;
			while ((Object)(object)val != (Object)null && num < 4)
			{
				if (!string.IsNullOrEmpty(((Object)val).name) && (IsMeshOrLodName(((Object)val).name) || NameContains(((Object)val).name, "Leaf") || NameContains(((Object)val).name, "Leaves") || NameContains(((Object)val).name, "Crown") || NameContains(((Object)val).name, "Frond") || NameContains(((Object)val).name, "Foliage") || NameContains(((Object)val).name, "Vine")))
				{
					return true;
				}
				val = val.parent;
				num++;
			}
			return false;
		}

		private static bool IsStandableHit(RaycastHit hit, float minY, float maxDrop)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL