Decompiled source of PEAKLevelLoader v0.4.6

off_grid.PEAKLevelLoader.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Mono.Cecil;
using Mono.Collections.Generic;
using PEAKLevelLoader;
using PEAKLevelLoader.Core;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;
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: IgnoresAccessChecksTo("")]
[assembly: AssemblyCompany("off_grid.PEAKLevelLoader")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.4.6.0")]
[assembly: AssemblyInformationalVersion("0.4.6")]
[assembly: AssemblyProduct("PEAKLevelLoader")]
[assembly: AssemblyTitle("off_grid.PEAKLevelLoader")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.4.6.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
public class PEAKPackSyncPhoton : MonoBehaviour, IOnEventCallback
{
	[Serializable]
	private class LevelPackDTO
	{
		public int index;

		public bool replace;

		public bool isVariant;

		public string? biome;

		public string? bundlePath;

		public string? prefabName;

		public string? campfirePrefabName;

		public string? packName;

		public string? id;
	}

	[Serializable]
	private class LevelPackCollectionDTO
	{
		public string? sendId;

		public LevelPackDTO[]? packs;
	}

	[Serializable]
	private class PackAppliedAck
	{
		public string? sendId;

		public int senderActorNumber;
	}

	private const byte EVENT_SYNC_PACKS = 200;

	private const byte EVENT_PACKS_APPLIED_ACK = 201;

	private static PEAKPackSyncPhoton? _instance;

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

	private int expectedAckCount;

	private string lastMasterSendId = Guid.Empty.ToString();

	public static PEAKPackSyncPhoton? Instance => _instance;

	private void Awake()
	{
		if ((Object)(object)_instance != (Object)null && (Object)(object)_instance != (Object)(object)this)
		{
			Object.Destroy((Object)(object)this);
			return;
		}
		_instance = this;
		Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
	}

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

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

	public void SendPacksToClients(LevelPack[] packs, bool waitForAcks = true, Action<bool> onComplete = null)
	{
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00af: Expected O, but got Unknown
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c1: 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)
		if (!PhotonNetwork.InRoom)
		{
			Debug.LogWarning((object)"PEAKPackSyncPhoton: not in a Photon room; skipping send.");
			onComplete?.Invoke(obj: false);
			return;
		}
		if (!PhotonNetwork.IsMasterClient)
		{
			Debug.LogWarning((object)"PEAKPackSyncPhoton: only master should call SendPacksToClients.");
			onComplete?.Invoke(obj: false);
			return;
		}
		LevelPackCollectionDTO levelPackCollectionDTO = new LevelPackCollectionDTO
		{
			sendId = Guid.NewGuid().ToString(),
			packs = packs.Select((LevelPack p) => new LevelPackDTO
			{
				index = p.index,
				replace = p.replace,
				isVariant = p.isVariant,
				biome = (p.biome ?? string.Empty),
				bundlePath = (p.bundlePath ?? string.Empty),
				prefabName = (p.prefabName ?? string.Empty),
				campfirePrefabName = (p.campfirePrefabName ?? string.Empty),
				packName = (p.packName ?? string.Empty),
				id = (p.id ?? string.Empty)
			}).ToArray()
		};
		string s = JsonUtility.ToJson((object)levelPackCollectionDTO);
		byte[] bytes = Encoding.UTF8.GetBytes(s);
		RaiseEventOptions val = new RaiseEventOptions
		{
			Receivers = (ReceiverGroup)0,
			CachingOption = (EventCaching)0
		};
		SendOptions val2 = default(SendOptions);
		((SendOptions)(ref val2)).Reliability = true;
		SendOptions val3 = val2;
		lastReceivedAcks.Clear();
		expectedAckCount = PhotonNetwork.CurrentRoom.PlayerCount - 1;
		lastMasterSendId = levelPackCollectionDTO.sendId;
		PhotonNetwork.RaiseEvent((byte)200, (object)bytes, val, val3);
		Debug.Log((object)$"PEAKPackSyncPhoton: Master sent {levelPackCollectionDTO.packs.Length} packs (sendId={levelPackCollectionDTO.sendId}) to clients. WaitingForAcks={waitForAcks}");
		if (waitForAcks)
		{
			((MonoBehaviour)this).StartCoroutine(WaitForAcksCoroutine(12f, onComplete));
		}
		else
		{
			onComplete?.Invoke(obj: true);
		}
	}

	private IEnumerator WaitForAcksCoroutine(float timeout, Action<bool> onComplete)
	{
		float start = Time.realtimeSinceStartup;
		while (Time.realtimeSinceStartup - start < timeout)
		{
			if (lastReceivedAcks.Count >= expectedAckCount)
			{
				Debug.Log((object)$"PEAKPackSyncPhoton: received all {lastReceivedAcks.Count}/{expectedAckCount} ACKs.");
				onComplete?.Invoke(obj: true);
				yield break;
			}
			yield return (object)new WaitForSeconds(0.15f);
		}
		Debug.LogWarning((object)$"PEAKPackSyncPhoton: Timeout waiting for ACKs ({lastReceivedAcks.Count}/{expectedAckCount}).");
		onComplete?.Invoke(obj: false);
	}

	public void OnEvent(EventData photonEvent)
	{
		try
		{
			if (photonEvent.Code == 200)
			{
				if (photonEvent.CustomData is byte[] bytes)
				{
					string @string = Encoding.UTF8.GetString(bytes);
					LevelPackCollectionDTO levelPackCollectionDTO = JsonUtility.FromJson<LevelPackCollectionDTO>(@string);
					if (levelPackCollectionDTO == null || levelPackCollectionDTO.packs == null || levelPackCollectionDTO.packs.Length == 0)
					{
						Debug.LogWarning((object)"PEAKPackSyncPhoton: empty pack payload received");
						return;
					}
					Debug.Log((object)$"PEAKPackSyncPhoton: client received {levelPackCollectionDTO.packs.Length} packs (sendId={levelPackCollectionDTO.sendId}). Starting apply...");
					((MonoBehaviour)this).StartCoroutine(ClientHandleReceivedPacks(levelPackCollectionDTO.sendId, levelPackCollectionDTO.packs));
				}
			}
			else
			{
				if (photonEvent.Code != 201 || !(photonEvent.CustomData is byte[] bytes2))
				{
					return;
				}
				string string2 = Encoding.UTF8.GetString(bytes2);
				PackAppliedAck packAppliedAck = JsonUtility.FromJson<PackAppliedAck>(string2);
				if (packAppliedAck == null || !PhotonNetwork.IsMasterClient)
				{
					return;
				}
				if (!string.Equals(packAppliedAck.sendId, lastMasterSendId, StringComparison.OrdinalIgnoreCase))
				{
					Debug.Log((object)("PEAKPackSyncPhoton: received ACK for unknown sendId " + packAppliedAck.sendId + " (current " + lastMasterSendId + "). Ignoring."));
				}
				else
				{
					lock (lastReceivedAcks)
					{
						lastReceivedAcks.Add(packAppliedAck.senderActorNumber);
					}
					Debug.Log((object)$"PEAKPackSyncPhoton: master received ACK from Actor {packAppliedAck.senderActorNumber} (total {lastReceivedAcks.Count}/{expectedAckCount})");
				}
			}
		}
		catch (Exception ex)
		{
			Debug.LogError((object)("PEAKPackSyncPhoton.OnEvent error: " + ex));
		}
	}

	private IEnumerator ClientHandleReceivedPacks(string sendId, LevelPackDTO[] dtos)
	{
		LevelPack[] packs = dtos.Select((LevelPackDTO d) => new LevelPack
		{
			index = d.index,
			replace = d.replace,
			isVariant = d.isVariant,
			biome = (d.biome ?? string.Empty),
			bundlePath = (d.bundlePath ?? string.Empty),
			prefabName = (d.prefabName ?? string.Empty),
			campfirePrefabName = (d.campfirePrefabName ?? string.Empty),
			packName = (d.packName ?? string.Empty),
			id = (d.id ?? string.Empty)
		}).ToArray();
		float timeout = 10f;
		float start = Time.realtimeSinceStartup;
		while (Time.realtimeSinceStartup - start < timeout)
		{
			bool flag = true;
			LevelPack[] array = packs;
			foreach (LevelPack levelPack in array)
			{
				if (!string.IsNullOrEmpty(levelPack.bundlePath) && !IsBundleGroupAvailableAndLoaded(levelPack.bundlePath))
				{
					flag = false;
					break;
				}
			}
			if (flag)
			{
				break;
			}
			yield return (object)new WaitForSeconds(0.25f);
		}
		try
		{
			if ((Object)(object)global::PEAKLevelLoader.PEAKLevelLoader.Instance != (Object)null)
			{
				global::PEAKLevelLoader.PEAKLevelLoader.Instance.AddPacks(new LevelPackCollection
				{
					packs = packs
				});
				global::PEAKLevelLoader.PEAKLevelLoader.Instance.ApplyPacksToMapHandler(Singleton<MapHandler>.Instance);
				Debug.Log((object)$"PEAKPackSyncPhoton: client applied {packs.Length} packs locally (sendId={sendId}). Sending ACK.");
			}
			else
			{
				Debug.LogError((object)"PEAKPackSyncPhoton: client PEAKLevelLoader.Instance null; cannot apply packs.");
			}
		}
		catch (Exception ex)
		{
			Debug.LogError((object)("PEAKPackSyncPhoton.ClientHandleReceivedPacks error: " + ex));
		}
		PackAppliedAck packAppliedAck = new PackAppliedAck
		{
			sendId = sendId,
			senderActorNumber = PhotonNetwork.LocalPlayer.ActorNumber
		};
		string s = JsonUtility.ToJson((object)packAppliedAck);
		byte[] bytes = Encoding.UTF8.GetBytes(s);
		RaiseEventOptions val = new RaiseEventOptions();
		if (PhotonNetwork.MasterClient != null)
		{
			val.TargetActors = new int[1] { PhotonNetwork.MasterClient.ActorNumber };
		}
		SendOptions val2 = default(SendOptions);
		((SendOptions)(ref val2)).Reliability = true;
		SendOptions val3 = val2;
		PhotonNetwork.RaiseEvent((byte)201, (object)bytes, val, val3);
	}

	private bool IsBundleGroupAvailableAndLoaded(string groupName)
	{
		if (string.IsNullOrEmpty(groupName))
		{
			return true;
		}
		Type type = Type.GetType("AssetBundleLoader") ?? Type.GetType("PEAKLevelLoader.AssetBundleLoader");
		if (type == null)
		{
			return false;
		}
		object obj = type.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(null);
		if (obj == null)
		{
			return false;
		}
		if (!(type.GetProperty("AssetBundleGroups", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(obj) is IEnumerable enumerable))
		{
			return false;
		}
		foreach (object item in enumerable)
		{
			Type type2 = item.GetType();
			string a = ((type2.GetProperty("GroupName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? type2.GetProperty("Name", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))?.GetValue(item) as string) ?? string.Empty;
			if (!string.Equals(a, groupName, StringComparison.OrdinalIgnoreCase))
			{
				continue;
			}
			PropertyInfo propertyInfo = type2.GetProperty("LoadedStatus", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? type2.GetProperty("IsLoaded", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? type2.GetProperty("Loaded", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (propertyInfo != null)
			{
				object value = propertyInfo.GetValue(item);
				if (value == null)
				{
					return false;
				}
				string text = value.ToString();
				if (text.IndexOf("load", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("true", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return true;
				}
				return false;
			}
			return true;
		}
		return false;
	}
}
public class Placeholder : MonoBehaviour
{
	[Tooltip("Key name used by SpawnableRegistry or the prefab name to look for in bundles.")]
	public string? spawnableName;

	[Tooltip("Optional role (e.g. 'campfire', 'spawner', 'fogOrigin', etc.).")]
	public string? role;

	[Tooltip("Optional JSON/options string used by loader (e.g. for fog size).")]
	[TextArea(2, 6)]
	public string? options;

	[Tooltip("Optional author notes.")]
	public string? notes;
}
public static class AssetBundleGroupDebugger
{
	public static class BundleResolveHelper
	{
		public static GameObject? ResolvePrefabFromLoadedGroups(string prefabName)
		{
			if (string.IsNullOrEmpty(prefabName))
			{
				return null;
			}
			Type typeFromHandle = typeof(AssetBundleLoader);
			AssetBundleLoader instance = AssetBundleLoader.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return null;
			}
			List<AssetBundleGroup> assetBundleGroups = instance.AssetBundleGroups;
			if (assetBundleGroups == null)
			{
				return null;
			}
			foreach (AssetBundleGroup item in assetBundleGroups)
			{
				if (item == null)
				{
					continue;
				}
				try
				{
					GameObject val = ResolvePrefabFromGroup(item, prefabName);
					if ((Object)(object)val != (Object)null)
					{
						return val;
					}
				}
				catch
				{
				}
			}
			return null;
		}
	}

	private static readonly Type[] GenericTryTypes = new Type[3]
	{
		typeof(GameObject),
		typeof(TextAsset),
		typeof(Object)
	};

	public static void LogGroupContents(object group)
	{
		if (group == null)
		{
			Debug.Log((object)"AssetBundleGroupDebugger: group is null");
			return;
		}
		Type type = group.GetType();
		Debug.Log((object)("AssetBundleGroupDebugger: Inspecting group type: " + type.FullName));
		string text = ((type.GetProperty("GroupName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? type.GetProperty("Name", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))?.GetValue(group) as string) ?? "(unknown)";
		Debug.Log((object)("GroupName: " + text));
		object obj = null;
		PropertyInfo property = type.GetProperty("AssetBundle", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		if (property != null)
		{
			obj = property.GetValue(group);
		}
		if (obj != null)
		{
			Type type2 = obj.GetType();
			MethodInfo method = type2.GetMethod("GetAllAssetNames", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (method != null)
			{
				try
				{
					if (method.Invoke(obj, null) is string[] array && array.Length != 0)
					{
						Debug.Log((object)$"AssetBundle: GetAllAssetNames returned {array.Length} entries:");
						string[] array2 = array;
						foreach (string text2 in array2)
						{
							Debug.Log((object)(" - " + text2));
						}
						return;
					}
				}
				catch (Exception ex)
				{
					Debug.LogWarning((object)("GetAllAssetNames invocation failed: " + ex));
				}
			}
		}
		MethodInfo[] array3 = (from m in type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
			where string.Equals(m.Name, "LoadAllAssets", StringComparison.OrdinalIgnoreCase) || string.Equals(m.Name, "LoadAll", StringComparison.OrdinalIgnoreCase)
			select m).ToArray();
		MethodInfo[] array4 = array3;
		foreach (MethodInfo methodInfo in array4)
		{
			try
			{
				if (methodInfo.ContainsGenericParameters)
				{
					Type[] genericTryTypes = GenericTryTypes;
					foreach (Type type3 in genericTryTypes)
					{
						try
						{
							MethodInfo methodInfo2 = methodInfo.MakeGenericMethod(type3);
							object result = methodInfo2.Invoke(group, null);
							if (TryLogEnumerableResult(result, $"LoadAllAssets<{type3.Name}> via {methodInfo}"))
							{
								return;
							}
						}
						catch (Exception ex2)
						{
							Debug.Log((object)("LoadAllAssets<" + type3.Name + "> failed: " + ex2.Message));
						}
					}
					continue;
				}
				ParameterInfo[] parameters = methodInfo.GetParameters();
				if (parameters.Length == 0)
				{
					object result2 = methodInfo.Invoke(group, null);
					if (TryLogEnumerableResult(result2, $"LoadAllAssets() via {methodInfo}"))
					{
						return;
					}
				}
				else
				{
					if (parameters.Length != 1 || !(parameters[0].ParameterType == typeof(Type)))
					{
						continue;
					}
					Type[] genericTryTypes2 = GenericTryTypes;
					foreach (Type type4 in genericTryTypes2)
					{
						try
						{
							object result3 = methodInfo.Invoke(group, new object[1] { type4 });
							if (TryLogEnumerableResult(result3, $"LoadAllAssets({type4.Name}) via {methodInfo}"))
							{
								return;
							}
						}
						catch (Exception arg)
						{
							Debug.LogWarning((object)$"LoadAllAssets failure: {arg}");
						}
					}
					continue;
				}
			}
			catch (Exception arg2)
			{
				Debug.LogWarning((object)$"LoadAllAssets invocation failed: {arg2}");
			}
		}
		Debug.Log((object)"Fallback: inspecting public enumerable fields/properties...");
		bool flag = false;
		PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public);
		foreach (PropertyInfo propertyInfo in properties)
		{
			if (!typeof(IEnumerable).IsAssignableFrom(propertyInfo.PropertyType) || !(propertyInfo.PropertyType != typeof(string)))
			{
				continue;
			}
			try
			{
				object value = propertyInfo.GetValue(group);
				if (!(value is IEnumerable enumerable))
				{
					continue;
				}
				int num = 0;
				foreach (object item in enumerable)
				{
					num++;
					if (item == null)
					{
						Debug.Log((object)$" - property {propertyInfo.Name} item {num} == null");
						continue;
					}
					string text3 = (item.GetType().GetProperty("name")?.GetValue(item) as string) ?? "(no name)";
					Debug.Log((object)$"Property {propertyInfo.Name} item {num}: {text3} ({item.GetType().Name})");
					flag = true;
				}
			}
			catch
			{
			}
		}
		if (!flag)
		{
			Debug.Log((object)"AssetBundleGroupDebugger: done (no asset names found by the strategies).");
		}
		else
		{
			Debug.Log((object)"AssetBundleGroupDebugger: done (fallback enumerated items).");
		}
	}

	private static bool TryLogEnumerableResult(object result, string label)
	{
		if (result == null)
		{
			return false;
		}
		if (result is IEnumerable enumerable)
		{
			Debug.Log((object)(label + " returned enumerable:"));
			int num = 0;
			foreach (object item in enumerable)
			{
				num++;
				if (item == null)
				{
					Debug.Log((object)$" - {num}: NULL");
					continue;
				}
				string arg = (item.GetType().GetProperty("name")?.GetValue(item) as string) ?? "(no name)";
				Debug.Log((object)$" - {num}: {arg} ({item.GetType().Name})");
			}
			if (num > 0)
			{
				return true;
			}
		}
		else
		{
			Debug.Log((object)(label + " returned a " + result.GetType().Name + " (not enumerable)"));
		}
		return false;
	}

	public static GameObject? ResolvePrefabFromGroup(AssetBundleGroup group, string prefabCandidate)
	{
		string prefabCandidate2 = prefabCandidate;
		if (group == null || string.IsNullOrEmpty(prefabCandidate2))
		{
			return null;
		}
		try
		{
			try
			{
				List<GameObject> list = group.LoadAllAssets<GameObject>();
				if (list != null && list.Count > 0)
				{
					GameObject val = ((IEnumerable<GameObject>)list).FirstOrDefault((Func<GameObject, bool>)((GameObject a) => (Object)(object)a != (Object)null && string.Equals(((Object)a).name, prefabCandidate2, StringComparison.OrdinalIgnoreCase)));
					if ((Object)(object)val != (Object)null)
					{
						return val;
					}
				}
			}
			catch
			{
			}
			try
			{
				List<AssetBundleInfo> assetBundleInfos = group.GetAssetBundleInfos();
				foreach (AssetBundleInfo item in assetBundleInfos)
				{
					AssetBundle assetBundleReference = item.AssetBundleReference;
					if ((Object)(object)assetBundleReference == (Object)null)
					{
						continue;
					}
					string[] allAssetNames = assetBundleReference.GetAllAssetNames();
					foreach (string text in allAssetNames)
					{
						string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(text);
						if (string.Equals(fileNameWithoutExtension, prefabCandidate2, StringComparison.OrdinalIgnoreCase))
						{
							GameObject val2 = assetBundleReference.LoadAsset<GameObject>(text);
							if ((Object)(object)val2 != (Object)null)
							{
								return val2;
							}
						}
					}
				}
			}
			catch
			{
			}
			try
			{
				List<Object> list2 = group.LoadAllAssets<Object>();
				if (list2 != null)
				{
					foreach (Object item2 in list2)
					{
						if (item2 == (Object)null)
						{
							continue;
						}
						GameObject val3 = (GameObject)(object)((item2 is GameObject) ? item2 : null);
						if (val3 != null && string.Equals(((Object)val3).name, prefabCandidate2, StringComparison.OrdinalIgnoreCase))
						{
							return val3;
						}
						if (item2.name != null && string.Equals(Path.GetFileNameWithoutExtension(item2.name), prefabCandidate2, StringComparison.OrdinalIgnoreCase))
						{
							GameObject val4 = (GameObject)(object)((item2 is GameObject) ? item2 : null);
							if (val4 != null)
							{
								return val4;
							}
						}
					}
				}
			}
			catch
			{
			}
		}
		catch (Exception arg)
		{
			Debug.LogWarning((object)$"ResolvePrefabFromGroup error: {arg}");
		}
		return null;
	}

	private static GameObject? FindMatchingGameObjectInEnumerable(IEnumerable enumerable, string candidate)
	{
		if (enumerable == null)
		{
			return null;
		}
		foreach (object item in enumerable)
		{
			if (item == null)
			{
				continue;
			}
			Type type = item.GetType();
			string text = (type.GetProperty("name")?.GetValue(item) as string) ?? null;
			if (!string.IsNullOrEmpty(text) && (string.Equals(text, candidate, StringComparison.OrdinalIgnoreCase) || string.Equals(Path.GetFileNameWithoutExtension(text), candidate, StringComparison.OrdinalIgnoreCase)))
			{
				return (GameObject?)((item is GameObject) ? item : null);
			}
			if (item is string text2)
			{
				string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(text2);
				if (string.Equals(fileNameWithoutExtension, candidate, StringComparison.OrdinalIgnoreCase) || text2.IndexOf(candidate, StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return null;
				}
			}
		}
		return null;
	}
}
public class PatchedContentDebug : MonoBehaviour
{
	private void Update()
	{
		if (Input.GetKeyDown((KeyCode)290))
		{
			DumpPatchedContent();
		}
	}

	public static void DumpPatchedContent()
	{
		StringBuilder stringBuilder = new StringBuilder();
		stringBuilder.AppendLine("==== PatchedContent Dump ====");
		stringBuilder.AppendLine($"LoadedBundleHashes: {PatchedContent.LoadedBundleHashes.Count}");
		stringBuilder.AppendLine($"LoadedBundleNames: {PatchedContent.LoadedBundleNames.Count}");
		stringBuilder.AppendLine($"AllLevelSceneNames: {PatchedContent.AllLevelSceneNames.Count}");
		stringBuilder.AppendLine($"ExtendedMods: {PatchedContent.ExtendedMods.Count}");
		foreach (ExtendedMod extendedMod in PatchedContent.ExtendedMods)
		{
			stringBuilder.AppendLine(" - Mod: " + extendedMod.ModName + " (Author: " + extendedMod.AuthorName + ")");
			if (extendedMod.ExtendedContents == null)
			{
				continue;
			}
			foreach (ExtendedContent extendedContent in extendedMod.ExtendedContents)
			{
				stringBuilder.AppendLine(string.Format("   - Content: {0} (Type: {1}, Tags: {2})", ((Object)extendedContent).name, extendedContent.ContentType, string.Join(',', extendedContent.ContentTags?.ConvertAll((ContentTag t) => t?.contentTagName ?? "null") ?? new List<string>())));
			}
		}
		stringBuilder.AppendLine("==== End Dump ====");
		Debug.Log((object)stringBuilder.ToString());
	}
}
public static class SpawnerHelper
{
	public static Vector3 GetLossyScale(this Transform t)
	{
		//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_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		Vector3 val = t.localScale;
		Transform parent = t.parent;
		while ((Object)(object)parent != (Object)null)
		{
			val = Vector3.Scale(val, parent.localScale);
			parent = parent.parent;
		}
		return val;
	}

	public static void SetParentPreserveWorld(Transform child, Transform parent)
	{
		//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_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: 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_0094: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ad: 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_00ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ce: 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_00e0: Unknown result type (might be due to invalid IL or missing references)
		Vector3 position = child.position;
		Quaternion rotation = child.rotation;
		Vector3 lossyScale = child.GetLossyScale();
		child.SetParent(parent, true);
		Vector3 val = (((Object)(object)parent != (Object)null) ? parent.GetLossyScale() : Vector3.one);
		val.x = (Mathf.Approximately(val.x, 0f) ? 1f : val.x);
		val.y = (Mathf.Approximately(val.y, 0f) ? 1f : val.y);
		val.z = (Mathf.Approximately(val.z, 0f) ? 1f : val.z);
		child.localScale = new Vector3(lossyScale.x / val.x, lossyScale.y / val.y, lossyScale.z / val.z);
		child.position = position;
		child.rotation = rotation;
	}

	internal static void RegisterSegmentContentsSync(GameObject instGO, LevelPack pack, GameObject? campfirePrefab, object mapSegObj, Action<string, object?> TrySetBackingField)
	{
		//IL_0113: 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)
		try
		{
			Campfire componentInChildren = instGO.GetComponentInChildren<Campfire>(true);
			GameObject val = null;
			Transform val2 = instGO.transform.Find("CampfireAnchor") ?? instGO.transform.Find("campfireAnchor") ?? instGO.transform.Find("Campfire") ?? ((IEnumerable<Transform>)instGO.GetComponentsInChildren<Transform>(true)).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name.IndexOf("campfire", StringComparison.OrdinalIgnoreCase) >= 0));
			if ((Object)(object)componentInChildren != (Object)null)
			{
				val = ((Component)componentInChildren).gameObject;
				if ((Object)(object)val2 != (Object)null && (Object)(object)val.transform.parent != (Object)(object)val2)
				{
					SetParentPreserveWorld(val.transform, val2);
				}
			}
			else if ((Object)(object)campfirePrefab != (Object)null)
			{
				val = Object.Instantiate<GameObject>(campfirePrefab);
				((Object)val).name = "ModCampfire_" + pack.packName + "_" + (pack.campfirePrefabName ?? "campfire");
				Transform parent = val2 ?? instGO.transform;
				SetParentPreserveWorld(val.transform, parent);
				if ((Object)(object)val2 != (Object)null)
				{
					val.transform.localPosition = Vector3.zero;
					val.transform.localRotation = Quaternion.identity;
				}
			}
			if ((Object)(object)val != (Object)null)
			{
				TrySetBackingField("_segmentCampfire", val);
			}
			else
			{
				global::PEAKLevelLoader.PEAKLevelLoader.Logger.LogInfo((object)("RegisterSegmentContents: no campfire found/created for pack " + pack.packName + "."));
			}
		}
		catch (Exception arg)
		{
			global::PEAKLevelLoader.PEAKLevelLoader.Logger.LogWarning((object)$"RegisterSegmentContents: campfire registration failed for {pack.packName}: {arg}");
		}
		try
		{
			Spawner[] componentsInChildren = instGO.GetComponentsInChildren<Spawner>(true);
			if (componentsInChildren != null && componentsInChildren.Length != 0)
			{
				Spawner[] array = componentsInChildren;
				foreach (Spawner val3 in array)
				{
					if (val3.spawnSpots == null || val3.spawnSpots.Count == 0)
					{
						List<Transform> list = (from t in ((Component)val3).GetComponentsInChildren<Transform>(true)
							where ((Object)t).name.IndexOf("spawnspot", StringComparison.OrdinalIgnoreCase) >= 0 || ((Object)t).name.IndexOf("spawn_point", StringComparison.OrdinalIgnoreCase) >= 0 || ((Object)t).name.IndexOf("spawn", StringComparison.OrdinalIgnoreCase) >= 0
							select (t)).ToList();
						if (list.Count > 0)
						{
							val3.spawnSpots = list;
						}
					}
					SpawnMapping[] array2 = pack.spawnMappings ?? Array.Empty<SpawnMapping>();
					foreach (SpawnMapping mapping2 in array2)
					{
						Transform val4 = instGO.transform.Find(mapping2.spawnerMarker) ?? ((IEnumerable<Transform>)instGO.GetComponentsInChildren<Transform>(true)).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name.IndexOf(mapping2.spawnerMarker, StringComparison.OrdinalIgnoreCase) >= 0));
						if (!((Object)(object)val4 == (Object)null) && PatchedContent.SpawnableRegistry.Registry.TryGetValue(mapping2.spawnableName, out var value) && SpawnerResolveHelper.TryResolvePrefab(value, out GameObject resolvedPrefab) && (Object)(object)resolvedPrefab != (Object)null)
						{
							val3.spawnedObjectPrefab = resolvedPrefab;
							global::PEAKLevelLoader.PEAKLevelLoader.Logger.LogInfo((object)("Wired spawner '" + ((Object)val3).name + "' -> prefab '" + ((Object)resolvedPrefab).name + "'"));
						}
					}
					if ((!((Object)(object)val3.spawnedObjectPrefab == (Object)null) && !(((Object)val3.spawnedObjectPrefab).name == "null")) || pack == null)
					{
						continue;
					}
					SpawnMapping[] array3 = pack.spawnMappings ?? Array.Empty<SpawnMapping>();
					foreach (SpawnMapping mapping in array3)
					{
						Transform val5 = instGO.transform.Find(mapping.spawnerMarker) ?? ((IEnumerable<Transform>)instGO.GetComponentsInChildren<Transform>(true)).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name.IndexOf(mapping.spawnerMarker, StringComparison.OrdinalIgnoreCase) >= 0));
						if (!((Object)(object)val5 == (Object)null) && (val5.IsChildOf(((Component)val3).transform) || !((Object)(object)val5 != (Object)(object)((Component)val3).transform)) && PatchedContent.SpawnableRegistry.Registry.TryGetValue(mapping.spawnableName, out var value2))
						{
							GameObject val6 = AssetBundleGroupDebugger.BundleResolveHelper.ResolvePrefabFromLoadedGroups(value2.prefab);
							if ((Object)(object)val6 != (Object)null)
							{
								val3.spawnedObjectPrefab = val6;
								global::PEAKLevelLoader.PEAKLevelLoader.Logger.LogInfo((object)("Wired spawner '" + ((Object)val3).name + "' -> prefab '" + value2.prefab + "'"));
								break;
							}
						}
					}
				}
				return;
			}
			List<Transform> list2 = (from t in instGO.GetComponentsInChildren<Transform>(true)
				where ((Object)t).name.IndexOf("spawner", StringComparison.OrdinalIgnoreCase) >= 0 || ((Object)t).name.IndexOf("prop_spawner", StringComparison.OrdinalIgnoreCase) >= 0
				select t).ToList();
			foreach (Transform item in list2)
			{
				Spawner val7 = ((Component)item).gameObject.AddComponent<Spawner>();
				val7.spawnOnStart = true;
				List<Transform> spawnSpots = (from t in ((Component)item).GetComponentsInChildren<Transform>(true)
					where ((Object)t).name.IndexOf("spawnspot", StringComparison.OrdinalIgnoreCase) >= 0 || ((Object)t).name.IndexOf("spawn_point", StringComparison.OrdinalIgnoreCase) >= 0
					select (t)).ToList();
				val7.spawnSpots = spawnSpots;
			}
		}
		catch (Exception arg2)
		{
			global::PEAKLevelLoader.PEAKLevelLoader.Logger.LogWarning((object)$"RegisterSegmentContents: spawner registration failed for {pack.packName}: {arg2}");
		}
	}
}
public static class SpawnerResolveHelper
{
	public static string? GetPrefabNameFromEntry(object? entry)
	{
		if (entry == null)
		{
			return null;
		}
		Type type = entry.GetType();
		string[] array = new string[5] { "prefab", "prefabName", "PrefabName", "prefabPath", "path" };
		string[] array2 = array;
		foreach (string name in array2)
		{
			PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (property != null)
			{
				try
				{
					string text = property.GetValue(entry) as string;
					if (!string.IsNullOrEmpty(text))
					{
						return text;
					}
				}
				catch
				{
				}
			}
			FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (!(field != null))
			{
				continue;
			}
			try
			{
				string text2 = field.GetValue(entry) as string;
				if (!string.IsNullOrEmpty(text2))
				{
					return text2;
				}
			}
			catch
			{
			}
		}
		try
		{
			string text3 = entry.ToString();
			if (!string.IsNullOrEmpty(text3))
			{
				return text3;
			}
		}
		catch
		{
		}
		return null;
	}

	public static GameObject? ResolvePrefabFromRegistryEntry(object? entry)
	{
		string prefabNameFromEntry = GetPrefabNameFromEntry(entry);
		if (string.IsNullOrEmpty(prefabNameFromEntry))
		{
			return null;
		}
		try
		{
			return AssetBundleGroupDebugger.BundleResolveHelper.ResolvePrefabFromLoadedGroups(prefabNameFromEntry);
		}
		catch (Exception arg)
		{
			Debug.LogWarning((object)$"SpawnerResolveHelper.ResolvePrefabFromRegistryEntry: failed resolving '{prefabNameFromEntry}': {arg}");
			return null;
		}
	}

	public static bool TryResolvePrefab(object? registryEntry, out GameObject? resolvedPrefab)
	{
		resolvedPrefab = null;
		if (registryEntry == null)
		{
			return false;
		}
		if (registryEntry is string prefabName)
		{
			resolvedPrefab = AssetBundleGroupDebugger.BundleResolveHelper.ResolvePrefabFromLoadedGroups(prefabName);
			return (Object)(object)resolvedPrefab != (Object)null;
		}
		Type type = registryEntry.GetType();
		string[] array = new string[6] { "prefab", "prefabName", "Prefab", "PrefabName", "bundlePath", "path" };
		string[] array2 = array;
		foreach (string name in array2)
		{
			PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (property != null && property.PropertyType == typeof(string))
			{
				try
				{
					string text = property.GetValue(registryEntry) as string;
					if (!string.IsNullOrEmpty(text))
					{
						resolvedPrefab = AssetBundleGroupDebugger.BundleResolveHelper.ResolvePrefabFromLoadedGroups(text);
						if ((Object)(object)resolvedPrefab != (Object)null)
						{
							return true;
						}
					}
				}
				catch
				{
				}
			}
			FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (!(field != null) || !(field.FieldType == typeof(string)))
			{
				continue;
			}
			try
			{
				string text2 = field.GetValue(registryEntry) as string;
				if (!string.IsNullOrEmpty(text2))
				{
					resolvedPrefab = AssetBundleGroupDebugger.BundleResolveHelper.ResolvePrefabFromLoadedGroups(text2);
					if ((Object)(object)resolvedPrefab != (Object)null)
					{
						return true;
					}
				}
			}
			catch
			{
			}
		}
		try
		{
			string text3 = registryEntry.ToString() ?? "";
			string[] array3 = text3.Split(new char[3] { ':', '/', '\\' }, StringSplitOptions.RemoveEmptyEntries);
			if (array3.Length != 0)
			{
				string text4 = array3[^1];
				if (!string.IsNullOrEmpty(text4))
				{
					resolvedPrefab = AssetBundleGroupDebugger.BundleResolveHelper.ResolvePrefabFromLoadedGroups(text4);
					if ((Object)(object)resolvedPrefab != (Object)null)
					{
						return true;
					}
				}
			}
		}
		catch
		{
		}
		return false;
	}
}
public static class StringExtensions
{
	public static string ReplaceInvalidFileNameChars(this string s, char replaceWith = '_')
	{
		if (string.IsNullOrEmpty(s))
		{
			return s ?? string.Empty;
		}
		char[] invalidFileNameChars = Path.GetInvalidFileNameChars();
		char[] array = s.ToCharArray();
		for (int i = 0; i < array.Length; i++)
		{
			if (Array.IndexOf(invalidFileNameChars, array[i]) >= 0)
			{
				array[i] = replaceWith;
			}
		}
		return new string(array);
	}

	public static string SanitizeJson(string txt)
	{
		if (string.IsNullOrEmpty(txt))
		{
			return txt;
		}
		txt = txt.TrimStart('\ufeff', '\u200b', '\u200e', '\u200f', '\0');
		int i;
		for (i = 0; i < txt.Length && char.IsControl(txt[i]) && txt[i] != '\r' && txt[i] != '\n' && txt[i] != '\t'; i++)
		{
		}
		if (i > 0)
		{
			txt = txt.Substring(i);
		}
		return txt;
	}

	public static string ExtractTopLevelArray(string json, string key)
	{
		if (string.IsNullOrEmpty(json))
		{
			return string.Empty;
		}
		int num = json.IndexOf("\"" + key + "\"", StringComparison.OrdinalIgnoreCase);
		if (num < 0)
		{
			return string.Empty;
		}
		int num2 = json.IndexOf('[', num);
		if (num2 < 0)
		{
			return string.Empty;
		}
		int num3 = 0;
		for (int i = num2; i < json.Length; i++)
		{
			if (json[i] == '[')
			{
				num3++;
			}
			else if (json[i] == ']')
			{
				num3--;
			}
			if (num3 == 0)
			{
				return json.Substring(num2, i - num2 + 1);
			}
		}
		return string.Empty;
	}

	public static List<string> SplitTopLevelObjects(string arrayText)
	{
		List<string> list = new List<string>();
		if (string.IsNullOrWhiteSpace(arrayText))
		{
			return list;
		}
		int i;
		for (i = 0; i < arrayText.Length && arrayText[i] != '['; i++)
		{
		}
		if (i >= arrayText.Length)
		{
			return list;
		}
		i++;
		while (i < arrayText.Length)
		{
			for (; i < arrayText.Length && (char.IsWhiteSpace(arrayText[i]) || arrayText[i] == ','); i++)
			{
			}
			if (i >= arrayText.Length || arrayText[i] != '{')
			{
				break;
			}
			int num = i;
			int num2 = 0;
			for (; i < arrayText.Length; i++)
			{
				if (arrayText[i] == '{')
				{
					num2++;
				}
				else if (arrayText[i] == '}')
				{
					num2--;
				}
				if (num2 == 0)
				{
					i++;
					break;
				}
			}
			if (num2 != 0)
			{
				break;
			}
			list.Add(arrayText.Substring(num, i - num));
		}
		return list;
	}
}
public static class FogOriginRegistrar
{
	private static FieldInfo _originsField;

	private static Type _orbFogHandlerType;

	static FogOriginRegistrar()
	{
		_orbFogHandlerType = typeof(OrbFogHandler);
		_originsField = _orbFogHandlerType.GetField("origins", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
	}

	public static void InsertOriginAtIndex(FogSphereOrigin origin, int idx)
	{
		if ((Object)(object)origin == (Object)null)
		{
			return;
		}
		try
		{
			OrbFogHandler instance = Singleton<OrbFogHandler>.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				Debug.LogWarning((object)"FogOriginRegistrar: OrbFogHandler.Instance is null; cannot register fog origin now.");
				return;
			}
			if (_originsField == null)
			{
				Debug.LogWarning((object)"FogOriginRegistrar: couldn't find 'origins' field on OrbFogHandler via reflection.");
				return;
			}
			FogSphereOrigin[] source = (_originsField.GetValue(instance) as FogSphereOrigin[]) ?? Array.Empty<FogSphereOrigin>();
			List<FogSphereOrigin> list = source.ToList();
			if (idx < 0 || idx > list.Count)
			{
				idx = list.Count;
			}
			list.Insert(idx, origin);
			FogSphereOrigin[] array = list.ToArray();
			_originsField.SetValue(instance, array);
			MethodInfo method = _orbFogHandlerType.GetMethod("InitNewSphere", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (method != null)
			{
				FieldInfo field = _orbFogHandlerType.GetField("currentID", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				int num = ((field != null) ? ((int)field.GetValue(instance)) : 0);
				if (num >= 0 && num < array.Length)
				{
					method.Invoke(instance, new object[1] { array[num] });
				}
			}
			Debug.Log((object)$"FogOriginRegistrar: inserted origin at index {idx}. total origins now = {array.Length}");
		}
		catch (Exception ex)
		{
			Debug.LogWarning((object)("FogOriginRegistrar failed: " + ex));
		}
	}
}
public static class PlaceholderProcessor
{
	public class FogSphereOriginProxy : MonoBehaviour
	{
		public float size = 650f;

		public bool disableFog;

		public float moveOnHeight;

		public float moveOnForward;
	}

	public class ModLuggageMarker : MonoBehaviour
	{
		public string? packName;
	}

	private static readonly string[] LuggageTypeNames = new string[6] { "Luggage", "LuggageItem", "LuggageController", "Item", "Pickup", "LuggageBehaviour" };

	private static readonly string[] FogOriginTypeNames = new string[1] { "FogSphereOrigin" };

	private static readonly string[] CampfireTypeNames = new string[1] { "Campfire" };

	public static void ProcessPlaceholdersSync(GameObject instGO, LevelPack pack, object mapSegObj, int insertionIndex)
	{
		if ((Object)(object)instGO == (Object)null || pack == null)
		{
			return;
		}
		try
		{
			Placeholder[] array = instGO.GetComponentsInChildren<Placeholder>(true) ?? Array.Empty<Placeholder>();
			Placeholder[] array2 = array;
			foreach (Placeholder placeholder in array2)
			{
				try
				{
					HandleSinglePlaceholder(((Component)placeholder).gameObject, placeholder, pack, mapSegObj, insertionIndex);
				}
				catch (Exception arg)
				{
					global::PEAKLevelLoader.PEAKLevelLoader.Logger.LogWarning((object)$"PlaceholderProcessor: failed processing placeholder '{((Object)placeholder).name}': {arg}");
				}
			}
			Transform[] array3 = (from t in instGO.GetComponentsInChildren<Transform>(true)
				where ((Object)t).name.IndexOf("fogorigin", StringComparison.OrdinalIgnoreCase) >= 0 || ((Object)t).name.IndexOf("fog_origin", StringComparison.OrdinalIgnoreCase) >= 0
				select t).ToArray();
			Transform[] array4 = array3;
			foreach (Transform val in array4)
			{
				try
				{
					HandleFogOriginGameObject(((Component)val).gameObject, pack, insertionIndex);
				}
				catch (Exception arg2)
				{
					global::PEAKLevelLoader.PEAKLevelLoader.Logger.LogWarning((object)$"PlaceholderProcessor: FogOrigin handle failed for {((Object)val).name}: {arg2}");
				}
			}
			GameObject[] array5 = (from t in instGO.GetComponentsInChildren<Transform>(true)
				where ((Object)t).name.IndexOf("luggage_", StringComparison.OrdinalIgnoreCase) >= 0 || ((Object)t).name.IndexOf("luggage", StringComparison.OrdinalIgnoreCase) >= 0
				select ((Component)t).gameObject).ToArray();
			GameObject[] array6 = array5;
			foreach (GameObject val2 in array6)
			{
				try
				{
					HandleLuggageGameObject(val2, pack);
				}
				catch (Exception arg3)
				{
					global::PEAKLevelLoader.PEAKLevelLoader.Logger.LogWarning((object)$"PlaceholderProcessor: Luggage handle failed for {((Object)val2).name}: {arg3}");
				}
			}
		}
		catch (Exception arg4)
		{
			global::PEAKLevelLoader.PEAKLevelLoader.Logger.LogError((object)$"PlaceholderProcessor: top-level failure: {arg4}");
		}
	}

	private static void HandleSinglePlaceholder(GameObject placeholderGO, Placeholder ph, LevelPack pack, object mapSegObj, int insertionIndex)
	{
		//IL_00fd: 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_014e: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)placeholderGO == (Object)null)
		{
			return;
		}
		string text = (ph.role ?? "").Trim().ToLowerInvariant();
		string text2 = (ph.spawnableName ?? "").Trim();
		if (!string.IsNullOrEmpty(text))
		{
			switch (text)
			{
			case "fogorigin":
			case "fog_origin":
			case "fog":
				HandleFogOriginGameObject(placeholderGO, pack, insertionIndex, ph);
				return;
			}
			if (text.Contains("luggage") || text.Contains("bag") || text.Contains("suitcase"))
			{
				HandleLuggageGameObject(placeholderGO, pack, ph);
				return;
			}
			if (text.Contains("campfire"))
			{
				EnsureRuntimeCampfire(placeholderGO, pack);
				return;
			}
		}
		if (!string.IsNullOrEmpty(text2))
		{
			GameObject val = null;
			if (PatchedContent.SpawnableRegistry.Registry.TryGetValue(text2, out var value))
			{
				try
				{
					if (SpawnerResolveHelper.TryResolvePrefab(value, out GameObject resolvedPrefab) && (Object)(object)resolvedPrefab != (Object)null)
					{
						GameObject val2 = Object.Instantiate<GameObject>(val, placeholderGO.transform.position, placeholderGO.transform.rotation, placeholderGO.transform.parent);
						((Object)val2).name = "ModSpawn_" + pack.packName + "_" + ((Object)val).name;
						val2.transform.localScale = placeholderGO.transform.localScale;
						Object.DestroyImmediate((Object)(object)placeholderGO);
						if (text2.IndexOf("luggage", StringComparison.OrdinalIgnoreCase) >= 0)
						{
							EnsureLuggageBehaviour(val2, pack);
						}
						return;
					}
				}
				catch (Exception arg)
				{
					global::PEAKLevelLoader.PEAKLevelLoader.Logger.LogWarning((object)$"PlaceholderProcessor: SpawnableResolver invocation failed: {arg}");
				}
			}
		}
		if (placeholderGO.transform.childCount > 0)
		{
			GameObject val3 = Object.Instantiate<GameObject>(placeholderGO, placeholderGO.transform.parent);
			((Object)val3).name = "ModProp_" + pack.packName + "_" + ((Object)placeholderGO).name;
			if (((Object)placeholderGO).name.IndexOf("luggage", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				EnsureLuggageBehaviour(val3, pack);
			}
			Object.DestroyImmediate((Object)(object)placeholderGO);
		}
	}

	private static void HandleFogOriginGameObject(GameObject fogGO, LevelPack pack, int insertionIndex, Placeholder ph = null)
	{
		//IL_016f: Unknown result type (might be due to invalid IL or missing references)
		//IL_017a: Expected O, but got Unknown
		if ((Object)(object)fogGO == (Object)null)
		{
			return;
		}
		Type type = FindTypeInLoadedAssembliesByName(FogOriginTypeNames);
		if (type == null)
		{
			global::PEAKLevelLoader.PEAKLevelLoader.Logger.LogInfo((object)"PlaceholderProcessor: FogSphereOrigin type not found at runtime (will create plain GameObject and register).");
		}
		object obj = null;
		if (type != null)
		{
			Component component = fogGO.GetComponent(type);
			if ((Object)(object)component != (Object)null)
			{
				obj = component;
			}
			else
			{
				try
				{
					obj = fogGO.AddComponent(type);
				}
				catch (Exception arg)
				{
					global::PEAKLevelLoader.PEAKLevelLoader.Logger.LogWarning((object)$"PlaceholderProcessor: Failed to AddComponent({type.Name}) on {((Object)fogGO).name}: {arg}");
					obj = null;
				}
			}
		}
		else
		{
			FogSphereOriginProxy fogSphereOriginProxy = fogGO.GetComponent<FogSphereOriginProxy>() ?? fogGO.AddComponent<FogSphereOriginProxy>();
			obj = fogSphereOriginProxy;
		}
		float num = 650f;
		bool flag = false;
		float num2 = 0f;
		float num3 = 0f;
		try
		{
			if ((Object)(object)ph != (Object)null && !string.IsNullOrEmpty(ph.options))
			{
				Dictionary<string, string> dict = ParseOptionsString(ph.options);
				num = TryParseFloatFromDict(dict, "size", num);
				flag = TryParseBoolFromDict(dict, "disableFog", flag);
				num2 = TryParseFloatFromDict(dict, "moveOnHeight", num2);
				num3 = TryParseFloatFromDict(dict, "moveOnForward", num3);
			}
		}
		catch
		{
		}
		if (obj != null)
		{
			TrySetFieldOrProperty(obj, "size", num);
			TrySetFieldOrProperty(obj, "disableFog", flag);
			TrySetFieldOrProperty(obj, "moveOnHeight", num2);
			TrySetFieldOrProperty(obj, "moveOnForward", num3);
			TrySetFieldOrProperty(obj, "moveOnForward", num3);
		}
		try
		{
			FogOriginRegistrar.InsertOriginAtIndex((FogSphereOrigin)obj, insertionIndex);
			global::PEAKLevelLoader.PEAKLevelLoader.Logger.LogInfo((object)$"PlaceholderProcessor: Registered fog origin '{((Object)fogGO).name}' at index {insertionIndex} for pack {pack.packName}");
		}
		catch (Exception arg2)
		{
			global::PEAKLevelLoader.PEAKLevelLoader.Logger.LogWarning((object)$"PlaceholderProcessor: failed to register fog origin: {arg2}");
		}
	}

	private static void HandleLuggageGameObject(GameObject luggageGO, LevelPack pack, Placeholder ph = null)
	{
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: 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_005b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: 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)
		if ((Object)(object)luggageGO == (Object)null)
		{
			return;
		}
		string name = ((Object)luggageGO).name;
		string registryEntry = name;
		GameObject val = null;
		try
		{
			if (SpawnerResolveHelper.TryResolvePrefab(registryEntry, out GameObject resolvedPrefab) && (Object)(object)resolvedPrefab != (Object)null)
			{
				Transform parent = luggageGO.transform.parent;
				Vector3 position = luggageGO.transform.position;
				Quaternion rotation = luggageGO.transform.rotation;
				Vector3 localScale = luggageGO.transform.localScale;
				GameObject val2 = Object.Instantiate<GameObject>(val, position, rotation, parent);
				val2.transform.localScale = localScale;
				((Object)val2).name = "ModLuggage_" + pack.packName + "_" + ((Object)val).name;
				Object.DestroyImmediate((Object)(object)luggageGO);
				EnsureLuggageBehaviour(val2, pack);
				return;
			}
		}
		catch
		{
		}
		EnsureLuggageBehaviour(luggageGO, pack);
	}

	private static void EnsureRuntimeCampfire(GameObject campfireGO, LevelPack pack)
	{
		if ((Object)(object)campfireGO == (Object)null)
		{
			return;
		}
		Type type = FindTypeInLoadedAssembliesByName(CampfireTypeNames);
		if (type == null)
		{
			global::PEAKLevelLoader.PEAKLevelLoader.Logger.LogInfo((object)("PlaceholderProcessor: Campfire runtime type not found — leaving visual '" + ((Object)campfireGO).name + "' as-is."));
			return;
		}
		Component component = campfireGO.GetComponent(type);
		if (!((Object)(object)component == (Object)null))
		{
			return;
		}
		try
		{
			component = campfireGO.AddComponent(type);
			TrySetFieldOrProperty(component, "burnsFor", 180f);
			global::PEAKLevelLoader.PEAKLevelLoader.Logger.LogInfo((object)("PlaceholderProcessor: attached runtime Campfire component to '" + ((Object)campfireGO).name + "'"));
		}
		catch (Exception arg)
		{
			global::PEAKLevelLoader.PEAKLevelLoader.Logger.LogWarning((object)$"PlaceholderProcessor: failed to add Campfire component to {((Object)campfireGO).name}: {arg}");
		}
	}

	private static void EnsureLuggageBehaviour(GameObject go, LevelPack pack)
	{
		if ((Object)(object)go == (Object)null)
		{
			return;
		}
		Type type = FindTypeInLoadedAssembliesByName(LuggageTypeNames);
		if (type != null)
		{
			try
			{
				Component component = go.GetComponent(type);
				if ((Object)(object)component == (Object)null)
				{
					Component target = go.AddComponent(type);
					TrySetFieldOrProperty(target, "nameOverride", ((Object)go).name);
					TrySetFieldOrProperty(target, "disableFogFakeMountain", false);
				}
				global::PEAKLevelLoader.PEAKLevelLoader.Logger.LogInfo((object)("PlaceholderProcessor: attached luggage-like component (" + type.Name + ") to '" + ((Object)go).name + "'"));
			}
			catch (Exception arg)
			{
				global::PEAKLevelLoader.PEAKLevelLoader.Logger.LogWarning((object)$"PlaceholderProcessor: error attaching luggage type: {arg}");
			}
		}
		else
		{
			ModLuggageMarker modLuggageMarker = go.GetComponent<ModLuggageMarker>() ?? go.AddComponent<ModLuggageMarker>();
			modLuggageMarker.packName = pack?.packName ?? "<unknown>";
			global::PEAKLevelLoader.PEAKLevelLoader.Logger.LogInfo((object)("PlaceholderProcessor: added ModLuggageMarker to '" + ((Object)go).name + "' (no runtime luggage type found)."));
		}
		Type type2 = FindTypeInLoadedAssembliesByName("Photon.Pun.PhotonView", "PhotonView");
		if (!(type2 != null))
		{
			return;
		}
		try
		{
			if ((Object)(object)go.GetComponent(type2) == (Object)null)
			{
				go.AddComponent(type2);
				global::PEAKLevelLoader.PEAKLevelLoader.Logger.LogInfo((object)("PlaceholderProcessor: added PhotonView to '" + ((Object)go).name + "' for networking."));
			}
		}
		catch
		{
		}
	}

	private static Type? FindTypeInLoadedAssembliesByName(params string[] typeNameCandidates)
	{
		foreach (string text in typeNameCandidates)
		{
			Type type = FindTypeInLoadedAssembliesByName(text);
			if (type != null)
			{
				return type;
			}
		}
		return null;
	}

	private static Type? FindTypeInLoadedAssembliesByName(IEnumerable<string> candidates)
	{
		string[] source = candidates.ToArray();
		Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
		Assembly[] array = assemblies;
		foreach (Assembly assembly in array)
		{
			Type[] types;
			try
			{
				types = assembly.GetTypes();
			}
			catch
			{
				continue;
			}
			Type[] array2 = types;
			foreach (Type t in array2)
			{
				if (source.Any((string c) => string.Equals(t.Name, c, StringComparison.OrdinalIgnoreCase) || string.Equals(t.FullName, c, StringComparison.OrdinalIgnoreCase)))
				{
					return t;
				}
			}
		}
		return null;
	}

	private static void TrySetFieldOrProperty(object target, string name, object val)
	{
		if (target == null)
		{
			return;
		}
		Type type = target.GetType();
		FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		if (field != null)
		{
			try
			{
				field.SetValue(target, ConvertToType(val, field.FieldType));
				return;
			}
			catch
			{
			}
		}
		PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		if (!(property != null) || !property.CanWrite)
		{
			return;
		}
		try
		{
			property.SetValue(target, ConvertToType(val, property.PropertyType));
		}
		catch
		{
		}
	}

	private static object ConvertToType(object val, Type targetType)
	{
		if (val == null)
		{
			return null;
		}
		try
		{
			if (targetType.IsAssignableFrom(val.GetType()))
			{
				return val;
			}
			if (targetType.IsEnum)
			{
				if (val is string value)
				{
					return Enum.Parse(targetType, value, ignoreCase: true);
				}
				return Enum.ToObject(targetType, val);
			}
			return Convert.ChangeType(val, targetType);
		}
		catch
		{
			return val;
		}
	}

	private static Dictionary<string, string> ParseOptionsString(string raw)
	{
		Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
		if (string.IsNullOrEmpty(raw))
		{
			return dictionary;
		}
		string[] array = raw.Split(new char[3] { '\n', ';', '\r' }, StringSplitOptions.RemoveEmptyEntries);
		string[] array2 = array;
		foreach (string text in array2)
		{
			string[] array3 = text.Split(new char[1] { '=' }, 2);
			if (array3.Length == 2)
			{
				dictionary[array3[0].Trim()] = array3[1].Trim();
			}
		}
		return dictionary;
	}

	private static float TryParseFloatFromDict(Dictionary<string, string> dict, string key, float fallback)
	{
		if (dict.TryGetValue(key, out string value) && float.TryParse(value, out var result))
		{
			return result;
		}
		return fallback;
	}

	private static bool TryParseBoolFromDict(Dictionary<string, string> dict, string key, bool fallback)
	{
		if (dict.TryGetValue(key, out string value) && bool.TryParse(value, out var result))
		{
			return result;
		}
		return fallback;
	}
}
namespace PEAKLevelLoader
{
	public static class PEAKBundleManager
	{
		public enum ModProcessingStatus
		{
			Inactive,
			Loading,
			Complete
		}

		public static ModProcessingStatus CurrentStatus { get; internal set; }

		public static bool HasFinalisedFoundContent { get; internal set; }

		public static event Action? OnFinishedProcessing;

		internal static void Start()
		{
			PEAKLevelLoader.Logger.LogInfo((object)"PEAKBundleManager: Starting!");
			TryLoadPEAKBundles();
		}

		private static bool TryLoadPEAKBundles()
		{
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			PEAKLevelLoader.Logger.LogInfo((object)"PEAKBundleManager: Now scanning entire BepInEx plugins directory for .pll files...");
			List<string> list = new List<string>();
			try
			{
				string pluginPath = Paths.PluginPath;
				if (Directory.Exists(pluginPath))
				{
					list.Add(pluginPath);
				}
				else
				{
					PEAKLevelLoader.Logger.LogWarning((object)("PEAKBundleManager: Plugins root not found: " + pluginPath));
				}
				string text = Path.Combine(Path.GetTempPath(), "PEAKLevelLoader_embedded");
				if (!Directory.Exists(text))
				{
					Directory.CreateDirectory(text);
				}
				foreach (KeyValuePair<string, PluginInfo> pluginInfo in Chainloader.PluginInfos)
				{
					try
					{
						PluginInfo value = pluginInfo.Value;
						if (value == null)
						{
							continue;
						}
						Assembly assembly = null;
						if ((Object)(object)value.Instance != (Object)null)
						{
							assembly = ((object)value.Instance).GetType().Assembly;
							goto IL_0381;
						}
						if (!string.IsNullOrEmpty(value.Location))
						{
							try
							{
								string directoryName = Path.GetDirectoryName(value.Location);
								if (!string.IsNullOrEmpty(directoryName) && Directory.Exists(directoryName))
								{
									foreach (string item in Directory.EnumerateFiles(directoryName, "*.pll", SearchOption.TopDirectoryOnly))
									{
										if (!list.Contains(directoryName))
										{
											list.Add(directoryName);
										}
									}
								}
							}
							catch (Exception arg)
							{
								PEAKLevelLoader.Logger.LogWarning((object)$"PEAKBundleManager: failed scanning plugin folder for on-disk bundles: {arg}");
							}
						}
						if (!PEAKLevelLoader.AllowEmbeddedBundles)
						{
							ManualLogSource logger = PEAKLevelLoader.Logger;
							BepInPlugin metadata = value.Metadata;
							logger.LogDebug((object)("PEAKBundleManager: plugin " + (((metadata != null) ? metadata.GUID : null) ?? value.Location) + " not loaded into domain; skipping manifest resource extraction."));
							continue;
						}
						try
						{
							Type type = Type.GetType("Mono.Cecil.AssemblyDefinition, Mono.Cecil");
							if (type == null)
							{
								PEAKLevelLoader.Logger.LogInfo((object)"PEAKBundleManager: Mono.Cecil not available. Skipping embedded resource extraction for unloaded plugin.");
							}
							else if (!string.IsNullOrEmpty(value.Location) && File.Exists(value.Location))
							{
								try
								{
									AssemblyDefinition val = AssemblyDefinition.ReadAssembly(value.Location);
									Enumerator<Resource> enumerator3 = val.MainModule.Resources.GetEnumerator();
									try
									{
										while (enumerator3.MoveNext())
										{
											Resource current3 = enumerator3.Current;
											EmbeddedResource val2 = (EmbeddedResource)(object)((current3 is EmbeddedResource) ? current3 : null);
											if (val2 == null || !((Resource)val2).Name.EndsWith(".pll", StringComparison.OrdinalIgnoreCase))
											{
												continue;
											}
											try
											{
												using Stream stream = val2.GetResourceStream();
												if (stream != null)
												{
													BepInPlugin metadata2 = value.Metadata;
													string path = (((metadata2 != null) ? metadata2.GUID : null) ?? value.Location?.GetHashCode().ToString() ?? "plugin").ReplaceInvalidFileNameChars();
													string text2 = Path.Combine(text, path);
													if (!Directory.Exists(text2))
													{
														Directory.CreateDirectory(text2);
													}
													string path2 = Path.Combine(text2, Path.GetFileName(((Resource)val2).Name));
													using (FileStream destination = File.Create(path2))
													{
														stream.CopyTo(destination);
													}
													if (!list.Contains(text2))
													{
														list.Add(text2);
													}
												}
											}
											catch (Exception arg2)
											{
												PEAKLevelLoader.Logger.LogWarning((object)$"PEAKBundleManager: Failed to extract embedded resource '{current3.Name}' from plugin '{value.Location}': {arg2}");
											}
										}
									}
									finally
									{
										((IDisposable)enumerator3).Dispose();
									}
								}
								catch (Exception arg3)
								{
									PEAKLevelLoader.Logger.LogWarning((object)$"PEAKBundleManager: Mono.Cecil extraction failed for {value.Location}: {arg3}");
								}
							}
						}
						catch (Exception arg4)
						{
							PEAKLevelLoader.Logger.LogWarning((object)$"PEAKBundleManager: error checking for Mono.Cecil: {arg4}");
						}
						goto IL_0381;
						IL_0381:
						if (assembly == null)
						{
							continue;
						}
						string[] manifestResourceNames = assembly.GetManifestResourceNames();
						foreach (string text3 in manifestResourceNames)
						{
							if (!text3.EndsWith(".pll", StringComparison.OrdinalIgnoreCase))
							{
								continue;
							}
							try
							{
								using Stream stream2 = assembly.GetManifestResourceStream(text3);
								if (stream2 != null)
								{
									BepInPlugin metadata3 = value.Metadata;
									string path3 = (((metadata3 != null) ? metadata3.GUID : null) ?? value.Location?.GetHashCode().ToString() ?? "plugin").ReplaceInvalidFileNameChars();
									string text4 = Path.Combine(text, path3);
									if (!Directory.Exists(text4))
									{
										Directory.CreateDirectory(text4);
									}
									string path4 = Path.Combine(text4, Path.GetFileName(text3));
									using (FileStream destination2 = File.Create(path4))
									{
										stream2.CopyTo(destination2);
									}
									if (!list.Contains(text4))
									{
										list.Add(text4);
									}
								}
							}
							catch (Exception arg5)
							{
								PEAKLevelLoader.Logger.LogWarning((object)$"PEAKBundleManager: Failed to extract embedded resource '{text3}' from plugin '{value.Location}': {arg5}");
							}
						}
					}
					catch (Exception arg6)
					{
						PEAKLevelLoader.Logger.LogWarning((object)$"PEAKBundleManager: Failed inspecting plugin for embedded bundles: {arg6}");
					}
				}
			}
			catch (Exception arg7)
			{
				PEAKLevelLoader.Logger.LogError((object)$"PEAKBundleManager: Exception gathering folders to scan: {arg7}");
			}
			if (list.Count == 0)
			{
				PEAKLevelLoader.Logger.LogInfo((object)"PEAKBundleManager: No plugin folders found to scan for .pll files.");
				return false;
			}
			ParameterEvent<AssetBundleGroup> parameterEvent = new ParameterEvent<AssetBundleGroup>();
			parameterEvent.AddListener(OnAssetBundleGroupCreated);
			bool flag = AssetBundleLoader.LoadAllBundlesRequest(null, "*", ".pll", parameterEvent, list);
			if (flag)
			{
				PEAKLevelLoader.Logger.LogInfo((object)$"PEAKBundleManager: Initiated load request — scanning {list.Count} folder(s).");
				AssetBundleLoader.OnBundlesFinishedProcessing.AddListener(OnAssetBundleLoadRequestFinished);
			}
			else
			{
				PEAKLevelLoader.Logger.LogWarning((object)"PEAKBundleManager: LoadAllBundlesRequest returned false (no bundles found).");
			}
			return flag;
		}

		private static void OnAssetBundleGroupCreated(AssetBundleGroup group)
		{
			try
			{
				List<string> sceneNames = group.GetSceneNames();
				foreach (string item in sceneNames)
				{
					if (!PatchedContent.AllLevelSceneNames.Contains(item))
					{
						PatchedContent.AllLevelSceneNames.Add(item);
					}
				}
				List<TextAsset> list = group.LoadAllAssets<TextAsset>();
				TextAsset val = null;
				foreach (TextAsset item2 in list)
				{
					if (!((Object)(object)item2 == (Object)null) && ((Object)item2).name.Equals("mod.json", StringComparison.OrdinalIgnoreCase))
					{
						val = item2;
						break;
					}
				}
				try
				{
					List<ExtendedMod> list2 = new List<ExtendedMod>();
					try
					{
						List<ExtendedMod> list3 = group.LoadAllAssets<ExtendedMod>();
						if (list3 != null && list3.Count > 0)
						{
							foreach (ExtendedMod item3 in list3)
							{
								if ((Object)(object)item3 != (Object)null)
								{
									list2.Add(item3);
								}
							}
						}
					}
					catch
					{
					}
					List<ExtendedSegment> list4 = new List<ExtendedSegment>();
					try
					{
						List<ExtendedSegment> list5 = group.LoadAllAssets<ExtendedSegment>();
						if (list5 != null && list5.Count > 0)
						{
							foreach (ExtendedSegment item4 in list5)
							{
								if ((Object)(object)item4 != (Object)null)
								{
									list4.Add(item4);
								}
							}
						}
					}
					catch
					{
					}
					if (list2.Count > 0 || list4.Count > 0)
					{
						foreach (ExtendedMod item5 in list2)
						{
							string key = item5.ModName ?? group.GroupName ?? "mod";
							if (!PatchedContent.ModDefinedTags.ContainsKey(key))
							{
								PatchedContent.ModDefinedTags[key] = new List<ContentTag>();
							}
							foreach (ExtendedContent extendedContent in item5.ExtendedContents)
							{
								if (extendedContent is ExtendedSegment extendedSegment)
								{
									LevelPack levelPack = new LevelPack
									{
										index = extendedSegment.index,
										replace = extendedSegment.replace,
										isVariant = extendedSegment.isVariant,
										biome = (extendedSegment.biome ?? string.Empty),
										bundlePath = group.GroupName,
										prefabName = (extendedSegment.prefabName ?? string.Empty),
										campfirePrefabName = (extendedSegment.campfirePrefabName ?? string.Empty),
										packName = (extendedSegment.packName ?? ((Object)extendedSegment).name ?? Guid.NewGuid().ToString()),
										id = (extendedSegment.id ?? Guid.NewGuid().ToString()),
										spawnMappings = (extendedSegment.ResolvedSpawnables?.Select(delegate(KeyValuePair<string, GameObject> kv)
										{
											SpawnMapping obj3 = new SpawnMapping
											{
												spawnerMarker = kv.Key
											};
											GameObject value = kv.Value;
											obj3.spawnableName = ((value != null) ? ((Object)value).name : null) ?? "";
											return obj3;
										}).ToArray() ?? Array.Empty<SpawnMapping>())
									};
									if ((Object)(object)PEAKLevelLoader.Instance != (Object)null)
									{
										PEAKLevelLoader.Instance.AddPacks(new LevelPackCollection
										{
											packs = new LevelPack[1] { levelPack }
										});
										PEAKLevelLoader.Logger.LogInfo((object)("PEAKBundleManager: registered ExtendedSegment " + levelPack.packName + " from group " + group.GroupName));
									}
								}
							}
							PatchedContent.ExtendedMods.Add(item5);
							ContentTagManager.MergeExtendedModTags(item5);
						}
						{
							foreach (ExtendedSegment item6 in list4)
							{
								LevelPack levelPack2 = new LevelPack
								{
									index = item6.index,
									replace = item6.replace,
									isVariant = item6.isVariant,
									biome = (item6.biome ?? string.Empty),
									bundlePath = group.GroupName,
									prefabName = (item6.prefabName ?? string.Empty),
									campfirePrefabName = (item6.campfirePrefabName ?? string.Empty),
									packName = (item6.packName ?? ((Object)item6).name ?? Guid.NewGuid().ToString()),
									id = (item6.id ?? Guid.NewGuid().ToString())
								};
								if ((Object)(object)PEAKLevelLoader.Instance != (Object)null)
								{
									PEAKLevelLoader.Instance.AddPacks(new LevelPackCollection
									{
										packs = new LevelPack[1] { levelPack2 }
									});
								}
								PEAKLevelLoader.Logger.LogInfo((object)("PEAKBundleManager: registered ExtendedSegment " + levelPack2.packName + " from group " + group.GroupName));
							}
							return;
						}
					}
				}
				catch (Exception arg)
				{
					PEAKLevelLoader.Logger.LogWarning((object)$"PEAKBundleManager: extended asset manifest load attempt failed for {group.GroupName}: {arg}");
				}
				if ((Object)(object)val == (Object)null)
				{
					foreach (TextAsset item7 in list)
					{
						if (!((Object)(object)item7 == (Object)null) && !string.IsNullOrWhiteSpace(item7.text))
						{
							string text = item7.text?.Trim();
							if (!string.IsNullOrEmpty(text) && text.StartsWith("{") && text.Contains("modName"))
							{
								val = item7;
								break;
							}
						}
					}
				}
				if ((Object)(object)val != (Object)null)
				{
					try
					{
						string text2 = StringExtensions.SanitizeJson(val.text);
						ModJson modJson = JsonUtility.FromJson<ModJson>(text2) ?? new ModJson();
						ModJsonSegment[] array = modJson.segments ?? Array.Empty<ModJsonSegment>();
						if (array.Length == 0 && text2.IndexOf("\"segments\"", StringComparison.OrdinalIgnoreCase) >= 0)
						{
							PEAKLevelLoader.Logger.LogInfo((object)("PEAKBundleManager: raw JSON contains 'segments' substring? True - attempting manual extraction for group " + group.GroupName + "."));
							string text3 = StringExtensions.ExtractTopLevelArray(text2, "segments");
							if (!string.IsNullOrEmpty(text3))
							{
								List<string> list6 = StringExtensions.SplitTopLevelObjects(text3);
								List<ModJsonSegment> list7 = new List<ModJsonSegment>();
								for (int i = 0; i < list6.Count; i++)
								{
									try
									{
										ModJsonSegment modJsonSegment = JsonUtility.FromJson<ModJsonSegment>(list6[i]);
										if (modJsonSegment != null)
										{
											list7.Add(modJsonSegment);
										}
									}
									catch (Exception arg2)
									{
										PEAKLevelLoader.Logger.LogWarning((object)$"PEAKBundleManager: manual parse failed for object {i} in group {group.GroupName}: {arg2}");
									}
								}
								if (list7.Count > 0)
								{
									array = (modJson.segments = list7.ToArray());
									PEAKLevelLoader.Logger.LogInfo((object)$"PEAKBundleManager: manual fallback parsed segments length = {array.Length} for group {group.GroupName}.");
								}
								else
								{
									PEAKLevelLoader.Logger.LogInfo((object)("PEAKBundleManager: manual fallback found array but parsed 0 segment objects for group " + group.GroupName + "."));
								}
							}
							else
							{
								PEAKLevelLoader.Logger.LogInfo((object)("PEAKBundleManager: ExtractTopLevelArray didn't find a 'segments' array for group " + group.GroupName + "."));
							}
						}
						if (modJson.segments != null && modJson.segments.Length != 0 && !string.IsNullOrEmpty(modJson.modName))
						{
							if (string.IsNullOrWhiteSpace(modJson.version))
							{
								PEAKLevelLoader.Logger.LogError((object)"PEAKBundleManager: The compatiblity version is not defined, please define the version entry...\nAdditionally, the version check will be added later.");
							}
							PEAKLevelLoader.Logger.LogInfo((object)("PEAKBundleManager: Parsed mod.json from " + group.GroupName + ": " + modJson.modName));
							ExtendedMod extendedMod = ExtendedMod.CreateNewMod(modJson.modName, modJson.author ?? "Unknown", modJson.version);
							Dictionary<string, ContentTag> dictionary = new Dictionary<string, ContentTag>(StringComparer.OrdinalIgnoreCase);
							if (modJson.contentTags != null)
							{
								string[] contentTags = modJson.contentTags;
								foreach (string text4 in contentTags)
								{
									if (!string.IsNullOrEmpty(text4) && !dictionary.ContainsKey(text4))
									{
										dictionary[text4] = ContentTag.Create(text4);
									}
								}
							}
							if (modJson.spawnables != null)
							{
								ModJsonSpawnable[] spawnables = modJson.spawnables;
								foreach (ModJsonSpawnable modJsonSpawnable in spawnables)
								{
									if (!string.IsNullOrEmpty(modJsonSpawnable.name) && !string.IsNullOrEmpty(modJsonSpawnable.prefabName))
									{
										string text5 = ((!string.IsNullOrEmpty(modJsonSpawnable.bundlePath)) ? modJsonSpawnable.bundlePath : (group.GroupName ?? modJson.modName ?? "unknown"));
										PatchedContent.SpawnableRegistry.Registry[modJsonSpawnable.name] = new PatchedContent.SpawnableEntry(text5, modJsonSpawnable.prefabName);
										PEAKLevelLoader.Logger.LogInfo((object)("Spawnable registered: '" + modJsonSpawnable.name + "' -> " + text5 + "::" + modJsonSpawnable.prefabName));
									}
								}
							}
							array = modJson.segments ?? Array.Empty<ModJsonSegment>();
							List<LevelPack> list8 = new List<LevelPack>();
							ModJsonSegment[] array2 = array;
							foreach (ModJsonSegment modJsonSegment2 in array2)
							{
								LevelPack levelPack3 = new LevelPack
								{
									index = modJsonSegment2.index,
									replace = modJsonSegment2.replace,
									isVariant = modJsonSegment2.isVariant,
									biome = (modJsonSegment2.biome ?? string.Empty),
									bundlePath = group.GroupName,
									prefabName = (modJsonSegment2.segmentPrefab ?? string.Empty),
									campfirePrefabName = (modJsonSegment2.campfirePrefab ?? string.Empty),
									packName = modJson.modName + "_" + (modJsonSegment2.id ?? modJsonSegment2.index.ToString()),
									id = (modJsonSegment2.id ?? Guid.NewGuid().ToString())
								};
								levelPack3.spawnMappings = ((modJsonSegment2.spawnMappings != null) ? modJsonSegment2.spawnMappings.Select((ModJsonSpawnMapping sm) => new SpawnMapping
								{
									spawnerMarker = sm.spawnerMarker,
									spawnableName = sm.spawnableName
								}).ToArray() : Array.Empty<SpawnMapping>());
								list8.Add(levelPack3);
								ExtendedSegment extendedSegment2 = ScriptableObject.CreateInstance<ExtendedSegment>();
								((Object)extendedSegment2).name = levelPack3.packName;
								extendedSegment2.index = levelPack3.index;
								extendedSegment2.replace = levelPack3.replace;
								extendedSegment2.isVariant = levelPack3.isVariant;
								extendedSegment2.biome = levelPack3.biome;
								extendedSegment2.prefabName = levelPack3.prefabName;
								extendedSegment2.campfirePrefabName = levelPack3.campfirePrefabName;
								extendedSegment2.packName = levelPack3.packName;
								extendedSegment2.id = levelPack3.id;
								extendedSegment2.ContentType = ContentType.Custom;
								foreach (KeyValuePair<string, ContentTag> item8 in dictionary)
								{
									extendedSegment2.ContentTags.Add(item8.Value);
								}
								extendedMod.TryRegisterExtendedContent(extendedSegment2);
							}
							LevelPackCollection newPacks = new LevelPackCollection
							{
								packs = list8.ToArray()
							};
							if ((Object)(object)PEAKLevelLoader.Instance != (Object)null && list8.Count > 0)
							{
								PEAKLevelLoader.Instance.AddPacks(newPacks);
								PEAKLevelLoader.Logger.LogInfo((object)$"PEAKBundleManager: Added {list8.Count} LevelPack(s) to PEAKLevelLoader.");
							}
							else
							{
								PEAKLevelLoader.Logger.LogInfo((object)("PEAKBundleManager: no level packs to add for group " + group.GroupName + "."));
							}
							string key2 = extendedMod.ModName ?? group.GroupName;
							if (!PatchedContent.ModDefinedTags.ContainsKey(key2))
							{
								PatchedContent.ModDefinedTags[key2] = new List<ContentTag>();
							}
							foreach (ContentTag value2 in dictionary.Values)
							{
								if (!PatchedContent.ModDefinedTags[key2].Contains(value2))
								{
									PatchedContent.ModDefinedTags[key2].Add(value2);
								}
							}
							if (!PatchedContent.ModDefinedTags.ContainsKey(group.GroupName))
							{
								PatchedContent.ModDefinedTags[group.GroupName] = new List<ContentTag>(PatchedContent.ModDefinedTags[key2]);
							}
							PatchedContent.ExtendedMods.Add(extendedMod);
							ContentTagManager.MergeExtendedModTags(extendedMod);
							ContentTagManager.MergeAllExtendedModTags();
							ContentTagManager.PopulateContentTagData();
							PatchedContent.SortExtendedMods();
							PEAKLevelLoader.Logger.LogInfo((object)$"PEAKBundleManager: Registered runtime ExtendedMod for {modJson.modName} with {array.Length} segments and {dictionary.Count} tags.");
						}
					}
					catch (Exception arg3)
					{
						PEAKLevelLoader.Logger.LogWarning((object)$"PEAKBundleManager: failed to parse mod.json in {group.GroupName}: {arg3}");
					}
				}
				foreach (AssetBundleInfo assetBundleInfo in group.GetAssetBundleInfos())
				{
					string text6 = AssetBundleUtilities.ComputeSHA256(assetBundleInfo.AssetBundleFilePath);
					if (!string.IsNullOrEmpty(text6) && !PatchedContent.LoadedBundleHashes.Contains(text6))
					{
						PatchedContent.LoadedBundleHashes.Add(text6);
						PatchedContent.LoadedBundleNames.Add(assetBundleInfo.AssetBundleName);
					}
				}
			}
			catch (Exception arg4)
			{
				PEAKLevelLoader.Logger.LogError((object)$"PEAKBundleManager.OnAssetBundleGroupCreated exception: {arg4}");
			}
		}

		private static void OnAssetBundleLoadRequestFinished()
		{
			AssetBundleLoader.OnBundlesFinishedProcessing.RemoveListener(OnAssetBundleLoadRequestFinished);
			PEAKLevelLoader.Logger.LogInfo((object)"PEAKBundleManager: Finished processing bundles.");
			CurrentStatus = ModProcessingStatus.Complete;
			HasFinalisedFoundContent = true;
			PEAKBundleManager.OnFinishedProcessing?.Invoke();
		}
	}
	internal static class PatchHooks
	{
		public static void ApplyPatches(Harmony harmony)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Expected O, but got Unknown
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Expected O, but got Unknown
			try
			{
				Type type = Type.GetType("MapHandler") ?? Type.GetType("MapHandler, Assembly-CSharp");
				if (type != null)
				{
					MethodInfo method = type.GetMethod("Awake", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (method != null)
					{
						HarmonyMethod val = new HarmonyMethod(typeof(PatchHooks).GetMethod("MapHandler_Awake_Postfix", BindingFlags.Static | BindingFlags.NonPublic));
						harmony.Patch((MethodBase)method, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
						Debug.Log((object)"PatchHooks: patched MapHandler.Awake");
					}
				}
				Type type2 = Type.GetType("MapBaker") ?? Type.GetType("MapBaker, Assembly-CSharp");
				if (type2 != null)
				{
					MethodInfo method2 = type2.GetMethod("GetBiomeID", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (method2 != null)
					{
						HarmonyMethod val2 = new HarmonyMethod(typeof(PatchHooks).GetMethod("MapBaker_GetBiomeID_Postfix", BindingFlags.Static | BindingFlags.NonPublic));
						harmony.Patch((MethodBase)method2, (HarmonyMethod)null, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
						Debug.Log((object)"PatchHooks: patched MapBaker.GetBiomeID");
					}
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("PatchHooks.ApplyPatches failed: " + ex));
			}
		}

		private static void MapHandler_Awake_Postfix(object __instance)
		{
		}

		private static void MapBaker_GetBiomeID_Postfix(object __instance, int levelIndex, ref string __result)
		{
			try
			{
				if ((Object)(object)PEAKLevelLoader.Instance == (Object)null)
				{
					return;
				}
				LevelPackCollection packs = PEAKLevelLoader.Instance.GetPacks();
				if (packs == null || packs.packs == null)
				{
					return;
				}
				LevelPack[] packs2 = packs.packs;
				foreach (LevelPack levelPack in packs2)
				{
					if (levelPack != null && levelPack.index == levelIndex)
					{
						if (!string.IsNullOrEmpty(levelPack.biome))
						{
							__result = levelPack.biome;
						}
						break;
					}
				}
				if (string.IsNullOrEmpty(__result))
				{
					LevelPack[] packs3 = packs.packs;
					foreach (LevelPack levelPack2 in packs3)
					{
					}
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("MapBaker_GetBiomeID_Postfix error: " + ex));
			}
		}
	}
	[BepInPlugin("off_grid.PEAKLevelLoader", "PEAKLevelLoader", "0.4.6")]
	public class PEAKLevelLoader : BaseUnityPlugin
	{
		internal static Harmony Harmony = new Harmony("off_grid.PEAKLevelLoader");

		private LevelPackCollection _packs = new LevelPackCollection();

		private AssetBundleLoader assetBundleLoader;

		public ConfigFile config;

		internal static bool AllowEmbeddedBundles = false;

		public static PEAKLevelLoader Instance { get; private set; } = null;


		internal static ManualLogSource Logger { get; private set; } = null;


		private void Awake()
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected O, but got Unknown
			Logger = ((BaseUnityPlugin)this).Logger;
			Instance = this;
			InitializeConfig();
			Logger.LogWarning((object)"< Config initialized >");
			Logger.LogInfo((object)"< PEAKLevelLoader main sector loaded... >");
			Harmony.PatchAll();
			PatchHooks.ApplyPatches(Harmony);
			GameObject val = new GameObject("PEAKLevelLoader-AssetBundleLoader");
			assetBundleLoader = val.AddComponent<AssetBundleLoader>();
			if (Application.isEditor)
			{
				Object.DontDestroyOnLoad((Object)(object)val);
			}
			else
			{
				((Object)val).hideFlags = (HideFlags)61;
			}
			PEAKBundleManager.Start();
			((MonoBehaviour)this).StartCoroutine(WaitForMapHandlerAndApply());
			Logger.LogInfo((object)"off_grid.PEAKLevelLoader v0.4.6 has fully loaded!");
		}

		private void InitializeConfig()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			string text = Path.Combine(Paths.ConfigPath, "DAa Mods/PEAKLevelLoader");
			if (!Directory.Exists(text))
			{
				Directory.CreateDirectory(text);
			}
			string text2 = Path.Combine(text, "config.cfg");
			config = new ConfigFile(text2, true);
			if (config == null)
			{
				Logger.LogError((object)"The config file is null and the program cannot continue operations.");
				return;
			}
			string value = config.Bind<string>("Version", "Current Version", "", (ConfigDescription)null).Value;
			if (value != "0.4.6")
			{
				config.Clear();
			}
			DefineConfig();
		}

		private void DefineConfig()
		{
			config.Bind<string>("Version", "Current Version", "0.4.6", "Autoupdates the config / lets the mod know what version of config it is.");
			config.Bind<bool>("PEAKLevelLoader", "EnableCustoms", true, "Will custom segments load.");
			AllowEmbeddedBundles = config.Bind<bool>("PEAKLevelLoader", "AllowEmbeddedBundles", false, "If true, the loader will extract .pll resources embedded in already-loaded plugin assemblies. Not recommended due to extra memory usage.").Value;
		}

		public LevelPackCollection GetPacks()
		{
			return _packs ?? new LevelPackCollection();
		}

		public void AddPacks(LevelPackCollection newPacks)
		{
			if (newPacks != null && newPacks.packs != null && newPacks.packs.Length != 0)
			{
				LevelPack[] first = _packs?.packs ?? Array.Empty<LevelPack>();
				LevelPack[] source = first.Concat(newPacks.packs).ToArray();
				LevelPack[] packs = (from p in source
					group p by (!string.IsNullOrEmpty(p.id)) ? p.id : p.packName into g
					select g.First()).ToArray();
				_packs.packs = packs;
				Logger.LogInfo((object)$"PEAKLevelLoader: Added {newPacks.packs.Length} packs. Total unique packs: {_packs.packs.Length}");
			}
		}

		private IEnumerator WaitForMapHandlerAndApply()
		{
			float timeout = 10f;
			float start = Time.realtimeSinceStartup;
			while ((Object)(object)Singleton<MapHandler>.Instance == (Object)null)
			{
				if (Time.realtimeSinceStartup - start > timeout)
				{
					yield break;
				}
				yield return null;
			}
			float start2 = Time.realtimeSinceStartup;
			while (!PEAKBundleManager.HasFinalisedFoundContent)
			{
				if (Time.realtimeSinceStartup - start2 > timeout * 3f)
				{
					Logger.LogWarning((object)"WaitForMapHandlerAndApply: timed out waiting for PEAKBundleManager to finish.");
					break;
				}
				yield return null;
			}
			try
			{
				ApplyPacksToMapHandler(Singleton<MapHandler>.Instance);
			}
			catch (Exception ex)
			{
				Logger.LogError((object)("Error applying packs to MapHandler: " + ex));
			}
		}

		private IEnumerator EnsureGroupLoadedThenResolve(AssetBundleGroup group, string prefabCandidate, Action<GameObject?> onResolved)
		{
			if (group == null)
			{
				onResolved(null);
				yield break;
			}
			if (group.LoadedStatus != AssetBundleGroupLoadedStatus.Loaded)
			{
				try
				{
					group.TryLoadGroup();
				}
				catch
				{
				}
				float start = Time.realtimeSinceStartup;
				float timeout = 10f;
				while (group.LoadedStatus != AssetBundleGroupLoadedStatus.Loaded)
				{
					if (Time.realtimeSinceStartup - start > timeout)
					{
						Logger.LogWarning((object)("EnsureGroupLoadedThenResolve: timed out loading group " + group.GroupName));
						break;
					}
					yield return null;
				}
			}
			GameObject obj2 = AssetBundleGroupDebugger.ResolvePrefabFromGroup(group, prefabCandidate);
			onResolved(obj2);
		}

		public void ApplyPacksToMapHandler(MapHandler mapHandlerInstance)
		{
			((MonoBehaviour)this).StartCoroutine(ApplyPacksToMapHandlerCoroutine(mapHandlerInstance));
		}

		private IEnumerator ApplyPacksToMapHandlerCoroutine(MapHandler mapHandlerInstance)
		{
			if ((Object)(object)mapHandlerInstance == (Object)null || _packs == null || _packs.packs == null || _packs.packs.Length == 0)
			{
				yield break;
			}
			MapSegment[] source = mapHandlerInstance.segments ?? Array.Empty<MapSegment>();
			List<MapSegment> originalList = source.ToList();
			int origLen = originalList.Count;
			List<AssetBundleGroup> list = (assetBundleLoader?.AssetBundleGroups ?? AssetBundleLoader.Instance?.AssetBundleGroups)?.ToList() ?? new List<AssetBundleGroup>();
			if (list.Count == 0)
			{
				Logger.LogWarning((object)"ApplyPacksToMapHandlerCoroutine: no AssetBundleGroups available.");
			}
			LevelPack[] packs = _packs.packs;
			foreach (LevelPack pack in packs)
			{
				GameObject resolvedPrefab = null;
				yield return ((MonoBehaviour)this).StartCoroutine(FindPrefabAcrossGroups(pack.prefabName, delegate(GameObject? prefab)
				{
					resolvedPrefab = prefab;
				}));
				if ((Object)(object)resolvedPrefab == (Object)null)
				{
					Logger.LogWarning((object)("ApplyPacksToMapHandler: couldn't find prefab '" + pack.prefabName + "' for pack '" + pack.packName + "'."));
					yield return null;
					continue;
				}
				GameObject campfirePrefab = null;
				if (!string.IsNullOrEmpty(pack.campfirePrefabName))
				{
					yield return ((MonoBehaviour)this).StartCoroutine(FindPrefabAcrossGroups(pack.campfirePrefabName, delegate(GameObject? prefab)
					{
						campfirePrefab = prefab;
					}));
				}
				GameObject val2;
				try
				{
					Transform globalParent = mapHandlerInstance.globalParent;
					val2 = Object.Instantiate<GameObject>(resolvedPrefab, globalParent);
					((Object)val2).name = "ModSegment_" + pack.packName + "_" + pack.prefabName;
				}
				catch (Exception arg)
				{
					Logger.LogError((object)$"ApplyPacksToMapHandler: failed to instantiate prefab for pack {pack.packName}: {arg}");
					continue;
				}
				MapSegment mapSegObj = (MapSegment)Activator.CreateInstance(typeof(MapSegment));
				Type mapSegTypeLocal = typeof(MapSegment);
				object obj = null;
				if (!string.IsNullOrEmpty(pack.biome))
				{
					try
					{
						obj = Enum.Parse(typeof(BiomeType), pack.biome, ignoreCase: true);
					}
					catch
					{
						obj = null;
					}
				}
				if (obj != null)
				{
					TrySetBackingField("_biome", obj);
				}
				TrySetBackingField("_segmentParent", val2);
				TrySetBackingField("_segmentCampfire", null);
				SpawnerHelper.RegisterSegmentContentsSync(val2, pack, campfirePrefab, mapSegObj, delegate(string name, object? val)
				{
					FieldInfo field8 = typeof(MapSegment).GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (field8 != null)
					{
						field8.SetValue(mapSegObj, val);
					}
					else
					{
						PropertyInfo property2 = typeof(MapSegment).GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
						if (property2 != null && property2.CanWrite)
						{
							property2.SetValue(mapSegObj, val);
						}
					}
				});
				int insertionIndex = ((pack.index < origLen) ? pack.index : originalList.Count);
				PlaceholderProcessor.ProcessPlaceholdersSync(val2, pack, mapSegObj, insertionIndex);
				try
				{
					if ((Object)(object)campfirePrefab != (Object)null)
					{
						Transform val3 = val2.transform.Find("CampfireAnchor") ?? val2.transform.Find("campfireAnchor") ?? val2.transform.Find("Campfire") ?? ((IEnumerable<Transform>)val2.GetComponentsInChildren<Transform>()).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name.IndexOf("campfire", StringComparison.OrdinalIgnoreCase) >= 0));
						GameObject val4 = Object.Instantiate<GameObject>(campfirePrefab);
						((Object)val4).name = "ModCampfire_" + pack.packName + "_" + pack.campfirePrefabName;
						Vector3 lossyScale = val4.transform.lossyScale;
						Transform val5 = (((Object)(object)val3 != (Object)null) ? val3 : val2.transform);
						Vector3 val6 = (((Object)(object)val5 != (Object)null) ? val5.lossyScale : Vector3.one);
						val6.x = (Mathf.Approximately(val6.x, 0f) ? 1f : val6.x);
						val6.y = (Mathf.Approximately(val6.y, 0f) ? 1f : val6.y);
						val6.z = (Mathf.Approximately(val6.z, 0f) ? 1f : val6.z);
						val4.transform.SetParent(val5, false);
						val4.transform.localScale = new Vector3(lossyScale.x / val6.x, lossyScale.y / val6.y, lossyScale.z / val6.z);
						if ((Object)(object)val3 != (Object)null)
						{
							val4.transform.localPosition = Vector3.zero;
							val4.transform.localRotation = Quaternion.identity;
						}
						TrySetBackingField("_segmentCampfire", val4);
					}
					Transform val7 = val2.transform.Find("ReconnectSpawnPos") ?? val2.transform.Find("reconnectSpawnPos") ?? ((IEnumerable<Transform>)val2.GetComponentsInChildren<Transform>()).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name.IndexOf("reconnect", StringComparison.OrdinalIgnoreCase) >= 0));
					if ((Object)(object)val7 != (Object)null)
					{
						FieldInfo field = typeof(MapSegment).GetField("reconnectSpawnPos", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
						if (field != null)
						{
							field.SetValue(mapSegObj, val7);
						}
					}
					Transform val8 = val2.transform.Find("WallNext") ?? ((IEnumerable<Transform>)val2.GetComponentsInChildren<Transform>()).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name.IndexOf("wallnext", StringComparison.OrdinalIgnoreCase) >= 0));
					Transform val9 = val2.transform.Find("WallPrevious") ?? ((IEnumerable<Transform>)val2.GetComponentsInChildren<Transform>()).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name.IndexOf("wallprevious", StringComparison.OrdinalIgnoreCase) >= 0));
					if ((Object)(object)val8 != (Object)null)
					{
						FieldInfo field2 = typeof(MapSegment).GetField("wallNext", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
						if (field2 != null)
						{
							field2.SetValue(mapSegObj, ((Component)val8).gameObject);
						}
					}
					if ((Object)(object)val9 != (Object)null)
					{
						FieldInfo field3 = typeof(MapSegment).GetField("wallPrevious", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
						if (field3 != null)
						{
							field3.SetValue(mapSegObj, ((Component)val9).gameObject);
						}
					}
					Type typeFromHandle = typeof(MapSegment);
					FieldInfo field4 = typeFromHandle.GetField("hasVariant", BindingFlags.Instance | BindingFlags.Public);
					FieldInfo field5 = typeFromHandle.GetField("variantBiome", BindingFlags.Instance | BindingFlags.Public);
					FieldInfo field6 = typeFromHandle.GetField("isVariant", BindingFlags.Instance | BindingFlags.Public);
					if (field4 != null)
					{
						field4.SetValue(mapSegObj, pack.isVariant);
					}
					if (field6 != null)
					{
						field6.SetValue(mapSegObj, pack.isVariant);
					}
					if (field5 != null && obj != null && pack.isVariant)
					{
						field5.SetValue(mapSegObj, obj);
					}
					if (pack.index < origLen)
					{
						if (pack.replace)
						{
							originalList[pack.index] = mapSegObj;
						}
						else
						{
							originalList.Insert(pack.index + 1, mapSegObj);
						}
					}
					else
					{
						originalList.Add(mapSegObj);
					}
					string text = ((!string.IsNullOrEmpty(pack.bundlePath)) ? pack.bundlePath : pack.packName);
					if (!string.IsNullOrEmpty(text) && PatchedContent.ModDefinedTags != null && PatchedContent.ModDefinedTags.TryGetValue(text, out List<ContentTag> value2) && value2 != null && value2.Count > 0)
					{
						ModContentTagMarker modContentTagMarker = val2.GetComponent<ModContentTagMarker>() ?? val2.AddComponent<ModContentTagMarker>();
						modContentTagMarker.tags = value2.ToArray();
					}
				}
				catch (Exception arg2)
				{
					Logger.LogError((object)$"ApplyPacksToMapHandler error for pack {pack.packName}: {arg2}");
				}
				yield return null;
				void TrySetBackingField(string fieldName, object? value)
				{
					FieldInfo field7 = mapSegTypeLocal.GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (field7 != null)
					{
						try
						{
							Type fieldType = field7.FieldType;
							if (value == null)
							{
								field7.SetValue(mapSegObj, null);
								return;
							}
							if (fieldType.IsAssignableFrom(value.GetType()))
							{
								field7.SetValue(mapSegObj, value);
								return;
							}
							if (fieldType == typeof(Transform))
							{
								GameObject val10 = (GameObject)((value is GameObject) ? value : null);
								if (val10 != null)
								{
									field7.SetValue(mapSegObj, val10.transform);
									return;
								}
							}
							if (fieldType == typeof(GameObject))
							{
								Transform val11 = (Transform)((value is Transform) ? value : null);
								if (val11 != null)
								{
									field7.SetValue(mapSegObj, ((Component)val11).gameObject);
									return;
								}
							}
							Logger.LogWarning((object)("TrySetBackingField: type mismatch for " + fieldName + "."));
						}
						catch (Exception arg3)
						{
							Logger.LogWarning((object)$"TrySetBackingField: {arg3}");
						}
					}
					PropertyInfo property = mapSegTypeLocal.GetProperty(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (property != null && property.CanWrite)
					{
						try
						{
							Type propertyType = property.PropertyType;
							if (value == null)
							{
								property.SetValue(mapSegObj, null);
							}
							else if (propertyType.IsAssignableFrom(value.GetType()))
							{
								property.SetValue(mapSegObj, value);
							}
							else
							{
								if (propertyType == typeof(Transform))
								{
									GameObject val12 = (GameObject)((value is GameObject) ? value : null);
									if (val12 != null)
									{
										property.SetValue(mapSegObj, val12.transform);
										return;
									}
								}
								if (propertyType == typeof(GameObject))
								{
									Transform val13 = (Transform)((value is Transform) ? value : null);
									if (val13 != null)
									{
										property.SetValue(mapSegObj, ((Component)val13).gameObject);
										return;
									}
								}
								Logger.LogWarning((object)("TrySetBackingField(prop): type mismatch for " + fieldName + "."));
							}
						}
						catch (Exception arg4)
						{
							Logger.LogWarning((object)$"TrySetBackingField(prop): {arg4}");
						}
					}
				}
			}
			MapSegment[] array = (mapHandlerInstance.segments = originalList.ToArray());
			if (PhotonNetwork.InRoom && PhotonNetwork.IsMasterClient)
			{
				Logger.LogInfo((object)" < Awaiting for sync from non host clients. > ");
				LevelPack[] packs2 = _packs.packs;
				PEAKPackSyncPhoton instance = PEAKPackSyncPhoton.Instance;
				if ((Object)(object)instance != (Object)null)
				{
					instance.SendPacksToClients(packs2, waitForAcks: true, delegate(bool success)
					{
						if (!success)
						{
							Logger.LogWarning((object)"Not all clients ACK'd pack application in time.");
						}
						else
						{
							Logger.LogInfo((object)"All clients acknowledged pack application.");
						}
					});
				}
				else
				{
					Logger.LogWarning((object)"PEAKPackSyncPhoton.Instance is null. Ensure it exists in scene and is created in Awake.");
				}
			}
			Logger.LogInfo((object)$"ApplyPacksToMapHandler: finished applying packs, segments length {array.Length}");
		}

		private IEnumerator FindPrefabAcrossGroups(string prefabName, Action<GameObject?> onFound)
		{
			GameObject found = null;
			List<AssetBundleGroup> list = assetBundleLoader?.AssetBundleGroups ?? AssetBundleLoader.Instance?.AssetBundleGroups;
			if (list == null)
			{
				onFound(null);
				yield break;
			}
			foreach (AssetBundleGroup item in list)
			{
				if (item == null)
				{
					continue;
				}
				AssetBundleGroup assetBundleGroup = item;
				if (assetBundleGroup != null)
				{
					yield return ((MonoBehaviour)this).StartCoroutine(EnsureGroupLoadedThenResolve(assetBundleGroup, prefabName, delegate(GameObject? prefab)
					{
						found = prefab;
					}));
					if ((Object)(object)found != (Object)null)
					{
						break;
					}
				}
			}
			onFound(found);
		}

		internal static void TrySoftPatch(string pluginName, Type type)
		{
			if (Chainloader.PluginInfos.ContainsKey(pluginName))
			{
				Harmony.CreateClassProcessor(type, true).Patch();
				Logger.LogInfo((object)(pluginName + " found, enabling compatability patches."));
			}
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "off_grid.PEAKLevelLoader";

		public const string PLUGIN_NAME = "PEAKLevelLoader";

		public const string PLUGIN_VERSION = "0.4.6";
	}
}
namespace PEAKLevelLoader.Patches
{
	[HarmonyPatch(typeof(MapHandler))]
	internal class MapHandlerPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch("Awake")]
		private static void Postfix_Awake(MapHandler __instance)
		{
			try
			{
				if ((Object)(object)PEAKLevelLoader.Instance != (Object)null)
				{
					PEAKLevelLoader.Instance.ApplyPacksToMapHandler(__instance);
					try
					{
						typeof(MapHandler).GetMethod("DetectBiomes", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.Invoke(__instance, null);
						return;
					}
					catch (Exception arg)
					{
						PEAKLevelLoader.Logger.LogWarning((object)$"DetectBiomes failed after ApplyPacks: {arg}");
						return;
					}
				}
				PEAKLevelLoader.Logger.LogWarning((object)"PEAKLevelLoader.Instance is null — can't apply packs yet.");
			}
			catch (Exception arg2)
			{
				PEAKLevelLoader.Logger.LogErr