Decompiled source of MapKitLoader v1.0.2

SlipSkid.MapKit.Loader.dll

Decompiled 16 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Text;
using BepInEx;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.Mono;
using CameraUtils;
using Effects;
using Game;
using Game.Levels;
using HarmonyLib;
using Menus;
using Newtonsoft.Json.Linq;
using Obstacles;
using Player;
using SlipSkid.MapKit.SDK;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using Utils;
using Utils.Networking;
using World;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("SlipSkid.MapKit.Loader")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+afa60f15dde673ac3bacd5ea8ae4cb6c69489d42")]
[assembly: AssemblyProduct("SlipSkid.MapKit.Loader")]
[assembly: AssemblyTitle("SlipSkid.MapKit.Loader")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace SlipSkid.MapKit.Loader;

internal static class DecorBuilder
{
	private sealed class Piece
	{
		public MeshFilter Filter;

		public float Width;

		public float Height;

		public float Aspect => Height / Width;
	}

	private const float MinAspect = 0.12f;

	public static void Apply(LevelDefinition def)
	{
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_015c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0163: Expected O, but got Unknown
		if (MapBuilder.BuiltFor == null || (Object)(object)def == (Object)null)
		{
			return;
		}
		KitDecor[] array = Object.FindObjectsOfType<KitDecor>(true);
		if (array.Length == 0)
		{
			return;
		}
		float num = (((Object)(object)def.fogPlane != (Object)null) ? ((Component)def.fogPlane).transform.position.y : float.NaN);
		List<GameObject> list = new List<GameObject>();
		Dictionary<Surface, (LevelEnvironmentBiome, GameObject)> value = Traverse.Create((object)def).Field("_environmentBiomes").GetValue<Dictionary<Surface, (LevelEnvironmentBiome, GameObject)>>();
		if (value != null)
		{
			foreach (var value3 in value.Values)
			{
				if ((Object)(object)value3.Item2 != (Object)null)
				{
					list.Add(value3.Item2);
				}
			}
		}
		Component value2 = Traverse.Create((object)def).Field("_rushModeEnvironmentBiome").GetValue<Component>();
		if ((Object)(object)value2 != (Object)null)
		{
			list.Add(value2.gameObject);
		}
		int num2 = 0;
		foreach (GameObject item in list)
		{
			List<Piece> list2 = Candidates(item);
			if (list2.Count == 0)
			{
				continue;
			}
			for (int i = 0; i < array.Length; i++)
			{
				if (Place(list2, array[i], item.transform, i, num))
				{
					num2++;
				}
			}
		}
		ManualLogSource log = LoaderPlugin.Log;
		bool flag = default(bool);
		BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(71, 4, ref flag);
		if (flag)
		{
			((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Decoration: ");
			((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(array.Length);
			((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" spot(s) across ");
			((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(list.Count);
			((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" environment(s), ");
			((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(num2);
			((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" piece(s), standing on y=");
			((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(num, "0.#");
			((BepInExLogInterpolatedStringHandler)val).AppendLiteral(".");
		}
		log.LogInfo(val);
	}

	private static List<Piece> Candidates(GameObject root)
	{
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Expected O, but got Unknown
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
		List<Piece> list = new List<Piece>();
		foreach (Transform item in root.transform)
		{
			Transform val = item;
			MeshFilter component = ((Component)val).GetComponent<MeshFilter>();
			if (!((Object)(object)component == (Object)null) && !((Object)(object)component.sharedMesh == (Object)null) && !((Object)(object)((Component)val).GetComponent<MeshRenderer>() == (Object)null))
			{
				Bounds val2 = MapBuilder.TransformBounds(component.sharedMesh.bounds, Matrix4x4.TRS(Vector3.zero, val.rotation, val.lossyScale));
				Piece piece = new Piece
				{
					Filter = component,
					Width = Mathf.Max(((Bounds)(ref val2)).size.x, ((Bounds)(ref val2)).size.z),
					Height = ((Bounds)(ref val2)).size.y
				};
				if (!(piece.Width < 1f) && !(piece.Height < 1f) && !(piece.Aspect < 0.12f))
				{
					list.Add(piece);
				}
			}
		}
		return list;
	}

	private static bool Place(List<Piece> pieces, KitDecor spot, Transform parent, int index, float sea)
	{
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_0203: Unknown result type (might be due to invalid IL or missing references)
		//IL_0208: Unknown result type (might be due to invalid IL or missing references)
		//IL_020d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0212: Unknown result type (might be due to invalid IL or missing references)
		//IL_021a: Unknown result type (might be due to invalid IL or missing references)
		//IL_022f: Unknown result type (might be due to invalid IL or missing references)
		//IL_023a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0242: Unknown result type (might be due to invalid IL or missing references)
		//IL_024d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0252: Unknown result type (might be due to invalid IL or missing references)
		Vector3 position = ((Component)spot).transform.position;
		if (float.IsNaN(sea))
		{
			sea = position.y - 40f;
		}
		float num = position.y - sea + spot.size * 0.5f;
		float num2 = spot.size * 2f;
		List<Piece> list = pieces;
		if (!string.IsNullOrEmpty(spot.prefer))
		{
			List<Piece> list2 = pieces.FindAll((Piece p) => ((Object)p.Filter).name.IndexOf(spot.prefer, StringComparison.OrdinalIgnoreCase) >= 0);
			if (list2.Count > 0)
			{
				list = list2;
			}
		}
		float needAspect = num / num2;
		List<Piece> list3 = list.FindAll((Piece p) => p.Aspect >= needAspect);
		if (list3.Count == 0)
		{
			list3 = new List<Piece>(list);
			list3.Sort((Piece a, Piece b) => b.Aspect.CompareTo(a.Aspect));
			list3 = list3.GetRange(0, Mathf.Min(3, list3.Count));
		}
		Piece piece = list3[Hash(index, 7) % list3.Count];
		float num3 = Mathf.Min(num / piece.Height, num2 / piece.Width);
		Transform transform = ((Component)piece.Filter).transform;
		GameObject val = Object.Instantiate<GameObject>(((Component)transform).gameObject, parent);
		((Object)val).name = "MapKitDecor_" + ((Object)transform).name;
		Collider[] componentsInChildren = val.GetComponentsInChildren<Collider>(true);
		for (int num4 = 0; num4 < componentsInChildren.Length; num4++)
		{
			Object.Destroy((Object)(object)componentsInChildren[num4]);
		}
		Transform transform2 = val.transform;
		transform2.rotation = Quaternion.Euler(0f, (float)(Hash(index, 13) % 360), 0f) * transform.rotation;
		transform2.localScale = transform.localScale * num3;
		transform2.position = position;
		Bounds val2 = MapBuilder.TransformBounds(piece.Filter.sharedMesh.bounds, transform2.localToWorldMatrix);
		transform2.position += new Vector3(position.x - ((Bounds)(ref val2)).center.x, sea - 2f - ((Bounds)(ref val2)).min.y, position.z - ((Bounds)(ref val2)).center.z);
		return true;
	}

	private static int Hash(int index, int salt)
	{
		return ((index * 73856093) ^ (salt * 19349663)) & 0x7FFFFFFF;
	}
}
[HarmonyPatch(typeof(LevelManager), "InitLevel")]
internal static class DecorAfterInitLevelPatch
{
	private static void Postfix()
	{
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Expected O, but got Unknown
		try
		{
			LevelDefinition def = (((Object)(object)LevelManager.instance != (Object)null) ? LevelManager.instance.levelDefinition : null);
			EnvironmentFit.Apply(def);
			DecorBuilder.Apply(def);
		}
		catch (Exception ex)
		{
			ManualLogSource log = LoaderPlugin.Log;
			bool flag = default(bool);
			BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(19, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Decoration failed: ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
			}
			log.LogError(val);
		}
	}
}
internal static class EnvironmentFit
{
	private const float MaxScale = 4f;

	private const float Clearance = 15f;

	public static List<GameObject> BiomeRoots(LevelDefinition def)
	{
		List<GameObject> list = new List<GameObject>();
		Dictionary<Surface, (LevelEnvironmentBiome, GameObject)> value = Traverse.Create((object)def).Field("_environmentBiomes").GetValue<Dictionary<Surface, (LevelEnvironmentBiome, GameObject)>>();
		if (value != null)
		{
			foreach (var value3 in value.Values)
			{
				if ((Object)(object)value3.Item2 != (Object)null)
				{
					list.Add(value3.Item2);
				}
			}
		}
		Component value2 = Traverse.Create((object)def).Field("_rushModeEnvironmentBiome").GetValue<Component>();
		if ((Object)(object)value2 != (Object)null)
		{
			list.Add(value2.gameObject);
		}
		return list;
	}

	private static bool Overlaps(Bounds a, Bounds b)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_0093: Unknown result type (might be due to invalid IL or missing references)
		if (((Bounds)(ref a)).min.x <= ((Bounds)(ref b)).max.x && ((Bounds)(ref a)).max.x >= ((Bounds)(ref b)).min.x && ((Bounds)(ref a)).min.y <= ((Bounds)(ref b)).max.y && ((Bounds)(ref a)).max.y >= ((Bounds)(ref b)).min.y && ((Bounds)(ref a)).min.z <= ((Bounds)(ref b)).max.z)
		{
			return ((Bounds)(ref a)).max.z >= ((Bounds)(ref b)).min.z;
		}
		return false;
	}

	public static void Apply(LevelDefinition def)
	{
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_009f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_010b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0111: Unknown result type (might be due to invalid IL or missing references)
		//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e4: Expected O, but got Unknown
		//IL_0148: Unknown result type (might be due to invalid IL or missing references)
		//IL_0154: Unknown result type (might be due to invalid IL or missing references)
		//IL_0159: Unknown result type (might be due to invalid IL or missing references)
		//IL_015e: Unknown result type (might be due to invalid IL or missing references)
		//IL_016c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0171: Unknown result type (might be due to invalid IL or missing references)
		if (MapBuilder.BuiltFor == null || (Object)(object)def == (Object)null)
		{
			return;
		}
		List<GameObject> list = BiomeRoots(def);
		float num = ((MapBuilder.HostExtent > 1f) ? Mathf.Clamp(MapBuilder.TrackExtent / MapBuilder.HostExtent, 1f, 4f) : 1f);
		List<Bounds> list2 = new List<Bounds>();
		foreach (LevelTileObject tile in def.tiles)
		{
			MeshRenderer val = (((Object)(object)tile != (Object)null) ? ((Component)tile).GetComponent<MeshRenderer>() : null);
			if (!((Object)(object)val == (Object)null))
			{
				Bounds bounds = ((Renderer)val).bounds;
				list2.Add(new Bounds(((Bounds)(ref bounds)).center + Vector3.up * 40f, ((Bounds)(ref bounds)).size + new Vector3(30f, 80f, 30f)));
			}
		}
		int num2 = 0;
		foreach (GameObject item in list)
		{
			item.transform.localScale = Vector3.one * num;
			MeshFilter[] componentsInChildren = item.GetComponentsInChildren<MeshFilter>(true);
			foreach (MeshFilter val2 in componentsInChildren)
			{
				if ((Object)(object)val2.sharedMesh == (Object)null)
				{
					continue;
				}
				Bounds b = MapBuilder.TransformBounds(val2.sharedMesh.bounds, ((Component)val2).transform.localToWorldMatrix);
				foreach (Bounds item2 in list2)
				{
					if (Overlaps(item2, b))
					{
						((Component)val2).gameObject.SetActive(false);
						num2++;
						break;
					}
				}
			}
		}
		ManualLogSource log = LoaderPlugin.Log;
		bool flag = default(bool);
		BepInExInfoLogInterpolatedStringHandler val3 = new BepInExInfoLogInterpolatedStringHandler(72, 4, ref flag);
		if (flag)
		{
			((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Scenery scaled x");
			((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<float>(num, "0.0");
			((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" for a ");
			((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<float>(MapBuilder.TrackExtent, "0");
			((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" m map (host ");
			((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<float>(MapBuilder.HostExtent, "0");
			((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" m); ");
			((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(num2);
			((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" piece(s) hidden off the track.");
		}
		log.LogInfo(val3);
	}
}
internal static class MapFog
{
	private const float MaxFogEnd = 1200f;

	public static float Start;

	public static float End;

	public static bool Active;

	public static void FromBiome(LevelEnvironmentBiome biome)
	{
		//IL_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Expected O, but got Unknown
		if (MapBuilder.BuiltFor == null || (Object)(object)biome == (Object)null)
		{
			Active = false;
			return;
		}
		float num = Mathf.Clamp(MapBuilder.TrackExtent * 0.6f, biome.fogEndDistance, 1200f);
		float num2 = ((biome.fogEndDistance > 0f) ? (biome.fogStartDistance / biome.fogEndDistance) : 0.65f);
		End = num;
		Start = num * num2;
		Active = true;
		Apply();
		ManualLogSource log = LoaderPlugin.Log;
		bool flag = default(bool);
		BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(47, 6, ref flag);
		if (flag)
		{
			((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Fog for '");
			((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(((Object)biome).name);
			((BepInExLogInterpolatedStringHandler)val).AppendLiteral("': biome ");
			((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(biome.fogStartDistance, "0");
			((BepInExLogInterpolatedStringHandler)val).AppendLiteral("-");
			((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(biome.fogEndDistance, "0");
			((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" m, map ");
			((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(Start, "0");
			((BepInExLogInterpolatedStringHandler)val).AppendLiteral("-");
			((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(End, "0");
			((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" m (track ");
			((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(MapBuilder.TrackExtent, "0");
			((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" m wide).");
		}
		log.LogInfo(val);
	}

	public static void Apply()
	{
		if (Active && MapBuilder.BuiltFor != null)
		{
			RenderSettings.fogStartDistance = Start;
			RenderSettings.fogEndDistance = End;
		}
	}
}
[HarmonyPatch(typeof(LevelDefinition), "SwapEnvironment", new Type[]
{
	typeof(LevelEnvironmentBiome),
	typeof(GameObject)
})]
internal static class FogPatch
{
	private static void Postfix(LevelEnvironmentBiome target)
	{
		MapFog.FromBiome(target);
	}
}
internal sealed class MapFogKeeper : MonoBehaviour
{
	private void LateUpdate()
	{
		MapFog.Apply();
	}
}
internal sealed class KitBoostZone : MonoBehaviour
{
	public float boostSpeed = 20f;

	private const float Cooldown = 0.5f;

	private float _lastBoost = -999f;

	private void OnTriggerEnter(Collider other)
	{
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		if (Time.time - _lastBoost < 0.5f)
		{
			return;
		}
		Rigidbody attachedRigidbody = other.attachedRigidbody;
		if (!((Object)(object)attachedRigidbody == (Object)null))
		{
			SphereCarController componentInParent = ((Component)attachedRigidbody).GetComponentInParent<SphereCarController>();
			if (!((Object)(object)componentInParent == (Object)null))
			{
				Vector3 val = (((Object)(object)componentInParent.car != (Object)null) ? componentInParent.car.forward : ((Component)attachedRigidbody).transform.forward);
				attachedRigidbody.AddForce(val * boostSpeed, (ForceMode)2);
				_lastBoost = Time.time;
			}
		}
	}
}
internal static class LevelRegistry
{
	public static void Inject(LevelManager levelManager)
	{
		//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: Expected O, but got Unknown
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: Expected O, but got Unknown
		//IL_010e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0115: Expected O, but got Unknown
		if ((Object)(object)levelManager == (Object)null || levelManager.levels == null || MapCatalog.Maps.Count == 0)
		{
			return;
		}
		List<Level> list = new List<Level>(levelManager.levels);
		int num = 0;
		bool flag = default(bool);
		foreach (KitMapEntry map in MapCatalog.Maps)
		{
			if ((Object)(object)map.Prefab == (Object)null)
			{
				continue;
			}
			if ((Object)(object)map.Level == (Object)null)
			{
				Level val = FindHost(list, map.Host);
				if ((Object)(object)val == (Object)null)
				{
					ManualLogSource log = LoaderPlugin.Log;
					BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(28, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<KitMapEntry>(map);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": no stock level to host it.");
					}
					log.LogError(val2);
					continue;
				}
				try
				{
					map.Level = CreateLevel(map, val);
				}
				catch (Exception ex)
				{
					ManualLogSource log2 = LoaderPlugin.Log;
					BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(22, 2, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<KitMapEntry>(map);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": could not register: ");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<Exception>(ex);
					}
					log2.LogError(val2);
					continue;
				}
				ManualLogSource log3 = LoaderPlugin.Log;
				BepInExInfoLogInterpolatedStringHandler val3 = new BepInExInfoLogInterpolatedStringHandler(40, 3, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Registered ");
					((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<KitMapEntry>(map);
					((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" on host level '");
					((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(val.name);
					((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("' (scene '");
					((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(val.sceneName);
					((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("').");
				}
				log3.LogInfo(val3);
			}
			if (!list.Contains(map.Level))
			{
				list.Add(map.Level);
				num++;
			}
		}
		if (num > 0)
		{
			levelManager.levels = list.ToArray();
		}
	}

	public static void RefreshSurfaceCounts()
	{
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		foreach (KitMapEntry map in MapCatalog.Maps)
		{
			if (!((Object)(object)map.Level == (Object)null) && map.TileCount > 0)
			{
				Surface val = map.HostSurface;
				if ((Object)(object)val == (Object)null && (Object)(object)SurfaceManager.instance != (Object)null)
				{
					val = SurfaceManager.DefaultSurface;
				}
				if (!((Object)(object)val == (Object)null))
				{
					map.Level.surfaceTileCount = new List<SurfaceCount>
					{
						new SurfaceCount(val, map.TileCount)
					};
				}
			}
		}
	}

	private static Level FindHost(List<Level> levels, string wanted)
	{
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Expected O, but got Unknown
		Level val = null;
		foreach (Level level in levels)
		{
			if (!((Object)(object)level == (Object)null) && MapCatalog.FromLevel(level) == null && !string.IsNullOrEmpty(level.sceneName))
			{
				if ((Object)(object)val == (Object)null)
				{
					val = level;
				}
				if (!string.IsNullOrEmpty(wanted) && (Matches(level.name, wanted) || Matches(((Object)level).name, wanted) || Matches(level.sceneName, wanted)))
				{
					return level;
				}
			}
		}
		if (!string.IsNullOrEmpty(wanted) && (Object)(object)val != (Object)null)
		{
			ManualLogSource log = LoaderPlugin.Log;
			bool flag = default(bool);
			BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(34, 2, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Host level '");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(wanted);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("' not found; using '");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(val.name);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("'.");
			}
			log.LogWarning(val2);
		}
		return val;
	}

	private static bool Matches(string a, string b)
	{
		return string.Equals(a, b, StringComparison.OrdinalIgnoreCase);
	}

	private static Level CreateLevel(KitMapEntry map, Level host)
	{
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_005b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: Unknown result type (might be due to invalid IL or missing references)
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_018c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0191: Unknown result type (might be due to invalid IL or missing references)
		Level val = Object.Instantiate<Level>(host);
		((Object)val).hideFlags = (HideFlags)32;
		((Object)val).name = map.Name;
		val.name = map.Name;
		val.difficulty = Mathf.Clamp(map.Difficulty, 1, 5);
		LevelInGameStats inGameStats = val.inGameStats;
		inGameStats.isReversible = map.Reversible;
		val.inGameStats = inGameStats;
		val.ghostUnlockableContent = default(GhostUnlockableContent);
		map.HostSceneName = host.sceneName;
		if (host.surfaceTileCount != null)
		{
			int num = 0;
			foreach (SurfaceCount item in host.surfaceTileCount)
			{
				if (item.count > num)
				{
					num = item.count;
					map.HostSurface = item.surface;
				}
			}
		}
		Texture2D val2 = LoadTexture(map.ThumbnailFile);
		if ((Object)(object)val2 != (Object)null)
		{
			val.thumbnailImage = val2;
		}
		Texture2D val3 = LoadTexture(map.PreviewFile);
		if ((Object)(object)val3 != (Object)null)
		{
			val.previewImage = val3;
		}
		LevelPreviewMesh[] previewMeshes = host.previewMeshes;
		if ((Object)(object)map.PreviewMesh != (Object)null && previewMeshes != null && previewMeshes.Length != 0 && (Object)(object)previewMeshes[0].renderer != (Object)null)
		{
			Mesh val4 = map.PreviewMesh;
			if (val4.subMeshCount > previewMeshes[0].renderer.sharedMaterials.Length)
			{
				val4 = MergeSubmeshes(val4);
			}
			val.previewMeshes = (LevelPreviewMesh[])(object)new LevelPreviewMesh[1]
			{
				new LevelPreviewMesh(val4, previewMeshes[0].renderer, previewMeshes[0].surfaces)
			};
		}
		return val;
	}

	private static Texture2D LoadTexture(string path)
	{
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Expected O, but got Unknown
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Expected O, but got Unknown
		if (path == null)
		{
			return null;
		}
		Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
		if (ImageConversion.LoadImage(val, File.ReadAllBytes(path)))
		{
			((Object)val).hideFlags = (HideFlags)32;
			return val;
		}
		Object.Destroy((Object)(object)val);
		ManualLogSource log = LoaderPlugin.Log;
		bool flag = default(bool);
		BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(22, 1, ref flag);
		if (flag)
		{
			((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Could not read image ");
			((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(path);
			((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(".");
		}
		log.LogWarning(val2);
		return null;
	}

	private static Mesh MergeSubmeshes(Mesh mesh)
	{
		List<int> list = new List<int>();
		for (int i = 0; i < mesh.subMeshCount; i++)
		{
			list.AddRange(mesh.GetTriangles(i));
		}
		Mesh obj = Object.Instantiate<Mesh>(mesh);
		obj.subMeshCount = 1;
		obj.SetTriangles(list, 0);
		((Object)obj).hideFlags = (HideFlags)32;
		return obj;
	}
}
[BepInPlugin("slipskid.mapkit.loader", "Slip & Skid - Map Kit Loader", "1.0.2")]
public sealed class LoaderPlugin : BaseUnityPlugin
{
	public const string Guid = "slipskid.mapkit.loader";

	public const string Version = "1.0.2";

	internal static ManualLogSource Log;

	private void Awake()
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Expected O, but got Unknown
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Expected O, but got Unknown
		Log = ((BaseUnityPlugin)this).Logger;
		MapCatalog.Discover();
		Harmony val = new Harmony("slipskid.mapkit.loader");
		Type[] typesFromAssembly = AccessTools.GetTypesFromAssembly(typeof(LoaderPlugin).Assembly);
		bool flag = default(bool);
		foreach (Type type in typesFromAssembly)
		{
			try
			{
				val.CreateClassProcessor(type).Patch();
			}
			catch (Exception ex)
			{
				ManualLogSource log = Log;
				BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(15, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Patch ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(type.Name);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" failed: ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex.Message);
				}
				log.LogError(val2);
			}
		}
		SceneManager.sceneLoaded += MapBuilder.OnSceneLoaded;
		((MonoBehaviour)this).StartCoroutine(Startup());
	}

	private IEnumerator Startup()
	{
		yield return MapCatalog.LoadBundles();
		if ((Object)(object)LevelManager.instance != (Object)null)
		{
			LevelRegistry.Inject(LevelManager.instance);
		}
		ManualLogSource log = Log;
		bool flag = default(bool);
		BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(30, 1, ref flag);
		if (flag)
		{
			((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Map Kit Loader ready: ");
			((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(MapCatalog.Maps.Count);
			((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" map(s).");
		}
		log.LogInfo(val);
	}
}
internal static class MapBuilder
{
	private sealed class HostTrack
	{
		public Material Asphalt;

		public Material Concrete;

		public Surface Surface;

		public Bounds Bounds;

		public bool HasBounds;
	}

	private sealed class RoadSurfaces
	{
		private readonly HostTrack _host;

		private readonly Surface _default;

		private readonly Dictionary<string, Surface> _byName = new Dictionary<string, Surface>(StringComparer.OrdinalIgnoreCase);

		private readonly Dictionary<Surface, Material> _materials = new Dictionary<Surface, Material>();

		private readonly Dictionary<Surface, int> _counts = new Dictionary<Surface, int>();

		public RoadSurfaces(HostTrack host, Surface fallback)
		{
			_host = host;
			_default = fallback;
		}

		public Surface Find(string name)
		{
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Expected O, but got Unknown
			Surface value = _default;
			if (!string.IsNullOrEmpty(name))
			{
				if (!_byName.TryGetValue(name, out value))
				{
					value = null;
					Surface[] array = (((Object)(object)SurfaceManager.instance != (Object)null) ? SurfaceManager.instance.surfaces : null);
					if (array != null)
					{
						value = Array.Find(array, (Surface x) => (Object)(object)x != (Object)null && string.Equals(((Object)x).name, name, StringComparison.OrdinalIgnoreCase)) ?? Array.Find(array, (Surface x) => (Object)(object)x != (Object)null && ((Object)x).name.IndexOf(name, StringComparison.OrdinalIgnoreCase) >= 0);
					}
					if ((Object)(object)value == (Object)null)
					{
						ManualLogSource log = LoaderPlugin.Log;
						bool flag = default(bool);
						BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(53, 1, ref flag);
						if (flag)
						{
							((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Unknown road surface '");
							((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(name);
							((BepInExLogInterpolatedStringHandler)val).AppendLiteral("'; using the host road surface.");
						}
						log.LogWarning(val);
					}
					_byName[name] = value;
				}
				if ((Object)(object)value == (Object)null)
				{
					value = _default;
				}
			}
			if ((Object)(object)value != (Object)null)
			{
				_counts.TryGetValue(value, out var value2);
				_counts[value] = value2 + 1;
			}
			return value;
		}

		public Material MaterialFor(Surface surface)
		{
			if ((Object)(object)surface == (Object)null || (Object)(object)surface == (Object)(object)_host.Surface || surface.effects == null || (Object)(object)surface.effects.material == (Object)null)
			{
				return _host.Asphalt;
			}
			if (!_materials.TryGetValue(surface, out var value))
			{
				value = Object.Instantiate<Material>(surface.effects.material);
				_materials[surface] = value;
			}
			return value;
		}

		public void LogMix()
		{
			if (_counts.Count > 1)
			{
				LoaderPlugin.Log.LogInfo((object)("Road surfaces: " + string.Join(", ", _counts.Select((KeyValuePair<Surface, int> e) => $"{((Object)e.Key).name} {e.Value}")) + "."));
			}
		}
	}

	private sealed class ZonePose
	{
		public Transform Zone;

		public Transform Anchor;

		public Vector3 LocalPosition;

		public Quaternion LocalRotation;
	}

	public static KitMapEntry Pending;

	public static KitMapEntry BuiltFor;

	private const int RoadCombinedFallbackLayer = 16;

	public static float TrackExtent;

	public static float HostExtent;

	private static readonly int TrailsOrthoCamPosition = Shader.PropertyToID("_TrailsOrthoCamPosition");

	private static readonly int TrailsOrthoCam = Shader.PropertyToID("_TrailsOrthoCam");

	public static void OnSceneLoaded(Scene scene, LoadSceneMode mode)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_0058: Expected O, but got Unknown
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		if ((int)mode == 0)
		{
			BuiltFor = null;
		}
		KitMapEntry pending = Pending;
		if (pending == null || (Object)(object)pending.Prefab == (Object)null || !string.Equals(((Scene)(ref scene)).name, pending.HostSceneName, StringComparison.OrdinalIgnoreCase))
		{
			return;
		}
		try
		{
			Build(pending, scene);
			BuiltFor = pending;
		}
		catch (Exception ex)
		{
			ManualLogSource log = LoaderPlugin.Log;
			bool flag = default(bool);
			BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(18, 2, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Building ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<KitMapEntry>(pending);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" failed: ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
			}
			log.LogError(val);
		}
	}

	private static void Build(KitMapEntry map, Scene scene)
	{
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Expected O, but got Unknown
		//IL_009c: 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_013d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0144: Expected O, but got Unknown
		//IL_0146: Unknown result type (might be due to invalid IL or missing references)
		//IL_0189: Unknown result type (might be due to invalid IL or missing references)
		//IL_018e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0192: Unknown result type (might be due to invalid IL or missing references)
		//IL_019e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0206: Unknown result type (might be due to invalid IL or missing references)
		//IL_0226: Unknown result type (might be due to invalid IL or missing references)
		//IL_024b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0262: Unknown result type (might be due to invalid IL or missing references)
		//IL_0269: Expected O, but got Unknown
		GameObject[] rootGameObjects = ((Scene)(ref scene)).GetRootGameObjects();
		LevelDefinition val = Find<LevelDefinition>(rootGameObjects);
		bool flag = default(bool);
		if ((Object)(object)val == (Object)null)
		{
			ManualLogSource log = LoaderPlugin.Log;
			BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(37, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Host scene '");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(((Scene)(ref scene)).name);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("' has no LevelDefinition.");
			}
			log.LogError(val2);
			return;
		}
		StartLine start = Find<StartLine>(rootGameObjects);
		FinishLine val3 = Find<FinishLine>(rootGameObjects);
		EndGamePlatform val4 = Find<EndGamePlatform>(rootGameObjects);
		ObstacleLevelDefinition obstacles = Find<ObstacleLevelDefinition>(rootGameObjects);
		HostTrack hostTrack = ReadHostTrack(rootGameObjects, start, val3, val4);
		HostExtent = (hostTrack.HasBounds ? Mathf.Max(((Bounds)(ref hostTrack.Bounds)).size.x, ((Bounds)(ref hostTrack.Bounds)).size.z) : 0f);
		List<ZonePose> zones = RememberZones(obstacles, start, val3);
		int num = HideHostTrack(rootGameObjects, start, val3, val4);
		val.tiles.Clear();
		val.checkpoints?.Clear();
		val.scorePointZones?.Clear();
		val.speedCameras?.Clear();
		val.inSceneObstacles?.Clear();
		val.reflectionProbes?.Clear();
		GameObject val5 = new GameObject("MapKit_Holder");
		SceneManager.MoveGameObjectToScene(val5, scene);
		val5.SetActive(false);
		GameObject val6 = Object.Instantiate<GameObject>(map.Prefab, val5.transform);
		((Object)val6).name = ((Object)map.Prefab).name;
		KitMap component = val6.GetComponent<KitMap>();
		Bounds track = BuildRoad(map, val6, val, hostTrack);
		TrackExtent = Mathf.Max(((Bounds)(ref track)).size.x, ((Bounds)(ref track)).size.z);
		BuildBoostPads(val6);
		BuildGravity(val6);
		PlaceStart(val6, start);
		Place<KitFinish>(val6, ((Object)(object)val3 != (Object)null) ? ((Component)val3).transform : null);
		Place<KitPodium>(val6, ((Object)(object)val4 != (Object)null) ? ((Component)val4).transform : null);
		RestoreZones(zones);
		MoveEnvironment(val, hostTrack, track, ((Object)(object)component != (Object)null) ? component.deathDepth : 30f);
		FitTrailsCamera(rootGameObjects, track);
		val6.AddComponent<MapFogKeeper>();
		MapFog.Active = false;
		val6.transform.SetParent((Transform)null, true);
		SceneManager.MoveGameObjectToScene(val6, scene);
		Object.Destroy((Object)(object)val5);
		ManualLogSource log2 = LoaderPlugin.Log;
		BepInExInfoLogInterpolatedStringHandler val7 = new BepInExInfoLogInterpolatedStringHandler(45, 4, ref flag);
		if (flag)
		{
			((BepInExLogInterpolatedStringHandler)val7).AppendLiteral("Built ");
			((BepInExLogInterpolatedStringHandler)val7).AppendFormatted<KitMapEntry>(map);
			((BepInExLogInterpolatedStringHandler)val7).AppendLiteral(" on '");
			((BepInExLogInterpolatedStringHandler)val7).AppendFormatted<string>(((Scene)(ref scene)).name);
			((BepInExLogInterpolatedStringHandler)val7).AppendLiteral("': ");
			((BepInExLogInterpolatedStringHandler)val7).AppendFormatted<int>(val.tiles.Count);
			((BepInExLogInterpolatedStringHandler)val7).AppendLiteral(" tiles, ");
			((BepInExLogInterpolatedStringHandler)val7).AppendFormatted<int>(num);
			((BepInExLogInterpolatedStringHandler)val7).AppendLiteral(" host object(s) hidden.");
		}
		log2.LogInfo(val7);
	}

	private static HostTrack ReadHostTrack(GameObject[] roots, StartLine start, FinishLine finish, EndGamePlatform podium)
	{
		//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c1: Expected O, but got Unknown
		//IL_0131: Unknown result type (might be due to invalid IL or missing references)
		//IL_0136: Unknown result type (might be due to invalid IL or missing references)
		//IL_0122: Unknown result type (might be due to invalid IL or missing references)
		HostTrack hostTrack = new HostTrack();
		Dictionary<Surface, int> dictionary = new Dictionary<Surface, int>();
		for (int i = 0; i < roots.Length; i++)
		{
			LevelTileObject[] componentsInChildren = roots[i].GetComponentsInChildren<LevelTileObject>(true);
			foreach (LevelTileObject val in componentsInChildren)
			{
				if (IsUnder(((Component)val).transform, start, finish, podium))
				{
					continue;
				}
				MeshRenderer component = ((Component)val).GetComponent<MeshRenderer>();
				if ((Object)(object)component == (Object)null || (Object)(object)((Renderer)component).sharedMaterial == (Object)null)
				{
					continue;
				}
				bool flag = ((Object)val).name.StartsWith("Border", StringComparison.OrdinalIgnoreCase);
				SurfaceInfo component2 = ((Component)val).GetComponent<SurfaceInfo>();
				if (!flag && (Object)(object)component2 != (Object)null && (Object)(object)component2.surface != (Object)null)
				{
					dictionary.TryGetValue(component2.surface, out var value);
					dictionary[component2.surface] = value + 1;
				}
				if (flag)
				{
					if ((Object)(object)hostTrack.Concrete == (Object)null)
					{
						hostTrack.Concrete = ((Renderer)component).sharedMaterial;
					}
				}
				else if ((Object)(object)hostTrack.Asphalt == (Object)null && SafeIsSwappable(((Renderer)component).sharedMaterial))
				{
					hostTrack.Asphalt = ((Renderer)component).sharedMaterial;
				}
				if (hostTrack.HasBounds)
				{
					((Bounds)(ref hostTrack.Bounds)).Encapsulate(((Renderer)component).bounds);
					continue;
				}
				hostTrack.Bounds = ((Renderer)component).bounds;
				hostTrack.HasBounds = true;
			}
		}
		int num = 0;
		foreach (KeyValuePair<Surface, int> item in dictionary)
		{
			if (item.Value > num)
			{
				num = item.Value;
				hostTrack.Surface = item.Key;
			}
		}
		ManualLogSource log = LoaderPlugin.Log;
		bool flag2 = default(bool);
		BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(31, 2, ref flag2);
		if (flag2)
		{
			((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Host road surface: ");
			((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(((Object)(object)hostTrack.Surface != (Object)null) ? ((Object)hostTrack.Surface).name : "none");
			((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("; material ");
			((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(((Object)(object)hostTrack.Asphalt != (Object)null) ? ((Object)hostTrack.Asphalt).name : "none");
			((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(".");
		}
		log.LogInfo(val2);
		if ((Object)(object)hostTrack.Asphalt == (Object)null)
		{
			LoaderPlugin.Log.LogWarning((object)"Host level has no swappable road material; roads keep their own.");
		}
		if ((Object)(object)hostTrack.Concrete == (Object)null)
		{
			hostTrack.Concrete = hostTrack.Asphalt;
		}
		return hostTrack;
	}

	private static bool SafeIsSwappable(Material m)
	{
		try
		{
			return (Object)(object)SurfaceManager.instance == (Object)null || SurfaceManager.IsSwappableMaterial(m);
		}
		catch
		{
			return true;
		}
	}

	private static bool IsSystem(GameObject root)
	{
		if (!((Object)(object)root.GetComponentInChildren<LevelDefinition>(true) != (Object)null) && !((Object)(object)root.GetComponentInChildren<LevelLighting>(true) != (Object)null) && !((Object)(object)root.GetComponentInChildren<GravityShape>(true) != (Object)null) && !((Object)(object)root.GetComponentInChildren<CameraManager>(true) != (Object)null) && !((Object)(object)root.GetComponentInChildren<StartLine>(true) != (Object)null) && !((Object)(object)root.GetComponentInChildren<FinishLine>(true) != (Object)null) && !((Object)(object)root.GetComponentInChildren<EndGamePlatform>(true) != (Object)null) && !((Object)(object)root.GetComponentInChildren<ObstacleLevelDefinition>(true) != (Object)null))
		{
			return (Object)(object)root.GetComponentInChildren<SkidMarkGenerator>(true) != (Object)null;
		}
		return true;
	}

	private static int HideHostTrack(GameObject[] roots, StartLine start, FinishLine finish, EndGamePlatform podium)
	{
		int num = 0;
		foreach (GameObject val in roots)
		{
			if (!IsSystem(val))
			{
				if (val.activeSelf)
				{
					val.SetActive(false);
					num++;
				}
				continue;
			}
			LevelTileObject[] componentsInChildren = val.GetComponentsInChildren<LevelTileObject>(true);
			foreach (LevelTileObject val2 in componentsInChildren)
			{
				if (!IsUnder(((Component)val2).transform, start, finish, podium) && ((Component)val2).gameObject.activeSelf)
				{
					((Component)val2).gameObject.SetActive(false);
					num++;
				}
			}
		}
		return num;
	}

	private static bool IsUnder(Transform t, StartLine start, FinishLine finish, EndGamePlatform podium)
	{
		if ((!((Object)(object)start != (Object)null) || !t.IsChildOf(((Component)start).transform)) && (!((Object)(object)finish != (Object)null) || !t.IsChildOf(((Component)finish).transform)))
		{
			if ((Object)(object)podium != (Object)null)
			{
				return t.IsChildOf(((Component)podium).transform);
			}
			return false;
		}
		return true;
	}

	private static Bounds BuildRoad(KitMapEntry map, GameObject mapGo, LevelDefinition def, HostTrack host)
	{
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_007d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0296: Unknown result type (might be due to invalid IL or missing references)
		//IL_0099: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a8: Invalid comparison between Unknown and I4
		//IL_0114: Unknown result type (might be due to invalid IL or missing references)
		//IL_011a: Invalid comparison between Unknown and I4
		//IL_0121: Unknown result type (might be due to invalid IL or missing references)
		//IL_0127: Invalid comparison between Unknown and I4
		//IL_0194: Unknown result type (might be due to invalid IL or missing references)
		//IL_019e: Expected O, but got Unknown
		//IL_0253: Unknown result type (might be due to invalid IL or missing references)
		//IL_025f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0264: Unknown result type (might be due to invalid IL or missing references)
		//IL_0269: Unknown result type (might be due to invalid IL or missing references)
		//IL_0279: Unknown result type (might be due to invalid IL or missing references)
		//IL_027b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0270: Unknown result type (might be due to invalid IL or missing references)
		Surface val = (((Object)(object)host.Surface != (Object)null) ? host.Surface : (((Object)(object)SurfaceManager.instance != (Object)null) ? SurfaceManager.DefaultSurface : null));
		int num = LayerMask.NameToLayer("RoadCombined");
		if (num < 0)
		{
			num = 16;
		}
		Bounds result = default(Bounds);
		bool flag = false;
		RoadSurfaces roadSurfaces = new RoadSurfaces(host, val);
		KitRoad[] componentsInChildren = mapGo.GetComponentsInChildren<KitRoad>(true);
		foreach (KitRoad val2 in componentsInChildren)
		{
			MeshRenderer component = ((Component)val2).GetComponent<MeshRenderer>();
			MeshFilter component2 = ((Component)val2).GetComponent<MeshFilter>();
			Surface surface = (((int)val2.kind == 0) ? roadSurfaces.Find(val2.surface) : val);
			Material val3 = (((int)val2.kind == 0) ? roadSurfaces.MaterialFor(surface) : (((int)val2.kind == 3) ? host.Asphalt : host.Concrete));
			if ((Object)(object)component != (Object)null && (Object)(object)val3 != (Object)null)
			{
				Material[] array = (Material[])(object)new Material[Mathf.Max(1, ((Renderer)component).sharedMaterials.Length)];
				for (int j = 0; j < array.Length; j++)
				{
					array[j] = val3;
				}
				((Renderer)component).materials = array;
			}
			if ((int)val2.kind == 2 || (int)val2.kind == 3)
			{
				continue;
			}
			((Component)val2).gameObject.layer = 0;
			((Component)val2).gameObject.AddComponent<SurfaceInfo>().surface = surface;
			LevelTileObject val4 = ((Component)val2).gameObject.AddComponent<LevelTileObject>();
			val4.id = new SerializableGuid(StableGuid(map.Id + "/" + (string.IsNullOrEmpty(val2.tileGuid) ? PathOf(((Component)val2).transform) : val2.tileGuid)));
			val4.nonBatchedMesh = (((Object)(object)component2 != (Object)null) ? component2.sharedMesh : null);
			def.tiles.Add(val4);
			Collider[] componentsInChildren2 = ((Component)val2).GetComponentsInChildren<Collider>(true);
			foreach (Collider val5 in componentsInChildren2)
			{
				if ((Object)(object)((Component)val5).gameObject != (Object)(object)((Component)val2).gameObject && (Object)(object)((Component)val5).gameObject.GetComponent<KitRoad>() == (Object)null && ((Object)val5).name == "RoadCombined")
				{
					((Component)val5).gameObject.layer = num;
				}
			}
			if ((Object)(object)component2 != (Object)null && (Object)(object)component2.sharedMesh != (Object)null)
			{
				Bounds val6 = TransformBounds(component2.sharedMesh.bounds, ((Component)val2).transform.localToWorldMatrix);
				if (flag)
				{
					((Bounds)(ref result)).Encapsulate(val6);
					continue;
				}
				result = val6;
				flag = true;
			}
		}
		roadSurfaces.LogMix();
		return result;
	}

	private static void BuildBoostPads(GameObject mapGo)
	{
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Expected O, but got Unknown
		int num = LayerMask.NameToLayer("RoadCombined");
		if (num < 0)
		{
			num = 16;
		}
		KitBoostPad[] componentsInChildren = mapGo.GetComponentsInChildren<KitBoostPad>(true);
		bool flag = default(bool);
		foreach (KitBoostPad val in componentsInChildren)
		{
			BoxCollider component = ((Component)val).GetComponent<BoxCollider>();
			if ((Object)(object)component == (Object)null)
			{
				ManualLogSource log = LoaderPlugin.Log;
				BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(41, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Boost pad '");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(((Object)val).name);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("' has no BoxCollider; skipped.");
				}
				log.LogWarning(val2);
				continue;
			}
			((Collider)component).isTrigger = true;
			((Component)val).gameObject.layer = num;
			if (val.capAtBoostSpeed)
			{
				AccelerationZone obj = ((Component)val).gameObject.AddComponent<AccelerationZone>();
				obj.trigger = component;
				obj.setVelocityOnEnter = val.boostSpeed > 0f;
				obj.velocityOnEnter = val.boostSpeed;
				obj.acceleration = val.continuousAcceleration;
				obj.dynamicResize = false;
			}
			else
			{
				((Component)val).gameObject.AddComponent<KitBoostZone>().boostSpeed = val.boostSpeed;
			}
		}
	}

	private static void BuildGravity(GameObject mapGo)
	{
		KitGravitySphere[] componentsInChildren = mapGo.GetComponentsInChildren<KitGravitySphere>(true);
		foreach (KitGravitySphere val in componentsInChildren)
		{
			GravityShapeSimpleSphere obj = ((Component)val).gameObject.AddComponent<GravityShapeSimpleSphere>();
			obj.gravity = val.gravity;
			obj.innerRadius = val.innerRadius;
			obj.outerRadius = val.outerRadius;
			obj.useObjectScale = false;
		}
	}

	private static void PlaceStart(GameObject mapGo, StartLine start)
	{
		if ((Object)(object)start == (Object)null)
		{
			return;
		}
		Place<KitStart>(mapGo, ((Component)start).transform);
		KitSpawns componentInChildren = mapGo.GetComponentInChildren<KitSpawns>(true);
		RandomPositionPlayerSpawner componentInChildren2 = ((Component)start).GetComponentInChildren<RandomPositionPlayerSpawner>(true);
		if (!((Object)(object)componentInChildren == (Object)null) && !((Object)(object)componentInChildren2 == (Object)null))
		{
			List<Transform> list = componentInChildren.Resolve();
			if (list.Count != 0)
			{
				Traverse.Create((object)componentInChildren2).Field("spawnPositions").SetValue((object)list);
				Transform val = FindDeep(mapGo.transform, "Spawn_TimeTrial");
				componentInChildren2.timeTrialSpawn = (((Object)(object)val != (Object)null) ? val : list[0]);
			}
		}
	}

	private static void Place<T>(GameObject mapGo, Transform target) where T : Component
	{
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Expected O, but got Unknown
		if ((Object)(object)target == (Object)null)
		{
			return;
		}
		T componentInChildren = mapGo.GetComponentInChildren<T>(true);
		if ((Object)(object)componentInChildren == (Object)null)
		{
			ManualLogSource log = LoaderPlugin.Log;
			bool flag = default(bool);
			BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(43, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Map has no ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(typeof(T).Name);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; the host's stays where it was.");
			}
			log.LogWarning(val);
		}
		else
		{
			target.SetPositionAndRotation(((Component)componentInChildren).transform.position, ((Component)componentInChildren).transform.rotation);
		}
	}

	private static List<ZonePose> RememberZones(ObstacleLevelDefinition obstacles, StartLine start, FinishLine finish)
	{
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00af: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
		List<ZonePose> list = new List<ZonePose>();
		if ((Object)(object)obstacles == (Object)null || obstacles.forbiddenObstacleZones == null)
		{
			return list;
		}
		BoxCollider[] forbiddenObstacleZones = obstacles.forbiddenObstacleZones;
		foreach (BoxCollider val in forbiddenObstacleZones)
		{
			if (!((Object)(object)val == (Object)null))
			{
				Transform val2 = Nearest(((Component)val).transform.position, ((Object)(object)start != (Object)null) ? ((Component)start).transform : null, ((Object)(object)finish != (Object)null) ? ((Component)finish).transform : null);
				if (!((Object)(object)val2 == (Object)null))
				{
					Quaternion val3 = Quaternion.Inverse(val2.rotation);
					list.Add(new ZonePose
					{
						Zone = ((Component)val).transform,
						Anchor = val2,
						LocalPosition = val3 * (((Component)val).transform.position - val2.position),
						LocalRotation = val3 * ((Component)val).transform.rotation
					});
				}
			}
		}
		return list;
	}

	private static void RestoreZones(List<ZonePose> zones)
	{
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: 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_006b: Expected O, but got Unknown
		//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
		bool flag = default(bool);
		foreach (ZonePose zone in zones)
		{
			zone.Zone.SetPositionAndRotation(zone.Anchor.position + zone.Anchor.rotation * zone.LocalPosition, zone.Anchor.rotation * zone.LocalRotation);
			ManualLogSource log = LoaderPlugin.Log;
			BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(36, 3, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("No-trap zone '");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(((Object)zone.Zone).name);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' follows '");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(((Object)zone.Anchor).name);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("', now at ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Vector3>(zone.Zone.position);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(".");
			}
			log.LogInfo(val);
		}
		if (zones.Count == 0)
		{
			LoaderPlugin.Log.LogWarning((object)"Host level has no no-trap zones; start and finish are unprotected.");
		}
	}

	private static Transform FindDeep(Transform parent, string name)
	{
		Transform[] componentsInChildren = ((Component)parent).GetComponentsInChildren<Transform>(true);
		foreach (Transform val in componentsInChildren)
		{
			if (((Object)val).name == name)
			{
				return val;
			}
		}
		return null;
	}

	private static Transform Nearest(Vector3 p, Transform a, Transform b)
	{
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: 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)
		if ((Object)(object)a == (Object)null)
		{
			return b;
		}
		if ((Object)(object)b == (Object)null)
		{
			return a;
		}
		Vector3 val = a.position - p;
		float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
		val = b.position - p;
		if (!(sqrMagnitude <= ((Vector3)(ref val)).sqrMagnitude))
		{
			return b;
		}
		return a;
	}

	private static void MoveEnvironment(LevelDefinition def, HostTrack host, Bounds track, float deathDepth)
	{
		//IL_000a: 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_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00de: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fe: 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_010f: Unknown result type (might be due to invalid IL or missing references)
		if (host.HasBounds && !(((Bounds)(ref track)).size == Vector3.zero))
		{
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(((Bounds)(ref track)).center.x - ((Bounds)(ref host.Bounds)).center.x, ((Bounds)(ref track)).min.y - ((Bounds)(ref host.Bounds)).min.y, ((Bounds)(ref track)).center.z - ((Bounds)(ref host.Bounds)).center.z);
			if ((Object)(object)def.environmentVisualRoot != (Object)null)
			{
				Transform environmentVisualRoot = def.environmentVisualRoot;
				environmentVisualRoot.position += val;
			}
			if ((Object)(object)def.fogPlane != (Object)null)
			{
				Transform transform = ((Component)def.fogPlane).transform;
				float num = Mathf.Max(deathDepth, ((Bounds)(ref host.Bounds)).min.y - transform.position.y);
				transform.position = new Vector3(transform.position.x + val.x, ((Bounds)(ref track)).min.y - num, transform.position.z + val.z);
			}
		}
	}

	private static void FitTrailsCamera(GameObject[] roots, Bounds track)
	{
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00de: Unknown result type (might be due to invalid IL or missing references)
		//IL_0104: Unknown result type (might be due to invalid IL or missing references)
		//IL_0109: Unknown result type (might be due to invalid IL or missing references)
		//IL_012d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0134: Expected O, but got Unknown
		TrailCameraShaderValuesAssigner val = Find<TrailCameraShaderValuesAssigner>(roots);
		if ((Object)(object)val == (Object)null || (Object)(object)val.trailCamera == (Object)null || ((Bounds)(ref track)).size == Vector3.zero)
		{
			LoaderPlugin.Log.LogWarning((object)"No trails camera found; far parts of the map may draw flat.");
			return;
		}
		Camera trailCamera = val.trailCamera;
		float orthographicSize = trailCamera.orthographicSize;
		float num = Mathf.Max(((Bounds)(ref track)).extents.x, ((Bounds)(ref track)).extents.z) + 20f;
		float num2 = Mathf.Max(((Component)trailCamera).transform.position.y, ((Bounds)(ref track)).max.y + 50f);
		((Component)trailCamera).transform.position = new Vector3(((Bounds)(ref track)).center.x, num2, ((Bounds)(ref track)).center.z);
		trailCamera.orthographicSize = Mathf.Max(orthographicSize, num);
		trailCamera.farClipPlane = Mathf.Max(trailCamera.farClipPlane, num2 - ((Bounds)(ref track)).min.y + 100f);
		Shader.SetGlobalVector(TrailsOrthoCamPosition, Vector4.op_Implicit(((Component)trailCamera).transform.position));
		Shader.SetGlobalFloat(TrailsOrthoCam, trailCamera.orthographicSize);
		ManualLogSource log = LoaderPlugin.Log;
		bool flag = default(bool);
		BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(51, 2, ref flag);
		if (flag)
		{
			((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Trails camera: ");
			((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<float>(orthographicSize * 2f, "0");
			((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" m square -> ");
			((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<float>(trailCamera.orthographicSize * 2f, "0");
			((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" m, centred on the map.");
		}
		log.LogInfo(val2);
	}

	private static T Find<T>(GameObject[] roots) where T : Component
	{
		for (int i = 0; i < roots.Length; i++)
		{
			T componentInChildren = roots[i].GetComponentInChildren<T>(true);
			if ((Object)(object)componentInChildren != (Object)null)
			{
				return componentInChildren;
			}
		}
		return default(T);
	}

	private static Guid StableGuid(string key)
	{
		using MD5 mD = MD5.Create();
		return new Guid(mD.ComputeHash(Encoding.UTF8.GetBytes(key)));
	}

	private static string PathOf(Transform t)
	{
		StringBuilder stringBuilder = new StringBuilder(((Object)t).name);
		Transform parent = t.parent;
		while ((Object)(object)parent != (Object)null)
		{
			stringBuilder.Insert(0, ((Object)parent).name + "/");
			parent = parent.parent;
		}
		return stringBuilder.ToString();
	}

	internal static Bounds TransformBounds(Bounds b, Matrix4x4 m)
	{
		//IL_0004: Unknown result type (might be due to invalid IL or missing references)
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: 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)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_0092: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: 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_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
		Vector3 val = ((Matrix4x4)(ref m)).MultiplyPoint3x4(((Bounds)(ref b)).center);
		Vector3 extents = ((Bounds)(ref b)).extents;
		Vector3 val2 = ((Matrix4x4)(ref m)).MultiplyVector(new Vector3(extents.x, 0f, 0f));
		Vector3 val3 = ((Matrix4x4)(ref m)).MultiplyVector(new Vector3(0f, extents.y, 0f));
		Vector3 val4 = ((Matrix4x4)(ref m)).MultiplyVector(new Vector3(0f, 0f, extents.z));
		Vector3 val5 = default(Vector3);
		((Vector3)(ref val5))..ctor(Mathf.Abs(val2.x) + Mathf.Abs(val3.x) + Mathf.Abs(val4.x), Mathf.Abs(val2.y) + Mathf.Abs(val3.y) + Mathf.Abs(val4.y), Mathf.Abs(val2.z) + Mathf.Abs(val3.z) + Mathf.Abs(val4.z));
		return new Bounds(val, val5 * 2f);
	}
}
internal sealed class KitMapEntry
{
	public string Folder;

	public string Id;

	public string Name;

	public string Host;

	public int Difficulty = 1;

	public bool Reversible;

	public string ThumbnailFile;

	public string PreviewFile;

	public string PreviewModelFile;

	public string BundlePath;

	public GameObject Prefab;

	public Level Level;

	public string HostSceneName;

	public Surface HostSurface;

	public Mesh PreviewMesh;

	public int TileCount;

	public override string ToString()
	{
		return Name + " [" + Id + "]";
	}
}
internal static class MapCatalog
{
	public const string ManifestName = "mapkit.json";

	public static readonly List<KitMapEntry> Maps = new List<KitMapEntry>();

	public static void Discover()
	{
		//IL_0138: Unknown result type (might be due to invalid IL or missing references)
		//IL_013f: Expected O, but got Unknown
		//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fe: Expected O, but got Unknown
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0091: Expected O, but got Unknown
		HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
		string[] array = new string[2]
		{
			Path.Combine(Paths.BepInExRootPath, "CustomMaps"),
			Paths.PluginPath
		};
		bool flag = default(bool);
		foreach (string path in array)
		{
			if (!Directory.Exists(path))
			{
				continue;
			}
			string[] files = Directory.GetFiles(path, "mapkit.json", SearchOption.AllDirectories);
			foreach (string text in files)
			{
				try
				{
					KitMapEntry kitMapEntry = Load(text);
					if (kitMapEntry == null)
					{
						continue;
					}
					if (!hashSet.Add(kitMapEntry.Id))
					{
						ManualLogSource log = LoaderPlugin.Log;
						BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(30, 2, ref flag);
						if (flag)
						{
							((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Skipping duplicate map '");
							((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(kitMapEntry.Id);
							((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' in ");
							((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(kitMapEntry.Folder);
							((BepInExLogInterpolatedStringHandler)val).AppendLiteral(".");
						}
						log.LogWarning(val);
					}
					else
					{
						Maps.Add(kitMapEntry);
						ManualLogSource log2 = LoaderPlugin.Log;
						BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(11, 1, ref flag);
						if (flag)
						{
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Found map ");
							((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<KitMapEntry>(kitMapEntry);
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(".");
						}
						log2.LogInfo(val2);
					}
				}
				catch (Exception ex)
				{
					ManualLogSource log3 = LoaderPlugin.Log;
					BepInExErrorLogInterpolatedStringHandler val3 = new BepInExErrorLogInterpolatedStringHandler(26, 2, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Could not load map from ");
						((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(text);
						((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(": ");
						((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(ex.Message);
					}
					log3.LogError(val3);
				}
			}
		}
	}

	private static KitMapEntry Load(string manifestPath)
	{
		//IL_0121: Unknown result type (might be due to invalid IL or missing references)
		//IL_0128: Expected O, but got Unknown
		//IL_0177: Unknown result type (might be due to invalid IL or missing references)
		//IL_017e: Expected O, but got Unknown
		string directoryName = Path.GetDirectoryName(manifestPath);
		JObject val = JObject.Parse(File.ReadAllText(manifestPath));
		KitMapEntry kitMapEntry = new KitMapEntry
		{
			Folder = directoryName,
			Id = (string)val["id"],
			Name = (string)val["name"],
			Host = (((string)val["host"]) ?? ""),
			Difficulty = (((int?)val["difficulty"]) ?? 1),
			Reversible = ((bool?)val["isReversible"] == true),
			ThumbnailFile = Resolve(directoryName, (string)val["thumbnail"]),
			PreviewFile = Resolve(directoryName, (string)val["preview"]),
			PreviewModelFile = Resolve(directoryName, (string)val["previewModel"])
		};
		bool flag = default(bool);
		if (string.IsNullOrEmpty(kitMapEntry.Id) || string.IsNullOrEmpty(kitMapEntry.Name))
		{
			ManualLogSource log = LoaderPlugin.Log;
			BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(31, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(manifestPath);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": 'id' and 'name' are required.");
			}
			log.LogError(val2);
			return null;
		}
		kitMapEntry.BundlePath = Resolve(directoryName, (string)val["bundle"]);
		if (kitMapEntry.BundlePath == null)
		{
			ManualLogSource log2 = LoaderPlugin.Log;
			BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(19, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<KitMapEntry>(kitMapEntry);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": bundle not found.");
			}
			log2.LogError(val2);
			return null;
		}
		if (kitMapEntry.PreviewModelFile != null)
		{
			kitMapEntry.PreviewMesh = LoadPreviewModel(kitMapEntry.PreviewModelFile);
		}
		return kitMapEntry;
	}

	public static IEnumerator LoadBundles()
	{
		KitMapEntry[] array = Maps.ToArray();
		bool flag = default(bool);
		foreach (KitMapEntry map in array)
		{
			AssetBundleCreateRequest create = AssetBundle.LoadFromFileAsync(map.BundlePath);
			yield return create;
			AssetBundle assetBundle = create.assetBundle;
			if ((Object)(object)assetBundle == (Object)null)
			{
				ManualLogSource log = LoaderPlugin.Log;
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(52, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<KitMapEntry>(map);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(Path.GetFileName(map.BundlePath));
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" is not a valid bundle (built with Unity 2022.3?).");
				}
				log.LogError(val);
				Maps.Remove(map);
				continue;
			}
			AssetBundleRequest assets = assetBundle.LoadAllAssetsAsync<GameObject>();
			yield return assets;
			Object[] allAssets = assets.allAssets;
			foreach (Object obj in allAssets)
			{
				GameObject val2 = (GameObject)(object)((obj is GameObject) ? obj : null);
				if (val2 != null && (Object)(object)val2.GetComponent<KitMap>() != (Object)null)
				{
					map.Prefab = val2;
					break;
				}
			}
			if ((Object)(object)map.Prefab == (Object)null)
			{
				ManualLogSource log2 = LoaderPlugin.Log;
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(51, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<KitMapEntry>(map);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": the bundle has no prefab with a KitMap component.");
				}
				log2.LogError(val);
				Maps.Remove(map);
				continue;
			}
			KitRoad[] componentsInChildren = map.Prefab.GetComponentsInChildren<KitRoad>(true);
			foreach (KitRoad val3 in componentsInChildren)
			{
				if ((int)val3.kind == 0 || (int)val3.kind == 1)
				{
					map.TileCount++;
				}
			}
			ManualLogSource log3 = LoaderPlugin.Log;
			BepInExInfoLogInterpolatedStringHandler val4 = new BepInExInfoLogInterpolatedStringHandler(16, 2, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("Loaded ");
				((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<KitMapEntry>(map);
				((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(": ");
				((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<int>(map.TileCount);
				((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" tiles.");
			}
			log3.LogInfo(val4);
		}
	}

	public static KitMapEntry FromLevel(Level level)
	{
		if ((Object)(object)level == (Object)null)
		{
			return null;
		}
		foreach (KitMapEntry map in Maps)
		{
			if ((Object)(object)map.Level == (Object)(object)level)
			{
				return map;
			}
		}
		return null;
	}

	public static bool IsCustomLevelName(string name)
	{
		foreach (KitMapEntry map in Maps)
		{
			if ((Object)(object)map.Level != (Object)null && string.Equals(map.Level.name, name, StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
		}
		return false;
	}

	private static string Resolve(string folder, string file)
	{
		if (string.IsNullOrEmpty(file))
		{
			return null;
		}
		string text = Path.Combine(folder, file);
		if (!File.Exists(text))
		{
			return null;
		}
		return text;
	}

	private static Mesh LoadPreviewModel(string path)
	{
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_0129: Unknown result type (might be due to invalid IL or missing references)
		//IL_012e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0149: Unknown result type (might be due to invalid IL or missing references)
		//IL_0151: Expected O, but got Unknown
		List<Vector3> list = new List<Vector3>();
		List<List<int>> list2 = new List<List<int>>
		{
			new List<int>()
		};
		CultureInfo invariantCulture = CultureInfo.InvariantCulture;
		foreach (string item in File.ReadLines(path))
		{
			if (item.StartsWith("v "))
			{
				string[] array = item.Split(new char[1] { ' ' });
				list.Add(new Vector3(float.Parse(array[1], invariantCulture), float.Parse(array[2], invariantCulture), float.Parse(array[3], invariantCulture)));
			}
			else if (item.StartsWith("f "))
			{
				string[] array2 = item.Split(new char[1] { ' ' });
				List<int> list3 = list2[list2.Count - 1];
				for (int i = 1; i <= 3; i++)
				{
					list3.Add(int.Parse(array2[i], invariantCulture) - 1);
				}
			}
			else if (item.StartsWith("g ") && list2[list2.Count - 1].Count > 0)
			{
				list2.Add(new List<int>());
			}
		}
		Mesh val = new Mesh
		{
			name = Path.GetFileName(Path.GetDirectoryName(path)) + "_Preview",
			indexFormat = (IndexFormat)1
		};
		val.SetVertices(list);
		val.subMeshCount = list2.Count;
		for (int j = 0; j < list2.Count; j++)
		{
			val.SetTriangles(list2[j], j);
		}
		val.RecalculateNormals();
		val.RecalculateBounds();
		((Object)val).hideFlags = (HideFlags)32;
		return val;
	}
}
[HarmonyPatch(typeof(LevelManager), "Awake")]
internal static class LevelManagerAwakePatch
{
	private static void Postfix(LevelManager __instance)
	{
		if ((Object)(object)LevelManager.instance == (Object)(object)__instance)
		{
			LevelRegistry.Inject(__instance);
		}
	}
}
[HarmonyPatch(typeof(SceneManager), "LoadLevel", new Type[] { typeof(Level) })]
internal static class LoadLevelPatch
{
	private static void Prefix(Level selectedLevel)
	{
		MapBuilder.Pending = MapCatalog.FromLevel(selectedLevel);
	}
}
[HarmonyPatch(typeof(SceneManager), "LoadAsyncScene")]
internal static class LoadAsyncScenePatch
{
	private static bool Prefix(SceneManager __instance, string sceneName, Action onComplete)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		Scene activeScene = SceneManager.GetActiveScene();
		if (((Scene)(ref activeScene)).name != sceneName || MapBuilder.BuiltFor == MapBuilder.Pending)
		{
			return true;
		}
		((MonoBehaviour)__instance).StartCoroutine(Reload(sceneName, onComplete));
		return false;
	}

	private static IEnumerator Reload(string sceneName, Action onComplete)
	{
		AsyncOperation op = SceneManager.LoadSceneAsync(sceneName);
		while (!op.isDone)
		{
			yield return null;
		}
		onComplete?.Invoke();
	}
}
[HarmonyPatch(typeof(PlayerGhostUtils), "LoadGameGhost", new Type[]
{
	typeof(string),
	typeof(Action<ValueTuple<bool, PlayerGhost>>)
})]
internal static class SkipGameGhostPatch
{
	private static bool Prefix(string levelName, Action<(bool, PlayerGhost)> loadedCallBack)
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		if (!MapCatalog.IsCustomLevelName(levelName))
		{
			return true;
		}
		loadedCallBack?.Invoke((false, default(PlayerGhost)));
		return false;
	}
}
[HarmonyPatch(typeof(LevelSelect), "BuildUI")]
internal static class LevelSelectBuildUiPatch
{
	private static void Prefix()
	{
		if ((Object)(object)LevelManager.instance != (Object)null)
		{
			LevelRegistry.Inject(LevelManager.instance);
		}
		LevelRegistry.RefreshSurfaceCounts();
	}
}

SlipSkid.MapKit.SDK.dll

Decompiled 16 hours ago
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("SlipSkid.MapKit.SDK")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+afa60f15dde673ac3bacd5ea8ae4cb6c69489d42")]
[assembly: AssemblyProduct("SlipSkid.MapKit.SDK")]
[assembly: AssemblyTitle("SlipSkid.MapKit.SDK")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace SlipSkid.MapKit.SDK;

public class KitBoostPad : MonoBehaviour
{
	[Tooltip("Speed added along the car's forward when it enters.")]
	public float boostSpeed = 20f;

	[Tooltip("Off: boostSpeed is always added. On: the game's own behaviour - cars slower than boostSpeed get boostSpeed added, and continuousAcceleration pushes while inside.")]
	public bool capAtBoostSpeed;

	[Tooltip("Push along this object's forward while a car is inside (only with capAtBoostSpeed).")]
	public float continuousAcceleration;
}
public class KitDecor : MonoBehaviour
{
	[Tooltip("Width of the piece, in metres. Its base sits on this marker.")]
	public float size = 40f;

	[Tooltip("Only use environment pieces whose name contains this (e.g. Mountain, City). Empty = any.")]
	public string prefer = "";
}
public class KitFinish : MonoBehaviour
{
}
public class KitGravitySphere : MonoBehaviour
{
	public float gravity = -90f;

	public float innerRadius;

	public float outerRadius = 20f;
}
[DisallowMultipleComponent]
public class KitMap : MonoBehaviour
{
	public string mapName = "My Map";

	public string author = "";

	[Range(1f, 5f)]
	public int difficulty = 1;

	public bool isReversible;

	[Tooltip("Stock level whose scenery, lighting and music this map uses. Empty = the first stock level.")]
	public string hostLevel = "";

	[Tooltip("How far below the lowest road the death plane sits, in metres.")]
	public float deathDepth = 30f;
}
public class KitPodium : MonoBehaviour
{
}
public enum KitRoadKind
{
	Road,
	Border,
	Concrete,
	Dark
}
[DisallowMultipleComponent]
public class KitRoad : MonoBehaviour
{
	public KitRoadKind kind;

	[Tooltip("Stable unique id; surface swaps are networked by it. Filled in by the kit.")]
	public string tileGuid = "";

	[Tooltip("Road tiles: game surface to use (e.g. \"Asphalt\", \"Mud\", \"Ice\"; matched by name). Empty = the host level's road surface.")]
	public string surface = "";
}
public class KitSpawns : MonoBehaviour
{
	public List<Transform> points = new List<Transform>();

	public List<Transform> Resolve()
	{
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Expected O, but got Unknown
		if (points != null && points.Count > 0)
		{
			return points;
		}
		List<Transform> list = new List<Transform>();
		foreach (Transform item2 in ((Component)this).transform)
		{
			Transform item = item2;
			list.Add(item);
		}
		return list;
	}
}
public class KitStart : MonoBehaviour
{
}