Decompiled source of CustomBuildings v1.0.0

plugins/CustomBuildings/CustomBuildings.dll

Decompiled 15 hours ago
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Text.Json.Serialization;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using CustomBuildings.Shared;
using HarmonyLib;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Il2CppSystem.Reflection;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("CustomBuildings")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("CustomBuildings")]
[assembly: AssemblyTitle("CustomBuildings")]
[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 CustomBuildings
{
	internal static class BuildingNames
	{
		private static readonly HashSet<string> Logged = new HashSet<string>();

		public static void Apply(string from)
		{
			//IL_028e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0295: Expected O, but got Unknown
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Expected O, but got Unknown
			bool flag = default(bool);
			try
			{
				if (Strings.stringTable == null)
				{
					return;
				}
				int num = 0;
				foreach (BuildingDef definition in ContentLoader.Definitions)
				{
					if (string.IsNullOrEmpty(definition.BasePreset) || string.IsNullOrEmpty(definition.Id))
					{
						continue;
					}
					int num2 = AddTo(Strings.stringTable, definition) + AddTo(Strings.stringTableENG, definition);
					num += num2;
					if (num2 > 0 && Logged.Add(definition.Id + "|ok"))
					{
						ManualLogSource l = Plugin.L;
						BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(26, 5, ref flag);
						if (flag)
						{
							((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[");
							((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(from);
							((BepInExLogInterpolatedStringHandler)val).AppendLiteral("] Named ");
							((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(definition.Id);
							((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" \"");
							((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(definition.GameName());
							((BepInExLogInterpolatedStringHandler)val).AppendLiteral("\" (");
							((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(num2);
							((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" text entr");
							((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>((num2 == 1) ? "y" : "ies");
							((BepInExLogInterpolatedStringHandler)val).AppendLiteral(").");
						}
						l.LogInfo(val);
					}
					else if (num2 == 0 && !HasName(Strings.stringTable, definition) && Strings.textFilesLoaded && Logged.Add(definition.Id + "|none"))
					{
						Plugin.L.LogWarning((object)($"[{from}] Couldn't find a name entry for '{definition.BasePreset}' to copy, so {definition.Id} may show without a name. " + "Turn on VerboseLogging and send the log."));
					}
				}
				if (num > 0)
				{
					Plugin.Verbose($"[{from}] Added {num} name entr{((num == 1) ? "y" : "ies")}.");
				}
			}
			catch (Exception ex)
			{
				if (Logged.Add("error"))
				{
					ManualLogSource l2 = Plugin.L;
					BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(29, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Couldn't add building names: ");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex.Message);
					}
					l2.LogWarning(val2);
				}
			}
		}

		private static bool HasName(Dictionary<string, Dictionary<string, DisplayString>> table, BuildingDef def)
		{
			if (table == null)
			{
				return false;
			}
			Enumerator<string, Dictionary<string, DisplayString>> enumerator = table.GetEnumerator();
			while (enumerator.MoveNext())
			{
				Enumerator<string, DisplayString> enumerator2 = enumerator.Current.Value.GetEnumerator();
				while (enumerator2.MoveNext())
				{
					if (MatchKey(enumerator2.Current.Key, def.Id) != null)
					{
						return true;
					}
				}
			}
			return false;
		}

		private static int AddTo(Dictionary<string, Dictionary<string, DisplayString>> table, BuildingDef def)
		{
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Expected O, but got Unknown
			if (table == null)
			{
				return 0;
			}
			int num = 0;
			string text = def.GameName();
			Enumerator<string, Dictionary<string, DisplayString>> enumerator = table.GetEnumerator();
			while (enumerator.MoveNext())
			{
				KeyValuePair<string, Dictionary<string, DisplayString>> current = enumerator.Current;
				Dictionary<string, DisplayString> value = current.Value;
				if (value == null)
				{
					continue;
				}
				List<string> list = new List<string>();
				Enumerator<string, DisplayString> enumerator2 = value.GetEnumerator();
				while (enumerator2.MoveNext())
				{
					KeyValuePair<string, DisplayString> current2 = enumerator2.Current;
					string text2 = ((MatchKey(current2.Key, def.BasePreset) != null) ? Replace(current2.Key, def.BasePreset, def.Id) : null);
					if (text2 != null && !value.ContainsKey(text2))
					{
						list.Add(text2);
					}
				}
				foreach (string item in list)
				{
					DisplayString val = new DisplayString
					{
						displayStr = text,
						alternateStr = text
					};
					value[item] = val;
					num++;
					Plugin.Verbose($"  name: [{current.Key}] {item} = {text}");
				}
			}
			return num;
		}

		private static string MatchKey(string key, string preset)
		{
			if (string.IsNullOrEmpty(key) || string.IsNullOrEmpty(preset))
			{
				return null;
			}
			int num = key.IndexOf(preset, StringComparison.OrdinalIgnoreCase);
			if (num < 0)
			{
				return null;
			}
			bool num2 = num == 0 || IsSep(key[num - 1]);
			int num3 = num + preset.Length;
			bool flag = num3 == key.Length || IsSep(key[num3]);
			if (!(num2 && flag))
			{
				return null;
			}
			return key;
		}

		private static bool IsSep(char c)
		{
			if (c != '_' && c != '.' && c != '-')
			{
				return c == ' ';
			}
			return true;
		}

		private static string Replace(string key, string basePreset, string id)
		{
			int num = key.IndexOf(basePreset, StringComparison.OrdinalIgnoreCase);
			string text = key.Substring(num, basePreset.Length);
			string text2 = ((text == text.ToLowerInvariant()) ? id.ToLowerInvariant() : ((text == text.ToUpperInvariant()) ? id.ToUpperInvariant() : id));
			return key.Substring(0, num) + text2 + key.Substring(num + basePreset.Length);
		}
	}
	internal static class ContentLoader
	{
		private class FloorFile
		{
			public string Name;

			public string Json;

			public string Source;
		}

		private static readonly List<BuildingDef> Defs = new List<BuildingDef>();

		private static readonly Dictionary<string, string> DefDirs = new Dictionary<string, string>(StringComparer.Ordinal);

		private static readonly SortedDictionary<string, FloorFile> Floors = new SortedDictionary<string, FloorFile>(StringComparer.Ordinal);

		internal static readonly Dictionary<string, TextAsset> FloorAssets = new Dictionary<string, TextAsset>(StringComparer.Ordinal);

		internal static readonly Dictionary<string, BuildingPreset> Buildings = new Dictionary<string, BuildingPreset>(StringComparer.Ordinal);

		private static readonly HashSet<string> WarnedMissingBase = new HashSet<string>();

		public static bool FloorDataParsed;

		private static readonly HashSet<string> CacheLogged = new HashSet<string>(StringComparer.Ordinal);

		internal static IReadOnlyList<BuildingDef> Definitions => Defs;

		public static string ContentHash { get; private set; } = "";

		internal static string DirOf(string id)
		{
			if (!DefDirs.TryGetValue(id, out var value))
			{
				return null;
			}
			return value;
		}

		internal static BuildingPreset FindOurPreset(string id)
		{
			if (!Buildings.TryGetValue(id, out var value) || !((SoCustomComparison)(object)value != (SoCustomComparison)null) || ((Il2CppObjectBase)value).WasCollected)
			{
				return null;
			}
			return value;
		}

		public static bool IsOurFloor(string name)
		{
			if (name != null)
			{
				return Floors.ContainsKey(name);
			}
			return false;
		}

		public static bool IsOurBuilding(string name)
		{
			if (name != null)
			{
				return Defs.Any((BuildingDef d) => d.Id == name);
			}
			return false;
		}

		public static void ReadFiles()
		{
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_021b: Expected O, but got Unknown
			//IL_039a: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a1: Expected O, but got Unknown
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d9: Expected O, but got Unknown
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Expected O, but got Unknown
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Expected O, but got Unknown
			//IL_047e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0484: Expected O, but got Unknown
			//IL_04f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_04fd: Expected O, but got Unknown
			Defs.Clear();
			DefDirs.Clear();
			Floors.Clear();
			string text = Path.Combine(Plugin.ModDir, "Buildings");
			bool flag = default(bool);
			foreach (string item in EdgeStore.Migrate(Plugin.ModDir))
			{
				ManualLogSource l = Plugin.L;
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(7, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[edge] ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(item);
				}
				l.LogInfo(val);
			}
			foreach (string item2 in Directory.GetDirectories(text).OrderBy<string, string>((string d) => d, StringComparer.Ordinal))
			{
				string text2 = Path.Combine(item2, "building.json");
				if (File.Exists(text2))
				{
					try
					{
						byte[] bytes = File.ReadAllBytes(text2);
						BuildingDef def = JsonSerializer.Deserialize<BuildingDef>(Encoding.UTF8.GetString(bytes).TrimStart('\ufeff'), Json.Options);
						if (def == null || string.IsNullOrWhiteSpace(def.Id))
						{
							ManualLogSource l2 = Plugin.L;
							BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(22, 1, ref flag);
							if (flag)
							{
								((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(text2);
								((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": missing Id, skipped.");
							}
							l2.LogError(val2);
						}
						else if (Defs.Any((BuildingDef d) => d.Id == def.Id))
						{
							ManualLogSource l3 = Plugin.L;
							BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(31, 2, ref flag);
							if (flag)
							{
								((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(text2);
								((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": Id '");
								((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(def.Id);
								((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("' is used twice, skipped.");
							}
							l3.LogError(val2);
						}
						else
						{
							Defs.Add(def);
							DefDirs[def.Id] = item2;
						}
					}
					catch (Exception ex)
					{
						ManualLogSource l4 = Plugin.L;
						BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(2, 2, ref flag);
						if (flag)
						{
							((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(text2);
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": ");
							((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex.Message);
						}
						l4.LogError(val2);
					}
				}
				string path = Path.Combine(item2, "floors");
				if (!Directory.Exists(path))
				{
					continue;
				}
				foreach (string item3 in Directory.GetFiles(path, "*.json").OrderBy<string, string>((string f) => f, StringComparer.Ordinal))
				{
					string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(item3);
					if (Floors.TryGetValue(fileNameWithoutExtension, out var value))
					{
						ManualLogSource l5 = Plugin.L;
						BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(85, 3, ref flag);
						if (flag)
						{
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Floor '");
							((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(fileNameWithoutExtension);
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("' exists twice (");
							((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(value.Source);
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" and ");
							((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(item3);
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("). Floor names must be unique; the second one is skipped.");
						}
						l5.LogError(val2);
						continue;
					}
					try
					{
						byte[] bytes2 = File.ReadAllBytes(item3);
						string json = FixFloorName(Encoding.UTF8.GetString(bytes2).TrimStart('\ufeff'), fileNameWithoutExtension, item3);
						Floors[fileNameWithoutExtension] = new FloorFile
						{
							Name = fileNameWithoutExtension,
							Json = json,
							Source = item3
						};
					}
					catch (Exception ex2)
					{
						ManualLogSource l6 = Plugin.L;
						BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(2, 2, ref flag);
						if (flag)
						{
							((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(item3);
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": ");
							((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex2.Message);
						}
						l6.LogError(val2);
					}
				}
			}
			foreach (var item4 in EdgeStore.LoadPieces(EdgeStore.Root(Plugin.ModDir), delegate(string err)
			{
				Plugin.L.LogError((object)("[edge] " + err));
			}))
			{
				var (piece, value2) = item4;
				if (!piece.Enabled)
				{
					ManualLogSource l7 = Plugin.L;
					BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(23, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[edge] ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(piece.Id);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" is switched off");
					}
					l7.LogInfo(val);
				}
				else if (GameEdgePieces.All.Contains(piece.Id) || Defs.Any((BuildingDef d) => d.Id == piece.Id))
				{
					ManualLogSource l8 = Plugin.L;
					BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(70, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[edge] ");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(piece.Id);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": that Id is already used (by the game or a building); skipped.");
					}
					l8.LogError(val2);
				}
				else
				{
					BuildingDef buildingDef = piece.ToBuildingDef();
					Defs.Add(buildingDef);
					DefDirs[buildingDef.Id] = value2;
				}
			}
			Defs.Sort((BuildingDef a, BuildingDef b) => string.CompareOrdinal(a.Id, b.Id));
			ContentHash = CustomBuildings.Shared.ContentHash.Compute(text);
			Plugin.L.LogInfo((object)($"Read {Defs.Count} building(s) and {Floors.Count} floor(s). Content hash {ContentHash} " + "(every player in a multiplayer game must show the same hash)."));
		}

		private static string FixFloorName(string json, string name, string file)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			if (!(JsonNode.Parse(json) is JsonObject jsonObject))
			{
				throw new Exception("not a JSON object");
			}
			string text = jsonObject["floorName"]?.GetValue<string>();
			if (text == name)
			{
				return json;
			}
			ManualLogSource l = Plugin.L;
			bool flag = default(bool);
			BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(54, 3, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(file);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": floorName '");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(text);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' does not match the file name; using '");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(name);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("'.");
			}
			l.LogWarning(val);
			jsonObject["floorName"] = name;
			return jsonObject.ToJsonString();
		}

		public static void RegisterAll(string from)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			try
			{
				RegisterFloors(from);
				RegisterBuildings(from);
				BuildingNames.Apply(from);
			}
			catch (Exception ex)
			{
				ManualLogSource l = Plugin.L;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(40, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Registering custom buildings (");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(from);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(") failed: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
				}
				l.LogError(val);
			}
		}

		public static void RegisterFloors(string from)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Expected O, but got Unknown
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Expected O, but got Unknown
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Expected O, but got Unknown
			AssetLoader instance = AssetLoader.Instance;
			CityData instance2 = CityData.Instance;
			bool flag3 = default(bool);
			foreach (FloorFile value2 in Floors.Values)
			{
				if (!FloorAssets.TryGetValue(value2.Name, out var value) || (Object)(object)value == (Object)null || ((Il2CppObjectBase)value).WasCollected)
				{
					value = new TextAsset(value2.Json);
					((Object)value).name = value2.Name;
					((Object)value).hideFlags = (HideFlags)32;
					FloorAssets[value2.Name] = value;
				}
				if (instance != null && instance.allFloorData != null)
				{
					bool flag = false;
					bool flag2 = false;
					Enumerator<TextAsset> enumerator2 = instance.allFloorData.GetEnumerator();
					while (enumerator2.MoveNext())
					{
						TextAsset current2 = enumerator2.Current;
						if (!((Object)(object)current2 == (Object)null) && !(((Object)current2).name != value2.Name))
						{
							if (((Il2CppObjectBase)current2).Pointer == ((Il2CppObjectBase)value).Pointer)
							{
								flag = true;
							}
							else
							{
								flag2 = true;
							}
						}
					}
					if (flag2)
					{
						ManualLogSource l = Plugin.L;
						BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(74, 1, ref flag3);
						if (flag3)
						{
							((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Floor '");
							((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(value2.Name);
							((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' already exists in the game; rename yours (use a prefix like cb_).");
						}
						l.LogWarning(val);
					}
					else if (!flag)
					{
						instance.allFloorData.Add(value);
						Plugin.Verbose($"[{from}] floor asset {value2.Name} added");
					}
				}
				if (!FloorDataParsed || !((Object)(object)instance2 != (Object)null) || instance2.floorData == null || instance2.floorData.ContainsKey(value2.Name))
				{
					continue;
				}
				Object obj = JsonUtility.FromJson(value2.Json, Il2CppType.Of<FloorSaveData>());
				FloorSaveData val2 = ((obj != null) ? ((Il2CppObjectBase)obj).TryCast<FloorSaveData>() : null);
				if (val2 == null)
				{
					ManualLogSource l2 = Plugin.L;
					BepInExErrorLogInterpolatedStringHandler val3 = new BepInExErrorLogInterpolatedStringHandler(71, 1, ref flag3);
					if (flag3)
					{
						((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Floor '");
						((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(value2.Name);
						((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("' could not be parsed by the game. Check the file in the editor.");
					}
					l2.LogError(val3);
				}
				else
				{
					val2.floorName = value2.Name;
					instance2.floorData.Add(value2.Name, val2);
					Plugin.Verbose($"[{from}] floor data {value2.Name} added");
				}
			}
		}

		public static void RegisterBuildings(string from)
		{
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Expected O, but got Unknown
			//IL_02eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f2: Expected O, but got Unknown
			AssetLoader instance = AssetLoader.Instance;
			if (instance == null || instance.allBuildingData == null)
			{
				return;
			}
			bool flag = default(bool);
			foreach (BuildingDef def in Defs)
			{
				if (Buildings.TryGetValue(def.Id, out var value) && (SoCustomComparison)(object)value != (SoCustomComparison)null && !((Il2CppObjectBase)value).WasCollected)
				{
					EnsureInList(instance, value);
					EnsureCached(value, from);
					continue;
				}
				BuildingPreset val = FindVanillaPreset(def.BasePreset);
				if ((SoCustomComparison)(object)val == (SoCustomComparison)null)
				{
					if (WarnedMissingBase.Add(def.Id))
					{
						ManualLogSource l = Plugin.L;
						BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(48, 3, ref flag);
						if (flag)
						{
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[");
							((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(from);
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("] ");
							((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(def.Id);
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": base building '");
							((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(def.BasePreset);
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("' not found yet; will retry.");
						}
						l.LogWarning(val2);
					}
					continue;
				}
				BuildingPreset val3 = ((Il2CppObjectBase)Object.Instantiate<BuildingPreset>(val)).Cast<BuildingPreset>();
				((Object)val3).name = def.Id;
				((SoCustomComparison)val3).presetName = def.Id;
				((Object)val3).hideFlags = (HideFlags)32;
				if (def.ReplaceFloorLayouts && def.FloorLayouts.Count > 0)
				{
					val3.floorLayouts = BuildLayouts(def, def.FloorLayouts, val3.floorLayouts, "floor");
				}
				if (def.ReplaceBasementLayouts)
				{
					val3.basementLayouts = BuildLayouts(def, def.BasementLayouts, val3.basementLayouts, "basement");
				}
				ApplyOverrides(val3, def.Overrides);
				string value2;
				bool flag2 = DefDirs.TryGetValue(def.Id, out value2) && ExteriorLoader.Apply(val3, val, def, value2);
				Buildings[def.Id] = val3;
				EnsureInList(instance, val3);
				EnsureCached(val3, from);
				Places.ShareLimits(val, val3);
				int num = 0;
				int num2 = 0;
				Enumerator<InteriorFloorSetting> enumerator2 = val3.floorLayouts.GetEnumerator();
				while (enumerator2.MoveNext())
				{
					InteriorFloorSetting current2 = enumerator2.Current;
					num += current2.floorsWithThisSetting;
				}
				enumerator2 = val.floorLayouts.GetEnumerator();
				while (enumerator2.MoveNext())
				{
					InteriorFloorSetting current3 = enumerator2.Current;
					num2 += current3.floorsWithThisSetting;
				}
				if (!flag2 && num != num2)
				{
					Plugin.L.LogWarning((object)($"{def.Id}: layouts cover {num} storey(s) but '{def.BasePreset}' uses {num2}. " + "Windows and floors may not line up."));
				}
				ManualLogSource l2 = Plugin.L;
				BepInExInfoLogInterpolatedStringHandler val4 = new BepInExInfoLogInterpolatedStringHandler(36, 3, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("[");
					((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(from);
					((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("] Registered building ");
					((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(def.Id);
					((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" (based on ");
					((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(def.BasePreset);
					((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(").");
				}
				l2.LogInfo(val4);
				if (def.Edge != null)
				{
					EdgePieces.OnRegistered(def, val3, val);
				}
			}
		}

		internal static void EnsureCached(BuildingPreset preset, string from)
		{
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Expected O, but got Unknown
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Expected O, but got Unknown
			Toolbox instance = Toolbox.Instance;
			if ((Object)(object)instance == (Object)null || (SoCustomComparison)(object)preset == (SoCustomComparison)null)
			{
				return;
			}
			string text = "?";
			bool flag3 = default(bool);
			try
			{
				BuildingPreset val = Find(instance, ((SoCustomComparison)preset).presetName);
				if (val != null && ((Il2CppObjectBase)val).Pointer == ((Il2CppObjectBase)preset).Pointer)
				{
					return;
				}
				bool flag = false;
				try
				{
					flag = instance.TryReplaceInResourcesCache((ScriptableObject)(object)preset);
				}
				catch (Exception ex)
				{
					text = "replace failed: " + ex.Message;
				}
				BuildingPreset val2 = Find(instance, ((SoCustomComparison)preset).presetName);
				if (val2 == null || !(((Il2CppObjectBase)val2).Pointer == ((Il2CppObjectBase)preset).Pointer))
				{
					instance.ProcessLoadedScriptableObject((ScriptableObject)(object)preset);
					text = (flag ? "replaced, then added" : "added");
				}
				else
				{
					text = "replaced";
				}
				BuildingPreset val3 = Find(instance, ((SoCustomComparison)preset).presetName);
				bool flag2 = val3 != null && ((Il2CppObjectBase)val3).Pointer == ((Il2CppObjectBase)preset).Pointer;
				if (CacheLogged.Add(((SoCustomComparison)preset).presetName + text))
				{
					ManualLogSource l = Plugin.L;
					BepInExInfoLogInterpolatedStringHandler val4 = new BepInExInfoLogInterpolatedStringHandler(39, 4, ref flag3);
					if (flag3)
					{
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("[");
						((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(from);
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("] ");
						((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(((SoCustomComparison)preset).presetName);
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(": put in the game's preset cache (");
						((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(text);
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(")");
						((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(flag2 ? "" : " – but the game still can't find it by name");
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(".");
					}
					l.LogInfo(val4);
				}
			}
			catch (Exception ex2)
			{
				ManualLogSource l2 = Plugin.L;
				BepInExWarningLogInterpolatedStringHandler val5 = new BepInExWarningLogInterpolatedStringHandler(54, 5, ref flag3);
				if (flag3)
				{
					((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("[");
					((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(from);
					((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("] ");
					((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(((SoCustomComparison)preset).presetName);
					((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(": couldn't put it in the game's preset cache (");
					((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(text);
					((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("): ");
					((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(ex2.GetType().Name);
					((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(": ");
					((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(ex2.Message);
				}
				l2.LogWarning(val5);
			}
		}

		internal static BuildingPreset Find(Toolbox tb, string name)
		{
			try
			{
				BuildingPreset val = default(BuildingPreset);
				return tb.LoadDataFromResources<BuildingPreset>(name, ref val) ? val : null;
			}
			catch
			{
				return null;
			}
		}

		internal static void EnsureAllCached(string from)
		{
			foreach (BuildingPreset value in Buildings.Values)
			{
				if ((SoCustomComparison)(object)value != (SoCustomComparison)null && !((Il2CppObjectBase)value).WasCollected)
				{
					EnsureCached(value, from);
				}
			}
		}

		private static void EnsureInList(AssetLoader loader, BuildingPreset preset)
		{
			BuildingPreset val = null;
			Enumerator<BuildingPreset> enumerator = loader.allBuildingData.GetEnumerator();
			while (enumerator.MoveNext())
			{
				BuildingPreset current = enumerator.Current;
				if (!((SoCustomComparison)(object)current == (SoCustomComparison)null) && !(((SoCustomComparison)current).presetName != ((SoCustomComparison)preset).presetName))
				{
					if (((Il2CppObjectBase)current).Pointer == ((Il2CppObjectBase)preset).Pointer)
					{
						return;
					}
					val = current;
				}
			}
			if ((SoCustomComparison)(object)val != (SoCustomComparison)null)
			{
				loader.allBuildingData.Remove(val);
			}
			loader.allBuildingData.Add(preset);
		}

		private static BuildingPreset FindVanillaPreset(string name)
		{
			if (string.IsNullOrEmpty(name))
			{
				return null;
			}
			AssetLoader instance = AssetLoader.Instance;
			if (instance != null && instance.allBuildingData != null)
			{
				Enumerator<BuildingPreset> enumerator = instance.allBuildingData.GetEnumerator();
				while (enumerator.MoveNext())
				{
					BuildingPreset current = enumerator.Current;
					if ((SoCustomComparison)(object)current != (SoCustomComparison)null && (((SoCustomComparison)current).presetName == name || ((Object)current).name == name) && !IsOurBuilding(((SoCustomComparison)current).presetName))
					{
						return current;
					}
				}
			}
			foreach (Object item in (Il2CppArrayBase<Object>)(object)Resources.FindObjectsOfTypeAll(Il2CppType.Of<BuildingPreset>()))
			{
				BuildingPreset val = ((item != null) ? ((Il2CppObjectBase)item).TryCast<BuildingPreset>() : null);
				if ((SoCustomComparison)(object)val != (SoCustomComparison)null && (((SoCustomComparison)val).presetName == name || ((Object)val).name == name) && !IsOurBuilding(((SoCustomComparison)val).presetName))
				{
					return val;
				}
			}
			return null;
		}

		private static List<InteriorFloorSetting> BuildLayouts(BuildingDef def, List<FloorLayoutDef> defs, List<InteriorFloorSetting> templates, string what)
		{
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Expected O, but got Unknown
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Expected O, but got Unknown
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Expected O, but got Unknown
			List<InteriorFloorSetting> list = new List<InteriorFloorSetting>();
			if (templates != null)
			{
				Enumerator<InteriorFloorSetting> enumerator = templates.GetEnumerator();
				while (enumerator.MoveNext())
				{
					InteriorFloorSetting current = enumerator.Current;
					list.Add(current);
				}
			}
			List<InteriorFloorSetting> val = new List<InteriorFloorSetting>();
			bool flag = default(bool);
			for (int i = 0; i < defs.Count; i++)
			{
				FloorLayoutDef floorLayoutDef = defs[i];
				InteriorFloorSetting val2 = ((list.Count == 0) ? null : list[Math.Min(i, list.Count - 1)]);
				InteriorFloorSetting val3 = new InteriorFloorSetting();
				if (val2 != null)
				{
					val3.airVentMaximumExtrusion = val2.airVentMaximumExtrusion;
					val3.controlRoomVariants = val2.controlRoomVariants;
					val3.forceShowModel = val2.forceShowModel;
					val3.forceHideModels = val2.forceHideModels;
					val3.forceHideModelsInRooms = val2.forceHideModelsInRooms;
					val3.forceHideModelsOutside = val2.forceHideModelsOutside;
					val3.overrideCeilingHeight = val2.overrideCeilingHeight;
					val3.newCeilingHeight = val2.newCeilingHeight;
				}
				else
				{
					val3.controlRoomVariants = new List<TextAsset>();
					val3.forceHideModels = new List<string>();
					val3.forceHideModelsOutside = new List<string>();
				}
				val3.floorsWithThisSetting = Math.Max(1, floorLayoutDef.Floors);
				val3.blueprints = new List<TextAsset>();
				foreach (string blueprint in floorLayoutDef.Blueprints)
				{
					TextAsset val4 = ResolveFloor(blueprint);
					if ((Object)(object)val4 != (Object)null)
					{
						val3.blueprints.Add(val4);
						continue;
					}
					ManualLogSource l = Plugin.L;
					BepInExErrorLogInterpolatedStringHandler val5 = new BepInExErrorLogInterpolatedStringHandler(46, 4, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(def.Id);
						((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(": ");
						((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(what);
						((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" layout ");
						((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<int>(i + 1);
						((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" uses floor '");
						((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(blueprint);
						((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("', which doesn't exist.");
					}
					l.LogError(val5);
				}
				if (val3.blueprints.Count == 0)
				{
					ManualLogSource l2 = Plugin.L;
					BepInExErrorLogInterpolatedStringHandler val5 = new BepInExErrorLogInterpolatedStringHandler(63, 3, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(def.Id);
						((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(": ");
						((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(what);
						((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" layout ");
						((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<int>(i + 1);
						((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" has no usable floors; the game may fail to build it.");
					}
					l2.LogError(val5);
				}
				val.Add(val3);
			}
			return val;
		}

		private static TextAsset ResolveFloor(string name)
		{
			if (FloorAssets.TryGetValue(name, out var value) && (Object)(object)value != (Object)null)
			{
				return value;
			}
			AssetLoader instance = AssetLoader.Instance;
			if (((instance != null) ? instance.allFloorData : null) != null)
			{
				Enumerator<TextAsset> enumerator = instance.allFloorData.GetEnumerator();
				while (enumerator.MoveNext())
				{
					TextAsset current = enumerator.Current;
					if ((Object)(object)current != (Object)null && ((Object)current).name == name)
					{
						return current;
					}
				}
			}
			return null;
		}

		private static void ApplyOverrides(BuildingPreset p, BuildingOverrides o)
		{
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0242: Expected O, but got Unknown
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Expected O, but got Unknown
			if (o == null)
			{
				return;
			}
			if (o.Disable.HasValue)
			{
				p.disable = o.Disable.Value;
			}
			if (o.Zone.HasValue)
			{
				p.displayedZone = (ZoneType)o.Zone.Value;
			}
			if (o.DensityMinimum.HasValue)
			{
				p.densityMinimum = (Density)o.DensityMinimum.Value;
			}
			if (o.DensityMaximum.HasValue)
			{
				p.densityMaximum = (Density)o.DensityMaximum.Value;
			}
			if (o.LandValueMinimum.HasValue)
			{
				p.landValueMinimum = (LandValue)o.LandValueMinimum.Value;
			}
			if (o.LandValueMaximum.HasValue)
			{
				p.landValueMaximum = (LandValue)o.LandValueMaximum.Value;
			}
			if (o.Minimum.HasValue)
			{
				p.minimum = o.Minimum.Value;
			}
			if (o.HardLimit.HasValue)
			{
				p.hardLimit = o.HardLimit.Value;
			}
			if (o.DesiredRatio.HasValue)
			{
				p.desiredRatio = o.DesiredRatio.Value;
			}
			if (o.FeatureImportance.HasValue)
			{
				p.featureImportance = o.FeatureImportance.Value;
			}
			if (o.AllowedInAllDistricts.HasValue)
			{
				p.allowedInAllDistricts = o.AllowedInAllDistricts.Value;
			}
			if (!string.IsNullOrWhiteSpace(o.StairsFrom))
			{
				BuildingPreset val = FindVanillaPreset(o.StairsFrom.Trim());
				bool flag = default(bool);
				if ((SoCustomComparison)(object)val == (SoCustomComparison)null)
				{
					ManualLogSource l = Plugin.L;
					BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(74, 2, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(((SoCustomComparison)p).presetName);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": StairsFrom '");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(o.StairsFrom);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("' isn't a game building; keeping the base building's stairs.");
					}
					l.LogWarning(val2);
				}
				else
				{
					p.stairwellRegular = val.stairwellRegular;
					p.stairwellLarge = val.stairwellLarge;
					ManualLogSource l2 = Plugin.L;
					BepInExInfoLogInterpolatedStringHandler val3 = new BepInExInfoLogInterpolatedStringHandler(26, 4, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(((SoCustomComparison)p).presetName);
						((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(": stairs from ");
						((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(o.StairsFrom);
						((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" (");
						StairwellPreset stairwellRegular = val.stairwellRegular;
						((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>((stairwellRegular != null) ? ((Object)stairwellRegular).name : null);
						((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(", lift: ");
						((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(((SoCustomComparison)(object)val.stairwellRegular != (SoCustomComparison)null && val.stairwellRegular.featuresElevator) ? "yes" : "no");
						((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(").");
					}
					l2.LogInfo(val3);
				}
			}
			if (o.PossibleNames == null || o.PossibleNames.Count <= 0)
			{
				return;
			}
			List<string> val4 = new List<string>();
			foreach (string possibleName in o.PossibleNames)
			{
				val4.Add(possibleName);
			}
			p.possibleNames = val4;
			p.overrideNaming = true;
		}
	}
	[HarmonyPatch(typeof(NewBuilding), "SetupEmissionTexture")]
	internal static class BuildingDiagnostics
	{
		private static readonly HashSet<string> Done = new HashSet<string>();

		private static int _vanillaShown;

		private static string Fmt(Texture t)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)t == (Object)null)
			{
				return "none";
			}
			try
			{
				return $"{((Object)t).name} {t.graphicsFormat}";
			}
			catch
			{
				return ((Object)t).name;
			}
		}

		private static string Describe(Material m)
		{
			//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)
			if ((Object)(object)m == (Object)null)
			{
				return "no material";
			}
			string value;
			try
			{
				value = string.Join(" ", Il2CppArrayBase<string>.op_Implicit((Il2CppArrayBase<string>)(object)m.shaderKeywords));
			}
			catch
			{
				value = "?";
			}
			string value2;
			try
			{
				object obj2;
				if (!m.HasProperty("_BaseColorMap") || !((Object)(object)m.GetTexture("_BaseColorMap") != (Object)null))
				{
					obj2 = "-";
				}
				else
				{
					Color32? val = ExteriorLoader.Average(m.GetTexture("_BaseColorMap"));
					obj2 = (val.HasValue ? ((object)val.GetValueOrDefault()/*cast due to .constrained prefix*/).ToString() : null) ?? "?";
				}
				value2 = (string)obj2;
			}
			catch
			{
				value2 = "?";
			}
			DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(124, 20);
			defaultInterpolatedStringHandler.AppendLiteral("material ");
			defaultInterpolatedStringHandler.AppendFormatted(((Object)m).name);
			defaultInterpolatedStringHandler.AppendLiteral(" / ");
			Shader shader = m.shader;
			defaultInterpolatedStringHandler.AppendFormatted((shader != null) ? ((Object)shader).name : null);
			defaultInterpolatedStringHandler.AppendLiteral("; base ");
			defaultInterpolatedStringHandler.AppendFormatted(T("_BaseColorMap"));
			defaultInterpolatedStringHandler.AppendLiteral(" (linear avg ");
			defaultInterpolatedStringHandler.AppendFormatted(value2);
			defaultInterpolatedStringHandler.AppendLiteral(") x ");
			defaultInterpolatedStringHandler.AppendFormatted(C("_BaseColor"));
			defaultInterpolatedStringHandler.AppendLiteral("; mask ");
			defaultInterpolatedStringHandler.AppendFormatted(T("_MaskMap"));
			defaultInterpolatedStringHandler.AppendLiteral(" metal ");
			defaultInterpolatedStringHandler.AppendFormatted(F("_Metallic"));
			defaultInterpolatedStringHandler.AppendLiteral(" (");
			defaultInterpolatedStringHandler.AppendFormatted(F("_MetallicRemapMin"));
			defaultInterpolatedStringHandler.AppendLiteral("-");
			defaultInterpolatedStringHandler.AppendFormatted(F("_MetallicRemapMax"));
			defaultInterpolatedStringHandler.AppendLiteral(") ");
			defaultInterpolatedStringHandler.AppendLiteral("smooth ");
			defaultInterpolatedStringHandler.AppendFormatted(F("_Smoothness"));
			defaultInterpolatedStringHandler.AppendLiteral(" (");
			defaultInterpolatedStringHandler.AppendFormatted(F("_SmoothnessRemapMin"));
			defaultInterpolatedStringHandler.AppendLiteral("-");
			defaultInterpolatedStringHandler.AppendFormatted(F("_SmoothnessRemapMax"));
			defaultInterpolatedStringHandler.AppendLiteral(") AO ");
			defaultInterpolatedStringHandler.AppendFormatted(F("_AORemapMin"));
			defaultInterpolatedStringHandler.AppendLiteral("-");
			defaultInterpolatedStringHandler.AppendFormatted(F("_AORemapMax"));
			defaultInterpolatedStringHandler.AppendLiteral("; normal ");
			defaultInterpolatedStringHandler.AppendFormatted(T("_NormalMap"));
			defaultInterpolatedStringHandler.AppendLiteral(" x");
			defaultInterpolatedStringHandler.AppendFormatted(F("_NormalScale"));
			defaultInterpolatedStringHandler.AppendLiteral("; ");
			defaultInterpolatedStringHandler.AppendLiteral("emissive ");
			defaultInterpolatedStringHandler.AppendFormatted(T("_EmissiveColorMap"));
			defaultInterpolatedStringHandler.AppendLiteral(" x ");
			defaultInterpolatedStringHandler.AppendFormatted(C("_EmissiveColor"));
			defaultInterpolatedStringHandler.AppendLiteral(" albedoAffects ");
			defaultInterpolatedStringHandler.AppendFormatted(F("_AlbedoAffectEmissive"));
			defaultInterpolatedStringHandler.AppendLiteral("; keywords [");
			defaultInterpolatedStringHandler.AppendFormatted(value);
			defaultInterpolatedStringHandler.AppendLiteral("]");
			return defaultInterpolatedStringHandler.ToStringAndClear();
			string C(string p)
			{
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0021: Unknown result type (might be due to invalid IL or missing references)
				try
				{
					return m.HasProperty(p) ? ((object)m.GetColor(p)/*cast due to .constrained prefix*/).ToString() : "-";
				}
				catch
				{
					return "?";
				}
			}
			string F(string p)
			{
				try
				{
					return m.HasProperty(p) ? m.GetFloat(p).ToString("0.###") : "-";
				}
				catch
				{
					return "?";
				}
			}
			string T(string p)
			{
				try
				{
					return m.HasProperty(p) ? Fmt(m.GetTexture(p)) : "-";
				}
				catch
				{
					return "?";
				}
			}
		}

		private static void Postfix(NewBuilding __instance)
		{
			//IL_03a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ac: Expected O, but got Unknown
			//IL_029c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
			if (Plugin.VerboseLogging == null || !Plugin.VerboseLogging.Value)
			{
				return;
			}
			try
			{
				BuildingPreset preset = __instance.preset;
				if ((SoCustomComparison)(object)preset == (SoCustomComparison)null)
				{
					return;
				}
				string name = ((SoCustomComparison)preset).presetName;
				bool flag = ContentLoader.IsOurBuilding(name);
				string item = (flag ? name : ("vanilla:" + name));
				if ((!flag && !ContentLoader.Definitions.Any((BuildingDef d) => d.BasePreset == name) && _vanillaShown >= 2) || !Done.Add(item))
				{
					return;
				}
				if (!flag)
				{
					_vanillaShown++;
				}
				List<string> lines = new List<string> { $"[diag] {(flag ? "custom" : "game")} building {name}:" };
				lines.Add("  emissionTextureInstanced: " + Tex((Texture)(object)__instance.emissionTextureInstanced));
				lines.Add("  emissionTextureUnlit: " + Tex((Texture)(object)__instance.emissionTextureUnlit));
				lines.Add($"  preset maps: unlit {Tex((Texture)(object)preset.emissionMapUnlit)}, lit {Tex((Texture)(object)preset.emissionMapLit)}, window {Tex((Texture)(object)preset.windowMap)}");
				Material extMat = __instance.extMat;
				if ((Object)(object)extMat != (Object)null)
				{
					List<string> list = lines;
					DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(61, 5);
					defaultInterpolatedStringHandler.AppendLiteral("  extMat ");
					defaultInterpolatedStringHandler.AppendFormatted(((Object)extMat).name);
					defaultInterpolatedStringHandler.AppendLiteral(" shader ");
					Shader shader = extMat.shader;
					defaultInterpolatedStringHandler.AppendFormatted((shader != null) ? ((Object)shader).name : null);
					defaultInterpolatedStringHandler.AppendLiteral(": emissive map ");
					defaultInterpolatedStringHandler.AppendFormatted(Tex(extMat.HasProperty("_EmissiveColorMap") ? extMat.GetTexture("_EmissiveColorMap") : null));
					defaultInterpolatedStringHandler.AppendLiteral(", ");
					defaultInterpolatedStringHandler.AppendLiteral("emissive colour ");
					defaultInterpolatedStringHandler.AppendFormatted(extMat.HasProperty("_EmissiveColor") ? ((object)extMat.GetColor("_EmissiveColor")/*cast due to .constrained prefix*/).ToString() : "-");
					defaultInterpolatedStringHandler.AppendLiteral(", base map ");
					object value;
					if (!extMat.HasProperty("_BaseColorMap"))
					{
						value = "-";
					}
					else
					{
						Texture texture = extMat.GetTexture("_BaseColorMap");
						value = ((texture != null) ? ((Object)texture).name : null);
					}
					defaultInterpolatedStringHandler.AppendFormatted((string?)value);
					list.Add(defaultInterpolatedStringHandler.ToStringAndClear());
				}
				Models("base", __instance.buildingModelBase);
				if (__instance.buildingModelsActual != null)
				{
					Enumerator<GameObject> enumerator = __instance.buildingModelsActual.GetEnumerator();
					while (enumerator.MoveNext())
					{
						GameObject current = enumerator.Current;
						Models("actual", current);
					}
				}
				if (__instance.buildingModelsLights != null)
				{
					Enumerator<GameObject> enumerator = __instance.buildingModelsLights.GetEnumerator();
					while (enumerator.MoveNext())
					{
						GameObject current2 = enumerator.Current;
						Models("lights", current2);
					}
				}
				Plugin.L.LogInfo((object)string.Join("\n", lines));
				void Models(string label, GameObject go)
				{
					//IL_0029: Unknown result type (might be due to invalid IL or missing references)
					//IL_002f: Expected O, but got Unknown
					//IL_007f: 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_013c: Unknown result type (might be due to invalid IL or missing references)
					//IL_0255: Unknown result type (might be due to invalid IL or missing references)
					if ((Object)(object)go == (Object)null)
					{
						return;
					}
					foreach (MeshRenderer componentsInChild in go.GetComponentsInChildren<MeshRenderer>(true))
					{
						MaterialPropertyBlock val2 = new MaterialPropertyBlock();
						((Renderer)componentsInChild).GetPropertyBlock(val2);
						string value2 = (val2.isEmpty ? "no property block" : $"block emissive map {Tex(val2.GetTexture("_EmissiveColorMap"))}, emissive colour {val2.GetColor("_EmissiveColor")}");
						Material sharedMaterial = ((Renderer)componentsInChild).sharedMaterial;
						MeshFilter mf = ((Component)componentsInChild).GetComponent<MeshFilter>();
						MeshFilter obj = mf;
						object obj2;
						if (!((Object)(object)((obj != null) ? obj.sharedMesh : null) == (Object)null))
						{
							DefaultInterpolatedStringHandler defaultInterpolatedStringHandler2 = new DefaultInterpolatedStringHandler(31, 3);
							defaultInterpolatedStringHandler2.AppendLiteral("mesh ");
							defaultInterpolatedStringHandler2.AppendFormatted(((Object)mf.sharedMesh).name);
							defaultInterpolatedStringHandler2.AppendLiteral(" ");
							defaultInterpolatedStringHandler2.AppendFormatted(mf.sharedMesh.vertexCount);
							defaultInterpolatedStringHandler2.AppendLiteral(" verts, bounds ");
							Bounds bounds = mf.sharedMesh.bounds;
							defaultInterpolatedStringHandler2.AppendFormatted<Vector3>(((Bounds)(ref bounds)).size);
							defaultInterpolatedStringHandler2.AppendLiteral(", uv sets ");
							obj2 = defaultInterpolatedStringHandler2.ToStringAndClear() + string.Join("", from k in Enumerable.Range(0, 4)
								select (!mf.sharedMesh.HasVertexAttribute((VertexAttribute)(4 + k))) ? "-" : k.ToString());
						}
						else
						{
							obj2 = "no mesh";
						}
						string value3 = (string)obj2;
						lines.Add($"  {label} {((Object)((Component)componentsInChild).gameObject).name} (active {((Component)componentsInChild).gameObject.activeInHierarchy}, enabled {((Renderer)componentsInChild).enabled}, layer {((Component)componentsInChild).gameObject.layer}, renderingLayers {((Renderer)componentsInChild).renderingLayerMask}, probes {((Renderer)componentsInChild).lightProbeUsage}, {value3}): {Describe(sharedMaterial)}; {value2}");
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource l = Plugin.L;
				bool flag2 = default(bool);
				BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(7, 1, ref flag2);
				if (flag2)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[diag] ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
				}
				l.LogWarning(val);
			}
			static string Tex(Texture t)
			{
				//IL_008a: 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_00d7: Unknown result type (might be due to invalid IL or missing references)
				//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)t == (Object)null))
				{
					Color32? val2 = ExteriorLoader.Average(t);
					Texture2D val3 = ((Il2CppObjectBase)t).TryCast<Texture2D>();
					return $"{((Object)t).name} {t.width}x{t.height} {(((Object)(object)val3 != (Object)null) ? (((object)val3.format/*cast due to .constrained prefix*/).ToString() + " mips " + ((Texture)val3).mipmapCount) : ((MemberInfo)((Object)t).GetIl2CppType()).Name)} avg {(val2.HasValue ? ((object)val2.GetValueOrDefault()/*cast due to .constrained prefix*/).ToString() : null) ?? "?"}";
				}
				return "none";
			}
		}
	}
	[HarmonyPatch(typeof(SessionData), "Update")]
	internal static class EdgeLog
	{
		private static int _frames;

		private static bool _done;

		private static string _cityDone;

		private static void Postfix()
		{
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Expected O, but got Unknown
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (Plugin.EdgeReport != null && !Plugin.EdgeReport.Value)
				{
					return;
				}
				if (Input.GetKeyDown((KeyCode)57) && Held((KeyCode)306, (KeyCode)305) && Held((KeyCode)304, (KeyCode)303))
				{
					Probe();
				}
				if (++_frames % 300 != 0)
				{
					return;
				}
				CityData instance = CityData.Instance;
				if ((Object)(object)instance == (Object)null || !PierBuilder.CityReady())
				{
					return;
				}
				string text = instance.cityName + "|" + ((object)instance.citySize/*cast due to .constrained prefix*/).ToString();
				if (!_done || !(text == _cityDone))
				{
					List<NewBuilding> list = EdgePieces();
					if (list.Count != 0)
					{
						_done = true;
						_cityDone = text;
						Report(list);
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource l = Plugin.L;
				bool flag = default(bool);
				BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(9, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[edge] ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.GetType().Name);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
				}
				l.LogWarning(val);
			}
		}

		private static bool Held(KeyCode a, KeyCode b)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			if (!Input.GetKey(a))
			{
				return Input.GetKey(b);
			}
			return true;
		}

		internal static List<NewBuilding> EdgePieces()
		{
			List<NewBuilding> list = new List<NewBuilding>();
			foreach (Object item in (Il2CppArrayBase<Object>)(object)Object.FindObjectsOfType(Il2CppType.Of<NewBuilding>()))
			{
				NewBuilding val = ((item != null) ? ((Il2CppObjectBase)item).TryCast<NewBuilding>() : null);
				if (!((Object)(object)val == (Object)null) && (SoCustomComparison)(object)val.preset != (SoCustomComparison)null && (val.preset.boundary || val.preset.boundaryCorner))
				{
					list.Add(val);
				}
			}
			return list;
		}

		private static string V(Vector3 v)
		{
			//IL_0017: 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_0053: Unknown result type (might be due to invalid IL or missing references)
			return $"({v.x:0.##}, {v.y:0.##}, {v.z:0.##})";
		}

		private static void Report(List<NewBuilding> pieces)
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_021a: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			//IL_025f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0283: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0742: Unknown result type (might be due to invalid IL or missing references)
			//IL_0761: Unknown result type (might be due to invalid IL or missing references)
			//IL_0823: Unknown result type (might be due to invalid IL or missing references)
			//IL_0847: Unknown result type (might be due to invalid IL or missing references)
			//IL_087b: Unknown result type (might be due to invalid IL or missing references)
			//IL_09a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_09ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ae5: Unknown result type (might be due to invalid IL or missing references)
			//IL_09c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b04: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b1e: Unknown result type (might be due to invalid IL or missing references)
			//IL_09ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a00: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b97: Unknown result type (might be due to invalid IL or missing references)
			//IL_0bbb: Unknown result type (might be due to invalid IL or missing references)
			StringBuilder sb = new StringBuilder();
			CityData instance = CityData.Instance;
			Line("===== city edge report (plugin 1.0.0) =====");
			Line($"city '{instance.cityName}' size {instance.citySize} boundary L {instance.boundaryLeft:0.##} R {instance.boundaryRight:0.##} U {instance.boundaryUp:0.##} D {instance.boundaryDown:0.##}");
			CityControls instance2 = CityControls.Instance;
			if ((Object)(object)instance2 != (Object)null)
			{
				Line($"tile size {V(instance2.cityTileSize)} multiplier {instance2.tileMultiplier}  basementWaterLevel {instance2.basementWaterLevel:0.###}");
				if ((Object)(object)instance2.basementWaterTransform != (Object)null)
				{
					Line("basement water at " + V(instance2.basementWaterTransform.position));
				}
				if ((Object)(object)instance2.ships1 != (Object)null)
				{
					Line("ships at " + V(instance2.ships1.position));
				}
				if ((Object)(object)instance2.seaMaterial != (Object)null)
				{
					string name = ((Object)instance2.seaMaterial).name;
					Shader shader = instance2.seaMaterial.shader;
					Line("sea material " + name + " shader " + ((shader != null) ? ((Object)shader).name : null));
				}
				MeshRenderer seaRenderer = instance2.seaRenderer;
				if ((Object)(object)seaRenderer != (Object)null)
				{
					Bounds bounds = ((Renderer)seaRenderer).bounds;
					DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(54, 7);
					defaultInterpolatedStringHandler.AppendLiteral("sea renderer '");
					defaultInterpolatedStringHandler.AppendFormatted(((Object)((Component)seaRenderer).gameObject).name);
					defaultInterpolatedStringHandler.AppendLiteral("' at ");
					defaultInterpolatedStringHandler.AppendFormatted(V(((Component)seaRenderer).transform.position));
					defaultInterpolatedStringHandler.AppendLiteral(" scale ");
					defaultInterpolatedStringHandler.AppendFormatted(V(((Component)seaRenderer).transform.lossyScale));
					defaultInterpolatedStringHandler.AppendLiteral(" bounds ");
					defaultInterpolatedStringHandler.AppendFormatted(V(((Bounds)(ref bounds)).min));
					defaultInterpolatedStringHandler.AppendLiteral(" – ");
					defaultInterpolatedStringHandler.AppendFormatted(V(((Bounds)(ref bounds)).max));
					defaultInterpolatedStringHandler.AppendLiteral(" ");
					defaultInterpolatedStringHandler.AppendLiteral("layer ");
					defaultInterpolatedStringHandler.AppendFormatted(((Component)seaRenderer).gameObject.layer);
					defaultInterpolatedStringHandler.AppendLiteral(" material ");
					Material sharedMaterial = ((Renderer)seaRenderer).sharedMaterial;
					defaultInterpolatedStringHandler.AppendFormatted((sharedMaterial != null) ? ((Object)sharedMaterial).name : null);
					Line(defaultInterpolatedStringHandler.ToStringAndClear());
				}
			}
			foreach (Object item in (Il2CppArrayBase<Object>)(object)Object.FindObjectsOfType(Il2CppType.Of<SeaCollider>()))
			{
				SeaCollider val = ((item != null) ? ((Il2CppObjectBase)item).TryCast<SeaCollider>() : null);
				if (!((Object)(object)val == (Object)null))
				{
					Il2CppArrayBase<Collider> components = ((Component)val).GetComponents<Collider>();
					string value = string.Join(", ", ((IEnumerable<Collider>)components).Select(delegate(Collider x)
					{
						//IL_002b: Unknown result type (might be due to invalid IL or missing references)
						//IL_0030: Unknown result type (might be due to invalid IL or missing references)
						//IL_0033: Unknown result type (might be due to invalid IL or missing references)
						//IL_0051: Unknown result type (might be due to invalid IL or missing references)
						//IL_0056: Unknown result type (might be due to invalid IL or missing references)
						//IL_0059: Unknown result type (might be due to invalid IL or missing references)
						DefaultInterpolatedStringHandler defaultInterpolatedStringHandler6 = new DefaultInterpolatedStringHandler(11, 4);
						defaultInterpolatedStringHandler6.AppendFormatted(((MemberInfo)((Object)x).GetIl2CppType()).Name);
						defaultInterpolatedStringHandler6.AppendLiteral(" ");
						Bounds bounds3 = x.bounds;
						defaultInterpolatedStringHandler6.AppendFormatted(V(((Bounds)(ref bounds3)).min));
						defaultInterpolatedStringHandler6.AppendLiteral("–");
						bounds3 = x.bounds;
						defaultInterpolatedStringHandler6.AppendFormatted(V(((Bounds)(ref bounds3)).max));
						defaultInterpolatedStringHandler6.AppendLiteral(" trigger ");
						defaultInterpolatedStringHandler6.AppendFormatted(x.isTrigger);
						return defaultInterpolatedStringHandler6.ToStringAndClear();
					}));
					Line($"SeaCollider '{((Object)((Component)val).gameObject).name}' at {V(((Component)val).transform.position)} layer {((Component)val).gameObject.layer}: {value}");
				}
			}
			AssetLoader instance3 = AssetLoader.Instance;
			if (((instance3 != null) ? instance3.allBuildingData : null) != null)
			{
				Enumerator<BuildingPreset> enumerator2 = instance3.allBuildingData.GetEnumerator();
				while (enumerator2.MoveNext())
				{
					BuildingPreset current2 = enumerator2.Current;
					if ((SoCustomComparison)(object)current2 != (SoCustomComparison)null && (current2.boundary || current2.boundaryCorner))
					{
						DefaultInterpolatedStringHandler defaultInterpolatedStringHandler2 = new DefaultInterpolatedStringHandler(56, 6);
						defaultInterpolatedStringHandler2.AppendLiteral("preset ");
						defaultInterpolatedStringHandler2.AppendFormatted(((SoCustomComparison)current2).presetName);
						defaultInterpolatedStringHandler2.AppendLiteral(": boundary ");
						defaultInterpolatedStringHandler2.AppendFormatted(current2.boundary);
						defaultInterpolatedStringHandler2.AppendLiteral(" corner ");
						defaultInterpolatedStringHandler2.AppendFormatted(current2.boundaryCorner);
						defaultInterpolatedStringHandler2.AppendLiteral(" prefab ");
						GameObject prefab = current2.prefab;
						defaultInterpolatedStringHandler2.AppendFormatted((prefab != null) ? ((Object)prefab).name : null);
						defaultInterpolatedStringHandler2.AppendLiteral(" nonEnterable ");
						defaultInterpolatedStringHandler2.AppendFormatted(current2.nonEnterable);
						defaultInterpolatedStringHandler2.AppendLiteral(" floors ");
						defaultInterpolatedStringHandler2.AppendFormatted(current2.floorCount);
						Line(defaultInterpolatedStringHandler2.ToStringAndClear());
					}
				}
			}
			List<CityTile> list = (from o in (IEnumerable<Object>)Object.FindObjectsOfType(Il2CppType.Of<CityTile>())
				select (o == null) ? null : ((Il2CppObjectBase)o).TryCast<CityTile>() into t
				where (Object)(object)t != (Object)null
				select t).ToList();
			if (list.Count > 0)
			{
				int minX = list.Min(delegate(CityTile t)
				{
					//IL_0001: Unknown result type (might be due to invalid IL or missing references)
					//IL_0006: Unknown result type (might be due to invalid IL or missing references)
					Vector2Int cityCoord = t.cityCoord;
					return ((Vector2Int)(ref cityCoord)).x;
				});
				int value2 = list.Max(delegate(CityTile t)
				{
					//IL_0001: Unknown result type (might be due to invalid IL or missing references)
					//IL_0006: Unknown result type (might be due to invalid IL or missing references)
					Vector2Int cityCoord = t.cityCoord;
					return ((Vector2Int)(ref cityCoord)).x;
				});
				int minY = list.Min(delegate(CityTile t)
				{
					//IL_0001: Unknown result type (might be due to invalid IL or missing references)
					//IL_0006: Unknown result type (might be due to invalid IL or missing references)
					Vector2Int cityCoord = t.cityCoord;
					return ((Vector2Int)(ref cityCoord)).y;
				});
				int value3 = list.Max(delegate(CityTile t)
				{
					//IL_0001: Unknown result type (might be due to invalid IL or missing references)
					//IL_0006: Unknown result type (might be due to invalid IL or missing references)
					Vector2Int cityCoord = t.cityCoord;
					return ((Vector2Int)(ref cityCoord)).y;
				});
				Line($"{list.Count} city tiles, x {minX}..{value2}, y {minY}..{value3}");
				CityTile val2 = ((IEnumerable<CityTile>)list).FirstOrDefault((Func<CityTile, bool>)delegate(CityTile t)
				{
					//IL_0001: Unknown result type (might be due to invalid IL or missing references)
					//IL_0006: Unknown result type (might be due to invalid IL or missing references)
					//IL_0019: Unknown result type (might be due to invalid IL or missing references)
					//IL_001e: Unknown result type (might be due to invalid IL or missing references)
					Vector2Int cityCoord = t.cityCoord;
					if (((Vector2Int)(ref cityCoord)).x == minX + 2)
					{
						cityCoord = t.cityCoord;
						return ((Vector2Int)(ref cityCoord)).y == minY + 2;
					}
					return false;
				}) ?? list[0];
				Line($"tile {val2.cityCoord} at {V(((Component)val2).transform.position)}");
			}
			foreach (Object item2 in (Il2CppArrayBase<Object>)(object)Object.FindObjectsOfType(Il2CppType.Of<NewBuilding>()))
			{
				NewBuilding val3 = ((item2 != null) ? ((Il2CppObjectBase)item2).TryCast<NewBuilding>() : null);
				if (!((Object)(object)val3 == (Object)null) && !((SoCustomComparison)(object)val3.preset == (SoCustomComparison)null) && !val3.preset.boundary && !val3.preset.boundaryCorner)
				{
					DefaultInterpolatedStringHandler defaultInterpolatedStringHandler3 = new DefaultInterpolatedStringHandler(48, 4);
					defaultInterpolatedStringHandler3.AppendLiteral("normal building ");
					defaultInterpolatedStringHandler3.AppendFormatted(((SoCustomComparison)val3.preset).presetName);
					defaultInterpolatedStringHandler3.AppendLiteral(" worldPosition ");
					defaultInterpolatedStringHandler3.AppendFormatted(V(val3.worldPosition));
					defaultInterpolatedStringHandler3.AppendLiteral(" transform ");
					defaultInterpolatedStringHandler3.AppendFormatted(V(((Component)val3).transform.position));
					defaultInterpolatedStringHandler3.AppendLiteral(" tile ");
					CityTile cityTile = val3.cityTile;
					defaultInterpolatedStringHandler3.AppendFormatted((cityTile != null) ? new Vector2Int?(cityTile.cityCoord) : ((Vector2Int?)null));
					Line(defaultInterpolatedStringHandler3.ToStringAndClear());
					break;
				}
			}
			Line($"{pieces.Count} edge pieces:");
			Dictionary<string, int> dictionary = new Dictionary<string, int>();
			foreach (NewBuilding item3 in pieces.OrderBy(delegate(NewBuilding p)
			{
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				//IL_001b: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)p.cityTile != (Object)null))
				{
					return 0;
				}
				Vector2Int cityCoord = p.cityTile.cityCoord;
				return ((Vector2Int)(ref cityCoord)).y;
			}).ThenBy(delegate(NewBuilding p)
			{
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				//IL_001b: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)p.cityTile != (Object)null))
				{
					return 0;
				}
				Vector2Int cityCoord = p.cityTile.cityCoord;
				return ((Vector2Int)(ref cityCoord)).x;
			}))
			{
				BuildingPreset preset = item3.preset;
				string text = ((preset != null) ? ((SoCustomComparison)preset).presetName : null) ?? "?";
				dictionary[text] = ((!dictionary.TryGetValue(text, out var value4)) ? 1 : (value4 + 1));
				Il2CppArrayBase<Renderer> componentsInChildren = ((Component)item3).GetComponentsInChildren<Renderer>(true);
				string value5 = "no renderers";
				if (componentsInChildren.Length > 0)
				{
					Bounds bounds2 = componentsInChildren[0].bounds;
					foreach (Renderer item4 in componentsInChildren)
					{
						((Bounds)(ref bounds2)).Encapsulate(item4.bounds);
					}
					value5 = "bounds " + V(((Bounds)(ref bounds2)).min) + " – " + V(((Bounds)(ref bounds2)).max);
				}
				Il2CppArrayBase<Collider> componentsInChildren2 = ((Component)item3).GetComponentsInChildren<Collider>(true);
				string value6 = ((componentsInChildren2.Length == 0) ? "no colliders" : $"{componentsInChildren2.Length} colliders ({string.Join(",", ((IEnumerable<Collider>)componentsInChildren2).Select((Collider c) => ((MemberInfo)((Object)c).GetIl2CppType()).Name).Distinct())})");
				DefaultInterpolatedStringHandler defaultInterpolatedStringHandler4 = new DefaultInterpolatedStringHandler(65, 11);
				defaultInterpolatedStringHandler4.AppendLiteral("  ");
				defaultInterpolatedStringHandler4.AppendFormatted(text);
				defaultInterpolatedStringHandler4.AppendLiteral(" tile ");
				CityTile cityTile2 = item3.cityTile;
				defaultInterpolatedStringHandler4.AppendFormatted((cityTile2 != null) ? new Vector2Int?(cityTile2.cityCoord) : ((Vector2Int?)null));
				defaultInterpolatedStringHandler4.AppendLiteral(" global ");
				defaultInterpolatedStringHandler4.AppendFormatted<Vector3Int>(item3.globalTileCoords);
				defaultInterpolatedStringHandler4.AppendLiteral(" facing ");
				defaultInterpolatedStringHandler4.AppendFormatted<Direction>(item3.facing);
				defaultInterpolatedStringHandler4.AppendLiteral(" rotations ");
				defaultInterpolatedStringHandler4.AppendFormatted(item3.rotations);
				defaultInterpolatedStringHandler4.AppendLiteral(" ");
				defaultInterpolatedStringHandler4.AppendLiteral("corner ");
				BuildingPreset preset2 = item3.preset;
				defaultInterpolatedStringHandler4.AppendFormatted((preset2 != null) ? new bool?(preset2.boundaryCorner) : ((bool?)null));
				defaultInterpolatedStringHandler4.AppendLiteral(" pos ");
				defaultInterpolatedStringHandler4.AppendFormatted(V(((Component)item3).transform.position));
				defaultInterpolatedStringHandler4.AppendLiteral(" rotY ");
				defaultInterpolatedStringHandler4.AppendFormatted(((Component)item3).transform.eulerAngles.y, "0");
				defaultInterpolatedStringHandler4.AppendLiteral(" ");
				defaultInterpolatedStringHandler4.AppendFormatted(value5);
				defaultInterpolatedStringHandler4.AppendLiteral("; ");
				defaultInterpolatedStringHandler4.AppendFormatted(value6);
				defaultInterpolatedStringHandler4.AppendLiteral("; ");
				defaultInterpolatedStringHandler4.AppendLiteral("model ");
				GameObject buildingModelBase = item3.buildingModelBase;
				defaultInterpolatedStringHandler4.AppendFormatted((buildingModelBase != null) ? ((Object)buildingModelBase).name : null);
				Line(defaultInterpolatedStringHandler4.ToStringAndClear());
			}
			Line("counts: " + string.Join(", ", dictionary.Select((KeyValuePair<string, int> kv) => $"{kv.Key} ×{kv.Value}")));
			Object obj = Object.FindObjectOfType(Il2CppType.Of<CityBoundaryAndTiles>());
			CityBoundaryAndTiles val4 = ((obj != null) ? ((Il2CppObjectBase)obj).TryCast<CityBoundaryAndTiles>() : null);
			if ((Object)(object)val4 != (Object)null)
			{
				DefaultInterpolatedStringHandler defaultInterpolatedStringHandler5 = new DefaultInterpolatedStringHandler(53, 6);
				defaultInterpolatedStringHandler5.AppendLiteral("CityBoundaryAndTiles: L ");
				defaultInterpolatedStringHandler5.AppendFormatted(val4.boundaryLeft, "0.##");
				defaultInterpolatedStringHandler5.AppendLiteral(" R ");
				defaultInterpolatedStringHandler5.AppendFormatted(val4.boundaryRight, "0.##");
				defaultInterpolatedStringHandler5.AppendLiteral(" U ");
				defaultInterpolatedStringHandler5.AppendFormatted(val4.boundaryUp, "0.##");
				defaultInterpolatedStringHandler5.AppendLiteral(" D ");
				defaultInterpolatedStringHandler5.AppendFormatted(val4.boundaryDown, "0.##");
				defaultInterpolatedStringHandler5.AppendLiteral(" ");
				defaultInterpolatedStringHandler5.AppendLiteral("tiles ");
				defaultInterpolatedStringHandler5.AppendFormatted(val4.cityTiles?.Count);
				defaultInterpolatedStringHandler5.AppendLiteral(" tile prefab ");
				GameObject cityTilePrefab = val4.cityTilePrefab;
				defaultInterpolatedStringHandler5.AppendFormatted((cityTilePrefab != null) ? ((Object)cityTilePrefab).name : null);
				Line(defaultInterpolatedStringHandler5.ToStringAndClear());
			}
			Line("===== end of city edge report (Ctrl+Shift+9 at the edge adds more) =====");
			Plugin.L.LogInfo((object)("\n" + sb));
			void Line(string s)
			{
				sb.Append("[edge] ").AppendLine(s);
			}
		}

		private static void Probe()
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: 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_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0432: Unknown result type (might be due to invalid IL or missing references)
			//IL_0437: Unknown result type (might be due to invalid IL or missing references)
			//IL_043b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0360: Unknown result type (might be due to invalid IL or missing references)
			//IL_049f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0384: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_050c: Unknown result type (might be due to invalid IL or missing references)
			Camera main = Camera.main;
			if ((Object)(object)main == (Object)null)
			{
				Plugin.L.LogInfo((object)"[edge] probe: no camera");
				return;
			}
			StringBuilder stringBuilder = new StringBuilder();
			Vector3 position = ((Component)main).transform.position;
			Vector3 forward = ((Component)main).transform.forward;
			forward.y = 0f;
			if (((Vector3)(ref forward)).sqrMagnitude < 0.001f)
			{
				forward = Vector3.forward;
			}
			((Vector3)(ref forward)).Normalize();
			StringBuilder stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder3 = stringBuilder2;
			StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(33, 2, stringBuilder2);
			handler.AppendLiteral("[edge] probe: camera at ");
			handler.AppendFormatted(V(position));
			handler.AppendLiteral(" looking ");
			handler.AppendFormatted(V(forward));
			stringBuilder3.AppendLine(ref handler);
			CityData instance = CityData.Instance;
			if ((Object)(object)instance != (Object)null)
			{
				stringBuilder2 = stringBuilder;
				StringBuilder stringBuilder4 = stringBuilder2;
				handler = new StringBuilder.AppendInterpolatedStringHandler(42, 4, stringBuilder2);
				handler.AppendLiteral("[edge]   distance to boundary: L ");
				handler.AppendFormatted(position.x - instance.boundaryLeft, "0.#");
				handler.AppendLiteral(" R ");
				handler.AppendFormatted(instance.boundaryRight - position.x, "0.#");
				handler.AppendLiteral(" D ");
				handler.AppendFormatted(position.z - instance.boundaryDown, "0.#");
				handler.AppendLiteral(" U ");
				handler.AppendFormatted(instance.boundaryUp - position.z, "0.#");
				stringBuilder4.AppendLine(ref handler);
			}
			float[] array = new float[9] { 0f, 3f, 6f, 10f, 15f, 20f, 30f, 45f, 60f };
			foreach (float num in array)
			{
				Il2CppStructArray<RaycastHit> val = Physics.RaycastAll(position + forward * num + Vector3.up * 30f, Vector3.down, 300f, -1, (QueryTriggerInteraction)2);
				IEnumerable<string> values = from h in ((IEnumerable<RaycastHit>)val).OrderBy((RaycastHit h) => ((RaycastHit)(ref h)).distance).Take(4)
					select $"{((RaycastHit)(ref h)).point.y:0.##} '{((Object)((Component)((RaycastHit)(ref h)).collider).gameObject).name}'{(((RaycastHit)(ref h)).collider.isTrigger ? " (trigger)" : "")} layer {((Component)((RaycastHit)(ref h)).collider).gameObject.layer}";
				stringBuilder2 = stringBuilder;
				StringBuilder stringBuilder5 = stringBuilder2;
				handler = new StringBuilder.AppendInterpolatedStringHandler(19, 2, stringBuilder2);
				handler.AppendLiteral("[edge]   ");
				handler.AppendFormatted(num, 2, "0");
				handler.AppendLiteral(" m ahead: ");
				handler.AppendFormatted((((Il2CppArrayBase<RaycastHit>)(object)val).Length == 0) ? "nothing below" : string.Join(" | ", values));
				stringBuilder5.AppendLine(ref handler);
			}
			NewBuilding val2 = null;
			float num2 = float.MaxValue;
			foreach (NewBuilding item in EdgePieces())
			{
				Vector3 val3 = ((Component)item).transform.position - position;
				float sqrMagnitude = ((Vector3)(ref val3)).sqrMagnitude;
				if (sqrMagnitude < num2)
				{
					num2 = sqrMagnitude;
					val2 = item;
				}
			}
			if ((Object)(object)val2 != (Object)null)
			{
				stringBuilder2 = stringBuilder;
				StringBuilder stringBuilder6 = stringBuilder2;
				handler = new StringBuilder.AppendInterpolatedStringHandler(53, 5, stringBuilder2);
				handler.AppendLiteral("[edge]   nearest edge piece ");
				BuildingPreset preset = val2.preset;
				handler.AppendFormatted((preset != null) ? ((SoCustomComparison)preset).presetName : null);
				handler.AppendLiteral(" tile ");
				CityTile cityTile = val2.cityTile;
				handler.AppendFormatted((cityTile != null) ? new Vector2Int?(cityTile.cityCoord) : ((Vector2Int?)null));
				handler.AppendLiteral(" at ");
				handler.AppendFormatted(V(((Component)val2).transform.position));
				handler.AppendLiteral(" rotY ");
				handler.AppendFormatted(((Component)val2).transform.eulerAngles.y, "0");
				handler.AppendLiteral(", ");
				handler.AppendFormatted(Mathf.Sqrt(num2), "0.#");
				handler.AppendLiteral(" m away");
				stringBuilder6.AppendLine(ref handler);
			}
			CityControls instance2 = CityControls.Instance;
			if ((Object)(object)((instance2 != null) ? instance2.seaRenderer : null) != (Object)null)
			{
				stringBuilder2 = stringBuilder;
				StringBuilder stringBuilder7 = stringBuilder2;
				handler = new StringBuilder.AppendInterpolatedStringHandler(25, 1, stringBuilder2);
				handler.AppendLiteral("[edge]   sea surface top ");
				Bounds bounds = ((Renderer)instance2.seaRenderer).bounds;
				handler.AppendFormatted(((Bounds)(ref bounds)).max.y, "0.##");
				stringBuilder7.AppendLine(ref handler);
			}
			if ((Object)(object)instance2 != (Object)null)
			{
				stringBuilder2 = stringBuilder;
				StringBuilder stringBuilder8 = stringBuilder2;
				handler = new StringBuilder.AppendInterpolatedStringHandler(52, 2, stringBuilder2);
				handler.AppendLiteral("[edge]   basement water level ");
				handler.AppendFormatted(instance2.basementWaterLevel, "0.##");
				handler.AppendLiteral(" (you are ");
				handler.AppendFormatted(position.y - 1.6f - instance2.basementWaterLevel, "+0.##;-0.##");
				handler.AppendLiteral(" m above it)");
				stringBuilder8.AppendLine(ref handler);
			}
			try
			{
				Player instance3 = Player.Instance;
				if ((Object)(object)instance3 != (Object)null)
				{
					stringBuilder2 = stringBuilder;
					StringBuilder stringBuilder9 = stringBuilder2;
					handler = new StringBuilder.AppendInterpolatedStringHandler(42, 4, stringBuilder2);
					handler.AppendLiteral("[edge]   player feet ");
					handler.AppendFormatted(((Component)instance3).transform.position.y, "0.##");
					handler.AppendLiteral(", speed ");
					handler.AppendFormatted(((Human)instance3).currentMovementSpeed, "0.##");
					handler.AppendLiteral(", walk ");
					handler.AppendFormatted(instance3.desiredWalkSpeed, "0.##");
					handler.AppendLiteral(", run ");
					handler.AppendFormatted(instance3.desiredRunSpeed, "0.##");
					stringBuilder9.AppendLine(ref handler);
				}
				StatusController instance4 = StatusController.Instance;
				if ((Object)(object)instance4 != (Object)null)
				{
					List<string> list = new List<string>();
					if (instance4.activeStatuses != null)
					{
						Enumerator<StatusPreset> enumerator2 = instance4.activeStatuses.GetEnumerator();
						while (enumerator2.MoveNext())
						{
							StatusPreset current2 = enumerator2.Current;
							if ((SoCustomComparison)(object)current2 != (SoCustomComparison)null)
							{
								list.Add(((Object)current2).name);
							}
						}
					}
					stringBuilder2 = stringBuilder;
					StringBuilder stringBuilder10 = stringBuilder2;
					handler = new StringBuilder.AppendInterpolatedStringHandler(37, 2, stringBuilder2);
					handler.AppendLiteral("[edge]   movement speed x");
					handler.AppendFormatted(instance4.movementSpeedMultiplier, "0.##");
					handler.AppendLiteral(", statuses: ");
					handler.AppendFormatted((list.Count == 0) ? "none" : string.Join(", ", list));
					stringBuilder10.AppendLine(ref handler);
				}
			}
			catch (Exception ex)
			{
				stringBuilder2 = stringBuilder;
				StringBuilder stringBuilder11 = stringBuilder2;
				handler = new StringBuilder.AppendInterpolatedStringHandler(24, 1, stringBuilder2);
				handler.AppendLiteral("[edge]   (player info: ");
				handler.AppendFormatted(ex.Message);
				handler.AppendLiteral(")");
				stringBuilder11.AppendLine(ref handler);
			}
			Plugin.L.LogInfo((object)stringBuilder.ToString().TrimEnd());
		}
	}
	internal static class EdgeModel
	{
		private sealed class Part
		{
			public string Material = "";

			public bool CollisionOnly;

			public readonly List<Vector3> V = new List<Vector3>();

			public readonly List<Vector3> N = new List<Vector3>();

			public readonly List<Vector2> Uv = new List<Vector2>();

			public readonly List<int> Tris = new List<int>();

			public readonly Dictionary<(int, int, int), int> Map = new Dictionary<(int, int, int), int>();
		}

		private static readonly Dictionary<string, List<Part>> Cache = new Dictionary<string, List<Part>>(StringComparer.OrdinalIgnoreCase);

		private static readonly HashSet<IntPtr> Done = new HashSet<IntPtr>();

		internal static bool HasOwnModel(NewBuilding piece)
		{
			if ((SoCustomComparison)(object)((piece != null) ? piece.preset : null) != (SoCustomComparison)null && EdgePieces.Ours.TryGetValue(((SoCustomComparison)piece.preset).presetName, out var value))
			{
				return value.Edge?.Model != null;
			}
			return false;
		}

		internal static bool Apply(NewBuilding piece, EdgePieceDef def, string dir)
		{
			//IL_04ff: 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_0386: Unknown result type (might be due to invalid IL or missing references)
			//IL_038d: Expected O, but got Unknown
			//IL_056b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Expected O, but got Unknown
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Expected O, but got Unknown
			//IL_0330: Unknown result type (might be due to invalid IL or missing references)
			//IL_0337: Expected O, but got Unknown
			EdgeModelInfo model = def.Model;
			if (model == null || (Object)(object)piece == (Object)null || Done.Contains(((Il2CppObjectBase)piece).Pointer))
			{
				return false;
			}
			string text = Path.Combine(dir, "model");
			string text2 = Path.Combine(text, model.Obj ?? "model.obj");
			bool flag = default(bool);
			if (!File.Exists(text2))
			{
				ManualLogSource l = Plugin.L;
				BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(55, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[edge] ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(def.Id);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": its model ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(text2);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" is missing; keeping the game's wall");
				}
				l.LogWarning(val);
				return false;
			}
			if (!Cache.TryGetValue(text2, out var value))
			{
				value = ReadObj(text2, model);
				Cache[text2] = value;
			}
			if (value.Count == 0)
			{
				ManualLogSource l2 = Plugin.L;
				BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(31, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[edge] ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(def.Id);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": its model has no faces");
				}
				l2.LogWarning(val);
				return false;
			}
			Dictionary<string, (string, Color)> mats = ReadMtl(Path.Combine(text, model.Mtl ?? "model.mtl"));
			Transform val2 = null;
			string text3 = (((Object)(object)piece.preset.prefab != (Object)null) ? ((Object)piece.preset.prefab).name : null);
			for (int i = 0; i < ((Component)piece).transform.childCount; i++)
			{
				if (!((Object)(object)val2 == (Object)null))
				{
					break;
				}
				Transform child = ((Component)piece).transform.GetChild(i);
				if (text3 != null && ((Object)child).name.StartsWith(text3, StringComparison.Ordinal))
				{
					val2 = child;
				}
			}
			if ((Object)(object)val2 == (Object)null && (Object)(object)piece.buildingModelBase != (Object)null)
			{
				val2 = piece.buildingModelBase.transform;
			}
			if ((Object)(object)val2 == (Object)null)
			{
				val2 = ((Component)piece).transform;
			}
			MeshRenderer val3 = ((IEnumerable<MeshRenderer>)((Component)val2).GetComponentsInChildren<MeshRenderer>(true)).FirstOrDefault((Func<MeshRenderer, bool>)((MeshRenderer r) => (Object)(object)r != (Object)null && (Object)(object)((Renderer)r).sharedMaterial != (Object)null));
			Material src = ((val3 != null) ? ((Renderer)val3).sharedMaterial : null);
			int layer = (((Object)(object)val3 != (Object)null) ? ((Component)val3).gameObject.layer : ((Component)val2).gameObject.layer);
			int num = 0;
			int num2 = 0;
			if (!model.KeepGameWall)
			{
				foreach (LODGroup componentsInChild in ((Component)piece).GetComponentsInChildren<LODGroup>(true))
				{
					componentsInChild.enabled = false;
				}
				foreach (Renderer componentsInChild2 in ((Component)piece).GetComponentsInChildren<Renderer>(true))
				{
					if (componentsInChild2.enabled)
					{
						componentsInChild2.enabled = false;
						num++;
					}
				}
				foreach (Collider componentsInChild3 in ((Component)piece).GetComponentsInChildren<Collider>(true))
				{
					if (componentsInChild3.enabled && !componentsInChild3.isTrigger)
					{
						componentsInChild3.enabled = false;
						num2++;
					}
				}
			}
			GameObject val4 = new GameObject(def.Id + "_OwnModel");
			val4.transform.SetParent(val2, false);
			val4.layer = layer;
			Dictionary<string, Material> dictionary = new Dictionary<string, Material>();
			int num3 = 0;
			foreach (Part item in value)
			{
				GameObject val5 = new GameObject(item.CollisionOnly ? "Collision" : item.Material);
				val5.transform.SetParent(val4.transform, false);
				val5.layer = layer;
				Mesh sharedMesh = BuildMesh(item, def.Id + "_" + item.Material);
				num3 += item.Tris.Count / 3;
				if (!item.CollisionOnly)
				{
					val5.AddComponent<MeshFilter>().sharedMesh = sharedMesh;
					MeshRenderer val6 = val5.AddComponent<MeshRenderer>();
					if (!dictionary.TryGetValue(item.Material, out var value2))
					{
						value2 = (dictionary[item.Material] = MakeMaterial(src, mats, item.Material, text, def.Id));
					}
					if ((Object)(object)value2 != (Object)null)
					{
						((Renderer)val6).sharedMaterial = value2;
					}
					if ((Object)(object)val3 != (Object)null)
					{
						ExteriorLoader.CopyRendererSettings(val3, val6);
					}
				}
				bool flag2 = value.Any((Part q) => q.CollisionOnly);
				if (item.CollisionOnly || !flag2)
				{
					try
					{
						val5.AddComponent<MeshCollider>().sharedMesh = sharedMesh;
					}
					catch (Exception ex)
					{
						Plugin.Verbose("[edge] " + def.Id + ": collider: " + ex.Message);
					}
				}
			}
			Physics.SyncTransforms();
			PierBuilder.AddRescue(def.Id, val2.TransformPoint(new Vector3(0f, 1.2f, 12.5f)));
			Done.Add(((Il2CppObjectBase)piece).Pointer);
			ManualLogSource l3 = Plugin.L;
			DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(53, 4);
			defaultInterpolatedStringHandler.AppendLiteral("[edge] ");
			defaultInterpolatedStringHandler.AppendFormatted(def.Id);
			defaultInterpolatedStringHandler.AppendLiteral(" on tile ");
			CityTile cityTile = piece.cityTile;
			defaultInterpolatedStringHandler.AppendFormatted((cityTile != null) ? new Vector2Int?(cityTile.cityCoord) : ((Vector2Int?)null));
			defaultInterpolatedStringHandler.AppendLiteral(": own model in (");
			defaultInterpolatedStringHandler.AppendFormatted(value.Count);
			defaultInterpolatedStringHandler.AppendLiteral(" parts, ");
			defaultInterpolatedStringHandler.AppendFormatted(num3);
			defaultInterpolatedStringHandler.AppendLiteral(" triangles); ");
			l3.LogInfo((object)(defaultInterpolatedStringHandler.ToStringAndClear() + (model.KeepGameWall ? "the game's wall stays" : $"game's wall hidden ({num} renderers, {num2} colliders)")));
			return true;
		}

		internal static void Clear()
		{
			Done.Clear();
		}

		private static List<Part> ReadObj(string path, EdgeModelInfo info)
		{
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Unknown result type (might be due to invalid IL or missing references)
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_023f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: Unknown result type (might be due to invalid IL or missing references)
			CultureInfo invariantCulture = CultureInfo.InvariantCulture;
			List<Vector3> list = new List<Vector3>();
			List<Vector2> list2 = new List<Vector2>();
			List<Vector3> list3 = new List<Vector3>();
			Dictionary<(string, bool), Part> parts = new Dictionary<(string, bool), Part>();
			string mat = "";
			string obj = "";
			float k = ((info.Scale > 0f) ? info.Scale : 1f);
			foreach (string item in File.ReadLines(path))
			{
				string text = item.Trim();
				if (text.Length < 2 || text[0] == '#')
				{
					continue;
				}
				string[] array = text.Split(' ', StringSplitOptions.RemoveEmptyEntries);
				string text2 = array[0];
				if (text2 == null)
				{
					continue;
				}
				switch (text2.Length)
				{
				case 1:
					switch (text2[0])
					{
					case 'g':
					case 'o':
						obj = ((array.Length > 1) ? array[1] : "");
						break;
					case 'v':
						list.Add(Fix(float.Parse(array[1], invariantCulture), float.Parse(array[2], invariantCulture), float.Parse(array[3], invariantCulture), scale: true));
						break;
					case 'f':
					{
						Part part = Cur();
						int[] array2 = new int[array.Length - 1];
						for (int i = 1; i < array.Length; i++)
						{
							array2[i - 1] = Vertex(part, array[i], list, list2, list3);
						}
						for (int j = 1; j + 1 < array2.Length; j++)
						{
							part.Tris.Add(array2[0]);
							part.Tris.Add(array2[j + 1]);
							part.Tris.Add(array2[j]);
						}
						break;
					}
					}
					break;
				case 2:
					switch (text2[1])
					{
					case 't':
						if (text2 == "vt")
						{
							list2.Add(new Vector2(float.Parse(array[1], invariantCulture), (array.Length > 2) ? float.Parse(array[2], invariantCulture) : 0f));
						}
						break;
					case 'n':
						if (text2 == "vn")
						{
							Vector3 val = Fix(float.Parse(array[1], invariantCulture), float.Parse(array[2], invariantCulture), float.Parse(array[3], invariantCulture), scale: false);
							list3.Add(((Vector3)(ref val)).normalized);
						}
						break;
					}
					break;
				case 6:
					if (text2 == "usemtl")
					{
						mat = ((array.Length > 1) ? array[1] : "");
					}
					break;
				}
			}
			return parts.Values.Where((Part p) => p.Tris.Count > 0).ToList();
			Part Cur()
			{
				bool flag = obj.StartsWith("collision", StringComparison.OrdinalIgnoreCase);
				(string, bool) tuple = (flag ? "collision" : mat, flag);
				if (!parts.TryGetValue(tuple, out var value))
				{
					Dictionary<(string, bool), Part> dictionary = parts;
					(string, bool) key = tuple;
					Part obj2 = new Part
					{
						Material = tuple.Item1,
						CollisionOnly = flag
					};
					value = obj2;
					dictionary[key] = obj2;
				}
				return value;
			}
			Vector3 Fix(float x, float y, float z, bool scale)
			{
				//IL_001e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				//IL_0023: 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_0031: Unknown result type (might be due to invalid IL or missing references)
				//IL_0027: Unknown result type (might be due to invalid IL or missing references)
				Vector3 val2 = (info.SwapYZ ? new Vector3(0f - x, z, 0f - y) : new Vector3(0f - x, y, z));
				if (!scale)
				{
					return val2;
				}
				return val2 * k;
			}
		}

		private static int Vertex(Part p, string token, List<Vector3> v, List<Vector2> vt, List<Vector3> vn)
		{
			//IL_006d: 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_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			string[] f = token.Split('/');
			(int, int, int) key = (Ix(0, v.Count), Ix(1, vt.Count), Ix(2, vn.Count));
			if (p.Map.TryGetValue(key, out var value))
			{
				return value;
			}
			value = p.V.Count;
			p.V.Add(v[key.Item1]);
			p.Uv.Add((key.Item2 >= 0) ? vt[key.Item2] : Vector2.zero);
			p.N.Add((key.Item3 >= 0) ? vn[key.Item3] : Vector3.zero);
			p.Map[key] = value;
			return value;
			int Ix(int i, int count)
			{
				if (f.Length <= i || f[i].Length == 0)
				{
					return -1;
				}
				int num = int.Parse(f[i], CultureInfo.InvariantCulture);
				if (num >= 0)
				{
					return num - 1;
				}
				return count + num;
			}
		}

		private static Dictionary<string, (string tex, Color kd)> ReadMtl(string path)
		{
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<string, (string, Color)> dictionary = new Dictionary<string, (string, Color)>(StringComparer.Ordinal);
			if (!File.Exists(path))
			{
				return dictionary;
			}
			CultureInfo invariantCulture = CultureInfo.InvariantCulture;
			string text = null;
			foreach (string item in File.ReadLines(path))
			{
				string text2 = item.Trim();
				string[] array = text2.Split(' ', StringSplitOptions.RemoveEmptyEntries);
				if (array.Length >= 2)
				{
					if (array[0] == "newmtl")
					{
						text = text2.Substring(7).Trim();
						dictionary[text] = (null, Color.white);
					}
					else if (text != null && array[0] == "map_Kd")
					{
						dictionary[text] = (text2.Substring(6).Trim(), dictionary[text].Item2);
					}
					else if (text != null && array[0] == "Kd" && array.Length >= 4)
					{
						dictionary[text] = (dictionary[text].Item1, new Color(float.Parse(array[1], invariantCulture), float.Parse(array[2], invariantCulture), float.Parse(array[3], invariantCulture)));
					}
				}
			}
			return dictionary;
		}

		private static Material MakeMaterial(Material src, Dictionary<string, (string tex, Color kd)> mats, string name, string folder, string id)
		{
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Expected O, but got Unknown
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unk