Decompiled source of TheControlRoomFix v1.1.0
ControlRoomFix.dll
Decompiled 3 days 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.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Core.Logging.Interpolation; using BepInEx.Logging; using BepInEx.Unity.IL2CPP; using HarmonyLib; using Il2CppInterop.Runtime.InteropTypes; using Il2CppSystem; using Il2CppSystem.Collections.Generic; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("ControlRoomFix")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+e52342af4c398be223895f8d39a4b6bf7f3db602")] [assembly: AssemblyProduct("ControlRoomFix")] [assembly: AssemblyTitle("ControlRoomFix")] [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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [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 ControlRoomFix { [HarmonyPatch(typeof(CitizenCreator), "StartLoading")] internal static class CitizenGenerationPatch { [HarmonyPrefix] private static void Prefix() { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown if (!Plugin.EnableCityHallGenerationFix.Value) { return; } try { CityHallGenerationFix.Apply(); } catch (Exception ex) { ManualLogSource logSource = Plugin.LogSource; bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(50, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Could not prepare duplicate City Hall generation: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex); } logSource.LogError(val); } } } internal static class CityHallGenerationFix { private const string CityHallName = "CityHall"; private static CompanyPreset? rememberedPreset; private static int originalMinimum; private static int originalMaximum; internal static void Apply() { //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Expected O, but got Unknown CityData instance = CityData.Instance; if (((instance != null) ? instance.addressDirectory : null) == null) { Plugin.LogSource.LogWarning((object)"City Hall generation fix skipped because addresses are not ready."); return; } CompanyPreset val = null; int num = 0; for (int i = 0; i < instance.addressDirectory.Count; i++) { NewAddress val2 = instance.addressDirectory[i]; if (IsCityHallCompanyAddress(val2)) { num++; if (val == null) { val = val2.addressPreset.company; } } } if ((SoCustomComparison)(object)val == (SoCustomComparison)null || num == 0) { Plugin.LogSource.LogInfo((object)"City Hall generation fix found no eligible City Hall company addresses."); return; } RememberOriginalLimits(val); int num2 = Math.Max(originalMinimum, num); int num3 = Math.Max(originalMaximum, num); val.minimumNumber = num2; val.maximumNumber = num3; ManualLogSource logSource = Plugin.LogSource; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val3 = new BepInExInfoLogInterpolatedStringHandler(92, 6, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("City Hall generation fix found "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(num); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" eligible addresses; "); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("'"); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(ControlRoomScanner.PresetName((Object)(object)val)); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("' company limits "); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("changed from "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(originalMinimum); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(".."); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(originalMaximum); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" to "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(num2); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(".."); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(num3); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("."); } logSource.LogInfo(val3); } internal static void LogResult() { //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Expected O, but got Unknown CityData instance = CityData.Instance; if (((instance != null) ? instance.addressDirectory : null) == null) { return; } HashSet<int> hashSet = new HashSet<int>(); int num = 0; int num2 = 0; for (int i = 0; i < instance.addressDirectory.Count; i++) { NewAddress val = instance.addressDirectory[i]; object obj; if (val == null) { obj = null; } else { NewBuilding building = ((NewGameLocation)val).building; obj = ((building != null) ? building.preset : null); } if ((SoCustomComparison)obj != (SoCustomComparison)null && ControlRoomScanner.PresetName((Object)(object)((NewGameLocation)val).building.preset).Equals("CityHall", StringComparison.OrdinalIgnoreCase)) { hashSet.Add(((NewGameLocation)val).building.buildingID); } if (IsCityHallCompanyAddress(val)) { num++; Company company = val.company; if ((SoCustomComparison)(object)((company != null) ? company.preset : null) != (SoCustomComparison)null && ControlRoomScanner.PresetName((Object)(object)company.preset).Equals("CityHall", StringComparison.OrdinalIgnoreCase)) { num2++; } } } string text = ((num > 0 && num2 == num) ? "OK" : "BROKEN"); ManualLogSource logSource = Plugin.LogSource; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(83, 4, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("["); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(text); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("] City Hall generation: buildings="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(hashSet.Count); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", "); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("eligibleCompanyAddresses="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(num); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", "); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("assignedCompanies="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(num2); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("."); } logSource.LogInfo(val2); } private static bool IsCityHallCompanyAddress(NewAddress? address) { object obj; if (address == null) { obj = null; } else { NewBuilding building = ((NewGameLocation)address).building; obj = ((building != null) ? building.preset : null); } if ((SoCustomComparison)obj != (SoCustomComparison)null && ControlRoomScanner.PresetName((Object)(object)((NewGameLocation)address).building.preset).Equals("CityHall", StringComparison.OrdinalIgnoreCase)) { AddressPreset addressPreset = address.addressPreset; if ((SoCustomComparison)(object)((addressPreset != null) ? addressPreset.company : null) != (SoCustomComparison)null) { return ControlRoomScanner.PresetName((Object)(object)address.addressPreset.company).Equals("CityHall", StringComparison.OrdinalIgnoreCase); } } return false; } private static void RememberOriginalLimits(CompanyPreset preset) { if (!((SoCustomComparison)(object)rememberedPreset == (SoCustomComparison)(object)preset)) { rememberedPreset = preset; originalMinimum = preset.minimumNumber; originalMaximum = preset.maximumNumber; } } } [HarmonyPatch(typeof(InteriorCreator), "StartLoading")] internal static class InteriorGenerationPatch { [HarmonyPrefix] private static void Prefix() { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown if (Plugin.DumpInteractablePipeline.Value) { InteractableCreationTrace.Phase = "interior-start"; VanillaInteractableApiProbe.LogCityConstructorState(); Plugin.LogSource.LogInfo((object)"[probe] InteriorCreator.StartLoading prefix; this is generateInteriors. Watch for later LoadObjects / CreateInteractables traces."); } if (!Plugin.EnableGenerationFix.Value) { return; } try { ControlRoomGenerationFix.Apply(); } catch (Exception ex) { ManualLogSource logSource = Plugin.LogSource; bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(52, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Could not prepare ControlRoom furniture generation: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex); } logSource.LogError(val); } } [HarmonyPostfix] private static void Postfix() { if (Plugin.DumpInteractablePipeline.Value) { InteractableCreationTrace.Phase = "interior-end"; Plugin.LogSource.LogInfo((object)"[probe] InteriorCreator.StartLoading postfix; interiors finished. The next vanilla object-load stage should follow if this is a new city."); VanillaInteractableApiProbe.LogCityConstructorState(); } } } internal static class ControlRoomGenerationFix { private const string ControlRoomClassName = "ControlRoom"; internal static void Apply() { //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Expected O, but got Unknown //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Expected O, but got Unknown Toolbox instance = Toolbox.Instance; if (((instance != null) ? instance.allFurnitureClusters : null) == null) { Plugin.LogSource.LogWarning((object)"ControlRoom generation fix skipped because furniture presets are not ready."); return; } int num = 0; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val5; for (int i = 0; i < Toolbox.Instance.allFurnitureClusters.Count; i++) { FurnitureCluster val = Toolbox.Instance.allFurnitureClusters[i]; if ((SoCustomComparison)(object)val == (SoCustomComparison)null || !val.skipIfNoAddressInhabitants || !TryGetControlRoomClass(val, out RoomClassPreset controlRoomClass) || (SoCustomComparison)(object)controlRoomClass == (SoCustomComparison)null) { continue; } FurnitureCluster val2 = val; if (val2.dontSkipNoInhabitantsIfIn == null) { List<RoomClassPreset> val3 = (val2.dontSkipNoInhabitantsIfIn = new List<RoomClassPreset>()); } if (!ContainsRoomClass(val.dontSkipNoInhabitantsIfIn, "ControlRoom")) { val.dontSkipNoInhabitantsIfIn.Add(controlRoomClass); num++; ManualLogSource logSource = Plugin.LogSource; val5 = new BepInExInfoLogInterpolatedStringHandler(46, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("ControlRoom generation fix enabled cluster "); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("'"); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(ControlRoomScanner.PresetName((Object)(object)val)); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("'."); } logSource.LogInfo(val5); } } ManualLogSource logSource2 = Plugin.LogSource; val5 = new BepInExInfoLogInterpolatedStringHandler(56, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("ControlRoom generation fix prepared "); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<int>(num); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" furniture clusters."); } logSource2.LogInfo(val5); } private static bool TryGetControlRoomClass(FurnitureCluster cluster, out RoomClassPreset? controlRoomClass) { controlRoomClass = null; if (cluster.allowedRoomFilters == null) { return false; } for (int i = 0; i < cluster.allowedRoomFilters.Count; i++) { RoomTypeFilter obj = cluster.allowedRoomFilters[i]; List<RoomClassPreset> val = ((obj != null) ? obj.roomClasses : null); if (val == null) { continue; } for (int j = 0; j < val.Count; j++) { RoomClassPreset val2 = val[j]; if ((SoCustomComparison)(object)val2 != (SoCustomComparison)null && ControlRoomScanner.PresetName((Object)(object)val2).Equals("ControlRoom", StringComparison.OrdinalIgnoreCase)) { controlRoomClass = val2; return true; } } } return false; } private static bool ContainsRoomClass(List<RoomClassPreset> classes, string className) { for (int i = 0; i < classes.Count; i++) { RoomClassPreset val = classes[i]; if ((SoCustomComparison)(object)val != (SoCustomComparison)null && ControlRoomScanner.PresetName((Object)(object)val).Equals(className, StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } } internal static class ControlRoomScanner { private static readonly string[] EssentialNameParts = new string[6] { "crunch", "computer", "blueprint", "buildingplan", "residentfile", "residentrecord" }; internal static void Run() { //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Expected O, but got Unknown if (!IsCityReady()) { Plugin.LogSource.LogWarning((object)"Skipped control-room scan because city loading or pre-simulation is still active."); return; } int num = 0; int num2 = 0; RoomConfiguration val = null; Enumerator<int, NewRoom> enumerator = CityData.Instance.roomDictionary.GetEnumerator(); while (enumerator.MoveNext()) { NewRoom value = enumerator.Current.Value; if (!((SoCustomComparison)(object)((value != null) ? value.preset : null) == (SoCustomComparison)null) && !(PresetName((Object)(object)value.preset) != "ControlRoom")) { num++; if (val == null) { val = value.preset; } if (LogRoom(value)) { num2++; } } } ManualLogSource logSource = Plugin.LogSource; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(60, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Control-room scan complete: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(num2); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("/"); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(num); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" rooms lack essential contents."); } logSource.LogInfo(val2); if (Plugin.DumpEligiblePresets.Value && (SoCustomComparison)(object)val != (SoCustomComparison)null) { VanillaPresetScanner.Dump(val); } } private static bool IsCityReady() { if ((Object)(object)CityData.Instance != (Object)null && (Object)(object)CityConstructor.Instance != (Object)null && !CityConstructor.Instance.loadingOperationActive && !CityConstructor.Instance.preSimActive && CityConstructor.Instance.isLoaded && (Object)(object)SessionData.Instance != (Object)null) { return SessionData.Instance.startedGame; } return false; } private static bool LogRoom(NewRoom room) { //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Expected O, but got Unknown //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Expected O, but got Unknown //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Expected O, but got Unknown List<string> list = new List<string>(); List<string> list2 = new List<string>(); bool hasMicroCruncher = false; bool hasBlueprints = false; if (room.individualFurniture != null) { for (int i = 0; i < room.individualFurniture.Count; i++) { FurnitureLocation val = room.individualFurniture[i]; if (!((SoCustomComparison)(object)((val != null) ? val.furniture : null) == (SoCustomComparison)null)) { string item = PresetName((Object)(object)val.furniture); list.Add(item); AddInteractables(val.integratedInteractables, list2, ref hasMicroCruncher, ref hasBlueprints); AddInteractables(val.spawnedInteractables, list2, ref hasMicroCruncher, ref hasBlueprints); } } } if (room.worldObjects != null) { Enumerator<Interactable> enumerator = room.worldObjects.GetEnumerator(); while (enumerator.MoveNext()) { Interactable current = enumerator.Current; if (!((SoCustomComparison)(object)((current != null) ? current.preset : null) == (SoCustomComparison)null)) { list2.Add(PresetName((Object)(object)current.preset)); } } } bool num = hasMicroCruncher && hasBlueprints; string text = (num ? "OK" : "BROKEN"); ManualLogSource logSource = Plugin.LogSource; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(57, 6, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("["); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(text); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("] ControlRoom roomID="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(room.roomID); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" name='"); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(room.name); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("' "); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("nodes="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(room.nodes?.Count ?? 0); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" "); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("furniture="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(list.Count); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" objects="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(list2.Count); } logSource.LogInfo(val2); LogScanCompany(room); ManualLogSource logSource2 = Plugin.LogSource; val2 = new BepInExInfoLogInterpolatedStringHandler(13, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" furniture: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(JoinNames(list)); } logSource2.LogInfo(val2); ManualLogSource logSource3 = Plugin.LogSource; val2 = new BepInExInfoLogInterpolatedStringHandler(11, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" objects: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(JoinNames(list2)); } logSource3.LogInfo(val2); return !num; } private static void LogScanCompany(NewRoom room) { //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Expected O, but got Unknown string text = "null"; try { text = room.roomID.ToString(); } catch { text = "null"; } string text2 = "null"; string text3 = "null"; string text4 = "null"; string text5 = "null"; NewAddress val = null; try { val = (((Object)(object)room.gameLocation != (Object)null) ? ((Il2CppObjectBase)room.gameLocation).TryCast<NewAddress>() : null); } catch { val = null; } Company val2 = null; if ((Object)(object)val != (Object)null) { try { val2 = val.company; } catch { val2 = null; } } if (val2 != null) { try { text2 = val2.name ?? "null"; } catch { text2 = "null"; } try { text3 = val2.companyID.ToString(); } catch { text3 = "null"; } List<Occupation> val3 = null; try { val3 = val2.companyRoster; } catch { val3 = null; } if (val3 != null) { try { text4 = val3.Count.ToString(); } catch { text4 = "null"; } } try { text5 = val2.GetNumberOfFilledJobs().ToString(); } catch { text5 = "null"; } } ManualLogSource logSource = Plugin.LogSource; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val4 = new BepInExInfoLogInterpolatedStringHandler(40, 5, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("[scan] room="); ((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(text); ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" company="); ((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(text2); ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" id="); ((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(text3); ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" "); ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("posts="); ((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(text4); ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" filled="); ((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(text5); } logSource.LogInfo(val4); } private static void AddInteractables(List<Interactable>? interactables, List<string> names, ref bool hasMicroCruncher, ref bool hasBlueprints) { if (interactables == null) { return; } for (int i = 0; i < interactables.Count; i++) { Interactable val = interactables[i]; if (!((SoCustomComparison)(object)((val != null) ? val.preset : null) == (SoCustomComparison)null)) { string text = PresetName((Object)(object)val.preset); names.Add(text); if (text == "MicroCruncher") { hasMicroCruncher = true; } if (text == "Blueprints") { hasBlueprints = true; } } } } private static bool IsEssential(string name) { string text = name.Replace("_", "").Replace(" ", ""); for (int i = 0; i < EssentialNameParts.Length; i++) { if (text.IndexOf(EssentialNameParts[i], StringComparison.OrdinalIgnoreCase) >= 0) { return true; } } return false; } private static string JoinNames(List<string> names) { if (names.Count == 0) { return "<none>"; } names.Sort(StringComparer.OrdinalIgnoreCase); StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < names.Count; i++) { if (i > 0) { stringBuilder.Append(", "); } stringBuilder.Append(names[i]); } return stringBuilder.ToString(); } internal static string PresetName(Object preset) { if (!(preset != (Object)null)) { return "<null>"; } return preset.name ?? "<unnamed>"; } } internal static class ExistingCityRepair { private static readonly string[] RequiredClusterNames = new string[3] { "DeskAgainstWall", "Shelf", "WallClock" }; private static readonly string[] FilingCabinetClusterNames = new string[2] { "FilingCabinetTall", "FilingCabinetShort" }; internal static void Run() { //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Expected O, but got Unknown if ((Object)(object)GenerationController.Instance == (Object)null || (Object)(object)Toolbox.Instance == (Object)null) { Plugin.LogSource.LogWarning((object)"Existing-city repair skipped because generation systems are not ready."); return; } ControlRoomGenerationFix.Apply(); int num = 0; Enumerator<int, NewRoom> enumerator = CityData.Instance.roomDictionary.GetEnumerator(); while (enumerator.MoveNext()) { NewRoom value = enumerator.Current.Value; if ((SoCustomComparison)(object)((value != null) ? value.preset : null) == (SoCustomComparison)null || !ControlRoomScanner.PresetName((Object)(object)value.preset).Equals("ControlRoom", StringComparison.OrdinalIgnoreCase) || HasMicroCruncher(value)) { continue; } CreateMissingDeskInteractables(value); int num2 = 0; for (int i = 0; i < RequiredClusterNames.Length; i++) { if (TryAddMissingCluster(value, RequiredClusterNames[i])) { num2++; } } if (TryAddOneFilingCabinet(value)) { num2++; } if (num2 > 0) { num++; } } ManualLogSource logSource = Plugin.LogSource; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(48, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Existing-city ControlRoom repair changed "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(num); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" rooms."); } logSource.LogInfo(val); } private static bool TryAddOneFilingCabinet(NewRoom room) { if (HasAnyFilingCabinet(room)) { return false; } for (int i = 0; i < FilingCabinetClusterNames.Length; i++) { if (TryAddMissingCluster(room, FilingCabinetClusterNames[i])) { return true; } } return false; } private static bool HasAnyFilingCabinet(NewRoom room) { for (int i = 0; i < FilingCabinetClusterNames.Length; i++) { if (HasCluster(room, FilingCabinetClusterNames[i])) { return true; } } return false; } private static bool TryAddMissingCluster(NewRoom room, string clusterName) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Expected O, but got Unknown //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Expected O, but got Unknown //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Expected O, but got Unknown if (HasCluster(room, clusterName)) { return false; } FurnitureCluster val = FindCluster(clusterName); bool flag = default(bool); if ((SoCustomComparison)(object)val == (SoCustomComparison)null) { ManualLogSource logSource = Plugin.LogSource; BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(46, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Cannot repair room "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(room.roomID); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": cluster '"); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(clusterName); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("' was not found."); } logSource.LogWarning(val2); return false; } bool flag2 = false; FurnitureClusterLocation bestFurnitureClusterLocation = GenerationController.Instance.GetBestFurnitureClusterLocation(room, val, false, false); if (bestFurnitureClusterLocation == null && clusterName == "DeskAgainstWall") { flag2 = true; bestFurnitureClusterLocation = GenerationController.Instance.GetBestFurnitureClusterLocation(room, val, false, true); } if (bestFurnitureClusterLocation == null) { ManualLogSource logSource2 = Plugin.LogSource; BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(38, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("No valid '"); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(clusterName); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("' placement in ControlRoom "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(room.roomID); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("."); } logSource2.LogWarning(val2); return false; } LogChosenFurniture(room, clusterName, bestFurnitureClusterLocation, "before-prefer"); if (clusterName == "DeskAgainstWall") { PreferDeskPresetWithMicroCruncher(bestFurnitureClusterLocation); } ManualLogSource logSource3 = Plugin.LogSource; BepInExInfoLogInterpolatedStringHandler val3 = new BepInExInfoLogInterpolatedStringHandler(62, 3, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("[repair-before-add] ControlRoom "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(room.roomID); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" cluster='"); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(clusterName); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("' "); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("ignoreLimitations="); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<bool>(flag2); } logSource3.LogInfo(val3); room.AddFurniture(bestFurnitureClusterLocation, true, true, true, flag2, (DesignStylePreset)null); CreateInteractables(room, bestFurnitureClusterLocation); LogChosenFurniture(room, clusterName, bestFurnitureClusterLocation, "after-add"); ManualLogSource logSource4 = Plugin.LogSource; val3 = new BepInExInfoLogInterpolatedStringHandler(25, 3, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Added '"); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(clusterName); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("' to ControlRoom "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(room.roomID); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(flag2 ? " using fallback placement" : ""); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("."); } logSource4.LogInfo(val3); return true; } private static void CreateInteractables(NewRoom room, FurnitureClusterLocation clusterLocation) { if (clusterLocation.clusterList == null) { return; } NewGameLocation gameLocation = room.gameLocation; NewAddress address = (NewAddress)(object)((gameLocation is NewAddress) ? gameLocation : null); for (int i = 0; i < clusterLocation.clusterList.Count; i++) { FurnitureLocation val = clusterLocation.clusterList[i]; if (val != null) { CreateInteractables(val, address); SpawnedLayerFill.FillSpawnedLayer(val, room.roomID); } } } private static void CreateMissingDeskInteractables(NewRoom room) { //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Expected O, but got Unknown if (room.individualFurniture == null) { return; } NewGameLocation gameLocation = room.gameLocation; NewAddress address = (NewAddress)(object)((gameLocation is NewAddress) ? gameLocation : null); bool flag = default(bool); for (int i = 0; i < room.individualFurniture.Count; i++) { FurnitureLocation val = room.individualFurniture[i]; object obj; if (val == null) { obj = null; } else { FurnitureClusterLocation cluster = val.cluster; obj = ((cluster != null) ? cluster.cluster : null); } if (!((SoCustomComparison)obj == (SoCustomComparison)null) && ControlRoomScanner.PresetName((Object)(object)val.cluster.cluster).Equals("DeskAgainstWall", StringComparison.OrdinalIgnoreCase) && !ContainsMicroCruncher(val.integratedInteractables) && (val.integratedInteractables?.Count ?? 0) <= 0) { Plugin.LogSource.LogInfo((object)($"[repair-before-existing-desk] ControlRoom {room.roomID} " + FurnitureInteractableAudit.Describe(val))); CreateInteractables(val, address); SpawnedLayerFill.FillSpawnedLayer(val, room.roomID); ManualLogSource logSource = Plugin.LogSource; BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(51, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Created missing desk interactables in ControlRoom "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(room.roomID); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("."); } logSource.LogInfo(val2); } } } private static void CreateInteractables(FurnitureLocation furniture, NewAddress? address) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Expected O, but got Unknown if ((Object)(object)address != (Object)null) { furniture.AssignOwner(address, false); } ManualLogSource logSource = Plugin.LogSource; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(23, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[repair-before-create] "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(FurnitureInteractableAudit.Describe(furniture)); } logSource.LogInfo(val); furniture.CreateInteractables(); furniture.UpdateIntegratedObjectOwnership(); furniture.SpawnObject(true); ManualLogSource logSource2 = Plugin.LogSource; val = new BepInExInfoLogInterpolatedStringHandler(22, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[repair-after-create] "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(FurnitureInteractableAudit.Describe(furniture)); } logSource2.LogInfo(val); if (Plugin.TryAlternateInteractableOrdering.Value && !FurnitureInteractableAudit.HasIntegratedInstances(furniture)) { TryAlternateInteractableOrdering(furniture); } } private static void TryAlternateInteractableOrdering(FurnitureLocation furniture) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Expected O, but got Unknown //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Expected O, but got Unknown Plugin.LogSource.LogInfo((object)"[repair-order-probe] current AssignOwner -> CreateInteractables -> UpdateIntegratedObjectOwnership -> SpawnObject left integrated=0; trying SpawnObject -> CreateInteractables."); furniture.SpawnObject(true); furniture.CreateInteractables(); furniture.UpdateIntegratedObjectOwnership(); ManualLogSource logSource = Plugin.LogSource; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(27, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[repair-after-spawn-first] "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(FurnitureInteractableAudit.Describe(furniture)); } logSource.LogInfo(val); if (FurnitureInteractableAudit.HasIntegratedInstances(furniture)) { return; } int value = FurnitureInteractableAudit.PresetDefinitionCount(furniture.furniture); Plugin.LogSource.LogInfo((object)("[repair-order-probe] spawn-first still integrated=0; " + $"presetIntegrated={value}. Invoking parameterless " + "FurnitureLocation methods whose names mention interactables.")); foreach (MethodInfo item in VanillaInteractableApiProbe.ParameterlessInteractableMethods(furniture)) { if (item.Name.Equals("CreateInteractables", StringComparison.Ordinal) || item.Name.Equals("SpawnObject", StringComparison.Ordinal) || item.Name.Equals("UpdateIntegratedObjectOwnership", StringComparison.Ordinal)) { continue; } try { InteractableCreationTrace.Phase = "repair-invoke-" + item.Name; item.Invoke(furniture, Array.Empty<object>()); Plugin.LogSource.LogInfo((object)("[repair-after-invoke " + item.Name + "] " + FurnitureInteractableAudit.Describe(furniture))); } catch (Exception ex) { ManualLogSource logSource2 = Plugin.LogSource; BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(30, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[repair-order-probe] "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(item.Name); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" failed: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex.Message); } logSource2.LogWarning(val2); } if (FurnitureInteractableAudit.HasIntegratedInstances(furniture)) { ManualLogSource logSource3 = Plugin.LogSource; val = new BepInExInfoLogInterpolatedStringHandler(56, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[repair-order-probe] "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(item.Name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" produced integrated interactables."); } logSource3.LogInfo(val); return; } } InteractableCreationTrace.Phase = "repair"; } private static void LogChosenFurniture(NewRoom room, string clusterName, FurnitureClusterLocation location, string phase) { //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Expected O, but got Unknown //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Expected O, but got Unknown if (location.clusterList == null) { Plugin.LogSource.LogInfo((object)($"[repair-chosen {phase}] ControlRoom {room.roomID} cluster='{clusterName}' " + "clusterList=<none>")); return; } ManualLogSource logSource = Plugin.LogSource; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(48, 4, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[repair-chosen "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(phase); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("] ControlRoom "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(room.roomID); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" cluster='"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(clusterName); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' "); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("pieces="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(location.clusterList.Count); } logSource.LogInfo(val); for (int i = 0; i < location.clusterList.Count; i++) { FurnitureLocation val2 = location.clusterList[i]; if (val2 != null) { ManualLogSource logSource2 = Plugin.LogSource; val = new BepInExInfoLogInterpolatedStringHandler(19, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[repair-chosen "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(phase); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("] "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(FurnitureInteractableAudit.Describe(val2)); } logSource2.LogInfo(val); if (clusterName == "DeskAgainstWall" && (SoCustomComparison)(object)val2.furniture != (SoCustomComparison)null && !FurnitureInteractableAudit.PresetDefines(val2.furniture, "MicroCruncher")) { Plugin.LogSource.LogWarning((object)($"[repair-chosen {phase}] DeskAgainstWall selected furniture '{ControlRoomScanner.PresetName((Object)(object)val2.furniture)}' " + "with no MicroCruncher preset definition.")); } } } } private static void PreferDeskPresetWithMicroCruncher(FurnitureClusterLocation location) { //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Expected O, but got Unknown if (!Plugin.PreferWorkingDeskPreset.Value || location.clusterList == null) { return; } FurniturePreset val = WorkingReferenceAudit.FindDeskPresetWithMicroCruncher(); if ((SoCustomComparison)(object)val == (SoCustomComparison)null) { Plugin.LogSource.LogWarning((object)"[repair-prefer] no Toolbox furniture preset defines a MicroCruncher."); return; } Plugin.LogSource.LogInfo((object)("[repair-prefer] candidate " + FurnitureInteractableAudit.DescribeFurniturePreset(val))); bool flag = default(bool); for (int i = 0; i < location.clusterList.Count; i++) { FurnitureLocation val2 = location.clusterList[i]; if (val2 != null && !FurnitureInteractableAudit.PresetDefines(val2.furniture, "MicroCruncher")) { string text = (((SoCustomComparison)(object)val2.furniture != (SoCustomComparison)null) ? ControlRoomScanner.PresetName((Object)(object)val2.furniture) : "<null>"); val2.furniture = val; ManualLogSource logSource = Plugin.LogSource; BepInExInfoLogInterpolatedStringHandler val3 = new BepInExInfoLogInterpolatedStringHandler(66, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("[repair-prefer] replaced furniture '"); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(text); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("' with "); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("'"); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(ControlRoomScanner.PresetName((Object)(object)val)); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("' before AddFurniture."); } logSource.LogInfo(val3); } } } private static FurnitureCluster? FindCluster(string name) { for (int i = 0; i < Toolbox.Instance.allFurnitureClusters.Count; i++) { FurnitureCluster val = Toolbox.Instance.allFurnitureClusters[i]; if ((SoCustomComparison)(object)val != (SoCustomComparison)null && ControlRoomScanner.PresetName((Object)(object)val).Equals(name, StringComparison.OrdinalIgnoreCase)) { return val; } } return null; } private static bool HasCluster(NewRoom room, string clusterName) { if (room.individualFurniture == null) { return false; } for (int i = 0; i < room.individualFurniture.Count; i++) { FurnitureLocation obj = room.individualFurniture[i]; object obj2; if (obj == null) { obj2 = null; } else { FurnitureClusterLocation cluster = obj.cluster; obj2 = ((cluster != null) ? cluster.cluster : null); } FurnitureCluster val = (FurnitureCluster)obj2; if ((SoCustomComparison)(object)val != (SoCustomComparison)null && ControlRoomScanner.PresetName((Object)(object)val).Equals(clusterName, StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } private static bool HasMicroCruncher(NewRoom room) { if (room.individualFurniture == null) { return false; } for (int i = 0; i < room.individualFurniture.Count; i++) { FurnitureLocation val = room.individualFurniture[i]; if (val != null && (ContainsMicroCruncher(val.integratedInteractables) || ContainsMicroCruncher(val.spawnedInteractables))) { return true; } } return false; } private static bool ContainsMicroCruncher(List<Interactable>? interactables) { if (interactables == null) { return false; } for (int i = 0; i < interactables.Count; i++) { Interactable val = interactables[i]; if ((SoCustomComparison)(object)((val != null) ? val.preset : null) != (SoCustomComparison)null && ControlRoomScanner.PresetName((Object)(object)val.preset).Equals("MicroCruncher", StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } } internal static class FurnitureInteractableAudit { internal static void LogControlRooms(string phase) { //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Expected O, but got Unknown CityData instance = CityData.Instance; bool flag = default(bool); if (((instance != null) ? instance.roomDictionary : null) == null) { ManualLogSource logSource = Plugin.LogSource; BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(60, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Interactable audit '"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(phase); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' skipped because the city is not ready."); } logSource.LogWarning(val); return; } int num = 0; int num2 = 0; Enumerator<int, NewRoom> enumerator = CityData.Instance.roomDictionary.GetEnumerator(); ManualLogSource logSource2 = Plugin.LogSource; BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(27, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("=== Interactable audit "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(phase); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" ==="); } logSource2.LogInfo(val2); while (enumerator.MoveNext()) { NewRoom value = enumerator.Current.Value; if (!((SoCustomComparison)(object)((value != null) ? value.preset : null) == (SoCustomComparison)null) && ControlRoomScanner.PresetName((Object)(object)value.preset).Equals("ControlRoom", StringComparison.OrdinalIgnoreCase)) { num++; num2 += LogRoom(value, phase); } } ManualLogSource logSource3 = Plugin.LogSource; val2 = new BepInExInfoLogInterpolatedStringHandler(56, 3, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("=== Interactable audit "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(phase); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" complete: rooms="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(num); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", "); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("furniture="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(num2); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" ==="); } logSource3.LogInfo(val2); } internal static int LogRoom(NewRoom room, string phase) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Expected O, but got Unknown //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Expected O, but got Unknown bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val; if (room.individualFurniture == null) { ManualLogSource logSource = Plugin.LogSource; val = new BepInExInfoLogInterpolatedStringHandler(39, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("["); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(phase); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("] ControlRoom roomID="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(room.roomID); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" furniture=<none>"); } logSource.LogInfo(val); return 0; } ManualLogSource logSource2 = Plugin.LogSource; val = new BepInExInfoLogInterpolatedStringHandler(33, 3, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("["); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(phase); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("] ControlRoom roomID="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(room.roomID); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" "); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("furniture="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(room.individualFurniture.Count); } logSource2.LogInfo(val); for (int i = 0; i < room.individualFurniture.Count; i++) { FurnitureLocation val2 = room.individualFurniture[i]; if (val2 != null) { ManualLogSource logSource3 = Plugin.LogSource; val = new BepInExInfoLogInterpolatedStringHandler(5, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("["); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(phase); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("] "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(Describe(val2)); } logSource3.LogInfo(val); } } return room.individualFurniture.Count; } internal static string Describe(FurnitureLocation location) { string value = (((SoCustomComparison)(object)location.furniture != (SoCustomComparison)null) ? ControlRoomScanner.PresetName((Object)(object)location.furniture) : "<null>"); FurnitureClusterLocation cluster = location.cluster; string value2 = (((SoCustomComparison)(object)((cluster != null) ? cluster.cluster : null) != (SoCustomComparison)null) ? ControlRoomScanner.PresetName((Object)(object)location.cluster.cluster) : "<none>"); return $"id={ReadId(location)} furniture='{value}' cluster='{value2}' presetIntegrated={DescribePresetDefinitions(location.furniture)} locationIntegrated={DescribeInteractables(location.integratedInteractables)} locationSpawned={DescribeInteractables(location.spawnedInteractables)}"; } internal static bool HasIntegratedInstances(FurnitureLocation location) { return (location.integratedInteractables?.Count ?? 0) > 0; } internal static int PresetDefinitionCount(object? furniture) { return CountIl2CppList(ReadMember(furniture, "integratedInteractables")); } internal static bool PresetDefines(object? furniture, string namePart) { List<string> list = NamesFromUnknownList(ReadMember(furniture, "integratedInteractables")); for (int i = 0; i < list.Count; i++) { if (list[i].IndexOf(namePart, StringComparison.OrdinalIgnoreCase) >= 0) { return true; } } return false; } internal static string DescribeFurniturePreset(object? furniture) { Object val = (Object)((furniture is Object) ? furniture : null); string text = ((val != null) ? ControlRoomScanner.PresetName(val) : "<null>"); return "furniture='" + text + "' presetIntegrated=" + DescribePresetDefinitions(furniture); } internal static string DescribePresetDefinitions(object? furniture) { if (furniture == null) { return "0[]"; } List<string> list = NamesFromUnknownList(ReadMember(furniture, "integratedInteractables")); int value = CountIl2CppList(ReadMember(furniture, "subObjects")); return $"{list.Count}[{JoinNames(list)}] subObjects={value}"; } private static string DescribeInteractables(List<Interactable>? interactables) { List<string> list = new List<string>(); if (interactables != null) { for (int i = 0; i < interactables.Count; i++) { Interactable val = interactables[i]; list.Add(((SoCustomComparison)(object)((val != null) ? val.preset : null) != (SoCustomComparison)null) ? ControlRoomScanner.PresetName((Object)(object)val.preset) : "<null>"); } } return $"{list.Count}[{JoinNames(list)}]"; } private static List<string> NamesFromUnknownList(object? list) { List<string> list2 = new List<string>(); int num = CountIl2CppList(list); for (int i = 0; i < num; i++) { list2.Add(NameFromUnknownItem(IndexIl2CppList(list, i))); } return list2; } private static string NameFromUnknownItem(object? item) { if (item == null) { return "<null>"; } object? obj = ReadMember(item, "preset"); Object val = (Object)((obj is Object) ? obj : null); if (val != null) { return ControlRoomScanner.PresetName(val); } Object val2 = (Object)((item is Object) ? item : null); if (val2 != null) { return ControlRoomScanner.PresetName(val2); } return item.GetType().Name; } private static object? ReadMember(object? target, string name) { if (target == null) { return null; } Type type = target.GetType(); PropertyInfo property = type.GetProperty(name); if (property != null) { return property.GetValue(target); } return type.GetField(name)?.GetValue(target); } private static int CountIl2CppList(object? list) { if (list == null) { return 0; } object obj = ReadMember(list, "Count"); if (obj is int) { return (int)obj; } return 0; } private static object? IndexIl2CppList(object? list, int index) { return list?.GetType().GetProperty("Item")?.GetValue(list, new object[1] { index }); } private static string ReadId(FurnitureLocation location) { string[] array = new string[4] { "id", "furnitureID", "furnID", "idnt" }; foreach (string text in array) { object obj = ReadMember(location, text); if (obj != null) { return $"{text}={obj}"; } } return "id=<unknown>"; } private static string JoinNames(List<string> names) { if (names.Count == 0) { return ""; } StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < names.Count; i++) { if (i > 0) { stringBuilder.Append(','); } stringBuilder.Append(names[i]); } return stringBuilder.ToString(); } } [HarmonyPatch(typeof(MurderController), "OnStartGame")] internal static class GameStartedPatch { [HarmonyPostfix] private static void Postfix() { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Expected O, but got Unknown //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Expected O, but got Unknown //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Expected O, but got Unknown if (Plugin.DumpInteractablePipeline.Value) { InteractableCreationTrace.Phase = "before-repair"; VanillaInteractableApiProbe.LogCityConstructorState(); WorkingReferenceAudit.LogReferences(); FurnitureInteractableAudit.LogControlRooms("before-repair"); } bool flag = default(bool); if (Plugin.RepairExistingControlRooms.Value) { try { InteractableCreationTrace.Phase = "repair"; ExistingCityRepair.Run(); } catch (Exception ex) { ManualLogSource logSource = Plugin.LogSource; BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(41, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Existing-city ControlRoom repair failed: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex); } logSource.LogError(val); } } if (Plugin.HireForVacantControlRooms.Value) { try { VacantPostHiring.Run(); } catch (Exception ex2) { ManualLogSource logSource2 = Plugin.LogSource; BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(35, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Vacant control-room hiring failed: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex2); } logSource2.LogError(val); } } if (Plugin.DumpInteractablePipeline.Value) { InteractableCreationTrace.Phase = "after-repair"; FurnitureInteractableAudit.LogControlRooms("after-repair"); } try { InteractableCreationTrace.Phase = "roster"; ResidentRosterCompleter.Run(); } catch (Exception ex3) { ManualLogSource logSource3 = Plugin.LogSource; BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(40, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("ResidentRoster one-drawer limit failed: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex3); } logSource3.LogError(val); } try { InteractableCreationTrace.Phase = "scan"; ControlRoomScanner.Run(); CityHallGenerationFix.LogResult(); } catch (Exception ex4) { ManualLogSource logSource4 = Plugin.LogSource; BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(40, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Post-generation diagnostic pass failed: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex4); } logSource4.LogError(val); } InteractableCreationTrace.Phase = "post-start"; } } internal static class InteractableCreationTrace { internal static string Phase { get; set; } = "startup"; public static void Postfix(object __instance, MethodBase __originalMethod) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Expected O, but got Unknown if (Plugin.DumpInteractablePipeline.Value && !(__originalMethod == null)) { string text = __originalMethod.DeclaringType?.Name ?? "<unknown>"; FurnitureLocation val = (FurnitureLocation)((__instance is FurnitureLocation) ? __instance : null); string text2 = ((val != null) ? FurnitureInteractableAudit.Describe(val) : (__instance?.ToString() ?? "<static>")); ManualLogSource logSource = Plugin.LogSource; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(17, 4, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[trace] "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(text); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("."); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(__originalMethod.Name); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" phase="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(Phase); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(text2); } logSource.LogInfo(val2); } } } [BepInPlugin("sm3gm.sod.controlroomfix", "Control Room Fix", "1.1.0")] public sealed class Plugin : BasePlugin { public const string PluginGuid = "sm3gm.sod.controlroomfix"; public const string PluginName = "Control Room Fix"; public const string PluginVersion = "1.1.0"; internal static ManualLogSource LogSource { get; private set; } internal static ConfigEntry<bool> DumpEligiblePresets { get; private set; } internal static ConfigEntry<bool> DumpInteractablePipeline { get; private set; } internal static ConfigEntry<bool> TryAlternateInteractableOrdering { get; private set; } internal static ConfigEntry<bool> PreferWorkingDeskPreset { get; private set; } internal static ConfigEntry<bool> EnableGenerationFix { get; private set; } internal static ConfigEntry<bool> RepairExistingControlRooms { get; private set; } internal static ConfigEntry<bool> HireForVacantControlRooms { get; private set; } internal static ConfigEntry<bool> EnableCityHallGenerationFix { get; private set; } internal static ConfigEntry<bool> CompleteResidentRosters { get; private set; } public override void Load() { //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Expected O, but got Unknown //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Expected O, but got Unknown LogSource = ((BasePlugin)this).Log; EnableGenerationFix = ((BasePlugin)this).Config.Bind<bool>("Fixes", "EnableControlRoomGenerationFix", true, "Allow functional furniture to generate in otherwise uninhabited ControlRoom addresses."); RepairExistingControlRooms = ((BasePlugin)this).Config.Bind<bool>("Fixes", "RepairExistingControlRooms", true, "Add missing vanilla functional clusters when an existing broken city is loaded."); HireForVacantControlRooms = ((BasePlugin)this).Config.Bind<bool>("Fixes", "HireForVacantControlRooms", true, "Give a control room's company one employee when all its posts are vacant, so its computer has a login. Re-applied on every load; nothing is saved."); EnableCityHallGenerationFix = ((BasePlugin)this).Config.Bind<bool>("Fixes", "EnableDuplicateCityHallLimitExperiment", false, "Experimental: raise CityHall company limits to eligible address count."); CompleteResidentRosters = ((BasePlugin)this).Config.Bind<bool>("Fixes", "CompleteResidentRosters", false, "Optional extra: add every building inhabitant to one ControlRoom ResidentRoster drawer. Extra drawers are emptied either way so files are not duplicated. Default off (vanilla-like partial folders)."); DumpEligiblePresets = ((BasePlugin)this).Config.Bind<bool>("Diagnostics", "DumpEligiblePresets", false, "Log furniture clusters and presets eligible for ControlRoom rooms."); DumpInteractablePipeline = ((BasePlugin)this).Config.Bind<bool>("Diagnostics", "DumpInteractablePipeline", false, "Log vanilla furniture/interactable APIs and before/after repair counts."); TryAlternateInteractableOrdering = ((BasePlugin)this).Config.Bind<bool>("Fixes", "TryAlternateInteractableOrdering", true, "If CreateInteractables leaves integrated=0, try SpawnObject-first and other parameterless interactable methods."); PreferWorkingDeskPreset = ((BasePlugin)this).Config.Bind<bool>("Fixes", "PreferWorkingDeskPreset", true, "If DeskAgainstWall picks a furniture preset with no MicroCruncher, assign a Toolbox desk preset that defines one."); Harmony.CreateAndPatchAll(typeof(GameStartedPatch), "sm3gm.sod.controlroomfix"); Harmony.CreateAndPatchAll(typeof(InteriorGenerationPatch), "sm3gm.sod.controlroomfix"); Harmony.CreateAndPatchAll(typeof(CitizenGenerationPatch), "sm3gm.sod.controlroomfix"); bool flag = default(bool); if (DumpInteractablePipeline.Value) { try { VanillaInteractableApiProbe.DumpAndTrace(); } catch (Exception ex) { ManualLogSource logSource = LogSource; BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(39, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Vanilla interactable API probe failed: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex); } logSource.LogError(val); } } ManualLogSource logSource2 = LogSource; BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(144, 7, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>("Control Room Fix"); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>("1.1.0"); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" loaded; fixes: "); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("ControlRoom generation="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(EnableGenerationFix.Value ? "enabled" : "disabled"); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", "); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("existing ControlRooms="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(RepairExistingControlRooms.Value ? "enabled" : "disabled"); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", "); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("complete resident rosters="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(CompleteResidentRosters.Value ? "enabled" : "disabled"); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", "); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("duplicate City Hall="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(EnableCityHallGenerationFix.Value ? "enabled" : "disabled"); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", "); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("interactable pipeline dump="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(DumpInteractablePipeline.Value ? "enabled" : "disabled"); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("."); } logSource2.LogInfo(val2); } } internal static class ResidentRosterCompleter { internal static void Run() { //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Expected O, but got Unknown //IL_0273: Unknown result type (might be due to invalid IL or missing references) //IL_027a: Expected O, but got Unknown //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Expected O, but got Unknown CityData instance = CityData.Instance; if (((instance != null) ? instance.roomDictionary : null) == null) { return; } int num = 0; int num2 = 0; int num3 = 0; int num4 = 0; int num5 = 0; Enumerator<int, NewRoom> enumerator = CityData.Instance.roomDictionary.GetEnumerator(); bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val3; while (enumerator.MoveNext()) { NewRoom value = enumerator.Current.Value; if ((SoCustomComparison)(object)((value != null) ? value.preset : null) == (SoCustomComparison)null || !ControlRoomScanner.PresetName((Object)(object)value.preset).Equals("ControlRoom", StringComparison.OrdinalIgnoreCase) || value.worldObjects == null) { continue; } List<EvidenceMultiPage> list = CollectResidentRosters(value); if (list.Count == 0) { continue; } EvidenceMultiPage val = PickKeeper(list); if (Plugin.CompleteResidentRosters.Value) { int num6 = AddMissingBuildingResidents(value, val); if (num6 > 0) { ((Evidence)val).forceSave = true; num4++; num5 += num6; } } int num7 = 0; int num8 = 0; for (int i = 0; i < list.Count; i++) { EvidenceMultiPage val2 = list[i]; if (val2 != val) { int num9 = ClearRosterPages(val2); if (num9 > 0) { num7++; num8 += num9; } } } if (list.Count > 1) { num++; num2 += num7; num3 += num8; ManualLogSource logSource = Plugin.LogSource; val3 = new BepInExInfoLogInterpolatedStringHandler(101, 4, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("ControlRoom "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(value.roomID); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" resident files: keeping 1 drawer "); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("with "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(PageCount(val)); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" pages; cleared "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(num7); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" extra "); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("drawers ("); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(num8); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" duplicate pages)."); } logSource.LogInfo(val3); } } ManualLogSource logSource2 = Plugin.LogSource; val3 = new BepInExInfoLogInterpolatedStringHandler(90, 3, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("ResidentRoster one-drawer limit: rooms="); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(num); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(", "); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("extra drawers cleared="); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(num2); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(", "); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("duplicate pages removed="); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(num3); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("."); } logSource2.LogInfo(val3); if (Plugin.CompleteResidentRosters.Value) { ManualLogSource logSource3 = Plugin.LogSource; val3 = new BepInExInfoLogInterpolatedStringHandler(74, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("ResidentRoster completion updated "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(num4); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" keeper rosters "); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("with "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(num5); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" missing residents."); } logSource3.LogInfo(val3); } } private static List<EvidenceMultiPage> CollectResidentRosters(NewRoom room) { List<EvidenceMultiPage> list = new List<EvidenceMultiPage>(); Enumerator<Interactable> enumerator = room.worldObjects.GetEnumerator(); while (enumerator.MoveNext()) { Interactable current = enumerator.Current; if (!((SoCustomComparison)(object)((current != null) ? current.preset : null) == (SoCustomComparison)null) && ControlRoomScanner.PresetName((Object)(object)current.preset).Equals("ResidentRoster", StringComparison.OrdinalIgnoreCase)) { Evidence evidence = current.evidence; EvidenceMultiPage val = (EvidenceMultiPage)(object)((evidence is EvidenceMultiPage) ? evidence : null); if (val != null) { list.Add(val); } } } return list; } private static EvidenceMultiPage PickKeeper(List<EvidenceMultiPage> rosters) { EvidenceMultiPage val = rosters[0]; int num = PageCount(val); for (int i = 1; i < rosters.Count; i++) { EvidenceMultiPage val2 = rosters[i]; int num2 = PageCount(val2); if (num2 > num) { val = val2; num = num2; } } return val; } private static int PageCount(EvidenceMultiPage roster) { return roster.pageContent?.Count ?? 0; } private static int ClearRosterPages(EvidenceMultiPage roster) { if (roster.pageContent == null) { return 0; } int count = roster.pageContent.Count; if (count == 0) { return 0; } while (roster.pageContent.Count > 0) { roster.pageContent.RemoveAt(roster.pageContent.Count - 1); } ((Evidence)roster).forceSave = true; return count; } private static int AddMissingBuildingResidents(NewRoom room, EvidenceMultiPage roster) { //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Expected O, but got Unknown HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase); if (roster.pageContent != null) { for (int i = 0; i < roster.pageContent.Count; i++) { MultiPageContent obj = roster.pageContent[i]; string text = ((obj != null) ? obj.evID : null); if (!string.IsNullOrWhiteSpace(text)) { hashSet.Add(text); } } } NewBuilding building = room.building; int num = ((building != null) ? building.buildingID : (-1)); if (num < 0) { return 0; } int num2 = 0; List<NewAddress> addressDirectory = CityData.Instance.addressDirectory; for (int j = 0; j < addressDirectory.Count; j++) { NewAddress val = addressDirectory[j]; if (val == null) { continue; } NewBuilding building2 = ((NewGameLocation)val).building; if (((building2 != null) ? new int?(building2.buildingID) : ((int?)null)) != num || val.inhabitants == null) { continue; } for (int k = 0; k < val.inhabitants.Count; k++) { Human obj2 = val.inhabitants[k]; EvidenceWitness val2 = ((obj2 != null) ? ((Actor)obj2).evidenceEntry : null); if (val2 != null && !string.IsNullOrWhiteSpace(((Evidence)val2).evID) && hashSet.Add(((Evidence)val2).evID)) { roster.AddEvidenceToNewPage((Evidence)(object)val2); num2++; } } } ManualLogSource logSource = Plugin.LogSource; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val3 = new BepInExInfoLogInterpolatedStringHandler(76, 3, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("ControlRoom "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(room.roomID); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" keeper ResidentRoster now references "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(hashSet.Count); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" unique residents; added="); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(num2); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("."); } logSource.LogInfo(val3); return num2; } } internal static class SpawnedLayerFill { private static readonly string[] RequiredPresetNames = new string[4] { "MicroCruncher", "Blueprints", "CompanyRoster", "ResidentRoster" }; internal static void FillSpawnedLayer(FurnitureLocation location, int roomID) { //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Expected O, but got Unknown if (location == null) { return; } FurniturePreset val = null; try { val = location.furniture; } catch { return; } if ((SoCustomComparison)(object)val == (SoCustomComparison)null) { return; } List<SubObject> val2 = null; try { val2 = val.subObjects; } catch { return; } if (val2 == null || val2.Count == 0) { return; } string text = SafePresetName((SoCustomComparison)(object)val); HashSet<int> hashSet = new HashSet<int>(); int num = 0; for (int i = 0; i < RequiredPresetNames.Length; i++) { string wanted = RequiredPresetNames[i]; int num2 = -1; InteractablePreset val3 = null; int num3 = -1; InteractablePreset val4 = null; for (int j = 0; j < val2.Count; j++) { SubObject val5 = null; try { val5 = val2[j]; } catch { continue; } if (val5 == null) { continue; } SubObjectClassPreset val6 = null; try { val6 = val5.preset; } catch { continue; } if ((SoCustomComparison)(object)val6 == (SoCustomComparison)null) { continue; } InteractablePreset val7 = FindByName(ResolveCandidates(val6), wanted); if (!((SoCustomComparison)(object)val7 == (SoCustomComparison)null)) { if (!hashSet.Contains(j)) { num2 = j; val3 = val7; break; } if (num3 < 0) { num3 = j; val4 = val7; } } } int num4 = num2; InteractablePreset val8 = val3; string reason = "fresh-slot"; if ((SoCustomComparison)(object)val8 == (SoCustomComparison)null) { num4 = num3; val8 = val4; reason = "stacked-slot"; } if (!((SoCustomComparison)(object)val8 == (SoCustomComparison)null)) { SubObject val9 = null; try { val9 = val2[num4]; } catch { continue; } if (val9 != null && Create(location, val9, val8, roomID, text, num4, reason)) { num++; hashSet.Add(num4); } } } if (num > 0) { ManualLogSource logSource = Plugin.LogSource; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val10 = new BepInExInfoLogInterpolatedStringHandler(41, 4, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val10).AppendLiteral("[fill] room="); ((BepInExLogInterpolatedStringHandler)val10).AppendFormatted<int>(roomID); ((BepInExLogInterpolatedStringHandler)val10).AppendLiteral(" furniture='"); ((BepInExLogInterpolatedStringHandler)val10).AppendFormatted<string>(text); ((BepInExLogInterpolatedStringHandler)val10).AppendLiteral("' slots="); ((BepInExLogInterpolatedStringHandler)val10).AppendFormatted<int>(val2.Count); ((BepInExLogInterpolatedStringHandler)val10).AppendLiteral(" created="); ((BepInExLogInterpolatedStringHandler)val10).AppendFormatted<int>(num); } logSource.LogInfo(val10); } } private static InteractablePreset FindByName(List<InteractablePreset> candidates, string wanted) { if (candidates == null) { return null; } for (int i = 0; i < candidates.Count; i++) { InteractablePreset val = null; try { val = candidates[i]; } catch { continue; } if (!((SoCustomComparison)(object)val == (SoCustomComparison)null) && SafePresetName((SoCustomComparison)(object)val) == wanted) { return val; } } return null; } private static bool Create(FurnitureLocation location, SubObject slot, InteractablePreset preset, int roomID, string furnitureName, int slotIndex, string reason) { //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Expected O, but got Unknown //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Expected O, but got Unknown //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown string text = ""; try { text = slot.parent; } catch { } bool flag2 = default(bool); try { if (InteractableCreator.Instance.CreateFurnitureSpawnedInteractable(preset, location, slot, (Human)null, (Human)null, (Human)null, (List<Passed>)null, (LightingPreset)null, (Object)null, "") == null) { ManualLogSource logSource = Plugin.LogSource; bool flag = default(bool); BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(73, 6, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[fill] room="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(roomID); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" furniture='"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(furnitureName); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' slot="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(slotIndex); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" "); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("parent='"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(text); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' preset='"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(SafePresetName((SoCustomComparison)(object)preset)); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' reason="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(reason); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" returned null"); } logSource.LogWarning(val); return false; } ManualLogSource logSource2 = Plugin.LogSource; BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(60, 6, ref flag2); if (flag2) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[fill] room="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(roomID); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" furniture='"); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(furnitureName); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("' slot="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(slotIndex); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" "); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("parent='"); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(text); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("' created='"); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(SafePresetName((SoCustomComparison)(object)preset)); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("' reason="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(reason); } logSource2.LogInfo(val2); return true; } catch (Exception ex) { ManualLogSource logSource3 = Plugin.LogSource; BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(67, 7, ref flag2); if (flag2) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[fill] room="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(roomID); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" furniture='"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(furnitureName); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' slot="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(slotIndex); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" "); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("parent='"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(text); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' preset='"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(SafePresetName((SoCustomComparison)(object)preset)); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' reason="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(reason); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" threw: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message); } logSource3.LogWarning(val); return false; } } private static List<InteractablePreset> ResolveCandidates(SubObjectClassPreset classPreset) { try { Dictionary<SubObjectClassPreset, List<InteractablePreset>> subObjectsDictionary = Toolbox.Instance.subObjectsDictionary; if (subObjectsDictionary == null) { return null; } if (!subObjectsDictionary.ContainsKey(classPreset)) { return null; } return subObjectsDictionary[classPreset]; } catch { return null; } } private static string SafePresetName(SoCustomComparison item) { if (item == (SoCustomComparison)null) { return "?"; } try { string presetName = item.GetPresetName(); if (!string.IsNullOrEmpty(presetName)) { return presetName; } } catch { } try { return ((Object)item).name; } catch { return "?"; } } } internal static class VacantPostHiring { internal static void Run() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Expected O, but got Unknown int controlRooms; int addressNull; int companyNull; List<Company> list = CollectCompanies(out controlRooms, out addressNull, out companyNull); string murdererId; string victimId; int previousCount; List<Citizen> list2 = CollectCandidates(CollectExcludedHumanIds(out murdererId, out victimId, out previousCount)); ManualLogSource logSource = Plugin.LogSource; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(89, 7, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[hire] murderer="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(murdererId); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" victim="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(victimId); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" "); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("previousMurderers="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(previousCount); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" pool="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(list2.Count); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("|controlRooms="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(controlRooms); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("|addressNull="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(addressNull); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("|companyNull="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(companyNull); } logSource.LogInfo(val); int num = 0; for (int i = 0; i < list.Count; i++) { Company company = list[i]; try { if (TryHireForCompany(company, list2)) { num++; } } catch (Exception exception) { LogThrew(exception); } } ManualLogSource logSource2 = Plugin.LogSource; val = new BepInExInfoLogInterpolatedStringHandler(27, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[hire] hired "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(num); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" of "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(list.Count); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" companies"); } logSource2.LogInfo(val); } private static List<Company> CollectCompanies(out int controlRooms, out int addressNull, out int companyNull) { controlRooms = 0; addressNull = 0; companyNull = 0; SortedDictionary<int, Company> sortedDictionary = new SortedDictionary<int, Company>(); CityData val = null; try { val = CityData.Instance; } catch (Exception exception) { LogThrew(exception); return new List<Company>(); } if ((Object)(object)val == (Object)null) { return new List<Company>(); } Dictionary<int, NewRoom> val2 = null; try { val2 = val.roomDictionary; } catch (Exception exception2) { LogThrew(exception2); return new List<Company>(); } if (val2 == null) { return new List<Company>(); } Enumerator<int, NewRoom> val3 = null; try { val3 = val2.GetEnumerator(); } catch (Exception exception3) { LogThrew(exception3); return new List<Company>(); } while (true) { bool flag; try { flag = val3.MoveNext(); } catch (Exception exception4) { LogThrew(exception4); break; } if (!flag) { break; } try { NewRoom value = val3.Current.Value; if ((Object)(object)value == (Object)null) { continue; } RoomConfiguration val4 = null; try { val4 = value.preset; } catch (Exception exception5) { LogThrew(exception5); goto end_IL_0097; } if ((SoCustomComparison)(object)val4 == (SoCustomComparison)null) { continue; } string text; try { text = ControlRoomScanner.PresetName((Object)(object)val4); } catch (Exception exception6) { LogThrew(exception6); goto end_IL_0097; } if (text != "ControlRoom") { continue; } controlRooms++; NewAddress val5 = null; try { val5 = (((Object)(object)value.gameLocation != (Object)null) ? ((Il2CppObjectBase)value.gameLocation).TryCast<NewAddress>() : null); } catch (Exception exception7) { LogThrew(exception7); goto end_IL_0097; } if ((Object)(object)val5 == (Object)null) { addressNull++; continue; } Company val6 = null; try { val6 = val5.company; } catch (Exception exception8) { LogThrew(exception8); goto end_IL_0097; } if (val6 == null) { companyNull++; continue; } int companyID; try { companyID = val6.companyID; } catch (Exception exception9) { LogThrew(exception9); goto end_IL_0097; } if (!sortedDictionary.ContainsKey(companyID)) { sortedDictionary[companyID] = val6; } end_IL_0097:; } catch (Exception exception10) { LogThrew(exception10); } } List<Company> list = new List<Company>(); foreach (KeyValuePair<int, Company> item in sortedDictionary) { list.Add(item.Value); } return list; } private static HashSet<int> CollectExcludedHumanIds(out string murdererId, out string victimId, out int previousCount) { murdererId = "null"; victimId = "null"; previousCount = 0; HashSet<int> hashSet = new HashSet<int>(); MurderController val = null; try { val = MurderController.Instance; } catch (Exception exception) { LogThrew(exception); return hashSet; } if ((Object)(object)val == (Object)null) { return hashSet; } Human human = null; try { human = val.currentMurderer; } catch (Exception exception2) { LogThrew(exception2); } TryExclude(human, hashSet, out murdererId); Human human2 = null; try { human2 = val.currentVictim; } catch (Exception exception3) { LogThrew(exception3); } TryExclude(human2, hashSet, out victimId); List<Human> val2 = null; try { val2 = val.previousMurderers; } catch (Exception exception4) { LogThrew(exception4); } if (val2 == null) { return hashSet; } try { previousCount = val2.Count; } catch (Exception exception5) { LogThrew(exception5); previousCount = 0; return hashSet; } for (int i = 0; i < previousCount; i++) { Human val3 = null; try { val3 = val2[i]; } catch (Exception exception6) { LogThrew(exception6); continue; } TryExclude(val3, hashSet, out string _); } return hashSet; } private static void TryExclude(Human? human, HashSet<int> excluded, out string loggedId) { loggedId = "null"; if ((Object)(object)human == (Object)null) { return; } try { int humanID = human.humanID; excluded.Add(humanID); loggedId = humanID.ToString(); } catch (Exception exception) { LogThrew(exception); } } private static List<Citizen> CollectCandidates(HashSet<int> excludedIds) { List<KeyValuePair<int, Citizen>> list = new List<KeyValuePair<int, Citizen>>(); CityData val = null; try { val = CityData.Instance; } catch (Exception exception) { LogThrew(exception); return new List<Citizen>(); } if ((Object)(object)val == (Object)null) { return new List<Citizen>(); } List<Citizen> val2 = null; try { val2 = val.citizenDirectory; } catch (Exception exception2) { LogThrew(exception2); return new List<Citizen>(); } if (val2 == null) { return new List<Citizen>(); } int count; try { count = val2.Count; } catch (Exception exception3) { LogThrew(exception3); return new List<Citizen>(); } for (int i = 0; i < count; i++) { Citizen val3 = null; try { val3 = val2[i]; } catch (Exception exception4) { LogThrew(exception4); continue; } if ((Object)(object)val3 == (Object)null) { continue; } bool isDead; try { isDead = ((Actor)val3).isDead; } catch (Exception exception5) { LogThrew(exception5); continue; } if (isDead) { continue; } bool removedFromWorld; try { removedFromWorld = ((Human)val3).removedFromWorld; } catch (Exception exception6) { LogThrew(exception6); continue; } if (removedFromWorld) { continue; } int humanID; try { humanID = ((Human)val3).humanID; } catch (Exception exception7) { LogThrew(exception7); continue; } if (excludedIds.Contains(humanID)) { continue; } Occupation val4 = null; try { val4 = ((Human)val3).job; } catch (Exception exception8) { LogThrew(exception8); continue; } if (val4 != null) { Company val5 = null; try { val5 = val4.employer; } catch (Exception exception9) { LogThrew(exception9); continue; } if (val5 != null || ReadOccupationPresetName(val4) != "Unemployed") { continue; } } list.Add(new KeyValuePair<int, Citizen>(humanID, val3)); } list.Sort((KeyValuePair<int, Citizen> left, KeyValuePair<int, Citizen> right) => left.Key.CompareTo(right.Key)); List<Citizen> list2 = new List<Citizen>(list.Count); for (int num = 0; num < list.Count; num++) { list2.Add(list[num].Value); } return list2; } private static bool TryHireForCompany(Company company, List<Citizen> pool) { //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Expected O, but got Unknown //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Expected O, but got Unknown //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Expected O, but got Unknown string text; try { text = company.name ?? ""; } catch (Exception exception) { LogThrew(exception); text = "FAILED"; } int companyID; try { companyID = company.companyID; } catch (Exception exception2) { LogThrew(exception2); return false; } int numberOfFilledJobs; try { numberOfFilledJobs = company.GetNumberOfFilledJobs(); } catch (Exception exception3) { LogThrew(exception3); return false; } bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val; if (numberOfFilledJobs > 0) { ManualLogSource logSource = Plugin.LogSource; val = new BepInExInfoLogInterpolatedStringHandler(32, 3, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[hire] skip company="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(text); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" id="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(companyID); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" filled="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(numberOfFilledJobs); } logSource.LogInfo(val); return false; } Occupation val2 = FindVacantPost(company); if (val2 == null) { ManualLogSource logSource2 = Plugin.LogSource; val = new BepInExInfoLogInterpolatedStringHandler(46, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[hire] skip company="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(text); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" id="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(companyID); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" reason=no-vacant-post"); } logSource2.LogInfo(val); return false; } if (pool.Count == 0) { ManualLogSource logSource3 = Plugin.LogSource; val = new BepInExInfoLogInterpolatedStringHandler(44, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[hire] skip company="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(text); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" id="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(companyID); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" reason=no-candidate"); } logSource3.LogInfo(val); return false; } Citizen val3 = pool[0]; try { ((Human)val3).SetJob(val2); } catch (Exception exception4) { LogThrew(exception4); return false; } pool.RemoveAt(0); string text2 = ReadOccupationPresetName(val2); string text3; try { text3 = ((Human)val3).humanID.ToString(); } catch (Exception exception5) { LogThrew(exception5); text3 = "FAILED"; } string text4; try { text4 = ((Human)val3).GetCitizenName() ?? ""; } catch (Exception exception6) { LogThrew(exception6); text4 = "FAILED"; } string text5 = "null"; Occupation val4 = null; try { val4 = ((Human)val3).job; } catch (Exception exception7) { LogThrew(exception7); text5 = "FAILED"; } if (val4 != null) { try { text5 = val4.name ?? ""; } catch (Exception exception8) { LogThrew(exception8); text5 = "FAILED"; } } string text6 = "null"; Human val5 = null; try { val5 = val2.employee; } catch (Exception exception9) { LogThrew(exception9); text6 = "FAILED"; } if ((Object)(object)val5 != (Object)null) { try { text6 = val5.humanID.ToString(); } catch (Exception exception10) { LogThrew(exception10); text6 = "FAILED"; } } ManualLogSource logSource4 = Plugin.LogSource; val = new BepInExInfoLogInterpolatedStringHandler(48, 7, ref flag); if (flag) {