Decompiled source of AllBiomes v0.20.6

AllBiomes.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Peak;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;
using UnityEngine.SceneManagement;
using Zorro.Core;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("AllBiomes")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("AllBiomes")]
[assembly: AssemblyTitle("AllBiomes")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace AllBiomes
{
	[BepInPlugin("peak.allbiomes", "AllBiomes", "0.20.6")]
	public sealed class AllBiomesPlugin : BaseUnityPlugin
	{
		private const BindingFlags Flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

		private readonly List<RuntimeSegment> _segments = new List<RuntimeSegment>();

		private int _builtMapId;

		private int _stableFrames;

		private bool _flight;

		private int _teleportIndex = -1;

		private bool _generationStarted;

		private Harmony _harmony;

		private string _markerFile;

		private int _markerNumber;

		private bool _debugFogOff;

		private int _localCharacterId;

		private int _fogHandlerId;

		private int _fogStateSegment = -1;

		private string _runId = "offline";

		private bool _startNewRun = true;

		private readonly List<GameObject> _debugFogRoots = new List<GameObject>();

		private readonly Dictionary<Rigidbody, Vector2> _flightBodies = new Dictionary<Rigidbody, Vector2>();

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

		private Vector3 _flightLastSafeCenter;

		private List<StaticReference> _pendingStaticSnapshot;

		private int _pendingDonorBuildIndex = -1;

		private GameObject _runtimeRoot;

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

		internal static int LifecycleBlockedBuildIndex = -1;

		internal static AllBiomesPlugin Instance;

		private const string NetworkPlanKey = "ALLBIOMES_PLAN_0205";

		private const string NetworkLayoutKey = "ALLBIOMES_LAYOUT_0205";

		private const string NetworkMobsKey = "ALLBIOMES_MOBS_0205";

		private const string ModVersion = "0.20.6";

		private static readonly Vector3 RescueOffsetFromSummitGem = new Vector3(-1.42f, 47.95f, -29.62f);

		private static Vector3 RescueZoneCenter = new Vector3(-27.25f, 2269.8f, 3750.81f);

		private const float RescueZoneRadius = 35f;

		private void Awake()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			Instance = this;
			_harmony = new Harmony("peak.allbiomes.runtimegenerator");
			_harmony.PatchAll(typeof(AllBiomesPlugin).Assembly);
			InstallDonorLifecycleProtection();
			SceneManager.sceneLoaded += OnSceneLoaded;
			_markerFile = Path.Combine(Paths.ConfigPath, "AllBiomesMarkers.txt");
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[AllBiomes] Runtime generator 0.20.6 loaded (host-authoritative donors)");
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[AllBiomes] F6 fly; F7 teleport; F8 marker; F9 fog; F10 bring players; F11 flare");
		}

		private void Update()
		{
			TryGenerate();
			MaintainRuntimeLifecycle();
			DebugControls();
		}

		private unsafe void FixedUpdate()
		{
			//IL_003c: 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_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: 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_0058: 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_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0240: Unknown result type (might be due to invalid IL or missing references)
			//IL_023a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0245: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0251: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Unknown result type (might be due to invalid IL or missing references)
			//IL_02be: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_029f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0377: Unknown result type (might be due to invalid IL or missing references)
			//IL_037c: Unknown result type (might be due to invalid IL or missing references)
			//IL_036e: Unknown result type (might be due to invalid IL or missing references)
			//IL_034f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0354: Unknown result type (might be due to invalid IL or missing references)
			//IL_035b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0360: Unknown result type (might be due to invalid IL or missing references)
			if (!_flight)
			{
				return;
			}
			Character localCharacter = Character.localCharacter;
			if ((Object)(object)localCharacter == (Object)null)
			{
				return;
			}
			if (_flightBodies.Count == 0)
			{
				BeginFlight(localCharacter);
			}
			if (_flightBodies.Count == 0)
			{
				return;
			}
			Vector3 center = localCharacter.Center;
			if (!IsFinite(center) || ((Vector3)(ref center)).sqrMagnitude > 100000000f || Vector3.Distance(center, _flightLastSafeCenter) > 100f)
			{
				Vector3 val = _flightLastSafeCenter - center;
				if (IsFinite(val))
				{
					localCharacter.refs.ragdoll.MoveAllRigsInDirection(val);
				}
				localCharacter.refs.ragdoll.HaltBodyVelocity(false);
				((BaseUnityPlugin)this).Logger.LogError((object)("[AllBiomes] Flight physics divergence recovered from=" + ((object)(*(Vector3*)(&center))/*cast due to .constrained prefix*/).ToString() + " to=" + ((object)Unsafe.As<Vector3, Vector3>(ref _flightLastSafeCenter)/*cast due to .constrained prefix*/).ToString()));
				return;
			}
			Camera main = Camera.main;
			Vector3 val2;
			Vector3 val3;
			if (!((Object)(object)main != (Object)null))
			{
				val2 = ((Component)localCharacter).transform.forward;
			}
			else
			{
				val3 = ((Component)main).transform.forward;
				val2 = ((Vector3)(ref val3)).normalized;
			}
			Vector3 val4;
			if (!((Object)(object)main != (Object)null))
			{
				val4 = ((Component)localCharacter).transform.right;
			}
			else
			{
				val3 = ((Component)main).transform.right;
				val4 = ((Vector3)(ref val3)).normalized;
			}
			Vector3 val5 = val4;
			float num = ((Input.GetKey((KeyCode)119) || Input.GetKey((KeyCode)273)) ? 1f : 0f) - ((Input.GetKey((KeyCode)115) || Input.GetKey((KeyCode)274)) ? 1f : 0f);
			float num2 = ((Input.GetKey((KeyCode)100) || Input.GetKey((KeyCode)275)) ? 1f : 0f) - ((Input.GetKey((KeyCode)97) || Input.GetKey((KeyCode)276)) ? 1f : 0f);
			Vector3 val6 = val2 * num + val5 * num2;
			float num3 = (Input.GetKey((KeyCode)32) ? 1f : 0f) - ((Input.GetKey((KeyCode)306) || Input.GetKey((KeyCode)99)) ? 1f : 0f);
			float num4 = (Input.GetKey((KeyCode)304) ? 30f : 15f);
			Vector3 val7 = (((((Vector3)(ref val6)).sqrMagnitude > 1f) ? ((Vector3)(ref val6)).normalized : val6) + Vector3.up * num3) * num4;
			foreach (Rigidbody key in _flightBodies.Keys)
			{
				if (!((Object)(object)key == (Object)null))
				{
					key.useGravity = false;
					if (key.isKinematic)
					{
						Transform transform = ((Component)key).transform;
						transform.position += val7 * Time.fixedUnscaledDeltaTime;
					}
					else
					{
						key.linearVelocity = val7;
						key.angularVelocity = Vector3.zero;
					}
				}
			}
			if ((Object)(object)localCharacter.data.currentItem != (Object)null && (Object)(object)localCharacter.data.currentItem.rig != (Object)null)
			{
				Rigidbody rig = localCharacter.data.currentItem.rig;
				if (!_flightBodies.ContainsKey(rig))
				{
					rig.useGravity = false;
					if (rig.isKinematic)
					{
						Transform transform2 = ((Component)rig).transform;
						transform2.position += val7 * Time.fixedUnscaledDeltaTime;
					}
					else
					{
						rig.linearVelocity = val7;
					}
				}
			}
			_flightLastSafeCenter = localCharacter.Center;
		}

		private void TryGenerate()
		{
			if (_generationStarted && _segments.Count > 0)
			{
				return;
			}
			MapHandler val = Object.FindAnyObjectByType<MapHandler>();
			if ((Object)(object)val == (Object)null || ((Object)val).GetInstanceID() == _builtMapId)
			{
				return;
			}
			if (typeof(MapHandler).GetField("segments", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(val) is Array { Length: >=6 } array)
			{
				if (++_stableFrames >= 30)
				{
					_builtMapId = ((Object)val).GetInstanceID();
					if (!_generationStarted)
					{
						_generationStarted = true;
						((MonoBehaviour)this).StartCoroutine(GenerateAllBiomes(val, array));
					}
				}
			}
			else
			{
				_stableFrames = 0;
			}
		}

		private IEnumerator GenerateAllBiomes(MapHandler map, Array vanilla)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[AllBiomes] Generator start");
			Scene mainScene = ((Component)map).gameObject.scene;
			BiomeAsset[] definitions = new BiomeAsset[10]
			{
				new BiomeAsset("Shore", (BiomeType)0, "Beach_Segment", 4, "WilIsland", "Biome_1", "Beach"),
				new BiomeAsset("Tropics", (BiomeType)1, "Jungle_Segment", 6, "Level_1", "Biome_2", "Tropics"),
				new BiomeAsset("Roots", (BiomeType)7, "Roots Segment", 5, "Level_0", "Biome_2", "Roots"),
				new BiomeAsset("Alpine", (BiomeType)2, "Snow_Segment", 6, "Level_1", "Biome_3", "Alpine"),
				new BiomeAsset("Mesa", (BiomeType)6, "Desert_Segment", 5, "Level_0", "Biome_3", "Mesa"),
				new BiomeAsset("Gloom", (BiomeType)8, "Swamp_Segment", 4, "WilIsland", "Biome_4", "Gloom"),
				new BiomeAsset("Caldera", (BiomeType)3, "Caldera_Segment", 4, "WilIsland", "Biome_4", "Caldera", "Volcano"),
				new BiomeAsset("The Kiln", (BiomeType)3, "Volcano_Segment", 4, "WilIsland", "Biome_4", "Caldera", "Volcano"),
				new BiomeAsset("The Citadel", (BiomeType)8, "Temple_Segment", 4, "WilIsland", "Biome_4", "Gloom"),
				new BiomeAsset("Peak", (BiomeType)5, "Peak", 4, "WilIsland", "Biome_4", "Gloom", "Temple_Segment")
			};
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[AllBiomes] Public biome | BiomeType | Root GameObject | Donor scene");
			BiomeAsset[] array = definitions;
			foreach (BiomeAsset biomeAsset in array)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] " + biomeAsset.Name.PadRight(11) + " type=" + ((object)biomeAsset.BiomeType/*cast due to .constrained prefix*/).ToString() + " root=" + biomeAsset.RootName + " donor=" + biomeAsset.DonorName));
			}
			GameObject runtimeRoot = (_runtimeRoot = new GameObject("AllBiomes Runtime Mountain"));
			SceneManager.MoveGameObjectToScene(runtimeRoot, mainScene);
			runtimeRoot.SetActive(false);
			Dictionary<string, GameObject> clonesByName = new Dictionary<string, GameObject>();
			BiomeAsset[] wanted = Array.FindAll(definitions, (BiomeAsset d) => d.Name != "Peak");
			Dictionary<string, DonorSelection> selections = new Dictionary<string, DonorSelection>();
			Dictionary<string, SegmentPose> hostLayout = null;
			bool isNetworkClient = PhotonNetwork.InRoom && !PhotonNetwork.IsMasterClient;
			if (isNetworkClient)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)"[AllBiomes] Client waiting for host donor plan");
				string encodedPlan = null;
				float deadline = Time.realtimeSinceStartup + 120f;
				while (Time.realtimeSinceStartup < deadline)
				{
					if (PhotonNetwork.CurrentRoom != null && ((Dictionary<object, object>)(object)((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties).TryGetValue((object)"ALLBIOMES_PLAN_0205", out object value))
					{
						encodedPlan = value as string;
					}
					if (!string.IsNullOrEmpty(encodedPlan))
					{
						break;
					}
					yield return null;
				}
				if (!TryParseNetworkPlan(encodedPlan, wanted, selections, out _runId))
				{
					((BaseUnityPlugin)this).Logger.LogError((object)"[AllBiomes] Client cannot build: missing/invalid host plan. All players must use AllBiomes 0.20.6");
					Object.Destroy((Object)(object)runtimeRoot);
					ResetGenerationForRetry("client host plan unavailable");
					yield break;
				}
				foreach (int donorIndex in UniqueDonors(selections))
				{
					BiomeAsset[] selectedDefinitions = Array.FindAll(wanted, (BiomeAsset d) => selections[d.Name].BuildIndex == donorIndex);
					((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Client loading host-selected buildIndex=" + donorIndex));
					Dictionary<string, DonorSelection> actual = new Dictionary<string, DonorSelection>();
					yield return ((MonoBehaviour)this).StartCoroutine(LoadDonor(mainScene, runtimeRoot, donorIndex, selectedDefinitions, clonesByName, actual));
					array = selectedDefinitions;
					foreach (BiomeAsset biomeAsset2 in array)
					{
						if (!actual.TryGetValue(biomeAsset2.Name, out var value2) || value2.Renderers != selections[biomeAsset2.Name].Renderers || value2.Colliders != selections[biomeAsset2.Name].Colliders)
						{
							((BaseUnityPlugin)this).Logger.LogWarning((object)("[AllBiomes] ASSET COUNT DIFFERENCE " + biomeAsset2.Name + " host=" + selections[biomeAsset2.Name]?.ToString() + " client=" + ((value2 == null) ? "missing" : value2.ToString()) + ". Continuing with local geometry; transforms remain deterministic."));
						}
					}
				}
				BiomeAsset[] array2 = Array.FindAll(wanted, (BiomeAsset d) => !clonesByName.ContainsKey(d.Name) || (Object)(object)clonesByName[d.Name] == (Object)null);
				if (array2.Length != 0)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("[AllBiomes] Client exact-donor retry for missing roots: " + string.Join(", ", Array.ConvertAll(array2, (BiomeAsset d) => d.Name))));
					foreach (int donorIndex2 in UniqueDonors(selections))
					{
						array2 = Array.FindAll(wanted, (BiomeAsset d) => (!clonesByName.ContainsKey(d.Name) || (Object)(object)clonesByName[d.Name] == (Object)null) && selections[d.Name].BuildIndex == donorIndex2);
						if (array2.Length != 0)
						{
							Dictionary<string, DonorSelection> selections2 = new Dictionary<string, DonorSelection>();
							yield return ((MonoBehaviour)this).StartCoroutine(LoadDonor(mainScene, runtimeRoot, donorIndex2, array2, clonesByName, selections2));
						}
					}
				}
				((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Client waiting for host final segment layout run=" + _runId));
				string encodedLayout = null;
				deadline = Time.realtimeSinceStartup + 120f;
				while (Time.realtimeSinceStartup < deadline)
				{
					if (PhotonNetwork.CurrentRoom != null && ((Dictionary<object, object>)(object)((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties).TryGetValue((object)"ALLBIOMES_LAYOUT_0205", out object value3))
					{
						encodedLayout = value3 as string;
					}
					if (TryParseNetworkLayout(encodedLayout, definitions, _runId, out hostLayout))
					{
						break;
					}
					yield return null;
				}
				if (hostLayout == null)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)("[AllBiomes] Client cannot build: host final segment layout unavailable run=" + _runId));
					Object.Destroy((Object)(object)runtimeRoot);
					ResetGenerationForRetry("host final layout unavailable");
					yield break;
				}
			}
			else
			{
				if (_startNewRun || string.IsNullOrEmpty(_runId) || _runId == "offline")
				{
					_runId = Guid.NewGuid().ToString("N").Substring(0, 12);
				}
				_startNewRun = false;
				if (PhotonNetwork.InRoom && PhotonNetwork.CurrentRoom != null)
				{
					Room currentRoom = PhotonNetwork.CurrentRoom;
					Hashtable val = new Hashtable();
					((Dictionary<object, object>)val).Add((object)"ALLBIOMES_PLAN_0205", (object)string.Empty);
					((Dictionary<object, object>)val).Add((object)"ALLBIOMES_LAYOUT_0205", (object)string.Empty);
					currentRoom.SetCustomProperties(val, (Hashtable)null, (WebFlags)null);
				}
				int[] array3 = new int[10] { 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 };
				for (int num = 0; num < array3.Length; num++)
				{
					int donorIndex3 = array3[num];
					((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Host discovery buildIndex=" + donorIndex3 + " comparing populated variants"));
					yield return ((MonoBehaviour)this).StartCoroutine(LoadDonor(mainScene, runtimeRoot, donorIndex3, wanted, clonesByName, selections));
					if (HasFullyPopulatedSet(clonesByName))
					{
						((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] All biome population thresholds reached; stopping Level_X scan at buildIndex=" + donorIndex3));
						break;
					}
				}
				if (PhotonNetwork.InRoom && PhotonNetwork.CurrentRoom != null)
				{
					string text = EncodeNetworkPlan(wanted, selections);
					Room currentRoom2 = PhotonNetwork.CurrentRoom;
					Hashtable val2 = new Hashtable();
					((Dictionary<object, object>)val2).Add((object)"ALLBIOMES_PLAN_0205", (object)text);
					currentRoom2.SetCustomProperties(val2, (Hashtable)null, (WebFlags)null);
					((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Host published donor plan: " + text));
				}
			}
			array = wanted;
			foreach (BiomeAsset biomeAsset3 in array)
			{
				if (!clonesByName.ContainsKey(biomeAsset3.Name))
				{
					((BaseUnityPlugin)this).Logger.LogError((object)("[AllBiomes] Dynamic discovery exhausted: missing " + biomeAsset3.Name));
					Object.Destroy((Object)(object)runtimeRoot);
					ResetGenerationForRetry("missing biome " + biomeAsset3.Name);
					yield break;
				}
			}
			GameObject root = ResolvePeak(map).Root;
			if ((Object)(object)root == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"[AllBiomes] Main-scene Peak root was not found");
				Object.Destroy((Object)(object)runtimeRoot);
				ResetGenerationForRetry("main-scene Peak missing");
				yield break;
			}
			root.transform.SetParent(runtimeRoot.transform, true);
			((Object)root).name = "Peak [AllBiomes Peak]";
			root.SetActive(false);
			List<GameObject> list = new List<GameObject>();
			for (int num2 = 0; num2 < definitions.Length - 1; num2++)
			{
				list.Add(clonesByName[definitions[num2].Name]);
			}
			list.Add(root);
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Main-scene Peak detached without cloning; renderers=" + root.GetComponentsInChildren<Renderer>(true).Length + " colliders=" + root.GetComponentsInChildren<Collider>(true).Length));
			runtimeRoot.SetActive(true);
			try
			{
				BuildRuntimeMountain(map, vanilla, definitions, list, hostLayout);
				if (!isNetworkClient && PhotonNetwork.InRoom && PhotonNetwork.CurrentRoom != null)
				{
					string text2 = EncodeNetworkLayout(_segments, _runId);
					Room currentRoom3 = PhotonNetwork.CurrentRoom;
					Hashtable val3 = new Hashtable();
					((Dictionary<object, object>)val3).Add((object)"ALLBIOMES_LAYOUT_0205", (object)text2);
					currentRoom3.SetCustomProperties(val3, (Hashtable)null, (WebFlags)null);
					((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Host published final segment layout: " + text2));
				}
				PublishBuildReady();
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("[AllBiomes] Generator failed: " + ex));
				ResetGenerationForRetry("generator exception");
			}
		}

		private void ResetGenerationForRetry(string reason)
		{
			_builtMapId = 0;
			_stableFrames = 0;
			_generationStarted = false;
			((BaseUnityPlugin)this).Logger.LogWarning((object)("[AllBiomes] Generation reset for retry: " + reason));
		}

		private void MaintainRuntimeLifecycle()
		{
			Character localCharacter = Character.localCharacter;
			int num = ((!((Object)(object)localCharacter == (Object)null)) ? ((Object)localCharacter).GetInstanceID() : 0);
			if (num == _localCharacterId)
			{
				return;
			}
			int localCharacterId = _localCharacterId;
			_localCharacterId = num;
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Local character lifecycle changed old=" + localCharacterId + " new=" + num));
			EndFlight();
			if (_flight && (Object)(object)localCharacter != (Object)null)
			{
				BeginFlight(localCharacter);
			}
			RuntimeCampfireAdapter[] array = Object.FindObjectsByType<RuntimeCampfireAdapter>((FindObjectsInactive)1, (FindObjectsSortMode)0);
			foreach (RuntimeCampfireAdapter runtimeCampfireAdapter in array)
			{
				if ((Object)(object)runtimeCampfireAdapter != (Object)null)
				{
					runtimeCampfireAdapter.RefreshAfterCharacterChange();
				}
			}
			RuntimeLuggageAdapter[] array2 = Object.FindObjectsByType<RuntimeLuggageAdapter>((FindObjectsInactive)1, (FindObjectsSortMode)0);
			foreach (RuntimeLuggageAdapter runtimeLuggageAdapter in array2)
			{
				if ((Object)(object)runtimeLuggageAdapter != (Object)null)
				{
					runtimeLuggageAdapter.RefreshAfterCharacterChange();
				}
			}
			if (_segments.Count > 0)
			{
				DisableVanillaFogWalls();
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[AllBiomes] Runtime state rebound after character respawn/reconnect");
		}

		private bool HasFullyPopulatedSet(Dictionary<string, GameObject> clones)
		{
			foreach (KeyValuePair<string, int> item in new Dictionary<string, int>
			{
				{ "Shore", 5000 },
				{ "Tropics", 5000 },
				{ "Roots", 3000 },
				{ "Alpine", 3000 },
				{ "Mesa", 5000 },
				{ "Gloom", 3000 },
				{ "Caldera", 1000 },
				{ "The Kiln", 1000 },
				{ "The Citadel", 100 }
			})
			{
				if (!clones.TryGetValue(item.Key, out var value) || (Object)(object)value == (Object)null)
				{
					return false;
				}
				int num = value.GetComponentsInChildren<Renderer>(true).Length;
				if (num < item.Value)
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Population threshold pending " + item.Key + " renderers=" + num + " required=" + item.Value));
					return false;
				}
			}
			return true;
		}

		private IEnumerator LoadDonor(Scene mainScene, GameObject runtimeRoot, int buildIndex, BiomeAsset[] definitions, Dictionary<string, GameObject> clones, Dictionary<string, DonorSelection> selections)
		{
			//IL_000e: 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)
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Loading donor " + definitions[0].DonorName + " buildIndex=" + buildIndex));
			HashSet<int> scenesBeforeLoad = new HashSet<int>();
			for (int i = 0; i < SceneManager.sceneCount; i++)
			{
				Scene sceneAt = SceneManager.GetSceneAt(i);
				scenesBeforeLoad.Add(SceneHandle.op_Implicit(((Scene)(ref sceneAt)).handle));
			}
			_pendingStaticSnapshot = CaptureStaticReferences();
			_pendingDonorBuildIndex = buildIndex;
			LifecycleBlockedBuildIndex = buildIndex;
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Protected main runtime references=" + _pendingStaticSnapshot.Count));
			AsyncOperation load;
			try
			{
				load = SceneManager.LoadSceneAsync(buildIndex, (LoadSceneMode)1);
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("[AllBiomes] Donor load call failed: " + ex));
				yield break;
			}
			if (load == null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"[AllBiomes] Donor LoadSceneAsync returned null");
				yield break;
			}
			while (!load.isDone)
			{
				yield return null;
			}
			Scene val = default(Scene);
			for (int j = 0; j < SceneManager.sceneCount; j++)
			{
				Scene sceneAt2 = SceneManager.GetSceneAt(j);
				if (((Scene)(ref sceneAt2)).buildIndex == buildIndex && !scenesBeforeLoad.Contains(SceneHandle.op_Implicit(((Scene)(ref sceneAt2)).handle)))
				{
					val = sceneAt2;
					break;
				}
			}
			if (!((Scene)(ref val)).IsValid() || !((Scene)(ref val)).isLoaded)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("[AllBiomes] Newly loaded additive donor unavailable buildIndex=" + buildIndex + "; main scene will not be touched"));
				yield break;
			}
			if (((Scene)(ref val)).handle == ((Scene)(ref mainScene)).handle)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"[AllBiomes] Refusing to use/unload main scene as donor");
				yield break;
			}
			RestoreStaticReferences(_pendingStaticSnapshot, "after donor load");
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Donor loaded name=" + ((Scene)(ref val)).name + " path=" + ((Scene)(ref val)).path + " roots=" + ((Scene)(ref val)).rootCount));
			BiomeAsset[] array = definitions;
			foreach (BiomeAsset biomeAsset in array)
			{
				GameObject val2 = FindSceneObject(val, biomeAsset);
				if ((Object)(object)val2 == (Object)null)
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] " + biomeAsset.Name + ": not present in donor=" + ((Scene)(ref val)).name));
					continue;
				}
				Bounds val3;
				try
				{
					val3 = BoundsOf(val2);
				}
				catch (Exception ex2)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)("[AllBiomes] " + biomeAsset.Name + " bounds failed: " + ex2));
					continue;
				}
				((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Found " + biomeAsset.Name + " path=" + PathOf(val2.transform) + " renderers=" + val2.GetComponentsInChildren<Renderer>(true).Length + " colliders=" + val2.GetComponentsInChildren<Collider>(true).Length + " bounds=" + ((object)((Bounds)(ref val3)).size/*cast due to .constrained prefix*/).ToString()));
				if (biomeAsset.Name == "Caldera")
				{
					LogCalderaBranches(val2);
				}
				if (biomeAsset.Name == "The Kiln")
				{
					LogKilnGeometryAndPeakCandidates(val, val2);
				}
				GameObject val4 = ResolveBiomeContainer(val2, biomeAsset.Name);
				((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Container " + biomeAsset.Name + " path=" + PathOf(val4.transform)));
				if (biomeAsset.Name == "The Kiln")
				{
					ManualLogSource logger = ((BaseUnityPlugin)this).Logger;
					string[] obj = new string[14]
					{
						"[AllBiomes] KILN ORIGINAL TRANSFORM container position=",
						((object)val4.transform.position/*cast due to .constrained prefix*/).ToString(),
						" rotation=",
						null,
						null,
						null,
						null,
						null,
						null,
						null,
						null,
						null,
						null,
						null
					};
					Quaternion rotation = val4.transform.rotation;
					obj[3] = ((object)((Quaternion)(ref rotation)).eulerAngles/*cast due to .constrained prefix*/).ToString();
					obj[4] = " scale=";
					obj[5] = ((object)val4.transform.lossyScale/*cast due to .constrained prefix*/).ToString();
					obj[6] = " interior position=";
					obj[7] = ((object)val2.transform.position/*cast due to .constrained prefix*/).ToString();
					obj[8] = " rotation=";
					rotation = val2.transform.rotation;
					obj[9] = ((object)((Quaternion)(ref rotation)).eulerAngles/*cast due to .constrained prefix*/).ToString();
					obj[10] = " scale=";
					obj[11] = ((object)val2.transform.lossyScale/*cast due to .constrained prefix*/).ToString();
					obj[12] = " upDot=";
					obj[13] = Vector3.Dot(val2.transform.up, Vector3.up).ToString();
					logger.LogWarning((object)string.Concat(obj));
				}
				GameObject val5 = Object.Instantiate<GameObject>(val4, runtimeRoot.transform, true);
				((Object)val5).name = biomeAsset.RootName + " [AllBiomes " + biomeAsset.Name + "]";
				val5.SetActive(false);
				if (biomeAsset.Name == "The Citadel")
				{
					AttachCitadelExterior(val2, val5);
				}
				PruneAlternativeGeometry(val5, biomeAsset.Name);
				if (biomeAsset.Name == "The Kiln")
				{
					PrepareVolcanoExterior(val5);
					CreateVolcanoVisualShell(val5);
				}
				AttachSerializedAnchors(val, val2, val5, biomeAsset.Name);
				SanitizeDonorClone(val5, biomeAsset.Name);
				int num = val5.GetComponentsInChildren<Renderer>(true).Length;
				int num2 = val5.GetComponentsInChildren<Collider>(true).Length;
				long num3 = (long)num * 4L + num2;
				if (clones.TryGetValue(biomeAsset.Name, out var value) && (Object)(object)value != (Object)null)
				{
					int num4 = value.GetComponentsInChildren<Renderer>(true).Length;
					int num5 = value.GetComponentsInChildren<Collider>(true).Length;
					long num6 = (long)num4 * 4L + num5;
					if (num6 >= num3)
					{
						((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Candidate rejected " + biomeAsset.Name + " score=" + num3 + " best=" + num6 + " donor=" + ((Scene)(ref val)).name));
						Object.DestroyImmediate((Object)(object)val5);
						continue;
					}
					((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Better populated variant " + biomeAsset.Name + " old=" + num6 + " new=" + num3 + " donor=" + ((Scene)(ref val)).name));
					Object.DestroyImmediate((Object)(object)value);
				}
				clones[biomeAsset.Name] = val5;
				selections[biomeAsset.Name] = new DonorSelection(buildIndex, num, num2);
				((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Best clone updated " + biomeAsset.Name + " renderers=" + num + " colliders=" + num2 + " score=" + num3));
			}
			CleanDonorPhotonViews(val);
			AsyncOperation unload = SceneManager.UnloadSceneAsync(val);
			if (unload != null)
			{
				while (!unload.isDone)
				{
					yield return null;
				}
			}
			RestoreStaticReferences(_pendingStaticSnapshot, "after donor unload");
			_pendingStaticSnapshot = null;
			_pendingDonorBuildIndex = -1;
			LifecycleBlockedBuildIndex = -1;
			yield return null;
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Donor unloaded " + definitions[0].DonorName));
			array = definitions;
			foreach (BiomeAsset biomeAsset2 in array)
			{
				if (!clones.TryGetValue(biomeAsset2.Name, out var value2) || (Object)(object)value2 == (Object)null)
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] No clone from this donor: " + biomeAsset2.Name));
					continue;
				}
				int num7 = value2.GetComponentsInChildren<Renderer>(true).Length;
				int num8 = value2.GetComponentsInChildren<Collider>(true).Length;
				((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Clone survived " + biomeAsset2.Name + " renderers=" + num7 + " colliders=" + num8));
				if (num7 == 0 || num8 == 0)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)("[AllBiomes] Clone has incomplete geometry: " + biomeAsset2.Name));
				}
			}
		}

		private void CleanDonorPhotonViews(Scene donor)
		{
			if (!((Scene)(ref donor)).IsValid() || !((Scene)(ref donor)).isLoaded)
			{
				return;
			}
			int num = 0;
			int num2 = 0;
			GameObject[] rootGameObjects = ((Scene)(ref donor)).GetRootGameObjects();
			for (int i = 0; i < rootGameObjects.Length; i++)
			{
				PhotonView[] componentsInChildren = rootGameObjects[i].GetComponentsInChildren<PhotonView>(true);
				foreach (PhotonView val in componentsInChildren)
				{
					if ((Object)(object)val == (Object)null)
					{
						continue;
					}
					num++;
					try
					{
						if (val.ViewID != 0 && (Object)(object)PhotonNetwork.GetPhotonView(val.ViewID) == (Object)(object)val)
						{
							PhotonNetwork.LocalCleanPhotonView(val);
							num2++;
						}
					}
					catch (Exception ex)
					{
						((BaseUnityPlugin)this).Logger.LogError((object)("[AllBiomes] Donor PhotonView cleanup failed scene=" + ((Scene)(ref donor)).name + " viewID=" + val.ViewID + " path=" + PathOf(((Component)val).transform) + ": " + ex));
					}
				}
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Donor PhotonViews cleaned scene=" + ((Scene)(ref donor)).name + " found=" + num + " unregistered=" + num2));
		}

		private string EncodeNetworkPlan(BiomeAsset[] definitions, Dictionary<string, DonorSelection> selections)
		{
			List<string> list = new List<string>
			{
				"0.20.6",
				Application.version,
				_runId
			};
			foreach (BiomeAsset biomeAsset in definitions)
			{
				if (selections.TryGetValue(biomeAsset.Name, out var value))
				{
					list.Add(biomeAsset.Name + "=" + value.BuildIndex + "," + value.Renderers + "," + value.Colliders);
				}
			}
			return string.Join(";", list);
		}

		private bool TryParseNetworkPlan(string plan, BiomeAsset[] definitions, Dictionary<string, DonorSelection> result, out string runId)
		{
			runId = null;
			if (string.IsNullOrEmpty(plan))
			{
				return false;
			}
			string[] array = plan.Split(';');
			if (array.Length < 3 || array[0] != "0.20.6" || array[1] != Application.version || string.IsNullOrEmpty(array[2]))
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("[AllBiomes] Plan version mismatch host=" + plan + " localMod=0.20.6 localGame=" + Application.version));
				return false;
			}
			runId = array[2];
			for (int i = 3; i < array.Length; i++)
			{
				int num = array[i].IndexOf('=');
				if (num > 0)
				{
					string[] array2 = array[i].Substring(num + 1).Split(',');
					if (array2.Length == 3 && int.TryParse(array2[0], out var result2) && int.TryParse(array2[1], out var result3) && int.TryParse(array2[2], out var result4))
					{
						result[array[i].Substring(0, num)] = new DonorSelection(result2, result3, result4);
					}
				}
			}
			foreach (BiomeAsset biomeAsset in definitions)
			{
				if (!result.ContainsKey(biomeAsset.Name))
				{
					return false;
				}
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Accepted host donor plan: " + plan));
			return true;
		}

		private static string EncodeNetworkLayout(List<RuntimeSegment> segments, string runId)
		{
			//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_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_0075: 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_00a1: 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_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			List<string> list = new List<string>
			{
				"0.20.6",
				Application.version,
				runId
			};
			foreach (RuntimeSegment segment in segments)
			{
				Vector3 position = segment.Root.transform.position;
				Quaternion rotation = segment.Root.transform.rotation;
				list.Add(segment.Name + "=" + F(position.x) + "," + F(position.y) + "," + F(position.z) + "," + F(rotation.x) + "," + F(rotation.y) + "," + F(rotation.z) + "," + F(rotation.w));
			}
			return string.Join(";", list);
		}

		private static bool TryParseNetworkLayout(string encoded, BiomeAsset[] definitions, string runId, out Dictionary<string, SegmentPose> result)
		{
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			result = null;
			if (string.IsNullOrEmpty(encoded))
			{
				return false;
			}
			string[] array = encoded.Split(';');
			if (array.Length < 3 || array[0] != "0.20.6" || array[1] != Application.version || array[2] != runId)
			{
				return false;
			}
			Dictionary<string, SegmentPose> dictionary = new Dictionary<string, SegmentPose>(StringComparer.Ordinal);
			for (int i = 3; i < array.Length; i++)
			{
				int num = array[i].IndexOf('=');
				if (num <= 0)
				{
					continue;
				}
				string[] array2 = array[i].Substring(num + 1).Split(',');
				if (array2.Length == 7)
				{
					float[] array3 = new float[7];
					bool flag = true;
					for (int j = 0; j < array3.Length; j++)
					{
						flag &= float.TryParse(array2[j], NumberStyles.Float, CultureInfo.InvariantCulture, out array3[j]);
					}
					if (flag)
					{
						dictionary[array[i].Substring(0, num)] = new SegmentPose(new Vector3(array3[0], array3[1], array3[2]), new Quaternion(array3[3], array3[4], array3[5], array3[6]));
					}
				}
			}
			foreach (BiomeAsset biomeAsset in definitions)
			{
				if (!dictionary.ContainsKey(biomeAsset.Name))
				{
					return false;
				}
			}
			result = dictionary;
			return true;
		}

		private static string F(float value)
		{
			return value.ToString("R", CultureInfo.InvariantCulture);
		}

		private void PublishBuildReady()
		{
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Expected O, but got Unknown
			//IL_00c2: Expected O, but got Unknown
			string text = EncodeNetworkLayout(_segments, _runId);
			uint num = 2166136261u;
			for (int i = 0; i < text.Length; i++)
			{
				num = (num ^ text[i]) * 16777619;
			}
			string text2 = num.ToString("X8", CultureInfo.InvariantCulture) + ":" + _segments.Count;
			if (PhotonNetwork.InRoom && PhotonNetwork.CurrentRoom != null && PhotonNetwork.LocalPlayer != null)
			{
				string key = "ABREADY_" + _runId + "_" + PhotonNetwork.LocalPlayer.ActorNumber;
				Room currentRoom = PhotonNetwork.CurrentRoom;
				Hashtable val = new Hashtable();
				((Dictionary<object, object>)val).Add((object)key, (object)text2);
				currentRoom.SetCustomProperties(val, (Hashtable)null, (WebFlags)null);
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] BUILD_READY run=" + _runId + " fingerprint=" + text2 + " actor=" + ((PhotonNetwork.LocalPlayer != null) ? PhotonNetwork.LocalPlayer.ActorNumber : 0)));
		}

		private static IEnumerable<int> UniqueDonors(Dictionary<string, DonorSelection> selections)
		{
			HashSet<int> seen = new HashSet<int>();
			foreach (DonorSelection value in selections.Values)
			{
				if (seen.Add(value.BuildIndex))
				{
					yield return value.BuildIndex;
				}
			}
		}

		private void AttachSerializedAnchors(Scene donor, GameObject source, GameObject clone, string biomeName)
		{
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			MapHandler val = null;
			GameObject[] rootGameObjects = ((Scene)(ref donor)).GetRootGameObjects();
			for (int i = 0; i < rootGameObjects.Length; i++)
			{
				val = rootGameObjects[i].GetComponentInChildren<MapHandler>(true);
				if ((Object)(object)val != (Object)null)
				{
					break;
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("[AllBiomes] Serialized anchors " + biomeName + ": donor MapHandler missing"));
			}
			else
			{
				if (!(typeof(MapHandler).GetField("segments", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(val) is Array array))
				{
					return;
				}
				for (int j = 0; j < array.Length; j++)
				{
					object value = array.GetValue(j);
					if (value == null)
					{
						continue;
					}
					Type type = value.GetType();
					object? obj = type.GetProperty("segmentParent", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(value, null);
					GameObject val2 = (GameObject)(((obj is GameObject) ? obj : null) ?? ((object)/*isinst with value type is only supported in some contexts*/));
					if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2 != (Object)(object)source))
					{
						object? obj2 = type.GetField("reconnectSpawnPos", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(value);
						Transform val3 = (Transform)((obj2 is Transform) ? obj2 : null);
						object? obj3 = type.GetField("wallNext", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(value);
						GameObject val4 = (GameObject)((obj3 is GameObject) ? obj3 : null);
						if ((Object)(object)val3 != (Object)null)
						{
							CreateAnchorMarker(clone, "AllBiomes_Entrance", val3.position);
						}
						if ((Object)(object)val4 != (Object)null)
						{
							CreateAnchorMarker(clone, "AllBiomes_Exit", val4.transform.position);
						}
						((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Serialized anchors " + biomeName + " segment=" + j + " entrance=" + (((Object)(object)val3 == (Object)null) ? "<null>" : ((object)val3.position/*cast due to .constrained prefix*/).ToString()) + " exit=" + (((Object)(object)val4 == (Object)null) ? "<null>" : ((object)val4.transform.position/*cast due to .constrained prefix*/).ToString())));
						return;
					}
				}
				((BaseUnityPlugin)this).Logger.LogWarning((object)("[AllBiomes] Serialized anchors " + biomeName + ": matching MapSegment missing"));
			}
		}

		private static void CreateAnchorMarker(GameObject clone, string markerName, Vector3 worldPosition)
		{
			//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_001d: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(markerName);
			val.transform.SetParent(clone.transform, false);
			val.transform.position = worldPosition;
		}

		private static GameObject ResolveBiomeContainer(GameObject source, string biomeName)
		{
			if ((Object)(object)source == (Object)null || (Object)(object)source.transform.parent == (Object)null)
			{
				return source;
			}
			switch (biomeName)
			{
			case "The Kiln":
				return ((Component)source.transform.parent).gameObject;
			case "Caldera":
			case "The Citadel":
				return source;
			default:
				return ((Component)source.transform.parent).gameObject;
			}
		}

		private void AttachCitadelExterior(GameObject templeInterior, GameObject citadelClone)
		{
			if ((Object)(object)templeInterior == (Object)null || (Object)(object)templeInterior.transform.parent == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"[AllBiomes] Citadel exterior attach failed: Temple_Segment parent missing");
				return;
			}
			Transform val = templeInterior.transform.parent.Find("Gloom Temple");
			if ((Object)(object)val == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("[AllBiomes] Citadel exterior attach failed: sibling Gloom Temple missing at " + PathOf(templeInterior.transform.parent)));
				return;
			}
			GameObject val2 = Object.Instantiate<GameObject>(((Component)val).gameObject, citadelClone.transform, true);
			((Object)val2).name = "Gloom Temple [AllBiomes Citadel Exterior]";
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Citadel exterior attached path=" + PathOf(val) + " renderers=" + val2.GetComponentsInChildren<Renderer>(true).Length + " colliders=" + val2.GetComponentsInChildren<Collider>(true).Length));
		}

		private void AttachVolcanoExterior(GameObject volcanoInterior, GameObject volcanoClone)
		{
			if ((Object)(object)volcanoInterior == (Object)null || (Object)(object)volcanoInterior.transform.parent == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"[AllBiomes] Volcano exterior attach failed: Volcano_Segment parent missing");
				return;
			}
			Transform parent = volcanoInterior.transform.parent;
			GameObject val = Object.Instantiate<GameObject>(((Component)parent).gameObject, volcanoClone.transform, true);
			((Object)val).name = "Volcano Exterior Shell [AllBiomes]";
			int num = 0;
			Transform[] componentsInChildren = val.GetComponentsInChildren<Transform>(true);
			foreach (Transform val2 in componentsInChildren)
			{
				if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2 == (Object)(object)val.transform) && (((Object)val2).name.IndexOf("Caldera_Segment", StringComparison.OrdinalIgnoreCase) >= 0 || ((Object)val2).name.IndexOf("Volcano_Segment", StringComparison.OrdinalIgnoreCase) >= 0))
				{
					Object.DestroyImmediate((Object)(object)((Component)val2).gameObject);
					num++;
				}
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Volcano exterior shell attached parent=" + PathOf(parent) + " removedSegments=" + num + " renderers=" + val.GetComponentsInChildren<Renderer>(true).Length + " colliders=" + val.GetComponentsInChildren<Collider>(true).Length));
		}

		private void LogCalderaBranches(GameObject caldera)
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//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)
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Caldera direct branches=" + caldera.transform.childCount));
			for (int i = 0; i < caldera.transform.childCount; i++)
			{
				Transform child = caldera.transform.GetChild(i);
				if ((Object)(object)child == (Object)null)
				{
					continue;
				}
				try
				{
					int num = ((Component)child).GetComponentsInChildren<Renderer>(true).Length;
					int num2 = ((Component)child).GetComponentsInChildren<Collider>(true).Length;
					if (num != 0 || num2 != 0)
					{
						Bounds val = BoundsOf(((Component)child).gameObject);
						((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Caldera branch name=" + ((Object)child).name + " active=" + ((Component)child).gameObject.activeSelf + " renderers=" + num + " colliders=" + num2 + " center=" + ((object)((Bounds)(ref val)).center/*cast due to .constrained prefix*/).ToString() + " size=" + ((object)((Bounds)(ref val)).size/*cast due to .constrained prefix*/).ToString()));
					}
				}
				catch (Exception ex)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("[AllBiomes] Caldera branch has no physical bounds " + ((Object)child).name + ": " + ex.Message));
				}
			}
		}

		private void LogKilnGeometryAndPeakCandidates(Scene donor, GameObject kiln)
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_042c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0431: Unknown result type (might be due to invalid IL or missing references)
			//IL_044f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0454: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fc: Unknown result type (might be due to invalid IL or missing references)
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Kiln direct branches=" + kiln.transform.childCount));
			for (int i = 0; i < kiln.transform.childCount; i++)
			{
				Transform child = kiln.transform.GetChild(i);
				if (!((Object)(object)child == (Object)null))
				{
					int num = ((Component)child).GetComponentsInChildren<Renderer>(true).Length;
					int num2 = ((Component)child).GetComponentsInChildren<Collider>(true).Length;
					try
					{
						Bounds val = BoundsOf(((Component)child).gameObject);
						((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Kiln branch name=" + ((Object)child).name + " active=" + ((Component)child).gameObject.activeSelf + " renderers=" + num + " colliders=" + num2 + " center=" + ((object)((Bounds)(ref val)).center/*cast due to .constrained prefix*/).ToString() + " size=" + ((object)((Bounds)(ref val)).size/*cast due to .constrained prefix*/).ToString()));
					}
					catch (Exception ex)
					{
						((BaseUnityPlugin)this).Logger.LogWarning((object)("[AllBiomes] Kiln branch bounds unavailable name=" + ((Object)child).name + " renderers=" + num + " colliders=" + num2 + " reason=" + ex.Message));
					}
				}
			}
			List<Renderer> list = new List<Renderer>(kiln.GetComponentsInChildren<Renderer>(true));
			list.RemoveAll((Renderer renderer) => (Object)(object)renderer == (Object)null || renderer is ParticleSystemRenderer);
			list.Sort(delegate(Renderer a, Renderer b)
			{
				//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_0009: Unknown result type (might be due to invalid IL or missing references)
				//IL_000e: 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_0022: Unknown result type (might be due to invalid IL or missing references)
				//IL_0027: Unknown result type (might be due to invalid IL or missing references)
				Bounds bounds2 = b.bounds;
				Vector3 size = ((Bounds)(ref bounds2)).size;
				float sqrMagnitude = ((Vector3)(ref size)).sqrMagnitude;
				bounds2 = a.bounds;
				size = ((Bounds)(ref bounds2)).size;
				return sqrMagnitude.CompareTo(((Vector3)(ref size)).sqrMagnitude);
			});
			for (int num3 = 0; num3 < Mathf.Min(24, list.Count); num3++)
			{
				Renderer val2 = list[num3];
				string text = ((val2.sharedMaterials == null) ? "<none>" : string.Join(",", Array.ConvertAll(val2.sharedMaterials, (Material material) => (!((Object)(object)material == (Object)null)) ? ((Object)material).name : "<null>")));
				ManualLogSource logger = ((BaseUnityPlugin)this).Logger;
				string[] obj = new string[14]
				{
					"[AllBiomes] Kiln large renderer ",
					num3.ToString(),
					" path=",
					PathOf(((Component)val2).transform),
					" active=",
					((Component)val2).gameObject.activeInHierarchy.ToString(),
					" enabled=",
					val2.enabled.ToString(),
					" center=",
					null,
					null,
					null,
					null,
					null
				};
				Bounds bounds = val2.bounds;
				obj[9] = ((object)((Bounds)(ref bounds)).center/*cast due to .constrained prefix*/).ToString();
				obj[10] = " size=";
				bounds = val2.bounds;
				obj[11] = ((object)((Bounds)(ref bounds)).size/*cast due to .constrained prefix*/).ToString();
				obj[12] = " materials=";
				obj[13] = text;
				logger.LogInfo((object)string.Concat(obj));
			}
			GameObject[] rootGameObjects = ((Scene)(ref donor)).GetRootGameObjects();
			for (int num4 = 0; num4 < rootGameObjects.Length; num4++)
			{
				Transform[] componentsInChildren = rootGameObjects[num4].GetComponentsInChildren<Transform>(true);
				foreach (Transform val3 in componentsInChildren)
				{
					if ((Object)(object)val3 == (Object)null || !string.Equals(((Object)val3).name, "Peak", StringComparison.OrdinalIgnoreCase))
					{
						continue;
					}
					int num6 = ((Component)val3).GetComponentsInChildren<Renderer>(true).Length;
					if (num6 != 0)
					{
						try
						{
							Bounds val4 = BoundsOf(((Component)val3).gameObject);
							((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Donor Peak candidate path=" + PathOf(val3) + " active=" + ((Component)val3).gameObject.activeSelf + " renderers=" + num6 + " colliders=" + ((Component)val3).GetComponentsInChildren<Collider>(true).Length + " center=" + ((object)((Bounds)(ref val4)).center/*cast due to .constrained prefix*/).ToString() + " size=" + ((object)((Bounds)(ref val4)).size/*cast due to .constrained prefix*/).ToString()));
						}
						catch (Exception ex2)
						{
							((BaseUnityPlugin)this).Logger.LogWarning((object)("[AllBiomes] Donor Peak candidate bounds unavailable path=" + PathOf(val3) + " reason=" + ex2.Message));
						}
					}
				}
			}
		}

		private void PrepareVolcanoExterior(GameObject volcanoClone)
		{
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			Transform val = FindDescendant(volcanoClone.transform, "Volcano_Segment");
			if ((Object)(object)val == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"[AllBiomes] Volcano exterior activation failed: Volcano_Segment missing");
				return;
			}
			int num = 0;
			int num2 = 0;
			Renderer[] componentsInChildren = volcanoClone.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val2 in componentsInChildren)
			{
				if ((Object)(object)val2 == (Object)null || val2 is ParticleSystemRenderer || ((Component)val2).transform.IsChildOf(val))
				{
					continue;
				}
				Transform val3 = ((Component)val2).transform;
				while ((Object)(object)val3 != (Object)null && (Object)(object)val3 != (Object)(object)volcanoClone.transform)
				{
					if (!((Component)val3).gameObject.activeSelf)
					{
						((Component)val3).gameObject.SetActive(true);
					}
					val3 = val3.parent;
				}
				val2.enabled = true;
				num++;
				string text = ((val2.sharedMaterials == null) ? "<none>" : string.Join(",", Array.ConvertAll(val2.sharedMaterials, (Material material) => (!((Object)(object)material == (Object)null)) ? ((Object)material).name : "<null>")));
				ManualLogSource logger = ((BaseUnityPlugin)this).Logger;
				string[] obj = new string[6]
				{
					"[AllBiomes] Volcano exterior renderer path=",
					PathOf(((Component)val2).transform),
					" bounds=",
					null,
					null,
					null
				};
				Bounds bounds = val2.bounds;
				obj[3] = ((object)((Bounds)(ref bounds)).size/*cast due to .constrained prefix*/).ToString();
				obj[4] = " materials=";
				obj[5] = text;
				logger.LogInfo((object)string.Concat(obj));
			}
			Collider[] componentsInChildren2 = volcanoClone.GetComponentsInChildren<Collider>(true);
			foreach (Collider val4 in componentsInChildren2)
			{
				if ((Object)(object)val4 == (Object)null || ((Component)val4).transform.IsChildOf(val))
				{
					continue;
				}
				Transform val5 = ((Component)val4).transform;
				while ((Object)(object)val5 != (Object)null && (Object)(object)val5 != (Object)(object)volcanoClone.transform)
				{
					if (!((Component)val5).gameObject.activeSelf)
					{
						((Component)val5).gameObject.SetActive(true);
					}
					val5 = val5.parent;
				}
				val4.enabled = true;
				num2++;
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Volcano exterior forced active renderers=" + num + " colliders=" + num2));
		}

		private unsafe void CreateVolcanoVisualShell(GameObject volcanoClone)
		{
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Expected O, but got Unknown
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: 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_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: 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)
			//IL_020f: 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_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			//IL_022f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0242: Unknown result type (might be due to invalid IL or missing references)
			//IL_0247: Unknown result type (might be due to invalid IL or missing references)
			//IL_024b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0250: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_0257: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0261: Unknown result type (might be due to invalid IL or missing references)
			//IL_0266: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: 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_028b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: Unknown result type (might be due to invalid IL or missing references)
			//IL_0341: Unknown result type (might be due to invalid IL or missing references)
			//IL_0343: Unknown result type (might be due to invalid IL or missing references)
			//IL_042c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0435: Unknown result type (might be due to invalid IL or missing references)
			//IL_043c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0441: Unknown result type (might be due to invalid IL or missing references)
			//IL_044e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0453: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f9: Unknown result type (might be due to invalid IL or missing references)
			Transform val = FindDescendant(volcanoClone.transform, "Volcano_Segment");
			Transform val2 = (((Object)(object)val == (Object)null) ? null : val.Find("Middle"));
			if ((Object)(object)val2 == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"[AllBiomes] Volcano visual shell failed: Volcano_Segment/Middle missing");
				return;
			}
			MeshRenderer val3 = null;
			float num = float.PositiveInfinity;
			MeshRenderer[] componentsInChildren = ((Component)val2).GetComponentsInChildren<MeshRenderer>(true);
			Bounds val5;
			foreach (MeshRenderer val4 in componentsInChildren)
			{
				if ((Object)(object)val4 == (Object)null || (Object)(object)((Component)val4).GetComponent<MeshFilter>() == (Object)null || (((Object)(object)((Renderer)val4).sharedMaterial == (Object)null) ? string.Empty : ((Object)((Renderer)val4).sharedMaterial).name).IndexOf("Rock_Volcano", StringComparison.OrdinalIgnoreCase) < 0)
				{
					continue;
				}
				val5 = ((Renderer)val4).bounds;
				Vector3 size = ((Bounds)(ref val5)).size;
				float num2 = Mathf.Max(size.x, Mathf.Max(size.y, size.z));
				if (!(num2 < 8f) && !(num2 > 45f))
				{
					float num3 = Mathf.Abs(num2 - 20f);
					if (num3 < num)
					{
						num = num3;
						val3 = val4;
					}
				}
			}
			if ((Object)(object)val3 == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"[AllBiomes] Volcano visual shell failed: suitable vanilla volcanic rock mesh missing");
				return;
			}
			GameObject val6 = new GameObject("AllBiomes Volcano Exterior Cone");
			val6.transform.SetParent(val, false);
			Bounds val7 = BoundsOf(((Component)val2).gameObject);
			Vector3 val8 = val.InverseTransformPoint(((Bounds)(ref val7)).center);
			Transform val9 = val.Find("Bridge");
			Bounds val10 = (((Object)(object)val9 == (Object)null) ? val7 : BoundsOf(((Component)val9).gameObject));
			float y = val.InverseTransformPoint(new Vector3(((Bounds)(ref val7)).center.x, Mathf.Min(((Bounds)(ref val7)).min.y - 8f, ((Bounds)(ref val10)).min.y - 6f), ((Bounds)(ref val7)).center.z)).y;
			float y2 = val.InverseTransformPoint(new Vector3(((Bounds)(ref val7)).center.x, ((Bounds)(ref val7)).max.y + 8f, ((Bounds)(ref val7)).center.z)).y;
			Vector3 val11 = Vector3.back;
			if ((Object)(object)val9 != (Object)null)
			{
				val5 = BoundsOf(((Component)val9).gameObject);
				Vector3 center = ((Bounds)(ref val5)).center;
				val11 = val.InverseTransformDirection(center - ((Bounds)(ref val7)).center);
				val11.y = 0f;
				if (((Vector3)(ref val11)).sqrMagnitude > 0.001f)
				{
					((Vector3)(ref val11)).Normalize();
				}
				else
				{
					val11 = Vector3.back;
				}
			}
			int num4 = 0;
			Vector3 val12 = default(Vector3);
			for (int j = 0; j < 10; j++)
			{
				float num5 = (float)j / 9f;
				float num6 = Mathf.Lerp(y, y2, num5);
				float num7 = Mathf.Lerp(168f, 82f, Mathf.Pow(num5, 0.82f));
				int num8 = Mathf.RoundToInt(Mathf.Lerp(14f, 8f, num5));
				for (int k = 0; k < 2; k++)
				{
					for (int l = 0; l < num8; l++)
					{
						float num9 = (float)l * MathF.PI * 2f / (float)num8 + (float)j * 0.19f + (float)k * MathF.PI / (float)num8;
						((Vector3)(ref val12))..ctor(Mathf.Sin(num9), 0f, Mathf.Cos(num9));
						float num10 = Vector3.Angle(val12, val11);
						if (num5 < 0.32f && num10 < Mathf.Lerp(22f, 12f, num5 / 0.32f))
						{
							continue;
						}
						GameObject val13 = Object.Instantiate<GameObject>(((Component)val3).gameObject, val6.transform, false);
						((Object)val13).name = "ExteriorRock_" + k + "_" + j + "_" + l;
						float num11 = Mathf.Sin((float)(j + 1) * 17.17f + (float)l * 9.31f + (float)k * 4.73f);
						float num12 = Mathf.Min(y2, num6 + (float)k * (y2 - y) / 9f * 0.38f);
						float num13 = num7 - (float)k * 14f;
						val13.transform.localPosition = new Vector3(val8.x, num12, val8.z) + val12 * (num13 + num11 * 5f);
						val13.transform.localRotation = Quaternion.Euler(num11 * 16f, num9 * 57.29578f + 90f, Mathf.Lerp(-28f, -8f, num5) * Mathf.Sign((num11 == 0f) ? 1f : num11));
						float num14 = Mathf.Lerp((k == 0) ? 4.2f : 3.8f, (k == 0) ? 2.8f : 2.55f, num5) * (1f + num11 * 0.08f);
						val13.transform.localScale = ((Component)val3).transform.localScale * num14;
						Collider[] componentsInChildren2 = val13.GetComponentsInChildren<Collider>(true);
						foreach (Collider val14 in componentsInChildren2)
						{
							if ((Object)(object)val14 != (Object)null)
							{
								Object.DestroyImmediate((Object)(object)val14);
							}
						}
						MonoBehaviour[] componentsInChildren3 = val13.GetComponentsInChildren<MonoBehaviour>(true);
						foreach (MonoBehaviour val15 in componentsInChildren3)
						{
							if ((Object)(object)val15 != (Object)null)
							{
								Object.DestroyImmediate((Object)(object)val15);
							}
						}
						val13.SetActive(true);
						num4++;
					}
				}
			}
			try
			{
				StaticBatchingUtility.Combine(val6);
				((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Volcano exterior static batching complete rocks=" + num4));
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("[AllBiomes] Volcano static batching skipped: " + ex.Message));
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Volcano exterior cone built from vanilla rocks rings=" + 10 + " rocks=" + num4 + " entranceDirection=" + ((object)(*(Vector3*)(&val11))/*cast due to .constrained prefix*/).ToString() + " renderers=" + val6.GetComponentsInChildren<Renderer>(true).Length + " colliders=" + val6.GetComponentsInChildren<Collider>(true).Length));
		}

		private void PruneAlternativeGeometry(GameObject clone, string biomeName)
		{
			string[] array = biomeName switch
			{
				"The Citadel" => new string[1] { "Peak" }, 
				"The Kiln" => new string[2] { "Caldera_Segment", "Peak" }, 
				"Gloom" => new string[4] { "Temple_Segment", "Gloom Temple", "Peak", "BG Rocks" }, 
				_ => Array.Empty<string>(), 
			};
			int num = 0;
			Transform[] componentsInChildren = clone.GetComponentsInChildren<Transform>(true);
			foreach (Transform val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)clone.transform) && Array.IndexOf(array, ((Object)val).name) >= 0)
				{
					Object.DestroyImmediate((Object)(object)((Component)val).gameObject);
					num++;
				}
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Pruned " + biomeName + " alternative roots=" + num));
		}

		private void InstallDonorLifecycleProtection()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			HarmonyMethod val = new HarmonyMethod(typeof(DonorLifecycleGuard).GetMethod("Prefix", BindingFlags.Static | BindingFlags.Public));
			int num = 0;
			HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal) { "Awake", "OnEnable", "Start", "OnDisable", "OnDestroy" };
			foreach (Assembly item in new HashSet<Assembly>
			{
				typeof(MapHandler).Assembly,
				typeof(PhotonView).Assembly,
				typeof(Singleton<>).Assembly
			})
			{
				Type[] types;
				try
				{
					types = item.GetTypes();
				}
				catch (ReflectionTypeLoadException ex)
				{
					types = ex.Types;
				}
				Type[] array = types;
				foreach (Type type in array)
				{
					if (type == null || !typeof(MonoBehaviour).IsAssignableFrom(type))
					{
						continue;
					}
					MethodInfo[] methods;
					try
					{
						methods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					}
					catch
					{
						continue;
					}
					MethodInfo[] array2 = methods;
					foreach (MethodInfo methodInfo in array2)
					{
						if (hashSet.Contains(methodInfo.Name) && !methodInfo.IsAbstract && !methodInfo.ContainsGenericParameters && !(methodInfo.ReturnType != typeof(void)) && methodInfo.GetParameters().Length == 0)
						{
							try
							{
								_harmony.Patch((MethodBase)methodInfo, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
								num++;
							}
							catch (Exception ex2)
							{
								((BaseUnityPlugin)this).Logger.LogWarning((object)("[AllBiomes] Lifecycle patch skipped " + type.FullName + "." + methodInfo.Name + ": " + ex2.Message));
							}
						}
					}
				}
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Donor lifecycle methods protected=" + num));
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Invalid comparison between Unknown and I4
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Invalid comparison between Unknown and I4
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			if ((int)mode == 0)
			{
				((MonoBehaviour)this).StopAllCoroutines();
				CleanupRuntimeForSceneChange(scene);
				_startNewRun = true;
				_abandonedDonorBuildIndices.Clear();
				if (_pendingDonorBuildIndex >= 0)
				{
					_abandonedDonorBuildIndices.Add(_pendingDonorBuildIndex);
				}
				_builtMapId = 0;
				_stableFrames = 0;
				_generationStarted = false;
				_teleportIndex = -1;
				_localCharacterId = 0;
				_fogHandlerId = 0;
				_fogStateSegment = -1;
				_segments.Clear();
				_pendingStaticSnapshot = null;
				_pendingDonorBuildIndex = -1;
				LifecycleBlockedBuildIndex = -1;
				((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Main scene changed to " + ((Scene)(ref scene)).name + "; runtime generator state reset for respawn/new run"));
				((MonoBehaviour)this).StartCoroutine(UnloadStrayDonorScenes(scene));
			}
			else if ((int)mode == 1 && _abandonedDonorBuildIndices.Contains(((Scene)(ref scene)).buildIndex))
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("[AllBiomes] Abandoned donor completed after scene change; unloading scene=" + ((Scene)(ref scene)).name + " buildIndex=" + ((Scene)(ref scene)).buildIndex));
				QuarantineScene(scene);
				CleanDonorPhotonViews(scene);
				((MonoBehaviour)this).StartCoroutine(UnloadAbandonedDonor(scene));
			}
			else if ((int)mode == 1 && ((Scene)(ref scene)).buildIndex == _pendingDonorBuildIndex)
			{
				try
				{
					int num = QuarantineScene(scene);
					RestoreStaticReferences(_pendingStaticSnapshot, "sceneLoaded quarantine");
					((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Donor quarantined before Start: scene=" + ((Scene)(ref scene)).name + " scripts=" + num));
				}
				catch (Exception ex)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)("[AllBiomes] Donor quarantine failed: " + ex));
				}
			}
		}

		private int QuarantineScene(Scene scene)
		{
			int num = 0;
			if (!((Scene)(ref scene)).IsValid() || !((Scene)(ref scene)).isLoaded)
			{
				return num;
			}
			GameObject[] rootGameObjects = ((Scene)(ref scene)).GetRootGameObjects();
			for (int i = 0; i < rootGameObjects.Length; i++)
			{
				MonoBehaviour[] componentsInChildren = rootGameObjects[i].GetComponentsInChildren<MonoBehaviour>(true);
				foreach (MonoBehaviour val in componentsInChildren)
				{
					if (!((Object)(object)val == (Object)null) && ((Behaviour)val).enabled)
					{
						((Behaviour)val).enabled = false;
						num++;
					}
				}
			}
			return num;
		}

		private void CleanupRuntimeForSceneChange(Scene destination)
		{
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				EndFlight();
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("[AllBiomes] Flight cleanup during scene change: " + ex.Message));
			}
			if ((Object)(object)_runtimeRoot != (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Destroying previous runtime mountain before entering " + ((Scene)(ref destination)).name));
				Object.Destroy((Object)(object)_runtimeRoot);
				_runtimeRoot = null;
			}
			int num = 0;
			Transform[] array = Object.FindObjectsByType<Transform>((FindObjectsInactive)1, (FindObjectsSortMode)0);
			foreach (Transform val in array)
			{
				if ((Object)(object)val == (Object)null || !IsAllBiomesObjectName(((Object)val).name))
				{
					continue;
				}
				Transform parent = val.parent;
				bool flag = false;
				while ((Object)(object)parent != (Object)null)
				{
					if (IsAllBiomesObjectName(((Object)parent).name))
					{
						flag = true;
						break;
					}
					parent = parent.parent;
				}
				if (!flag)
				{
					ManualLogSource logger = ((BaseUnityPlugin)this).Logger;
					string name = ((Object)val).name;
					Scene scene = ((Component)val).gameObject.scene;
					logger.LogWarning((object)("[AllBiomes] Destroying leftover runtime object '" + name + "' scene=" + ((Scene)(ref scene)).name));
					Object.Destroy((Object)(object)((Component)val).gameObject);
					num++;
				}
			}
			if (num > 0)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("[AllBiomes] Leftover runtime objects destroyed=" + num));
			}
			RuntimeTornadoRegistry.Clear();
			Shader.SetGlobalFloat("GlobalWind", 0f);
			Shader.SetGlobalFloat("HeightFogSpirit", 0f);
			Shader.SetGlobalFloat("HeightFogAmount", 0f);
			_debugFogRoots.Clear();
		}

		private static bool IsAllBiomesObjectName(string name)
		{
			if (string.IsNullOrEmpty(name))
			{
				return false;
			}
			if (!name.StartsWith("AllBiomes ", StringComparison.Ordinal))
			{
				return name.IndexOf("[AllBiomes ", StringComparison.Ordinal) >= 0;
			}
			return true;
		}

		private IEnumerator UnloadStrayDonorScenes(Scene destination)
		{
			//IL_000e: 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)
			for (int frame = 0; frame < 10; frame++)
			{
				yield return null;
			}
			for (int frame = SceneManager.sceneCount - 1; frame >= 0; frame--)
			{
				Scene candidate = SceneManager.GetSceneAt(frame);
				if (((Scene)(ref candidate)).IsValid() && ((Scene)(ref candidate)).isLoaded && !(((Scene)(ref candidate)).handle == ((Scene)(ref destination)).handle) && ((Scene)(ref candidate)).buildIndex >= 4 && ((Scene)(ref candidate)).buildIndex <= 13)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("[AllBiomes] Removing stray additive donor from " + ((Scene)(ref destination)).name + ": " + ((Scene)(ref candidate)).name + " buildIndex=" + ((Scene)(ref candidate)).buildIndex));
					QuarantineScene(candidate);
					CleanDonorPhotonViews(candidate);
					AsyncOperation unload = SceneManager.UnloadSceneAsync(candidate);
					if (unload != null)
					{
						while (!unload.isDone)
						{
							yield return null;
						}
					}
					_abandonedDonorBuildIndices.Remove(((Scene)(ref candidate)).buildIndex);
					candidate = default(Scene);
				}
			}
		}

		private IEnumerator UnloadAbandonedDonor(Scene scene)
		{
			//IL_000e: 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)
			if (!((Scene)(ref scene)).IsValid() || !((Scene)(ref scene)).isLoaded)
			{
				yield break;
			}
			int buildIndex = ((Scene)(ref scene)).buildIndex;
			string sceneName = ((Scene)(ref scene)).name;
			AsyncOperation unload = SceneManager.UnloadSceneAsync(scene);
			if (unload != null)
			{
				while (!unload.isDone)
				{
					yield return null;
				}
			}
			_abandonedDonorBuildIndices.Remove(buildIndex);
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Abandoned donor unloaded scene=" + sceneName));
		}

		private List<StaticReference> CaptureStaticReferences()
		{
			List<StaticReference> list = new List<StaticReference>();
			HashSet<FieldInfo> hashSet = new HashSet<FieldInfo>();
			Type[] types;
			try
			{
				types = typeof(MapHandler).Assembly.GetTypes();
			}
			catch (ReflectionTypeLoadException ex)
			{
				types = ex.Types;
			}
			Type[] array = types;
			for (int i = 0; i < array.Length; i++)
			{
				for (Type type = array[i]; type != null; type = type.BaseType)
				{
					FieldInfo[] fields;
					try
					{
						fields = type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
					}
					catch
					{
						continue;
					}
					FieldInfo[] array2 = fields;
					foreach (FieldInfo fieldInfo in array2)
					{
						if (!hashSet.Add(fieldInfo) || fieldInfo.IsLiteral || fieldInfo.IsInitOnly || !typeof(Object).IsAssignableFrom(fieldInfo.FieldType))
						{
							continue;
						}
						try
						{
							object? value = fieldInfo.GetValue(null);
							Object val = (Object)((value is Object) ? value : null);
							if (val != (Object)null)
							{
								list.Add(new StaticReference(fieldInfo, val));
							}
						}
						catch (Exception ex2)
						{
							((BaseUnityPlugin)this).Logger.LogWarning((object)("[AllBiomes] Static capture failed " + type.FullName + "." + fieldInfo.Name + ": " + ex2.Message));
						}
					}
				}
			}
			return list;
		}

		private void RestoreStaticReferences(List<StaticReference> snapshot, string stage)
		{
			if (snapshot == null)
			{
				return;
			}
			int num = 0;
			foreach (StaticReference item in snapshot)
			{
				if (item.Value == (Object)null)
				{
					continue;
				}
				try
				{
					object? value = item.Field.GetValue(null);
					if (!((Object)((value is Object) ? value : null) == item.Value))
					{
						item.Field.SetValue(null, item.Value);
						num++;
					}
				}
				catch (Exception ex)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("[AllBiomes] Static restore failed " + item.Field.DeclaringType.FullName + "." + item.Field.Name + ": " + ex.Message));
				}
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Main runtime references restored " + stage + ": changed=" + num));
		}

		private void SanitizeDonorClone(GameObject clone, string biomeName)
		{
			int num = 0;
			Transform[] componentsInChildren = clone.GetComponentsInChildren<Transform>(true);
			foreach (Transform val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)clone.transform) && ((Object)val).name.IndexOf("Anti Spawn Zone", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					Object.DestroyImmediate((Object)(object)((Component)val).gameObject);
					num++;
				}
			}
			int num2 = 0;
			PhotonView[] componentsInChildren2 = clone.GetComponentsInChildren<PhotonView>(true);
			foreach (PhotonView val2 in componentsInChildren2)
			{
				if ((Object)(object)val2 == (Object)null)
				{
					continue;
				}
				try
				{
					if (val2.ViewID != 0 && (Object)(object)PhotonNetwork.GetPhotonView(val2.ViewID) == (Object)(object)val2)
					{
						PhotonNetwork.LocalCleanPhotonView(val2);
					}
				}
				catch (Exception ex)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("[AllBiomes] PhotonView unregister failed biome=" + biomeName + " viewID=" + val2.ViewID + ": " + ex.Message));
				}
				Object.DestroyImmediate((Object)(object)val2);
				num2++;
			}
			int num3 = 0;
			MonoBehaviour[] componentsInChildren3 = clone.GetComponentsInChildren<MonoBehaviour>(true);
			foreach (MonoBehaviour val3 in componentsInChildren3)
			{
				if (!((Object)(object)val3 == (Object)null))
				{
					((Behaviour)val3).enabled = false;
					num3++;
				}
			}
			int num4 = 0;
			Animator[] componentsInChildren4 = clone.GetComponentsInChildren<Animator>(true);
			foreach (Animator val4 in componentsInChildren4)
			{
				if (!((Object)(object)val4 == (Object)null))
				{
					((Behaviour)val4).enabled = false;
					num4++;
				}
			}
			int num5 = 0;
			AudioSource[] componentsInChildren5 = clone.GetComponentsInChildren<AudioSource>(true);
			foreach (AudioSource val5 in componentsInChildren5)
			{
				if (!((Object)(object)val5 == (Object)null))
				{
					val5.Stop();
					((Behaviour)val5).enabled = false;
					num5++;
				}
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Sanitized " + biomeName + ": blockersRemoved=" + num + " photonViewsRemoved=" + num2 + " scripts=" + num3 + " animators=" + num4 + " audio=" + num5));
		}

		private unsafe void BuildRuntimeMountain(MapHandler map, Array vanilla, BiomeAsset[] definitions, List<GameObject> roots, Dictionary<string, SegmentPose> hostLayout)
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_026c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0271: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: 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_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: 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_0123: 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_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0424: Unknown result type (might be due to invalid IL or missing references)
			//IL_0429: Unknown result type (might be due to invalid IL or missing references)
			//IL_0438: Unknown result type (might be due to invalid IL or missing references)
			//IL_043d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0581: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_02de: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0308: Unknown result type (might be due to invalid IL or missing references)
			//IL_030f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0327: Unknown result type (might be due to invalid IL or missing references)
			//IL_0329: Unknown result type (might be due to invalid IL or missing references)
			//IL_032e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0341: Unknown result type (might be due to invalid IL or missing references)
			//IL_0343: Unknown result type (might be due to invalid IL or missing references)
			//IL_0348: Unknown result type (might be due to invalid IL or missing references)
			//IL_0356: Unknown result type (might be due to invalid IL or missing references)
			//IL_035b: Unknown result type (might be due to invalid IL or missing references)
			//IL_038a: Unknown result type (might be due to invalid IL or missing references)
			//IL_038f: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_047f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0484: Unknown result type (might be due to invalid IL or missing references)
			//IL_0489: Unknown result type (might be due to invalid IL or missing references)
			//IL_0499: Unknown result type (might be due to invalid IL or missing references)
			//IL_049e: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_0500: Unknown result type (might be due to invalid IL or missing references)
			//IL_0502: Unknown result type (might be due to invalid IL or missing references)
			//IL_0507: Unknown result type (might be due to invalid IL or missing references)
			//IL_0515: Unknown result type (might be due to invalid IL or missing references)
			//IL_051a: Unknown result type (might be due to invalid IL or missing references)
			//IL_053b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0540: Unknown result type (might be due to invalid IL or missing references)
			//IL_056b: Unknown result type (might be due to invalid IL or missing references)
			//IL_05c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0711: Unknown result type (might be due to invalid IL or missing references)
			//IL_0716: Unknown result type (might be due to invalid IL or missing references)
			//IL_0761: Unknown result type (might be due to invalid IL or missing references)
			//IL_0766: Unknown result type (might be due to invalid IL or missing references)
			//IL_0787: Unknown result type (might be due to invalid IL or missing references)
			//IL_078c: Unknown result type (might be due to invalid IL or missing references)
			//IL_060c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0612: Unknown result type (might be due to invalid IL or missing references)
			//IL_0617: Unknown result type (might be due to invalid IL or missing references)
			//IL_0621: Unknown result type (might be due to invalid IL or missing references)
			//IL_0626: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_07ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_07f4: Unknown result type (might be due to invalid IL or missing references)
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[AllBiomes] Overriding biome sequence...");
			for (int i = 0; i < vanilla.Length; i++)
			{
				Source source = Read(vanilla.GetValue(i), i);
				if ((Object)(object)source.Root != (Object)null && !roots.Contains(source.Root))
				{
					source.Root.SetActive(false);
				}
			}
			DisableOriginalBiomeHierarchy(((Component)map).gameObject.scene);
			_segments.Clear();
			_teleportIndex = -1;
			for (int j = 0; j < definitions.Length; j++)
			{
				GameObject val = roots[j];
				if ((Object)(object)val == (Object)null)
				{
					throw new InvalidOperationException("Runtime root was destroyed before build: " + definitions[j].Name);
				}
				((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Activating runtime root " + j + " " + definitions[j].Name + " object=" + ((Object)val).name));
				val.SetActive(true);
				Physics.SyncTransforms();
				Bounds bounds = BoundsOf(val);
				Vector3 entrance = FindAnchor(val, entrance: true, bounds);
				Vector3 exit = FindAnchor(val, entrance: false, bounds);
				ApplyCalibratedAnchors(definitions[j].Name, val, ref entrance, ref exit);
				_segments.Add(new RuntimeSegment(j, definitions[j].Name, val, bounds, entrance, exit));
				((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Creating segment " + j + ": " + definitions[j].Name));
				((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Anchors " + definitions[j].Name + " entrance=" + ((object)(*(Vector3*)(&entrance))/*cast due to .constrained prefix*/).ToString() + " exit=" + ((object)(*(Vector3*)(&exit))/*cast due to .constrained prefix*/).ToString()));
				int num = 0;
				Renderer[] componentsInChildren = val.GetComponentsInChildren<Renderer>(true);
				foreach (Renderer val2 in componentsInChildren)
				{
					if ((Object)(object)val2 != (Object)null && IsLocallyActive(val.transform, ((Component)val2).transform) && val2.isPartOfStaticBatch)
					{
						num++;
					}
				}
				((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Static-batched renderers " + definitions[j].Name + " = " + num));
			}
			Vector3 forward = Vector3.forward;
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Progression direction = " + ((object)(*(Vector3*)(&forward))/*cast due to .constrained prefix*/).ToString()));
			if (hostLayout != null)
			{
				foreach (RuntimeSegment segment in _segments)
				{
					Vector3 val3 = segment.Root.transform.InverseTransformPoint(segment.Entrance);
					Vector3 val4 = segment.Root.transform.InverseTransformPoint(segment.Exit);
					SegmentPose segmentPose = hostLayout[segment.Name];
					segment.Root.transform.SetPositionAndRotation(segmentPose.Position, segmentPose.Rotation);
					segment.Entrance = segment.Root.transform.TransformPoint(val3);
					segment.Exit = segment.Root.transform.TransformPoint(val4);
					segment.Bounds = BoundsOf(segment.Root);
					((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Client applied host pose " + segment.Name + " position=" + ((object)segmentPose.Position/*cast due to .constrained prefix*/).ToString() + " rotation=" + ((object)((Quaternion)(ref segmentPose.Rotation)).eulerAngles/*cast due to .constrained prefix*/).ToString()));
				}
				Physics.SyncTransforms();
			}
			else
			{
				for (int l = 1; l < _segments.Count; l++)
				{
					RuntimeSegment runtimeSegment = _segments[l - 1];
					RuntimeSegment runtimeSegment2 = _segments[l];
					float num2 = ProjectMax(BoundsOf(runtimeSegment.Root), forward);
					float num3 = ProjectMin(BoundsOf(runtimeSegment2.Root), forward);
					if (runtimeSegment.Name == "Caldera" && runtimeSegment2.Name == "The Kiln")
					{
						Vector3 val5 = runtimeSegment2.Root.transform.InverseTransformPoint(runtimeSegment2.Entrance);
						Vector3 val6 = runtimeSegment2.Root.transform.InverseTransformPoint(runtimeSegment2.Exit);
						runtimeSegment2.Root.transform.SetPositionAndRotation(runtimeSegment.Root.transform.position, runtimeSegment.Root.transform.rotation);
						runtimeSegment2.Entrance = runtimeSegment2.Root.transform.TransformPoint(val5);
						runtimeSegment2.Exit = runtimeSegment2.Root.transform.TransformPoint(val6);
						runtimeSegment2.Bounds = BoundsOf(runtimeSegment2.Root);
						Physics.SyncTransforms();
						((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Preserved vanilla Caldera/Kiln sibling transform; shared position=" + ((object)runtimeSegment2.Root.transform.position/*cast due to .constrained prefix*/).ToString()));
						NudgeSegment(runtimeSegment2, new Vector3(4.89f, -35.05f, -196.69f), "restore verified bridge/tunnel approach while exterior is isolated separately");
					}
					else
					{
						PlaceAfter(runtimeSegment, runtimeSegment2, forward);
					}
					if (!(runtimeSegment2.Name == "The Kiln"))
					{
						if (runtimeSegment2.Name == "Gloom")
						{
							NudgeSegment(runtimeSegment2, new Vector3(10.66f, -69.73f, 137.18f), "Mesa visible edge -> Gloom floor");
						}
						else if (runtimeSegment2.Name == "The Citadel")
						{
							NudgeSegment(runtimeSegment2, new Vector3(42.73f, -104.18f, 0f), "Kiln edge -> composite Citadel stairs");
						}
						else
						{
							NudgeSegment(runtimeSegment2, forward * -20f + Vector3.down * 25f, "global terrain overlap and descent");
						}
					}
					((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] " + runtimeSegment.Name + " -> " + runtimeSegment2.Name));
					((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Previous exit = " + num2 + " Next entrance = " + num3 + " Overlap = 2"));
				}
				ApplyFinalEdgeAlignment();
				ApplyRootsBlockLateralCalibration();
			}
			InstallRuntimeHazards();
			InstallRuntimeMobs();
			InstallRuntimeShoreBridges();
			DisableVanillaFogWalls();
			InstallRuntimeCampfires();
			InstallRuntimeLuggage();
			InstallNadirAccess();
			foreach (RuntimeSegment segment2 in _segments)
			{
				segment2.Bounds = BoundsOf(segment2.Root);
				((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Segment " + segment2.Index + " " + segment2.Name + " bounds center=" + ((object)((Bounds)(ref segment2.Bounds)).center/*cast due to .constrained prefix*/).ToString() + " size=" + ((object)((Bounds)(ref segment2.Bounds)).size/*cast due to .constrained prefix*/).ToString()));
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Peak placed at " + ((object)_segments[_segments.Count - 1].Root.transform.position/*cast due to .constrained prefix*/).ToString()));
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Runtime segment count = " + _segments.Count));
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Rescue zone center=" + ((object)Unsafe.As<Vector3, Vector3>(ref RescueZoneCenter)/*cast due to .constrained prefix*/).ToString() + " radius=" + 35f));
		}

		internal static bool TryGetRescueZoneResult(Vector3 position, out bool inside)
		{
			//IL_0024: 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)
			inside = false;
			if ((Object)(object)Instance == (Object)null || Instance._segments.Count == 0)
			{
				return false;
			}
			inside = Vector3.Distance(position, RescueZoneCenter) <= 35f;
			return true;
		}

		private void InstallNadirAccess()
		{
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			VoidBiome val = null;
			VoidBiome[] array = Resources.FindObjectsOfTypeAll<VoidBiome>();
			foreach (VoidBiome val2 in array)
			{
				if (!((Object)(object)val2 == (Object)null) && !((Object)(object)((Component)val2).gameObject == (Object)null))
				{
					val = val2;
					break;
				}
			}
			RuntimeSegment runtimeSegment = _segments.Find((RuntimeSegment segment) => segment.Name == "Peak");
			ScoutStatue val3 = (((Object)(object)runtimeSegment?.Root == (Object)null) ? null : runtimeSegment.Root.GetComponentInChildren<ScoutStatue>(true));
			if ((Object)(object)val == (Object)null || val.segment == null || (Object)(object)val.segment.segmentParent == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"[AllBiomes] Nadir unavailable: vanilla VoidBiome/MapSegment was not found");
				return;
			}
			if ((Object)(object)val3 == (Object)null || (Object)(object)val3.scoutsHonorPrefab == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"[AllBiomes] Nadir unavailable: Peak ScoutStatue/Scout's Honor prefab was not found");
				return;
			}
			RelocatePeakSummit(runtimeSegment.Root, val3);
			if ((Object)(object)val3.gemSpot != (Object)null)
			{
				RescueZoneCenter = val3.gemSpot.position + RescueOffsetFromSummitGem;
				((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Dynamic Peak summit resolved from ScoutStatue.gemSpot=" + ((object)Unsafe.As<Vector3, Vector3>(ref RescueZoneCenter)/*cast due to .constrained prefix*/).ToString()));
			}
			RuntimeNadirAccess runtimeNadirAccess = ((Component)this).gameObject.GetComponent<RuntimeNadirAccess>();
			if ((Object)(object)runtimeNadirAccess == (Object)null)
			{
				runtimeNadirAccess = ((Component)this).gameObject.AddComponent<RuntimeNadirAccess>();
			}
			runtimeNadirAccess.Initialize(val3, RescueZoneCenter);
			InstallRescuePlatform(runtimeSegment.Root);
			InstallPeakMissingColliders(runtimeSegment.Root);
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[AllBiomes] Nadir: FOUND root=" + PathOf(val.segment.segmentParent.transform) + " colliders=" + val.segment.segmentParent.GetComponentsInChildren<Collider>(true).Length + " access=vanilla Scout's Honor at Peak"));
		}

		private unsafe void RelocatePeakSummit(GameObject peakRoot, ScoutStatue statue)
		{
			//IL_0071: 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_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: 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_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Expected O, but got Unknown
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to inv