Decompiled source of MoreMaps v0.1.0

BepInEx/plugins/MoreMaps/SlipSkid.MoreMaps.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.Mono;
using Effects;
using Game;
using Game.Levels;
using HarmonyLib;
using Menus;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Obstacles;
using Player;
using Sounds;
using Sounds.SplitScreenAudio;
using Unity.Netcode;
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(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("SlipSkid.MoreMaps")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+7ead4b9d8640ee245917dc60b6725a6dd6f65a8a")]
[assembly: AssemblyProduct("SlipSkid.MoreMaps")]
[assembly: AssemblyTitle("SlipSkid.MoreMaps")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace SlipSkid.MoreMaps
{
	internal static class AutoDump
	{
		private static bool _started;

		internal static void OnSceneLoaded(string scene, MonoBehaviour host)
		{
			if (!_started && !(scene != "MainMenu") && (Plugin.DumpAllTracks.Value || Plugin.PreviewRoutes.Value || Plugin.RunProbe.Value || !string.IsNullOrWhiteSpace(Plugin.Gallery.Value) || !string.IsNullOrWhiteSpace(Plugin.Snapshot.Value) || Plugin.DumpBiomes.Value))
			{
				_started = true;
				host.StartCoroutine(Routine());
			}
		}

		private static IEnumerator Routine()
		{
			yield return (object)new WaitForSeconds(3f);
			Level[] levels = (Object.op_Implicit((Object)(object)LevelManager.instance) ? LevelManager.instance.levels : null);
			if (levels == null)
			{
				Plugin.Log.LogError((object)"AutoDump: no LevelManager");
				yield break;
			}
			if (Plugin.RunProbe.Value)
			{
				Guard.Run("Probe", Probe.Run);
			}
			string[] array = (from x in (Plugin.Gallery.Value ?? "").Split(',')
				select x.Trim() into x
				where x.Length > 0
				select x).ToArray();
			foreach (string scene in array)
			{
				yield return Probe.Gallery(scene);
			}
			array = (from x in (Plugin.Snapshot.Value ?? "").Split('|')
				select x.Trim() into x
				where x.Contains(":")
				select x).ToArray();
			foreach (string spec in array)
			{
				yield return Probe.Snapshot(spec);
			}
			if (Plugin.DumpAllTracks.Value)
			{
				Level[] array2 = levels.Where((Level l) => Object.op_Implicit((Object)(object)l) && CustomLevels.RouteFor(l) == null).ToArray();
				bool flag = default(bool);
				foreach (Level level in array2)
				{
					yield return Load(level.sceneName);
					LevelDefinition def = Object.FindObjectOfType<LevelDefinition>();
					if (Object.op_Implicit((Object)(object)def))
					{
						Guard.Run("AutoDump", delegate
						{
							KitDump.Run(def, level.name);
						});
						continue;
					}
					ManualLogSource log = Plugin.Log;
					BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(33, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("AutoDump: ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(level.sceneName);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" has no LevelDefinition");
					}
					log.LogWarning(val);
				}
			}
			if (Plugin.DumpBiomes.Value)
			{
				Level[] array2 = levels.Where((Level l) => Object.op_Implicit((Object)(object)l) && CustomLevels.RouteFor(l) == null).ToArray();
				foreach (Level level2 in array2)
				{
					yield return Load(level2.sceneName);
					LevelDefinition def2 = Object.FindObjectOfType<LevelDefinition>();
					if (Object.op_Implicit((Object)(object)def2))
					{
						ShowScenery(def2);
						Guard.Run("AutoDump", delegate
						{
							BiomeDump.Run(def2, level2.sceneName);
						});
					}
				}
			}
			if (Plugin.PreviewRoutes.Value)
			{
				Level[] array2 = levels.Where((Level l) => Object.op_Implicit((Object)(object)l) && CustomLevels.RouteFor(l) != null).ToArray();
				foreach (Level level3 in array2)
				{
					yield return KitLibrary.Harvest(CustomLevels.RouteFor(level3));
					yield return Load(level3.sceneName);
					LevelDefinition def3 = Object.FindObjectOfType<LevelDefinition>();
					RouteData route = CustomLevels.RouteFor(level3);
					if (!Object.op_Implicit((Object)(object)def3))
					{
						continue;
					}
					if (Plugin.DumpKit.Value)
					{
						Guard.Run("AutoDump", delegate
						{
							KitDump.Run(def3, level3.name);
						});
					}
					Guard.Run("AutoDump", delegate
					{
						TrackBuilder.Build(def3, route);
					});
					ShowScenery(def3);
					Guard.Run("SceneFit", delegate
					{
						SceneFit.Apply(def3, TrackBuilder.LastBuild);
					});
					Guard.Run("Scenery", delegate
					{
						Scenery.Place(def3, route, TrackBuilder.LastBuild);
					});
					yield return null;
					LevelSelectInfo.Prepare();
					yield return LevelSelectInfo.RenderPreviewMesh(level3);
					Guard.Run("AutoDump", delegate
					{
						TrackPreview.Report(def3, route);
					});
					yield return TrackPreview.Capture(def3, route);
				}
			}
			Plugin.DumpAllTracks.Value = false;
			Plugin.PreviewRoutes.Value = false;
			Plugin.RunProbe.Value = false;
			Plugin.Gallery.Value = "";
			Plugin.Snapshot.Value = "";
			Plugin.DumpBiomes.Value = false;
			Plugin.Log.LogInfo((object)"AutoDump: done");
			if (Plugin.QuitAfterDump.Value)
			{
				Application.Quit();
			}
			else
			{
				yield return Load("MainMenu");
			}
		}

		internal static void ShowScenery(LevelDefinition def)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Expected O, but got Unknown
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Expected O, but got Unknown
			bool flag = default(bool);
			try
			{
				def.Init();
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(70, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("AutoDump: LevelDefinition.Init stopped outside a match (");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.GetType().Name);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("), as expected");
				}
				log.LogInfo(val);
			}
			try
			{
				Traverse obj = Traverse.Create((object)def);
				obj.Method("CountTilesSurfaces", Array.Empty<object>()).GetValue();
				Surface value = obj.Field("_maxSurfaceTileCount").GetValue<Surface>();
				IDictionary value2 = obj.Field("_environmentBiomes").GetValue<IDictionary>();
				if (Object.op_Implicit((Object)(object)value) && value2 != null && value2.Contains(value))
				{
					object obj2 = value2[value];
					((GameObject)obj2.GetType().GetField("Item2").GetValue(obj2)).SetActive(true);
					ManualLogSource log2 = Plugin.Log;
					BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(30, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("AutoDump: showing the ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(((Object)value).name);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" scenery");
					}
					log2.LogInfo(val);
				}
			}
			catch (Exception ex2)
			{
				ManualLogSource log3 = Plugin.Log;
				BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(38, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("AutoDump: couldn't show the scenery: ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex2.GetType().Name);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex2.Message);
				}
				log3.LogWarning(val2);
			}
		}

		internal static IEnumerator Load(string scene)
		{
			ManualLogSource log = Plugin.Log;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(18, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("AutoDump: loading ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(scene);
			}
			log.LogInfo(val);
			AsyncOperation op = SceneManager.LoadSceneAsync(scene);
			while (!op.isDone)
			{
				yield return null;
			}
			yield return null;
			yield return null;
		}
	}
	internal static class BiomeDump
	{
		internal static void Run(LevelDefinition def, string scene)
		{
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: 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_0309: Unknown result type (might be due to invalid IL or missing references)
			//IL_0310: Expected O, but got Unknown
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: 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_0246: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_024b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0274: Unknown result type (might be due to invalid IL or missing references)
			StringBuilder stringBuilder = new StringBuilder();
			List<Vector3> list = (from t in def.tiles
				where Object.op_Implicit((Object)(object)t)
				select ((Component)t).transform.position).ToList();
			if (list.Count > 0)
			{
				stringBuilder.AppendLine($"road from {Min(list):F0} to {Max(list):F0}");
			}
			stringBuilder.AppendLine($"environmentVisualRoot at {(Object.op_Implicit((Object)(object)def.environmentVisualRoot) ? def.environmentVisualRoot.position : Vector3.zero):F0}");
			if (Traverse.Create((object)def).Field("_environmentBiomes").GetValue() is IDictionary dictionary)
			{
				foreach (DictionaryEntry item in dictionary)
				{
					object? obj = item.Value.GetType().GetField("Item2")?.GetValue(item.Value);
					GameObject val = (GameObject)((obj is GameObject) ? obj : null);
					if (!Object.op_Implicit((Object)(object)val))
					{
						continue;
					}
					stringBuilder.AppendLine();
					object key = item.Key;
					object obj2 = ((key is Object) ? key : null);
					stringBuilder.AppendLine($"== {((obj2 != null) ? ((Object)obj2).name : null)} biome: {((Object)val).name} at {val.transform.position:F0}");
					Tree(stringBuilder, val.transform, 0);
					stringBuilder.AppendLine("-- meshes:");
					foreach (IGrouping<string, MeshFilter> item2 in from f in val.GetComponentsInChildren<MeshFilter>(true)
						where Object.op_Implicit((Object)(object)f.sharedMesh)
						group f by ((Object)f.sharedMesh).name into g
						orderby g.Count() descending
						select g)
					{
						Renderer component = ((Component)item2.First()).GetComponent<Renderer>();
						Vector3 val2;
						if (component == null)
						{
							val2 = Vector3.zero;
						}
						else
						{
							Bounds bounds = component.bounds;
							val2 = ((Bounds)(ref bounds)).size;
						}
						Vector3 val3 = val2;
						stringBuilder.AppendLine($"   {item2.Key} x{item2.Count()} size {val3:F0} e.g. {KitDump.Path(((Component)item2.First()).transform)}");
					}
				}
			}
			string text = Path.Combine(Plugin.Dir, "biomes-" + scene + ".txt");
			File.WriteAllText(text, stringBuilder.ToString());
			ManualLogSource log = Plugin.Log;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val4 = new BepInExInfoLogInterpolatedStringHandler(17, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("BiomeDump: wrote ");
				((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(text);
			}
			log.LogInfo(val4);
		}

		private static void Tree(StringBuilder sb, Transform t, int depth)
		{
			//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_0025: 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_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Expected O, but got Unknown
			Renderer[] componentsInChildren = ((Component)t).GetComponentsInChildren<Renderer>(true);
			if (componentsInChildren.Length == 0)
			{
				return;
			}
			Bounds bounds = componentsInChildren[0].bounds;
			Renderer[] array = componentsInChildren;
			foreach (Renderer val in array)
			{
				((Bounds)(ref bounds)).Encapsulate(val.bounds);
			}
			sb.AppendLine(string.Format("{0}{1}{2}: {3} renderers, ", new string(' ', depth * 2), ((Object)t).name, ((Component)t).gameObject.activeSelf ? "" : " (off)", componentsInChildren.Length) + $"{((Bounds)(ref bounds)).min:F0}..{((Bounds)(ref bounds)).max:F0}");
			if (depth >= 3 || t.childCount > 60)
			{
				return;
			}
			foreach (Transform item in t)
			{
				Transform t2 = item;
				Tree(sb, t2, depth + 1);
			}
		}

		private static Vector3 Min(List<Vector3> v)
		{
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			return new Vector3(v.Min((Vector3 p) => p.x), v.Min((Vector3 p) => p.y), v.Min((Vector3 p) => p.z));
		}

		private static Vector3 Max(List<Vector3> v)
		{
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			return new Vector3(v.Max((Vector3 p) => p.x), v.Max((Vector3 p) => p.y), v.Max((Vector3 p) => p.z));
		}
	}
	internal static class KitDump
	{
		private static readonly Regex TileName = new Regex("R([0-9]{3})B([0-9]{3})", RegexOptions.IgnoreCase);

		internal static string Code(string name)
		{
			Match match = TileName.Match(name ?? "");
			if (!match.Success)
			{
				return null;
			}
			return "R" + match.Groups[1].Value + "B" + match.Groups[2].Value;
		}

		internal static void Run(LevelDefinition def, string label)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			//IL_0043: 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_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_0237: 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_0284: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0303: Unknown result type (might be due to invalid IL or missing references)
			//IL_030d: Expected O, but got Unknown
			//IL_030d: Unknown result type (might be due to invalid IL or missing references)
			//IL_036a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0374: Expected O, but got Unknown
			//IL_0374: Unknown result type (might be due to invalid IL or missing references)
			//IL_039b: Expected O, but got Unknown
			//IL_03c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_053d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0547: Expected O, but got Unknown
			//IL_0434: Unknown result type (might be due to invalid IL or missing references)
			//IL_043e: Expected O, but got Unknown
			//IL_043e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0504: Unknown result type (might be due to invalid IL or missing references)
			//IL_050e: Expected O, but got Unknown
			//IL_0473: Unknown result type (might be due to invalid IL or missing references)
			//IL_047d: Expected O, but got Unknown
			//IL_047d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0498: Expected O, but got Unknown
			//IL_0593: Unknown result type (might be due to invalid IL or missing references)
			//IL_059a: Expected O, but got Unknown
			//IL_063a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0644: Expected O, but got Unknown
			//IL_0650: Unknown result type (might be due to invalid IL or missing references)
			//IL_0655: Unknown result type (might be due to invalid IL or missing references)
			//IL_0682: Unknown result type (might be due to invalid IL or missing references)
			//IL_068c: Expected O, but got Unknown
			//IL_06c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_06cc: Expected O, but got Unknown
			//IL_0816: Unknown result type (might be due to invalid IL or missing references)
			//IL_081d: Expected O, but got Unknown
			//IL_08e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_08ed: Expected O, but got Unknown
			//IL_089e: Unknown result type (might be due to invalid IL or missing references)
			//IL_08a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_08a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0981: Unknown result type (might be due to invalid IL or missing references)
			//IL_0986: Unknown result type (might be due to invalid IL or missing references)
			Scene scene = ((Component)def).gameObject.scene;
			string name = ((Scene)(ref scene)).name;
			JObject val = new JObject
			{
				["scene"] = JToken.op_Implicit(name),
				["label"] = JToken.op_Implicit(label)
			};
			val["levelDefinition"] = (JToken)new JObject
			{
				["startLine"] = (JToken)(object)Pose(Object.op_Implicit((Object)(object)def.startLine) ? ((Component)def.startLine).transform : null),
				["startLineFinishOffset"] = (JToken)(object)Pose(Object.op_Implicit((Object)(object)def.startLine) ? def.startLine.finishLineRootOffset : null),
				["finishLine"] = (JToken)(object)Pose(Object.op_Implicit((Object)(object)def.finishLine) ? ((Component)def.finishLine).transform : null),
				["finishLineStartOffset"] = (JToken)(object)Pose(Object.op_Implicit((Object)(object)def.finishLine) ? def.finishLine.startLineRootOffset : null),
				["finishSnapshot"] = (JToken)(object)Pose(Object.op_Implicit((Object)(object)def.finishLine) ? def.finishLine.snapShotPos : null),
				["finishColliders"] = (JToken)(object)(Object.op_Implicit((Object)(object)def.finishLine) ? Colliders(((Component)def.finishLine).gameObject) : null),
				["startLineChildren"] = (JToken)(object)(Object.op_Implicit((Object)(object)def.startLine) ? Children(((Component)def.startLine).transform) : null),
				["finishLineChildren"] = (JToken)(object)(Object.op_Implicit((Object)(object)def.finishLine) ? Children(((Component)def.finishLine).transform) : null),
				["endGamePlatform"] = (JToken)(object)Pose(Object.op_Implicit((Object)(object)def.endGamePlatform) ? ((Component)def.endGamePlatform).transform : null),
				["environmentVisualRoot"] = (JToken)(object)Pose(def.environmentVisualRoot),
				["fogPlane"] = (JToken)(object)Pose(Object.op_Implicit((Object)(object)def.fogPlane) ? ((Component)def.fogPlane).transform : null),
				["fogPlaneBounds"] = (JToken)(object)(Object.op_Implicit((Object)(object)def.fogPlane) ? Box(((Renderer)def.fogPlane).bounds) : null),
				["levelLighting"] = (JToken)(object)Pose(Object.op_Implicit((Object)(object)def.levelLighting) ? ((Component)def.levelLighting).transform : null),
				["environmentBiomes"] = JToken.op_Implicit(def.environmentBiomes?.Count ?? 0),
				["reflectionProbes"] = JToken.op_Implicit(def.reflectionProbes?.Count ?? 0),
				["inSceneObstacles"] = (JToken)new JArray((object)(def.inSceneObstacles ?? new List<Obstacle>()).Where((Obstacle o) => Object.op_Implicit((Object)(object)o)).Select((Func<Obstacle, JObject>)((Obstacle o) => new JObject
				{
					["name"] = JToken.op_Implicit(((Object)o).name),
					["pose"] = (JToken)(object)Pose(((Component)o).transform)
				}))),
				["checkpoints"] = (JToken)new JArray((object)(def.checkpoints ?? new List<CheckPoint>()).Where((CheckPoint c) => Object.op_Implicit((Object)(object)c)).Select((Func<CheckPoint, JObject>)((CheckPoint c) => new JObject
				{
					["name"] = JToken.op_Implicit(((Object)c).name),
					["path"] = JToken.op_Implicit(Path(((Component)c).transform)),
					["index"] = JToken.op_Implicit(c.index),
					["pose"] = (JToken)(object)Pose(((Component)c).transform),
					["colliders"] = (JToken)(object)Colliders(((Component)c).gameObject),
					["gates"] = JToken.op_Implicit(Object.op_Implicit((Object)(object)c.splitScreenGates) ? Path(((Component)c.splitScreenGates).transform) : null)
				}))),
				["tileCount"] = JToken.op_Implicit(def.tiles?.Count ?? 0)
			};
			RandomPositionPlayerSpawner val2 = Object.FindObjectOfType<RandomPositionPlayerSpawner>();
			if (Object.op_Implicit((Object)(object)val2))
			{
				List<Transform> value = Traverse.Create((object)val2).Field("spawnPositions").GetValue<List<Transform>>();
				val["spawner"] = (JToken)new JObject
				{
					["pose"] = (JToken)(object)Pose(((Component)val2).transform),
					["path"] = JToken.op_Implicit(Path(((Component)val2).transform)),
					["spawns"] = (JToken)new JArray((object)(value ?? new List<Transform>()).Select((Transform t) => (JToken)(object)Pose(t))),
					["spawnPaths"] = (JToken)new JArray((object)(value ?? new List<Transform>()).Select((Transform t) => (!Object.op_Implicit((Object)(object)t)) ? null : Path(t))),
					["timeTrial"] = (JToken)(object)Pose(val2.timeTrialSpawn)
				};
			}
			ObstacleLevelDefinition val3 = Object.FindObjectOfType<ObstacleLevelDefinition>();
			if (Object.op_Implicit((Object)(object)val3))
			{
				val["forbiddenZones"] = (JToken)new JArray((object)((IEnumerable<BoxCollider>)(((object)val3.forbiddenObstacleZones) ?? ((object)new BoxCollider[0]))).Where((BoxCollider b) => Object.op_Implicit((Object)(object)b)).Select((Func<BoxCollider, JObject>)((BoxCollider b) => new JObject
				{
					["path"] = JToken.op_Implicit(Path(((Component)b).transform)),
					["pose"] = (JToken)(object)Pose(((Component)b).transform),
					["bounds"] = (JToken)(object)Box(((Collider)b).bounds)
				})));
			}
			val["gravityPlanes"] = (JToken)new JArray((object)((IEnumerable<GravityShapeInfinitePlane>)Object.FindObjectsOfType<GravityShapeInfinitePlane>()).Select((Func<GravityShapeInfinitePlane, JObject>)((GravityShapeInfinitePlane g) => new JObject
			{
				["path"] = JToken.op_Implicit(Path(((Component)g).transform)),
				["pose"] = (JToken)(object)Pose(((Component)g).transform),
				["gravity"] = JToken.op_Implicit(g.gravity)
			})));
			List<LevelTileObject> list = new List<LevelTileObject>(def.tiles ?? new List<LevelTileObject>());
			LevelTileObject[] array = Object.FindObjectsOfType<LevelTileObject>(true);
			foreach (LevelTileObject item in array)
			{
				if (!list.Contains(item))
				{
					list.Add(item);
				}
			}
			JArray val4 = new JArray();
			Dictionary<string, JObject> dictionary = new Dictionary<string, JObject>();
			foreach (LevelTileObject item2 in list.Where((LevelTileObject t) => Object.op_Implicit((Object)(object)t)))
			{
				val4.Add((JToken)(object)Tile(item2, def, dictionary));
			}
			val["tiles"] = (JToken)(object)val4;
			val["meshes"] = (JToken)new JObject((object)((IEnumerable<KeyValuePair<string, JObject>>)dictionary).Select((Func<KeyValuePair<string, JObject>, JProperty>)((KeyValuePair<string, JObject> kv) => new JProperty(kv.Key, (object)kv.Value))));
			scene = ((Component)def).gameObject.scene;
			val["hierarchy"] = (JToken)new JArray((object)(from g in ((Scene)(ref scene)).GetRootGameObjects()
				select Node(g.transform, 2)));
			string text = System.IO.Path.Combine(Plugin.Dir, "kit-" + name + ".json");
			File.WriteAllText(text, ((JToken)val).ToString((Formatting)1, Array.Empty<JsonConverter>()));
			ManualLogSource log = Plugin.Log;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val5 = new BepInExInfoLogInterpolatedStringHandler(56, 6, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("KitDump: ");
				((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(name);
				((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" (");
				((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(label);
				((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("): ");
				((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<int>(list.Count);
				((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" tiles (");
				((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<int>(def.tiles?.Count ?? 0);
				((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" registered), ");
				((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<int>(def.checkpoints?.Count ?? 0);
				((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" checkpoints, wrote ");
				((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(text);
			}
			log.LogInfo(val5);
			foreach (IGrouping<string, LevelTileObject> item3 in from t in list
				where Object.op_Implicit((Object)(object)t)
				group t by Code(((Object)t).name) ?? "(no code)" into g
				orderby g.Key
				select g)
			{
				Mesh val6 = MeshOf(item3.First());
				ManualLogSource log2 = Plugin.Log;
				val5 = new BepInExInfoLogInterpolatedStringHandler(25, 4, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("KitDump:   ");
					((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(item3.Key);
					((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" x");
					((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<int>(item3.Count());
					((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" mesh=");
					((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>((val6 != null) ? ((Object)val6).name : null);
					((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" size=");
					BepInExInfoLogInterpolatedStringHandler obj = val5;
					object obj2;
					if (!Object.op_Implicit((Object)(object)val6))
					{
						obj2 = "-";
					}
					else
					{
						Bounds bounds = val6.bounds;
						obj2 = $"{((Bounds)(ref bounds)).size:F2}";
					}
					((BepInExLogInterpolatedStringHandler)obj).AppendFormatted<string>((string)obj2);
				}
				log2.LogInfo(val5);
			}
			ManualLogSource log3 = Plugin.Log;
			val5 = new BepInExInfoLogInterpolatedStringHandler(31, 3, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("KitDump:   start=");
				BepInExInfoLogInterpolatedStringHandler obj3 = val5;
				StartLine startLine = def.startLine;
				((BepInExLogInterpolatedStringHandler)obj3).AppendFormatted<string>(Fmt((startLine != null) ? ((Component)startLine).transform : null));
				((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" finish=");
				BepInExInfoLogInterpolatedStringHandler obj4 = val5;
				FinishLine finishLine = def.finishLine;
				((BepInExLogInterpolatedStringHandler)obj4).AppendFormatted<string>(Fmt((finishLine != null) ? ((Component)finishLine).transform : null));
				((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" ");
				((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("fogY=");
				((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(Object.op_Implicit((Object)(object)def.fogPlane) ? ((Component)def.fogPlane).transform.position.y.ToString("F2") : "-");
			}
			log3.LogInfo(val5);
		}

		internal static Mesh MeshOf(LevelTileObject t)
		{
			if (Object.op_Implicit((Object)(object)t.nonBatchedMesh))
			{
				return t.nonBatchedMesh;
			}
			MeshFilter component = ((Component)t).GetComponent<MeshFilter>();
			if (!Object.op_Implicit((Object)(object)component))
			{
				return null;
			}
			return component.sharedMesh;
		}

		private static JObject Tile(LevelTileObject t, LevelDefinition def, Dictionary<string, JObject> meshes)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: 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_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: 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_0212: Expected O, but got Unknown
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_026e: Expected O, but got Unknown
			MeshFilter component = ((Component)t).GetComponent<MeshFilter>();
			MeshRenderer component2 = ((Component)t).GetComponent<MeshRenderer>();
			JObject val = new JObject
			{
				["name"] = JToken.op_Implicit(((Object)t).name),
				["code"] = JToken.op_Implicit(Code(((Object)t).name)),
				["id"] = JToken.op_Implicit(((object)t.id)?.ToString()),
				["registered"] = JToken.op_Implicit(def.tiles != null && def.tiles.Contains(t)),
				["active"] = JToken.op_Implicit(((Component)t).gameObject.activeInHierarchy),
				["static"] = JToken.op_Implicit(((Component)t).gameObject.isStatic),
				["layer"] = JToken.op_Implicit(LayerMask.LayerToName(((Component)t).gameObject.layer)),
				["path"] = JToken.op_Implicit(Path(((Component)t).transform)),
				["pose"] = (JToken)(object)Pose(((Component)t).transform),
				["filterMesh"] = JToken.op_Implicit((Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.sharedMesh)) ? ((Object)component.sharedMesh).name : null),
				["nonBatchedMesh"] = JToken.op_Implicit(Object.op_Implicit((Object)(object)t.nonBatchedMesh) ? ((Object)t.nonBatchedMesh).name : null),
				["rendererBounds"] = (JToken)(object)(Object.op_Implicit((Object)(object)component2) ? Box(((Renderer)component2).bounds) : null),
				["materials"] = (JToken)((!Object.op_Implicit((Object)(object)component2)) ? ((JArray)null) : new JArray((object)((Renderer)component2).sharedMaterials.Select((Material m) => (!Object.op_Implicit((Object)(object)m)) ? null : ((Object)m).name))),
				["surfaces"] = (JToken)new JArray((object)(from s in ((Component)t).GetComponents<SurfaceInfo>()
					select (!Object.op_Implicit((Object)(object)s.surface)) ? null : ((Object)s.surface).name)),
				["colliders"] = (JToken)(object)Colliders(((Component)t).gameObject),
				["children"] = (JToken)(object)Children(((Component)t).transform)
			};
			Mesh val2 = MeshOf(t);
			if (Object.op_Implicit((Object)(object)val2) && !meshes.ContainsKey(((Object)val2).name))
			{
				meshes[((Object)val2).name] = MeshInfo(val2);
			}
			return val;
		}

		private static JObject MeshInfo(Mesh mesh)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			//IL_0060: 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_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Expected O, but got Unknown
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			JObject val = new JObject
			{
				["bounds"] = (JToken)(object)Box(mesh.bounds),
				["vertexCount"] = JToken.op_Implicit(mesh.vertexCount),
				["readable"] = JToken.op_Implicit(mesh.isReadable)
			};
			if (!mesh.isReadable)
			{
				return val;
			}
			Vector3[] v = mesh.vertices;
			Bounds bounds = mesh.bounds;
			JObject faces = new JObject();
			Face("minX", (Vector3 p) => p.x, ((Bounds)(ref bounds)).min.x, (Vector3 p) => p.z);
			Face("maxX", (Vector3 p) => p.x, ((Bounds)(ref bounds)).max.x, (Vector3 p) => p.z);
			Face("minZ", (Vector3 p) => p.z, ((Bounds)(ref bounds)).min.z, (Vector3 p) => p.x);
			Face("maxZ", (Vector3 p) => p.z, ((Bounds)(ref bounds)).max.z, (Vector3 p) => p.x);
			val["faces"] = (JToken)(object)faces;
			return val;
			void Face(string name, Func<Vector3, float> axis, float value, Func<Vector3, float> across)
			{
				//IL_003f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0045: Expected O, but got Unknown
				//IL_008c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0096: Expected O, but got Unknown
				//IL_0106: Unknown result type (might be due to invalid IL or missing references)
				//IL_0110: Expected O, but got Unknown
				Vector3[] array = v.Where((Vector3 p) => Mathf.Abs(axis(p) - value) < 0.05f).ToArray();
				if (array.Length != 0)
				{
					JObject obj = faces;
					JObject val2 = new JObject();
					val2["count"] = JToken.op_Implicit(array.Length);
					val2["across"] = (JToken)new JArray(new object[2]
					{
						R(array.Min(across)),
						R(array.Max(across))
					});
					val2["y"] = (JToken)new JArray(new object[2]
					{
						R(array.Min((Vector3 p) => p.y)),
						R(array.Max((Vector3 p) => p.y))
					});
					obj[name] = (JToken)(object)val2;
				}
			}
		}

		private static JArray Colliders(GameObject go)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			return new JArray((object)go.GetComponentsInChildren<Collider>(true).Select(delegate(Collider c)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0005: Unknown result type (might be due to invalid IL or missing references)
				//IL_0020: 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_0066: Unknown result type (might be due to invalid IL or missing references)
				//IL_007c: Unknown result type (might be due to invalid IL or missing references)
				//IL_009c: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b3: Expected O, but got Unknown
				//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
				JObject val = new JObject
				{
					["type"] = JToken.op_Implicit(((object)c).GetType().Name),
					["on"] = JToken.op_Implicit(((Object)(object)((Component)c).gameObject == (Object)(object)go) ? "." : ((Object)c).name),
					["trigger"] = JToken.op_Implicit(c.isTrigger),
					["enabled"] = JToken.op_Implicit(c.enabled),
					["layer"] = JToken.op_Implicit(LayerMask.LayerToName(((Component)c).gameObject.layer)),
					["bounds"] = (JToken)(object)Box(c.bounds)
				};
				MeshCollider val2 = (MeshCollider)(object)((c is MeshCollider) ? c : null);
				if (val2 != null)
				{
					val["convex"] = JToken.op_Implicit(val2.convex);
				}
				BoxCollider val3 = (BoxCollider)(object)((c is BoxCollider) ? c : null);
				if (val3 != null)
				{
					val["center"] = (JToken)(object)V(val3.center);
					val["size"] = (JToken)(object)V(val3.size);
				}
				return val;
			}));
		}

		private static JArray Children(Transform t)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: 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_0088: Expected O, but got Unknown
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Expected O, but got Unknown
			JArray val = new JArray();
			foreach (Transform item in t)
			{
				Transform val2 = item;
				JObject val3 = new JObject();
				val3["name"] = JToken.op_Implicit(((Object)val2).name);
				val3["active"] = JToken.op_Implicit(((Component)val2).gameObject.activeSelf);
				val3["local"] = (JToken)new JArray(new object[2]
				{
					V(val2.localPosition),
					V(val2.localEulerAngles)
				});
				val3["components"] = (JToken)new JArray((object)(from x in ((Component)val2).GetComponents<Component>()
					where Object.op_Implicit((Object)(object)x) && !(x is Transform)
					select ((object)x).GetType().Name));
				val.Add((JToken)(object)val3);
			}
			return val;
		}

		private static JObject Node(Transform t, int depth)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: 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_0056: 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_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: 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_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Expected O, but got Unknown
			//IL_016b: Expected O, but got Unknown
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Expected O, but got Unknown
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Expected O, but got Unknown
			JObject val = new JObject
			{
				["name"] = JToken.op_Implicit(((Object)t).name),
				["active"] = JToken.op_Implicit(((Component)t).gameObject.activeSelf),
				["layer"] = JToken.op_Implicit(LayerMask.LayerToName(((Component)t).gameObject.layer)),
				["pos"] = (JToken)(object)V(t.position)
			};
			Collider component = ((Component)t).GetComponent<Collider>();
			val["collider"] = (JToken)(object)((component != null) ? Box(component.bounds) : null);
			MeshFilter component2 = ((Component)t).GetComponent<MeshFilter>();
			val["mesh"] = JToken.op_Implicit((component2 != null && Object.op_Implicit((Object)(object)component2.sharedMesh)) ? ((Object)component2.sharedMesh).name : null);
			val["children"] = JToken.op_Implicit(t.childCount);
			val["renderers"] = JToken.op_Implicit(((Component)t).GetComponentsInChildren<Renderer>(true).Length);
			val["tiles"] = JToken.op_Implicit(((Component)t).GetComponentsInChildren<LevelTileObject>(true).Length);
			val["components"] = (JToken)new JArray((object)(from x in ((Component)t).GetComponents<Component>()
				where Object.op_Implicit((Object)(object)x) && !(x is Transform)
				select ((object)x).GetType().Name));
			JObject val2 = val;
			if (depth > 0 && t.childCount > 0)
			{
				JArray val3 = new JArray();
				foreach (Transform item in t)
				{
					Transform t2 = item;
					val3.Add((JToken)(object)Node(t2, depth - 1));
				}
				val2["kids"] = (JToken)(object)val3;
			}
			return val2;
		}

		internal static string Path(Transform t)
		{
			List<string> list = new List<string>();
			while (Object.op_Implicit((Object)(object)t))
			{
				list.Add(((Object)t).name);
				t = t.parent;
			}
			list.Reverse();
			return string.Join("/", list);
		}

		private static JObject Pose(Transform t)
		{
			//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_0016: 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_002c: 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_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Expected O, but got Unknown
			if (!Object.op_Implicit((Object)(object)t))
			{
				return null;
			}
			return new JObject
			{
				["pos"] = (JToken)(object)V(t.position),
				["rot"] = (JToken)(object)V(t.eulerAngles),
				["scale"] = (JToken)(object)V(t.lossyScale)
			};
		}

		private static JObject Box(Bounds b)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: 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_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			return new JObject
			{
				["center"] = (JToken)(object)V(((Bounds)(ref b)).center),
				["size"] = (JToken)(object)V(((Bounds)(ref b)).size)
			};
		}

		private static JArray V(Vector3 v)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Expected O, but got Unknown
			return new JArray(new object[3]
			{
				R(v.x),
				R(v.y),
				R(v.z)
			});
		}

		private static float R(float f)
		{
			return Mathf.Round(f * 1000f) / 1000f;
		}

		private static string Fmt(Transform t)
		{
			//IL_0014: 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)
			if (!Object.op_Implicit((Object)(object)t))
			{
				return "-";
			}
			return $"{t.position:F1} rot {t.eulerAngles:F0}";
		}
	}
	internal static class Png
	{
		private static uint[] _crcTable;

		internal static byte[] Encode(Color32[] pixels, int width, int height, bool alpha = false)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: 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)
			int num = (alpha ? 4 : 3);
			byte[] array = new byte[height * (width * num + 1)];
			int num2 = 0;
			for (int num3 = height - 1; num3 >= 0; num3--)
			{
				array[num2++] = 0;
				for (int i = 0; i < width; i++)
				{
					Color32 val = pixels[num3 * width + i];
					array[num2++] = val.r;
					array[num2++] = val.g;
					array[num2++] = val.b;
					if (alpha)
					{
						array[num2++] = val.a;
					}
				}
			}
			MemoryStream memoryStream = new MemoryStream();
			memoryStream.WriteByte(120);
			memoryStream.WriteByte(1);
			using (DeflateStream deflateStream = new DeflateStream(memoryStream, CompressionLevel.Fastest, leaveOpen: true))
			{
				deflateStream.Write(array, 0, array.Length);
			}
			WriteBE(memoryStream, Adler32(array));
			MemoryStream memoryStream2 = new MemoryStream();
			memoryStream2.Write(new byte[8] { 137, 80, 78, 71, 13, 10, 26, 10 }, 0, 8);
			MemoryStream memoryStream3 = new MemoryStream();
			WriteBE(memoryStream3, (uint)width);
			WriteBE(memoryStream3, (uint)height);
			memoryStream3.Write(new byte[5]
			{
				8,
				(byte)(alpha ? 6u : 2u),
				0,
				0,
				0
			}, 0, 5);
			Chunk(memoryStream2, "IHDR", memoryStream3.ToArray());
			Chunk(memoryStream2, "IDAT", memoryStream.ToArray());
			Chunk(memoryStream2, "IEND", new byte[0]);
			return memoryStream2.ToArray();
		}

		private static void Chunk(Stream s, string type, byte[] data)
		{
			WriteBE(s, (uint)data.Length);
			byte[] array = new byte[4 + data.Length];
			for (int i = 0; i < 4; i++)
			{
				array[i] = (byte)type[i];
			}
			data.CopyTo(array, 4);
			s.Write(array, 0, array.Length);
			WriteBE(s, Crc(array));
		}

		private static void WriteBE(Stream s, uint v)
		{
			s.WriteByte((byte)(v >> 24));
			s.WriteByte((byte)(v >> 16));
			s.WriteByte((byte)(v >> 8));
			s.WriteByte((byte)v);
		}

		private static uint Adler32(byte[] data)
		{
			uint num = 1u;
			uint num2 = 0u;
			foreach (byte b in data)
			{
				num = (num + b) % 65521;
				num2 = (num2 + num) % 65521;
			}
			return (num2 << 16) | num;
		}

		private static uint Crc(byte[] data)
		{
			if (_crcTable == null)
			{
				_crcTable = new uint[256];
				for (uint num = 0u; num < 256; num++)
				{
					uint num2 = num;
					for (int i = 0; i < 8; i++)
					{
						num2 = (((num2 & 1) != 0) ? (0xEDB88320u ^ (num2 >> 1)) : (num2 >> 1));
					}
					_crcTable[num] = num2;
				}
			}
			uint num3 = uint.MaxValue;
			foreach (byte b in data)
			{
				num3 = _crcTable[(num3 ^ b) & 0xFF] ^ (num3 >> 8);
			}
			return num3 ^ 0xFFFFFFFFu;
		}
	}
	internal static class Probe
	{
		internal static void Run()
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Expected O, but got Unknown
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Expected O, but got Unknown
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: 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_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: 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_03a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03aa: Expected O, but got Unknown
			//IL_023c: Unknown result type (might be due to invalid IL or missing references)
			//IL_064e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0655: Expected O, but got Unknown
			//IL_0251: 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)
			//IL_028a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
			bool flag = default(bool);
			foreach (Level item in LevelManager.instance.levels.Where((Level l) => Object.op_Implicit((Object)(object)l)))
			{
				LevelPreviewMesh[] array = (LevelPreviewMesh[])(((object)item.previewMeshes) ?? ((object)new LevelPreviewMesh[0]));
				ManualLogSource log = Plugin.Log;
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(65, 6, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Probe: level '");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(item.name);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' preview ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(Tex((Texture)(object)item.previewImage));
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" thumb ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(Tex((Texture)(object)item.thumbnailImage));
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" ");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("biome ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(Object.op_Implicit((Object)(object)item.biomeSurface) ? ((Object)item.biomeSurface).name : "-");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" difficulty ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(item.difficulty);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" previewMeshes ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(array.Length);
				}
				log.LogInfo(val);
				LevelPreviewMesh[] array2 = array;
				foreach (LevelPreviewMesh val2 in array2)
				{
					ManualLogSource log2 = Plugin.Log;
					val = new BepInExInfoLogInterpolatedStringHandler(44, 4, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Probe:   mesh ");
						BepInExInfoLogInterpolatedStringHandler obj = val;
						object obj2;
						if (!Object.op_Implicit((Object)(object)val2.mesh))
						{
							obj2 = "-";
						}
						else
						{
							object[] obj3 = new object[6]
							{
								((Object)val2.mesh).name,
								val2.mesh.vertexCount,
								val2.mesh.subMeshCount,
								null,
								null,
								null
							};
							Bounds bounds = val2.mesh.bounds;
							obj3[3] = ((Bounds)(ref bounds)).center;
							bounds = val2.mesh.bounds;
							obj3[4] = ((Bounds)(ref bounds)).size;
							obj3[5] = val2.mesh.isReadable;
							obj2 = string.Format("{0} v{1} sub{2} bounds {3:F1}/{4:F1} readable {5}", obj3);
						}
						((BepInExLogInterpolatedStringHandler)obj).AppendFormatted<string>((string)obj2);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" ");
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("renderer ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(Object.op_Implicit((Object)(object)val2.renderer) ? ((Object)val2.renderer).name : "-");
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" mats [");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(Object.op_Implicit((Object)(object)val2.renderer) ? string.Join(",", val2.renderer.sharedMaterials.Select((Material val5) => (!Object.op_Implicit((Object)(object)val5)) ? "-" : (((Object)val5).name + "/" + ((Object)val5.shader).name))) : "");
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("] ");
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("surfaces [");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(string.Join(",", ((IEnumerable<Surface>)(((object)val2.surfaces) ?? ((object)new Surface[0]))).Select((Surface s) => (!Object.op_Implicit((Object)(object)s)) ? "-" : ((Object)s).name)));
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("]");
					}
					log2.LogInfo(val);
				}
			}
			Surface[] array3 = (Surface[])(Object.op_Implicit((Object)(object)SurfaceManager.instance) ? ((Array)SurfaceManager.instance.surfaces) : ((Array)new Surface[0]));
			for (int num2 = 0; num2 < array3.Length; num2++)
			{
				Surface val3 = array3[num2];
				if (!Object.op_Implicit((Object)(object)val3))
				{
					continue;
				}
				ManualLogSource log3 = Plugin.Log;
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(80, 10, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Probe: surface #");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(num2);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(((Object)val3).name);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" friction ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(val3.friction);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" accel ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(val3.accelerationModifier);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" sticky ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(val3.stickyness);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" drift ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(val3.driftFriction);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" ");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("bounce ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(val3.bouncyness);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" wet ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(val3.wetness);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" mat ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(Object.op_Implicit((Object)(object)val3.effects?.material) ? ((Object)val3.effects.material).name : "-");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" ");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("modifiers [");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(string.Join(",", from val5 in (IEnumerable<CarModifier>)(((object)val3.carModifiers) ?? ((object)new CarModifier[0]))
						where Object.op_Implicit((Object)(object)val5)
						select ((Object)val5).name + ":" + ((object)val5).GetType().Name));
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("]");
				}
				log3.LogInfo(val);
				foreach (CarModifier m in ((IEnumerable<CarModifier>)(((object)val3.carModifiers) ?? ((object)new CarModifier[0]))).Where((CarModifier val5) => Object.op_Implicit((Object)(object)val5)))
				{
					Plugin.Log.LogInfo((object)("Probe:   " + ((Object)m).name + ": " + string.Join(", ", from f in ((object)m).GetType().GetFields()
						select f.Name + "=" + Describe(f.GetValue(m)))));
				}
			}
			SphereCarController[] array4 = Resources.FindObjectsOfTypeAll<SphereCarController>();
			foreach (SphereCarController val4 in array4)
			{
				ManualLogSource log4 = Plugin.Log;
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(56, 6, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Probe: car '");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(((Object)val4).name);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' speed ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(val4.speed);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" maxSpeed ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(val4.maxSpeed);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" reverse ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(val4.reverseSpeed);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" drift ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(val4.driftSpeed);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" floorRay ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(val4.floorRaycastDistance);
				}
				log4.LogInfo(val);
			}
		}

		private static string Describe(object value)
		{
			if (value == null)
			{
				return "null";
			}
			Type type = value.GetType();
			if ((type.IsValueType && type.Namespace == "Game") || type.Name.StartsWith("ModifierValue"))
			{
				return "{" + string.Join(" ", from f in type.GetFields()
					where f.FieldType != typeof(AnimationCurve)
					select $"{f.Name}={f.GetValue(value)}") + "}";
			}
			return value.ToString();
		}

		private static string Tex(Texture t)
		{
			if (!Object.op_Implicit((Object)(object)t))
			{
				return "-";
			}
			return $"{((Object)t).name} {t.width}x{t.height}";
		}

		internal static IEnumerator Gallery(string scene)
		{
			AsyncOperation op = SceneManager.LoadSceneAsync(scene);
			while (!op.isDone)
			{
				yield return null;
			}
			yield return null;
			Scene activeScene = SceneManager.GetActiveScene();
			GameObject[] rootGameObjects = ((Scene)(ref activeScene)).GetRootGameObjects();
			SortedDictionary<string, GameObject> sortedDictionary = new SortedDictionary<string, GameObject>(StringComparer.Ordinal);
			GameObject[] array = rootGameObjects;
			foreach (GameObject val in array)
			{
				string text = KitDump.Code(((Object)val).name);
				if (text != null && Object.op_Implicit((Object)(object)val.GetComponent<LevelTileObject>()) && !(((Object)val).name != text))
				{
					bool flag = Mathf.Abs(Mathf.DeltaAngle(val.transform.eulerAngles.x, 270f)) < 1f;
					if (!sortedDictionary.TryGetValue(text, out var value) || (flag && Mathf.Abs(Mathf.DeltaAngle(value.transform.eulerAngles.x, 270f)) >= 1f))
					{
						sortedDictionary[text] = val;
					}
				}
			}
			array = rootGameObjects;
			foreach (GameObject val2 in array)
			{
				if (Object.op_Implicit((Object)(object)val2.GetComponentInChildren<LevelTileObject>(true)) || ((Object)val2).name == "CollisionMesh")
				{
					val2.SetActive(false);
				}
			}
			int rows = (sortedDictionary.Count + 6 - 1) / 6;
			Texture2D sheet = new Texture2D(1920, 320 * rows, (TextureFormat)3, false);
			RenderTexture rt = new RenderTexture(320, 320, 24);
			GameObject camGo = new GameObject("MoreMapsGalleryCamera");
			Camera cam = camGo.AddComponent<Camera>();
			cam.targetTexture = rt;
			cam.fieldOfView = 40f;
			int n = 0;
			Bounds val3 = default(Bounds);
			bool flag2 = default(bool);
			BepInExInfoLogInterpolatedStringHandler val6;
			foreach (KeyValuePair<string, GameObject> kv in sortedDictionary)
			{
				GameObject template = kv.Value;
				GameObject clone = Object.Instantiate<GameObject>(template);
				clone.transform.SetPositionAndRotation(new Vector3(5000f + (float)n * 600f, 500f, 5000f), template.transform.rotation);
				LevelTileObject[] componentsInChildren = clone.GetComponentsInChildren<LevelTileObject>(true);
				for (int j = 0; j < componentsInChildren.Length; j++)
				{
					TrackBuilder.SetUpTile(componentsInChildren[j], $"gallery/{n}/{j}");
				}
				clone.SetActive(true);
				yield return null;
				((Bounds)(ref val3))..ctor(clone.transform.position, Vector3.zero);
				Renderer[] componentsInChildren2 = clone.GetComponentsInChildren<Renderer>();
				foreach (Renderer val4 in componentsInChildren2)
				{
					((Bounds)(ref val3)).Encapsulate(val4.bounds);
				}
				float num = Mathf.Max(new float[4]
				{
					((Bounds)(ref val3)).size.x,
					((Bounds)(ref val3)).size.y,
					((Bounds)(ref val3)).size.z,
					5f
				});
				Vector3 val5 = clone.transform.rotation * new Vector3(-0.6f, -1f, 0.9f);
				Vector3 normalized = ((Vector3)(ref val5)).normalized;
				camGo.transform.position = ((Bounds)(ref val3)).center - normalized * num * 1.6f;
				camGo.transform.rotation = Quaternion.LookRotation(normalized);
				cam.farClipPlane = num * 4f;
				cam.Render();
				RenderTexture active = RenderTexture.active;
				RenderTexture.active = rt;
				int num2 = n % 6;
				int num3 = rows - 1 - n / 6;
				sheet.ReadPixels(new Rect(0f, 0f, 320f, 320f), num2 * 320, num3 * 320);
				RenderTexture.active = active;
				Vector3 eulerAngles = template.transform.eulerAngles;
				ManualLogSource log = Plugin.Log;
				val6 = new BepInExInfoLogInterpolatedStringHandler(47, 9, ref flag2);
				if (flag2)
				{
					((BepInExLogInterpolatedStringHandler)val6).AppendLiteral("Gallery: ");
					((BepInExLogInterpolatedStringHandler)val6).AppendFormatted<string>(scene);
					((BepInExLogInterpolatedStringHandler)val6).AppendLiteral(" #");
					((BepInExLogInterpolatedStringHandler)val6).AppendFormatted<int>(n);
					((BepInExLogInterpolatedStringHandler)val6).AppendLiteral(" ");
					((BepInExLogInterpolatedStringHandler)val6).AppendFormatted<string>(kv.Key);
					((BepInExLogInterpolatedStringHandler)val6).AppendLiteral(" size ");
					((BepInExLogInterpolatedStringHandler)val6).AppendFormatted<Vector3>(((Bounds)(ref val3)).size, "F0");
					((BepInExLogInterpolatedStringHandler)val6).AppendLiteral(" rot (");
					((BepInExLogInterpolatedStringHandler)val6).AppendFormatted<float>(eulerAngles.x, "F0");
					((BepInExLogInterpolatedStringHandler)val6).AppendLiteral(",");
					((BepInExLogInterpolatedStringHandler)val6).AppendFormatted<float>(eulerAngles.y, "F0");
					((BepInExLogInterpolatedStringHandler)val6).AppendLiteral(",");
					((BepInExLogInterpolatedStringHandler)val6).AppendFormatted<float>(eulerAngles.z, "F0");
					((BepInExLogInterpolatedStringHandler)val6).AppendLiteral(") ");
					((BepInExLogInterpolatedStringHandler)val6).AppendLiteral("kids [");
					((BepInExLogInterpolatedStringHandler)val6).AppendFormatted<string>(string.Join(",", (from t in template.GetComponentsInChildren<Transform>(true).Skip(1)
						select ((Object)t).name).Take(6)));
					((BepInExLogInterpolatedStringHandler)val6).AppendLiteral("] ");
					((BepInExLogInterpolatedStringHandler)val6).AppendLiteral("surfaces [");
					((BepInExLogInterpolatedStringHandler)val6).AppendFormatted<string>(string.Join(",", (from s in template.GetComponentsInChildren<SurfaceInfo>(true)
						select (!Object.op_Implicit((Object)(object)s.surface)) ? "-" : ((Object)s.surface).name.Replace("Surface", "")).Distinct()));
					((BepInExLogInterpolatedStringHandler)val6).AppendLiteral("]");
				}
				log.LogInfo(val6);
				Object.Destroy((Object)(object)clone);
				n++;
			}
			sheet.Apply();
			string text2 = Path.Combine(Plugin.Dir, "gallery-" + scene + ".png");
			File.WriteAllBytes(text2, Png.Encode(sheet.GetPixels32(), ((Texture)sheet).width, ((Texture)sheet).height));
			ManualLogSource log2 = Plugin.Log;
			val6 = new BepInExInfoLogInterpolatedStringHandler(25, 2, ref flag2);
			if (flag2)
			{
				((BepInExLogInterpolatedStringHandler)val6).AppendLiteral("Gallery: wrote ");
				((BepInExLogInterpolatedStringHandler)val6).AppendFormatted<string>(text2);
				((BepInExLogInterpolatedStringHandler)val6).AppendLiteral(" (");
				((BepInExLogInterpolatedStringHandler)val6).AppendFormatted<int>(n);
				((BepInExLogInterpolatedStringHandler)val6).AppendLiteral(" pieces)");
			}
			log2.LogInfo(val6);
			Object.Destroy((Object)(object)camGo);
			Object.Destroy((Object)(object)rt);
			Object.Destroy((Object)(object)sheet);
		}

		internal static IEnumerator Snapshot(string spec)
		{
			string[] array = spec.Split(':');
			string scene = array[0].Trim();
			List<Vector3> points = (from text in array[1].Split(';')
				select (from v in text.Split(',')
					select float.Parse(v.Trim(), CultureInfo.InvariantCulture)).ToArray() into v
				where v.Length == 3
				select v).Select((Func<float[], Vector3>)((float[] v) => new Vector3(v[0], v[1], v[2]))).ToList();
			yield return AutoDump.Load(scene);
			LevelDefinition val = Object.FindObjectOfType<LevelDefinition>();
			if (Object.op_Implicit((Object)(object)val))
			{
				AutoDump.ShowScenery(val);
			}
			ObstacleLevelDefinition val2 = Object.FindObjectOfType<ObstacleLevelDefinition>();
			if (Object.op_Implicit((Object)(object)val2))
			{
				val2.DisableObstaclePlacementMode();
			}
			yield return null;
			GameObject go = new GameObject("MoreMapsSnapshotCamera");
			Camera cam = go.AddComponent<Camera>();
			cam.farClipPlane = 2000f;
			cam.fieldOfView = 60f;
			for (int i = 0; i < points.Count; i++)
			{
				Vector3 p = points[i];
				float[] array2 = new float[4] { 0f, 90f, 180f, 270f };
				foreach (float num2 in array2)
				{
					Vector3 val3 = Quaternion.Euler(0f, num2, 0f) * Vector3.forward;
					go.transform.position = p - val3 * 45f + Vector3.up * 18f;
					go.transform.rotation = Quaternion.LookRotation(p - go.transform.position);
					yield return RenderTo(cam, Path.Combine(Plugin.Dir, $"snapshot-{scene}-{i}-{num2:0}.png"));
				}
				go.transform.SetPositionAndRotation(p + Vector3.up * 120f, Quaternion.Euler(90f, 0f, 0f));
				yield return RenderTo(cam, Path.Combine(Plugin.Dir, $"snapshot-{scene}-{i}-top.png"));
			}
			Object.Destroy((Object)(object)go);
		}

		private static IEnumerator RenderTo(Camera cam, string path)
		{
			yield return (object)new WaitForEndOfFrame();
			RenderTexture val = (cam.targetTexture = new RenderTexture(800, 600, 24));
			cam.Render();
			RenderTexture.active = val;
			Texture2D val3 = new Texture2D(800, 600, (TextureFormat)3, false);
			val3.ReadPixels(new Rect(0f, 0f, 800f, 600f), 0, 0);
			RenderTexture.active = null;
			cam.targetTexture = null;
			File.WriteAllBytes(path, Png.Encode(val3.GetPixels32(), 800, 600));
			Object.Destroy((Object)(object)val3);
			Object.Destroy((Object)(object)val);
			ManualLogSource log = Plugin.Log;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val4 = new BepInExInfoLogInterpolatedStringHandler(16, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("Snapshot: wrote ");
				((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(path);
			}
			log.LogInfo(val4);
		}
	}
	internal static class TrackPreview
	{
		internal static void Report(LevelDefinition def, RouteData route)
		{
			//IL_06bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_06c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_06cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_06d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_06d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_06da: Unknown result type (might be due to invalid IL or missing references)
			//IL_06df: Unknown result type (might be due to invalid IL or missing references)
			//IL_06e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_06ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_06f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_06f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_06f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_06f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_06fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0700: Unknown result type (might be due to invalid IL or missing references)
			//IL_0702: Unknown result type (might be due to invalid IL or missing references)
			//IL_0704: Unknown result type (might be due to invalid IL or missing references)
			//IL_0709: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: 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_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0726: Unknown result type (might be due to invalid IL or missing references)
			//IL_072b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0758: Unknown result type (might be due to invalid IL or missing references)
			//IL_075f: Expected O, but got Unknown
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_04fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0500: Unknown result type (might be due to invalid IL or missing references)
			//IL_0508: Unknown result type (might be due to invalid IL or missing references)
			//IL_050d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0517: Unknown result type (might be due to invalid IL or missing references)
			//IL_051c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0521: Unknown result type (might be due to invalid IL or missing references)
			//IL_0523: Unknown result type (might be due to invalid IL or missing references)
			//IL_0525: Unknown result type (might be due to invalid IL or missing references)
			//IL_0527: Unknown result type (might be due to invalid IL or missing references)
			//IL_0529: Unknown result type (might be due to invalid IL or missing references)
			//IL_052e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0530: Unknown result type (might be due to invalid IL or missing references)
			//IL_0532: Unknown result type (might be due to invalid IL or missing references)
			//IL_0537: Unknown result type (might be due to invalid IL or missing references)
			//IL_07b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: 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_01de: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02af: Unknown result type (might be due to invalid IL or missing references)
			//IL_021d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0224: Expected O, but got Unknown
			//IL_085c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0863: Expected O, but got Unknown
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_0554: Unknown result type (might be due to invalid IL or missing references)
			//IL_0559: Unknown result type (might be due to invalid IL or missing references)
			//IL_036f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0376: Expected O, but got Unknown
			//IL_0344: Unknown result type (might be due to invalid IL or missing references)
			//IL_0589: Unknown result type (might be due to invalid IL or missing references)
			//IL_0590: Expected O, but got Unknown
			//IL_0439: Unknown result type (might be due to invalid IL or missing references)
			//IL_05dd: Unknown result type (might be due to invalid IL or missing references)
			int num = 0;
			int num2 = 0;
			HashSet<GameObject> hashSet = new HashSet<GameObject>(TrackBuilder.LastBuild.SelectMany((RoutePlanner.Placed p) => p.Objects()));
			HashSet<GameObject> skip = new HashSet<GameObject>(from g in TrackBuilder.LastBuild.SelectMany((RoutePlanner.Placed p) => p.Extra)
				where Object.op_Implicit((Object)(object)g)
				select g);
			bool flag = default(bool);
			Vector3 val7;
			foreach (RoutePlanner.Placed item in TrackBuilder.LastBuild.Where((RoutePlanner.Placed p) => !p.IsGap))
			{
				foreach (Func<float, Vector3> item2 in RoutePlanner.Lines(item))
				{
					string text = item.Data.surface ?? route.surface;
					List<Vector3> list = new List<Vector3>();
					int num3 = ((item.Path != null) ? 40 : 8);
					for (int num4 = 0; num4 <= num3; num4++)
					{
						float num5 = Mathf.Lerp(0.02f, 0.98f, (float)num4 / (float)num3);
						Vector3 val = item2(num5);
						num2++;
						float y = val.y;
						List<RaycastHit> list2 = Hits(val + Vector3.up * 8f, Vector3.down, 20f, skip);
						Vector3[] array = (Vector3[])(object)new Vector3[2]
						{
							new Vector3(0.05f, 0f, 0.05f),
							new Vector3(-0.05f, 0f, -0.05f)
						};
						foreach (Vector3 val2 in array)
						{
							if (list2.Count == 0)
							{
								list2 = Hits(val + val2 + Vector3.up * 8f, Vector3.down, 20f, skip);
							}
						}
						if (list2.Count == 0)
						{
							num++;
							ManualLogSource log = Plugin.Log;
							BepInExWarningLogInterpolatedStringHandler val3 = new BepInExWarningLogInterpolatedStringHandler(30, 4, ref flag);
							if (flag)
							{
								((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Preview: #");
								((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(item.Index);
								((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" ");
								((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(item.Data.type);
								((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" t=");
								((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<float>(num5, "F2");
								((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(": nothing under ");
								((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<Vector3>(val, "F1");
							}
							log.LogWarning(val3);
							continue;
						}
						RaycastHit val4 = list2[0];
						list.Add(((RaycastHit)(ref val4)).point);
						bool flag2 = hashSet.Contains(((Component)((Component)((RaycastHit)(ref val4)).collider).transform.root).gameObject);
						SurfaceInfo component = ((Component)((RaycastHit)(ref val4)).collider).GetComponent<SurfaceInfo>();
						bool flag3 = text != null && (Object)(object)((Component)((RaycastHit)(ref val4)).collider).gameObject == (Object)(object)item.Clone && (!Object.op_Implicit((Object)(object)component) || !Object.op_Implicit((Object)(object)component.surface) || !Surfaces.Matches(((Object)component.surface).name, text));
						if (!flag2 || flag3 || Mathf.Abs(((RaycastHit)(ref val4)).point.y - y) > 2.5f)
						{
							num++;
							ManualLogSource log2 = Plugin.Log;
							BepInExWarningLogInterpolatedStringHandler val3 = new BepInExWarningLogInterpolatedStringHandler(64, 9, ref flag);
							if (flag)
							{
								((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Preview: #");
								((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(item.Index);
								((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" ");
								((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(item.Data.type);
								((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" t=");
								((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<float>(num5, "F2");
								((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(": hit ");
								((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(KitDump.Path(((Component)((RaycastHit)(ref val4)).collider).transform));
								((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" ");
								((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("(layer ");
								((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(LayerMask.LayerToName(((Component)((RaycastHit)(ref val4)).collider).gameObject.layer));
								((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(") at y=");
								((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<float>(((RaycastHit)(ref val4)).point.y, "F2");
								((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(", expected ~");
								((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<float>(y, "F2");
								((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(", ");
								((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("ours=");
								((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<bool>(flag2);
								((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(", surface=");
								((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>((Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.surface)) ? ((Object)component.surface).name : "-");
							}
							log2.LogWarning(val3);
						}
					}
					for (int num7 = 0; num7 + 1 < list.Count; num7++)
					{
						Vector3 val5 = list[num7] + Vector3.up * 1.2f;
						Vector3 val6 = list[num7 + 1] + Vector3.up * 1.2f;
						Vector3 direction = val6 - val5;
						val7 = val6 - val5;
						foreach (RaycastHit item3 in Hits(val5, direction, ((Vector3)(ref val7)).magnitude, skip))
						{
							RaycastHit current3 = item3;
							if (!KitDump.Path(((Component)((RaycastHit)(ref current3)).collider).transform).StartsWith("ObstacleDefinition/"))
							{
								num++;
								ManualLogSource log3 = Plugin.Log;
								BepInExWarningLogInterpolatedStringHandler val3 = new BepInExWarningLogInterpolatedStringHandler(28, 4, ref flag);
								if (flag)
								{
									((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Preview: #");
									((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(item.Index);
									((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" ");
									((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(item.Data.type);
									((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(": blocked at ");
									((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<Vector3>(((RaycastHit)(ref current3)).point, "F1");
									((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" by ");
									((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(KitDump.Path(((Component)((RaycastHit)(ref current3)).collider).transform));
								}
								log3.LogWarning(val3);
							}
						}
					}
				}
			}
			foreach (RoutePlanner.Placed item4 in TrackBuilder.LastBuild.Where((RoutePlanner.Placed p) => p.IsGap))
			{
				Vector3 val8 = item4.Entry + Vector3.up * 0.5f;
				Vector3 val9 = item4.Exit + Vector3.up * 0.5f;
				Vector3 direction2 = val9 - val8;
				val7 = val9 - val8;
				foreach (RaycastHit item5 in Hits(val8, direction2, ((Vector3)(ref val7)).magnitude, skip))
				{
					RaycastHit current5 = item5;
					if (!KitDump.Path(((Component)((RaycastHit)(ref current5)).collider).transform).StartsWith("ObstacleDefinition/"))
					{
						num++;
						ManualLogSource log4 = Plugin.Log;
						BepInExWarningLogInterpolatedStringHandler val3 = new BepInExWarningLogInterpolatedStringHandler(31, 3, ref flag);
						if (flag)
						{
							((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Preview: #");
							((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(item4.Index);
							((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" gap: ");
							((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(KitDump.Path(((Component)((RaycastHit)(ref current5)).collider).transform));
							((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" in the way at ");
							((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<Vector3>(((RaycastHit)(ref current5)).point, "F1");
						}
						log4.LogWarning(val3);
					}
				}
			}
			foreach (RoutePlanner.Placed item6 in TrackBuilder.LastBuild.Where((RoutePlanner.Placed p) => p.IsCannon))
			{
				TraceCannon(item6);
			}
			ManualLogSource log5 = Plugin.Log;
			BepInExInfoLogInterpolatedStringHandler val10 = new BepInExInfoLogInterpolatedStringHandler(55, 4, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val10).AppendLiteral("Preview: '");
				((BepInExLogInterpolatedStringHandler)val10).AppendFormatted<string>(route.name);
				((BepInExLogInterpolatedStringHandler)val10).AppendLiteral("': ");
				((BepInExLogInterpolatedStringHandler)val10).AppendFormatted<int>(num2);
				((BepInExLogInterpolatedStringHandler)val10).AppendLiteral(" centre-line samples, ");
				((BepInExLogInterpolatedStringHandler)val10).AppendFormatted<int>(num);
				((BepInExLogInterpolatedStringHandler)val10).AppendLiteral(" problems, ");
				((BepInExLogInterpolatedStringHandler)val10).AppendLiteral("length ");
				((BepInExLogInterpolatedStringHandler)val10).AppendFormatted<float>(Length(TrackBuilder.LastBuild), "F0");
				((BepInExLogInterpolatedStringHandler)val10).AppendLiteral(" m");
			}
			log5.LogInfo(val10);
		}

		private static void TraceCannon(RoutePlanner.Placed p)
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: 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_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0401: Unknown result type (might be due to invalid IL or missing references)
			//IL_0417: Unknown result type (might be due to invalid IL or missing references)
			//IL_041e: Expected O, but got Unknown
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Expected O, but got Unknown
			//IL_039b: Unknown result type (might be due to invalid IL or missing references)
			//IL_039d: Unknown result type (might be due to invalid IL or missing references)
			//IL_039f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0246: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0251: Unknown result type (might be due to invalid IL or missing references)
			//IL_0257: Unknown result type (might be due to invalid IL or missing references)
			//IL_0265: Unknown result type (might be due to invalid IL or missing references)
			//IL_026b: 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)
			//IL_0275: 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_0280: 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_029d: Expected O, but got Unknown
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_0367: Unknown result type (might be due to invalid IL or missing references)
			CannonLaunch cannonLaunch = p.Extra.SelectMany((GameObject g) => g.GetComponentsInChildren<CannonLaunch>()).FirstOrDefault();
			if (!Object.op_Implicit((Object)(object)cannonLaunch))
			{
				return;
			}
			float num = Object.FindObjectOfType<GravityShapeInfinitePlane>()?.gravity ?? 40f;
			Vector3 val = ((Component)cannonLaunch).transform.position;
			Vector3 val2 = cannonLaunch.velocity;
			HashSet<GameObject> own = new HashSet<GameObject>(p.Objects());
			bool flag = false;
			bool flag2 = default(bool);
			BepInExInfoLogInterpolatedStringHandler val4;
			for (float num2 = 0f; num2 < 6f; num2 += 0.01f)
			{
				Vector3 val3 = val + val2 * 0.01f;
				if (!flag && val2.y < 0f && val3.y <= p.Entry.y + 0.5f)
				{
					flag = true;
					ManualLogSource log = Plugin.Log;
					val4 = new BepInExInfoLogInterpolatedStringHandler(98, 4, ref flag2);
					if (flag2)
					{
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("Preview: cannon #");
						((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<int>(p.Index);
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(": back down at road height after ");
						((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<float>(num2, "F2");
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" s, ");
						((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<float>(Vector3.Dot(val3 - p.Entry, p.EntryHeading), "F0");
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" m along, ");
						((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<float>(Vector3.Dot(val3 - p.Entry, Vector3.Cross(Vector3.up, p.EntryHeading)), "F1");
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" m to the right of the road's line");
					}
					log.LogInfo(val4);
				}
				val2 += Vector3.down * num * 0.01f;
				Vector3 val5 = val;
				Vector3 val6 = val3 - val;
				Vector3 val7 = val3 - val;
				RaycastHit val8 = (from h in Physics.RaycastAll(val5, val6, ((Vector3)(ref val7)).magnitude, -1, (QueryTriggerInteraction)1)
					where !own.Contains(((Component)((Component)((RaycastHit)(ref h)).collider).transform.root).gameObject)
					orderby ((RaycastHit)(ref h)).distance
					select h).FirstOrDefault();
				if (Object.op_Implicit((Object)(object)((RaycastHit)(ref val8)).collider))
				{
					float num3 = Vector3.Dot(((RaycastHit)(ref val8)).point - p.Entry, p.EntryHeading);
					float num4 = Vector3.Dot(((RaycastHit)(ref val8)).point - p.Entry, Vector3.Cross(Vector3.up, p.EntryHeading));
					ManualLogSource log2 = Plugin.Log;
					val4 = new BepInExInfoLogInterpolatedStringHandler(112, 7, ref flag2);
					if (flag2)
					{
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("Preview: cannon #");
						((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<int>(p.Index);
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(": lands on ");
						((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(KitDump.Path(((Component)((RaycastHit)(ref val8)).collider).transform));
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" after ");
						((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<float>(num2, "F2");
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" s, ");
						((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<float>(num3, "F0");
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" m along the road from the cannon, ");
						((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<float>(num4, "F1");
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" m to the ");
						((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>((num4 >= 0f) ? "right" : "left");
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(", ");
						((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<float>(((RaycastHit)(ref val8)).point.y - p.Entry.y, "F1");
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" m below the cannon's road");
					}
					log2.LogInfo(val4);
					return;
				}
				val = val3;
				if (val.y < p.Entry.y - 60f)
				{
					break;
				}
			}
			float num5 = Vector3.Dot(val - p.Entry, p.EntryHeading);
			float num6 = Vector3.Dot(val - p.Entry, Vector3.Cross(Vector3.up, p.EntryHeading));
			ManualLogSource log3 = Plugin.Log;
			val4 = new BepInExInfoLogInterpolatedStringHandler(76, 3, ref flag2);
			if (flag2)
			{
				((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("Preview: cannon #");
				((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<int>(p.Index);
				((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(": hits nothing and falls (passing ");
				((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<float>(num5, "F0");
				((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" m along, ");
				((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<float>(num6, "F1");
				((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" m to the side)");
			}
			log3.LogInfo(val4);
		}

		private static List<RaycastHit> Hits(Vector3 from, Vector3 direction, float distance, HashSet<GameObject> skip)
		{
			//IL_000d: 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)
			return (from h in Physics.RaycastAll(@from, direction, distance, -1, (QueryTriggerInteraction)1)
				where !skip.Contains(((Component)((Component)((RaycastHit)(ref h)).collider).transform.root).gameObject)
				orderby ((RaycastHit)(ref h)).distance
				select h).ToList();
		}

		internal static float Length(List<RoutePlanner.Placed> plan)
		{
			//IL_0027: 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_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			float num = 0f;
			foreach (RoutePlanner.Placed item in plan)
			{
				for (int i = 0; i < 16; i++)
				{
					float num2 = num;
					Vector3 val = RoutePlanner.CentreLine(item, (float)(i + 1) / 16f) - RoutePlanner.CentreLine(item, (float)i / 16f);
					num = num2 + ((Vector3)(ref val)).magnitude;
				}
			}
			return num;
		}

		internal static IEnumerator Capture(LevelDefinition def, RouteData route)
		{
			List<RoutePlanner.Placed> build = TrackBuilder.LastBuild;
			if (build.Count == 0)
			{
				yield break;
			}
			ObstacleLevelDefinition val = Object.FindObjectOfType<ObstacleLevelDefinition>();
			if (Object.op_Implicit((Object)(object)val))
			{
				val.DisableObstaclePlacementMode();
			}
			Vector3 val2 = build.Select((RoutePlanner.Placed p) => p.Entry).Aggregate((Func<Vector3, Vector3, Vector3>)Vector3.Min);
			Vector3 val3 = build.Select((RoutePlanner.Placed p) => p.Entry).Aggregate((Func<Vector3, Vector3, Vector3>)Vector3.Max);
			foreach (RoutePlanner.Placed item in build)
			{
				val2 = Vector3.Min(val2, item.Exit);
				val3 = Vector3.Max(val3, item.Exit);
			}
			Vector3 val4 = (val2 + val3) / 2f;
			float orthographicSize = Mathf.Max(val3.x - val2.x, val3.z - val2.z) / 2f + 30f;
			GameObject go = new GameObject("MoreMapsPreviewCamera");
			Camera cam = go.AddComponent<Camera>();
			cam.farClipPlane = 3000f;
			cam.orthographic = true;
			cam.orthographicSize = orthographicSize;
			go.transform.SetPositionAndRotation(val4 + Vector3.up * 300f, Quaternion.Euler(90f, 0f, 0f));
			yield return Render(cam, 1280, 1280, Path.Combine(Plugin.Dir, "preview-" + route.name + "-top.png"));
			cam.orthographic = false;
			cam.fieldOfView = 60f;
			(RoutePlanner.Placed, string)[] array = new(RoutePlanner.Placed, string)[4]
			{
				(build[0], "start"),
				(build[build.Count / 3], "third"),
				(build[2 * build.Count / 3], "twothirds"),
				(build[build.Count - 3], "end")
			};
			for (int num = 0; num < array.Length; num++)
			{
				var (placed, text) = array[num];
				go.transform.position = placed.Entry - placed.EntryHeading * 25f + Vector3.up * 14f;
				go.transform.rotation = Quaternion.LookRotation(placed.Entry + placed.EntryHeading * 30f - go.transform.position);
				yield return Render(cam, 960, 960, Path.Combine(Plugin.Dir, "preview-" + route.name + "-" + text + ".png"));
			}
			go.transform.position = build[0].Entry + build[0].EntryHeading * 15f + Vector3.up * 9f;
			go.transform.rotation = Quaternion.LookRotation(build[0].Entry - build[0].EntryHeading * 18f - go.transform.position);
			yield return Render(cam, 960, 960, Path.Combine(Plugin.Dir, "preview-" + route.name + "-startback.png"));
			foreach (RoutePlanner.Placed item2 in build.Where((RoutePlanner.Placed p) => p.IsCannon))
			{
				go.transform.position = item2.Entry - item2.EntryHeading * 30f + Vector3.up * 18f - Vector3.Cross(Vector3.up, item2.EntryHeading) * 20f;
				go.transform.rotation = Quaternion.LookRotation(item2.Entry + item2.EntryHeading * 60f - go.transform.position);
				yield return Render(cam, 960, 960, Path.Combine(Plugin.Dir, $"preview-{route.name}-cannon{item2.Index}.png"));
			}
			Object.Destroy((Object)(object)go);
		}

		private static IEnumerator Render(Camera cam, int width, int height, string path)
		{
			yield return (object)new WaitForEndOfFrame();
			RenderTexture val = (ca