Decompiled source of CustomBuildings v1.0.0
plugins/CustomBuildings/CustomBuildings.dll
Decompiled 15 hours ago
The result has been truncated due to the large size, download it to view full contents!
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