using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using AssetsTools.NET; using AssetsTools.NET.Extra; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using DunGenPlus; using HarmonyLib; using JLL; using JLL.ScriptableObjects; using LethalLevelLoader; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("LCOfficeV81Compat")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("LCOfficeV81Compat")] [assembly: AssemblyTitle("LCOfficeV81Compat")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace LCOfficeV81Compat { internal static class BundlePatcher { private static readonly ManualLogSource Log = Logger.CreateLogSource("LCOfficeV81Compat"); private static readonly HashSet TargetScriptNames = new HashSet(StringComparer.Ordinal) { "DungeonFlow", "Tile", "Doorway", "LocalPropSet", "GlobalProp", "TileSet", "DungeonArchetype", "DoorwaySocket" }; public static string PatchedBundlePath { get; private set; } public static bool CreatePatchedBundleCopy(string originalBundlePath) { //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Expected O, but got Unknown //IL_0616: Unknown result type (might be due to invalid IL or missing references) //IL_061d: Expected O, but got Unknown Log.LogInfo((object)"[LCOfficeV81Compat] Local bundle patching starting."); if (string.IsNullOrWhiteSpace(originalBundlePath)) { Log.LogError((object)"[LCOfficeV81Compat] Original bundle path is empty."); return false; } if (!File.Exists(originalBundlePath)) { Log.LogError((object)("[LCOfficeV81Compat] Original bundle does not exist: " + originalBundlePath)); return false; } string text = Path.Combine(Paths.BepInExRootPath, "cache", "LCOfficeV81Compat"); Directory.CreateDirectory(text); string text2 = Path.Combine(text, "lcoffice_patched"); string text3 = Path.Combine(text, "lcoffice_patched.tmp"); string path = Path.Combine(text, "lcoffice_patched.sourceinfo"); Log.LogInfo((object)"[LCOfficeV81Compat] Original bundle:"); Log.LogInfo((object)("[LCOfficeV81Compat] " + originalBundlePath)); Log.LogInfo((object)"[LCOfficeV81Compat] Patched bundle target:"); Log.LogInfo((object)("[LCOfficeV81Compat] " + text2)); try { FileInfo fileInfo = new FileInfo(originalBundlePath); string b = fileInfo.Length + "|" + fileInfo.LastWriteTimeUtc.Ticks; if (File.Exists(text2) && File.Exists(path)) { string a = File.ReadAllText(path).Trim(); if (string.Equals(a, b, StringComparison.Ordinal)) { PatchedBundlePath = text2; Log.LogWarning((object)"[LCOfficeV81Compat] Patched bundle cache hit."); Log.LogInfo((object)"[LCOfficeV81Compat] Reusing cached patched bundle:"); Log.LogInfo((object)("[LCOfficeV81Compat] " + PatchedBundlePath)); return true; } Log.LogInfo((object)"[LCOfficeV81Compat] Patched bundle cache is stale; rebuilding."); } else { Log.LogInfo((object)"[LCOfficeV81Compat] No valid patched bundle cache found; building."); } } catch (Exception ex) { Log.LogWarning((object)("[LCOfficeV81Compat] Cache check failed; rebuilding patched bundle:\n" + ex)); } AssetsManager val = new AssetsManager(); try { if (File.Exists(text3)) { File.Delete(text3); } BundleFileInstance val2 = val.LoadBundleFile(originalBundlePath, true); if (val2 == null) { Log.LogError((object)"[LCOfficeV81Compat] Failed to open original bundle."); return false; } AssetBundleFile file = val2.file; List allFileNames = file.GetAllFileNames(); if (allFileNames.Count == 0) { Log.LogError((object)"[LCOfficeV81Compat] Bundle has no internal files."); return false; } Log.LogInfo((object)"[LCOfficeV81Compat] Bundle opened successfully."); Log.LogInfo((object)("[LCOfficeV81Compat] Internal file count: " + allFileNames.Count)); AssetsFileInstance val3 = val.LoadAssetsFileFromBundle(val2, 0, false); if (val3 == null) { Log.LogError((object)"[LCOfficeV81Compat] Failed to open internal assets file."); return false; } AssetsFile file2 = val3.file; int num = 0; int num2 = 0; foreach (AssetFileInfo item2 in file2.GetAssetsOfType((AssetClassID)115)) { AssetTypeValueField baseField; try { baseField = val.GetBaseField(val3, item2, (AssetReadFlags)0); } catch (Exception ex2) { Log.LogWarning((object)("[LCOfficeV81Compat] Could not deserialize MonoScript PathID " + item2.PathId + ":\n" + ex2)); continue; } if (baseField == null) { continue; } string item = ReadStringSafe(baseField, "m_Name"); string text4 = ReadStringSafe(baseField, "m_ClassName"); if (!TargetScriptNames.Contains(text4) && !TargetScriptNames.Contains(item)) { continue; } num++; string text5 = ReadStringSafe(baseField, "m_AssemblyName"); Log.LogInfo((object)("[LCOfficeV81Compat] Target found: " + text4 + " | assembly = " + text5)); if (!string.Equals(text5, "Assembly-CSharp", StringComparison.Ordinal)) { Log.LogWarning((object)("[LCOfficeV81Compat] Target already uses a different assembly; leaving unchanged: " + text4)); continue; } AssetTypeValueField val4 = baseField["m_AssemblyName"]; if (val4 == null) { Log.LogError((object)("[LCOfficeV81Compat] Target has no m_AssemblyName field: " + text4)); return false; } val4.AsString = "DunGen"; item2.SetNewData(baseField); num2++; Log.LogWarning((object)("[LCOfficeV81Compat] Patched MonoScript: " + text4 + " | Assembly-CSharp -> DunGen")); } Log.LogInfo((object)("[LCOfficeV81Compat] Target scripts found: " + num)); Log.LogInfo((object)("[LCOfficeV81Compat] Target scripts changed: " + num2)); if (num != TargetScriptNames.Count) { Log.LogError((object)("[LCOfficeV81Compat] Expected " + TargetScriptNames.Count + " target scripts but found " + num + ".")); Log.LogError((object)"[LCOfficeV81Compat] Refusing to write incomplete patched bundle."); return false; } if (num2 != TargetScriptNames.Count) { Log.LogError((object)("[LCOfficeV81Compat] Expected to patch " + TargetScriptNames.Count + " scripts but changed " + num2 + ".")); Log.LogError((object)"[LCOfficeV81Compat] Refusing to write unexpected bundle state."); return false; } file.BlockAndDirInfo.DirectoryInfos[0].SetNewData(file2); Log.LogInfo((object)"[LCOfficeV81Compat] Writing patched bundle to temporary output..."); AssetsFileWriter val5 = new AssetsFileWriter(text3); try { file.Write(val5, 0L); } finally { ((IDisposable)val5)?.Dispose(); } if (!File.Exists(text3)) { Log.LogError((object)"[LCOfficeV81Compat] Patched temporary bundle was not created."); return false; } long length = new FileInfo(text3).Length; if (length <= 0) { Log.LogError((object)"[LCOfficeV81Compat] Patched temporary bundle is empty."); return false; } Log.LogInfo((object)("[LCOfficeV81Compat] Temporary patched bundle size: " + length + " bytes")); if (File.Exists(text2)) { File.Delete(text2); } File.Move(text3, text2); PatchedBundlePath = text2; FileInfo fileInfo2 = new FileInfo(originalBundlePath); string contents = fileInfo2.Length + "|" + fileInfo2.LastWriteTimeUtc.Ticks; File.WriteAllText(path, contents); Log.LogWarning((object)"[LCOfficeV81Compat] Local patched bundle created successfully."); Log.LogInfo((object)"[LCOfficeV81Compat] Patched bundle path:"); Log.LogInfo((object)("[LCOfficeV81Compat] " + PatchedBundlePath)); if (!VerifyPatchedBundle(PatchedBundlePath)) { Log.LogError((object)"[LCOfficeV81Compat] Generated bundle failed post-write verification."); return false; } Log.LogWarning((object)"[LCOfficeV81Compat] Generated bundle passed post-write verification."); return true; } catch (Exception ex3) { Log.LogError((object)("[LCOfficeV81Compat] Local bundle patching failed:\n" + ex3)); return false; } finally { try { val.UnloadAll(false); } catch { } try { if (File.Exists(text3)) { File.Delete(text3); } } catch { } } } public static bool VerifyPatchedBundle(string patchedBundlePath) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Expected O, but got Unknown Log.LogInfo((object)"[LCOfficeV81Compat] Patched bundle verification starting."); if (string.IsNullOrWhiteSpace(patchedBundlePath)) { Log.LogError((object)"[LCOfficeV81Compat] Verification received an empty bundle path."); return false; } if (!File.Exists(patchedBundlePath)) { Log.LogError((object)("[LCOfficeV81Compat] Patched bundle does not exist: " + patchedBundlePath)); return false; } AssetsManager val = new AssetsManager(); try { BundleFileInstance val2 = val.LoadBundleFile(patchedBundlePath, true); if (val2 == null) { Log.LogError((object)"[LCOfficeV81Compat] Could not open patched bundle for verification."); return false; } List allFileNames = val2.file.GetAllFileNames(); if (allFileNames.Count == 0) { Log.LogError((object)"[LCOfficeV81Compat] Patched bundle contains no internal files."); return false; } AssetsFileInstance val3 = val.LoadAssetsFileFromBundle(val2, 0, false); if (val3 == null) { Log.LogError((object)"[LCOfficeV81Compat] Could not open patched bundle internal assets file."); return false; } AssetsFile file = val3.file; int num = 0; int num2 = 0; foreach (AssetFileInfo item2 in file.GetAssetsOfType((AssetClassID)115)) { AssetTypeValueField baseField; try { baseField = val.GetBaseField(val3, item2, (AssetReadFlags)0); } catch (Exception ex) { Log.LogWarning((object)("[LCOfficeV81Compat] Verification could not deserialize MonoScript PathID " + item2.PathId + ":\n" + ex)); continue; } if (baseField == null) { continue; } string item = ReadStringSafe(baseField, "m_Name"); string text = ReadStringSafe(baseField, "m_ClassName"); if (TargetScriptNames.Contains(text) || TargetScriptNames.Contains(item)) { num++; string text2 = ReadStringSafe(baseField, "m_AssemblyName"); Log.LogInfo((object)("[LCOfficeV81Compat] Verify target: " + text + " | assembly = " + text2)); if (string.Equals(text2, "DunGen", StringComparison.Ordinal)) { num2++; Log.LogInfo((object)("[LCOfficeV81Compat] Verified patched target: " + text)); } else { Log.LogError((object)("[LCOfficeV81Compat] Verification failed for target: " + text + " | expected DunGen, found " + text2)); } } } Log.LogInfo((object)("[LCOfficeV81Compat] Verification targets found: " + num)); Log.LogInfo((object)("[LCOfficeV81Compat] Verification targets correct: " + num2)); if (num != TargetScriptNames.Count) { Log.LogError((object)("[LCOfficeV81Compat] Verification expected " + TargetScriptNames.Count + " targets but found " + num + ".")); return false; } if (num2 != TargetScriptNames.Count) { Log.LogError((object)("[LCOfficeV81Compat] Verification expected all " + TargetScriptNames.Count + " targets to use DunGen.")); return false; } Log.LogWarning((object)"[LCOfficeV81Compat] Patched bundle verification succeeded."); return true; } catch (Exception ex2) { Log.LogError((object)("[LCOfficeV81Compat] Patched bundle verification failed:\n" + ex2)); return false; } finally { try { val.UnloadAll(false); } catch { } } } private static string ReadStringSafe(AssetTypeValueField root, string fieldName) { try { AssetTypeValueField val = root[fieldName]; if (val == null) { return ""; } return val.AsString; } catch { return ""; } } } internal static class CompatBootstrap { private static readonly ManualLogSource Log = Logger.CreateLogSource("LCOfficeV81Compat"); public static string OriginalBundlePath { get; private set; } public static bool Initialize() { Log.LogInfo((object)"[LCOfficeV81Compat] CompatBootstrap.Initialize reached."); string text = FindOriginalBundle(); if (text == null) { Log.LogError((object)"[LCOfficeV81Compat] Could not locate original 'lcoffice' bundle under BepInEx/plugins."); OriginalBundlePath = null; return false; } OriginalBundlePath = text; Log.LogInfo((object)"[LCOfficeV81Compat] Found original lcoffice bundle:"); Log.LogInfo((object)("[LCOfficeV81Compat] " + OriginalBundlePath)); try { FileInfo fileInfo = new FileInfo(OriginalBundlePath); Log.LogInfo((object)("[LCOfficeV81Compat] Bundle size: " + fileInfo.Length + " bytes")); } catch (Exception ex) { Log.LogWarning((object)("[LCOfficeV81Compat] Bundle found, but size check failed:\n" + ex)); } if (!BundlePatcher.CreatePatchedBundleCopy(OriginalBundlePath)) { Log.LogError((object)"[LCOfficeV81Compat] Local bundle patching failed."); return false; } Log.LogInfo((object)"[LCOfficeV81Compat] Local bundle patching succeeded."); Log.LogInfo((object)"[LCOfficeV81Compat] Patched bundle ready at:"); Log.LogInfo((object)("[LCOfficeV81Compat] " + BundlePatcher.PatchedBundlePath)); if (!CompatOfficeLoader.LoadAndValidate(BundlePatcher.PatchedBundlePath)) { Log.LogError((object)"[LCOfficeV81Compat] Patched bundle runtime load test failed."); return false; } Log.LogWarning((object)"[LCOfficeV81Compat] Patched bundle runtime load test succeeded."); if (!CompatOfficeLoader.RegisterMinimalOffice()) { Log.LogError((object)"[LCOfficeV81Compat] Minimal LC Office registration failed."); return false; } Log.LogWarning((object)"[LCOfficeV81Compat] Minimal LC Office registration succeeded."); if (!CompatRuntimeRestorer.Restore()) { Log.LogError((object)"[LCOfficeV81Compat] Runtime state restoration failed."); return false; } Log.LogWarning((object)"[LCOfficeV81Compat] Runtime state restoration succeeded."); return true; } private static string FindOriginalBundle() { if (!Directory.Exists(Paths.PluginPath)) { return null; } string[] files = Directory.GetFiles(Paths.PluginPath, "lcoffice", SearchOption.AllDirectories); if (files.Length == 0) { return null; } string text = files.FirstOrDefault((string path) => path.IndexOf("LCOfficeV81Compat", StringComparison.OrdinalIgnoreCase) < 0 && path.IndexOf("LCOfficeCompat", StringComparison.OrdinalIgnoreCase) < 0); return text ?? files[0]; } } internal static class CompatOfficeLoader { private static readonly ManualLogSource Log = Logger.CreateLogSource("LCOfficeV81Compat"); private static bool _registered; public static AssetBundle LoadedBundle { get; private set; } public static Object ExtendedOfficeFlowAsset { get; private set; } public static ExtendedMod OfficeMod { get; private set; } public static ExtendedDungeonFlow OfficeDungeon { get; private set; } public static DunGenExtender OfficeExtender { get; private set; } public static bool LoadAndValidate(string patchedBundlePath) { Log.LogInfo((object)"[LCOfficeV81Compat] Patched bundle runtime load test starting."); if (string.IsNullOrWhiteSpace(patchedBundlePath)) { Log.LogError((object)"[LCOfficeV81Compat] Patched bundle path is empty."); return false; } try { LoadedBundle = AssetBundle.LoadFromFile(patchedBundlePath); if ((Object)(object)LoadedBundle == (Object)null) { Log.LogError((object)"[LCOfficeV81Compat] Unity failed to load patched AssetBundle."); return false; } Log.LogWarning((object)"[LCOfficeV81Compat] Patched AssetBundle loaded successfully."); Type type = AccessTools.TypeByName("LethalLevelLoader.ExtendedDungeonFlow"); if (type == null) { Log.LogError((object)"[LCOfficeV81Compat] Could not resolve type LethalLevelLoader.ExtendedDungeonFlow."); return false; } Log.LogInfo((object)("[LCOfficeV81Compat] Resolved ExtendedDungeonFlow type: " + type.FullName)); ExtendedOfficeFlowAsset = LoadedBundle.LoadAsset("Assets/LethalCompany/Mods/LCOffice/ExtendedOfficeFlow.asset", type); if (ExtendedOfficeFlowAsset == (Object)null) { Log.LogError((object)"[LCOfficeV81Compat] Failed to load ExtendedOfficeFlow.asset."); return false; } Log.LogWarning((object)"[LCOfficeV81Compat] ExtendedOfficeFlow.asset loaded successfully."); Log.LogInfo((object)("[LCOfficeV81Compat] Loaded asset runtime type: " + ((object)ExtendedOfficeFlowAsset).GetType().FullName)); object obj = ReadDungeonFlowMember(ExtendedOfficeFlowAsset); if (obj == null) { Log.LogError((object)"[LCOfficeV81Compat] ExtendedOfficeFlow.DungeonFlow is null."); return false; } Log.LogWarning((object)"[LCOfficeV81Compat] ExtendedOfficeFlow.DungeonFlow is NON-NULL."); Log.LogInfo((object)("[LCOfficeV81Compat] DungeonFlow runtime type: " + obj.GetType().FullName)); Log.LogWarning((object)"[LCOfficeV81Compat] Patched bundle runtime validation succeeded."); return true; } catch (Exception ex) { Log.LogError((object)("[LCOfficeV81Compat] Patched bundle runtime validation failed:\n" + ex)); return false; } } public static bool RegisterMinimalOffice() { Log.LogInfo((object)"[LCOfficeV81Compat] Minimal LC Office registration starting."); if (_registered) { Log.LogWarning((object)"[LCOfficeV81Compat] LC Office is already registered."); return true; } if ((Object)(object)LoadedBundle == (Object)null) { Log.LogError((object)"[LCOfficeV81Compat] Cannot register LC Office because patched AssetBundle is null."); return false; } try { Object extendedOfficeFlowAsset = ExtendedOfficeFlowAsset; OfficeDungeon = (ExtendedDungeonFlow)(object)((extendedOfficeFlowAsset is ExtendedDungeonFlow) ? extendedOfficeFlowAsset : null); if ((Object)(object)OfficeDungeon == (Object)null) { Log.LogError((object)"[LCOfficeV81Compat] ExtendedOfficeFlowAsset could not be cast to ExtendedDungeonFlow."); return false; } if ((Object)(object)OfficeDungeon.DungeonFlow == (Object)null) { Log.LogError((object)"[LCOfficeV81Compat] OfficeDungeon.DungeonFlow is null."); return false; } Log.LogInfo((object)"[LCOfficeV81Compat] Creating ExtendedMod: LC Office / Piggy"); OfficeMod = ExtendedMod.Create("LC Office", "Piggy"); if ((Object)(object)OfficeMod == (Object)null) { Log.LogError((object)"[LCOfficeV81Compat] ExtendedMod.Create returned null."); return false; } Log.LogInfo((object)"[LCOfficeV81Compat] Adding ExtendedOfficeFlow to ExtendedMod."); OfficeMod.ExtendedDungeonFlows.Add(OfficeDungeon); Log.LogInfo((object)"[LCOfficeV81Compat] Loading OfficeExtender.asset."); OfficeExtender = LoadedBundle.LoadAsset("Assets/LethalCompany/Mods/LCOffice/OfficeExtender.asset"); if ((Object)(object)OfficeExtender == (Object)null) { Log.LogError((object)"[LCOfficeV81Compat] Failed to load OfficeExtender.asset."); return false; } Log.LogWarning((object)"[LCOfficeV81Compat] OfficeExtender.asset loaded successfully."); OfficeExtender.DungeonFlow = OfficeDungeon.DungeonFlow; Log.LogInfo((object)"[LCOfficeV81Compat] OfficeExtender.DungeonFlow assigned."); Log.LogInfo((object)"[LCOfficeV81Compat] Registering DunGenPlus extender."); API.AddDunGenExtender(OfficeDungeon.DungeonFlow, OfficeExtender); Log.LogInfo((object)"[LCOfficeV81Compat] Registering LC Office ExtendedMod with LethalLevelLoader."); PatchedContent.RegisterExtendedMod(OfficeMod); _registered = true; Log.LogWarning((object)"[LCOfficeV81Compat] Minimal LC Office registration succeeded."); Log.LogInfo((object)("[LCOfficeV81Compat] Registered dungeon flow: " + ((Object)OfficeDungeon).name)); Log.LogInfo((object)("[LCOfficeV81Compat] DungeonFlow runtime type: " + ((object)OfficeDungeon.DungeonFlow).GetType().FullName)); return true; } catch (Exception ex) { Log.LogError((object)("[LCOfficeV81Compat] Minimal LC Office registration failed:\n" + ex)); return false; } } private static object ReadDungeonFlowMember(object extendedOfficeFlow) { Type type = extendedOfficeFlow.GetType(); PropertyInfo propertyInfo = AccessTools.Property(type, "DungeonFlow"); if (propertyInfo != null) { Log.LogInfo((object)"[LCOfficeV81Compat] Reading DungeonFlow property."); return propertyInfo.GetValue(extendedOfficeFlow, null); } FieldInfo fieldInfo = AccessTools.Field(type, "DungeonFlow"); if (fieldInfo != null) { Log.LogInfo((object)"[LCOfficeV81Compat] Reading DungeonFlow field."); return fieldInfo.GetValue(extendedOfficeFlow); } FieldInfo fieldInfo2 = AccessTools.Field(type, "k__BackingField"); if (fieldInfo2 != null) { Log.LogInfo((object)"[LCOfficeV81Compat] Reading DungeonFlow backing field."); return fieldInfo2.GetValue(extendedOfficeFlow); } Log.LogError((object)"[LCOfficeV81Compat] Could not find DungeonFlow property, field, or backing field."); return null; } } internal static class CompatRuntimeRestorer { private static readonly ManualLogSource Log = Logger.CreateLogSource("LCOfficeV81Compat"); private static bool _restored; public static bool Restore() { //IL_027a: Unknown result type (might be due to invalid IL or missing references) //IL_027f: Unknown result type (might be due to invalid IL or missing references) //IL_028a: Unknown result type (might be due to invalid IL or missing references) //IL_0293: Expected O, but got Unknown //IL_0295: Unknown result type (might be due to invalid IL or missing references) //IL_029a: Unknown result type (might be due to invalid IL or missing references) //IL_02a5: Unknown result type (might be due to invalid IL or missing references) //IL_02ae: Expected O, but got Unknown if (_restored) { Log.LogWarning((object)"[LCOfficeV81Compat] Runtime state already restored."); return true; } Log.LogInfo((object)"[LCOfficeV81Compat] Restoring original LCOffice runtime state."); try { Type type = AccessTools.TypeByName("LCOffice.Plugin"); if (type == null) { Log.LogError((object)"[LCOfficeV81Compat] Could not resolve LCOffice.Plugin."); return false; } if (Plugin.CompatConfig == null) { Log.LogError((object)"[LCOfficeV81Compat] CompatConfig is null."); return false; } ConfigEntry value = Plugin.CompatConfig.Bind("General", "ElevatorMusicVolume", 100f, "Set the volume of music played in the elevator. (0 - 100) (Client Sided)"); ConfigEntry value2 = Plugin.CompatConfig.Bind("General", "ElevatorMusicPitchDown", false, "Change the pitch of the elevator music. (Client Sided)"); ConfigEntry value3 = Plugin.CompatConfig.Bind("General", "Disable Camera", false, "Disable cameras inside the office. (Client Sided)"); ConfigEntry value4 = Plugin.CompatConfig.Bind("General", "Disable Control Room Camera", false, "Disable camera inside the apparatus room. (Client Sided)"); ConfigEntry value5 = Plugin.CompatConfig.Bind("General", "Camera Frame Speed", 10, "Specifies the camera speed inside the office. Negative uses game frame rate."); SetStaticField(type, "musicVolume", value); SetStaticField(type, "elevatorMusicPitchdown", value2); SetStaticField(type, "cameraDisable", value3); SetStaticField(type, "controlRoomCameraDisable", value4); SetStaticField(type, "cameraFrameSpeed", value5); SetStaticField(type, "mls", Log); SetStaticField(type, "Bundle", CompatOfficeLoader.LoadedBundle); SetStaticField(type, "officeMod", CompatOfficeLoader.OfficeMod); SetStaticField(type, "officeDungeon", CompatOfficeLoader.OfficeDungeon); SetStaticField(type, "officeExtender", CompatOfficeLoader.OfficeExtender); Log.LogInfo((object)"[LCOfficeV81Compat] Core LCOffice statics restored."); GameObject val = CompatOfficeLoader.LoadedBundle.LoadAsset("Assets/LethalCompany/Mods/LCOffice/Prefab/ActualElevator.prefab"); GameObject val2 = CompatOfficeLoader.LoadedBundle.LoadAsset("Assets/LethalCompany/Mods/LCOffice/Prefab/ElevatorStorage.prefab"); if ((Object)(object)val == (Object)null) { Log.LogError((object)"[LCOfficeV81Compat] Failed to load ActualElevator.prefab."); return false; } if ((Object)(object)val2 == (Object)null) { Log.LogError((object)"[LCOfficeV81Compat] Failed to load ElevatorStorage.prefab."); return false; } SetStaticField(type, "ActualElevator", val); SetStaticField(type, "StoragePrefab", val2); Log.LogWarning((object)"[LCOfficeV81Compat] Elevator prefabs loaded successfully."); JNetworkPrefabSet val3 = ScriptableObject.CreateInstance(); val3.SetName = "LCOffice"; val3.AddPrefabs((JIdentifiablePrefab[])(object)new JIdentifiablePrefab[2] { new JIdentifiablePrefab { name = "Elevator", prefab = val }, new JIdentifiablePrefab { name = "StorageShelf", prefab = val2 } }); JNetworkPrefabSet.NetworkPrefabSets.Add(val3); Log.LogWarning((object)"[LCOfficeV81Compat] JLL network prefab set registered."); Object val4 = (Object)(object)CompatOfficeLoader.LoadedBundle.LoadAsset("Assets/LethalCompany/Mods/LCOffice/Terminal/Elevator1Node.asset"); Object val5 = (Object)(object)CompatOfficeLoader.LoadedBundle.LoadAsset("Assets/LethalCompany/Mods/LCOffice/Terminal/Elevator2Node.asset"); Object val6 = (Object)(object)CompatOfficeLoader.LoadedBundle.LoadAsset("Assets/LethalCompany/Mods/LCOffice/Terminal/Elevator3Node.asset"); Object val7 = (Object)(object)CompatOfficeLoader.LoadedBundle.LoadAsset("Assets/LethalCompany/Mods/LCOffice/Terminal/ElevatorKeyword.asset"); Object val8 = (Object)(object)CompatOfficeLoader.LoadedBundle.LoadAsset("Assets/LethalCompany/Mods/LCOffice/Terminal/Elevator1f.asset"); Object val9 = (Object)(object)CompatOfficeLoader.LoadedBundle.LoadAsset("Assets/LethalCompany/Mods/LCOffice/Terminal/Elevator2f.asset"); Object val10 = (Object)(object)CompatOfficeLoader.LoadedBundle.LoadAsset("Assets/LethalCompany/Mods/LCOffice/Terminal/Elevator3f.asset"); if (val4 == (Object)null || val5 == (Object)null || val6 == (Object)null || val7 == (Object)null || val8 == (Object)null || val9 == (Object)null || val10 == (Object)null) { Log.LogError((object)"[LCOfficeV81Compat] One or more terminal assets failed to load."); return false; } SetStaticField(type, "elevator1Node", val4); SetStaticField(type, "elevator2Node", val5); SetStaticField(type, "elevator3Node", val6); SetStaticField(type, "elevatorKeyword", val7); SetStaticField(type, "elevator1Keyword", val8); SetStaticField(type, "elevator2Keyword", val9); SetStaticField(type, "elevator3Keyword", val10); Log.LogWarning((object)"[LCOfficeV81Compat] Terminal assets restored."); if (!RestoreRemainingOriginalHooks(type)) { Log.LogError((object)"[LCOfficeV81Compat] Remaining original startup hooks failed."); return false; } _restored = true; Log.LogWarning((object)"[LCOfficeV81Compat] Runtime state restoration succeeded."); return true; } catch (Exception ex) { Log.LogError((object)("[LCOfficeV81Compat] Runtime state restoration failed:\n" + ex)); return false; } } private static bool RestoreRemainingOriginalHooks(Type originalPluginType) { //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Expected O, but got Unknown Log.LogInfo((object)"[LCOfficeV81Compat] Restoring remaining original LCOffice startup hooks."); try { Assembly assembly = originalPluginType.Assembly; if (assembly == null) { Log.LogError((object)"[LCOfficeV81Compat] Original LCOffice assembly is null."); return false; } FieldInfo fieldInfo = AccessTools.Field(originalPluginType, "configEnableScraps"); if (fieldInfo != null && fieldInfo.GetValue(null) == null) { ConfigEntry value = Plugin.CompatConfig.Bind("General", "OfficeCustomScrap", true, "When enabled, enables custom scrap spawning."); fieldInfo.SetValue(null, value); Log.LogInfo((object)"[LCOfficeV81Compat] Restored static field: configEnableScraps"); } Type type = AccessTools.TypeByName("LCOffice.Patches.TerminalPatch"); Type type2 = AccessTools.TypeByName("LCOffice.Patches.LungPropPatch"); Type type3 = AccessTools.TypeByName("LCOffice.Patches.MenuManagerPatch"); if (type == null || type2 == null || type3 == null) { Log.LogError((object)"[LCOfficeV81Compat] Could not resolve one or more original LCOffice patch types."); return false; } Harmony val = new Harmony("lcoffice.v81compat.originalhooks"); JLL.HarmonyPatch(val, Log, new Type[3] { type, type2, type3 }); Log.LogWarning((object)"[LCOfficeV81Compat] Original LCOffice Harmony patches restored."); Type[] array; try { array = assembly.GetTypes(); } catch (ReflectionTypeLoadException ex) { array = Array.FindAll(ex.Types, (Type type4) => type4 != null); Log.LogWarning((object)"[LCOfficeV81Compat] LCOffice assembly had partial type-load failures; using loadable types only."); } JLL.NetcodePatch(Log, array); Log.LogWarning((object)"[LCOfficeV81Compat] JLL netcode patch restored for original LCOffice assembly."); Log.LogWarning((object)"[LCOfficeV81Compat] Remaining original startup hooks restored."); return true; } catch (Exception ex2) { Log.LogError((object)("[LCOfficeV81Compat] Failed restoring remaining original startup hooks:\n" + ex2)); return false; } } private static void SetStaticField(Type targetType, string fieldName, object value) { FieldInfo fieldInfo = AccessTools.Field(targetType, fieldName); if (fieldInfo == null) { throw new MissingFieldException(targetType.FullName, fieldName); } fieldInfo.SetValue(null, value); Log.LogInfo((object)("[LCOfficeV81Compat] Restored static field: " + fieldName)); } } [BepInPlugin("lcoffice.v81compat.runtimepatch", "LC Office v81 Compatibility Test", "0.0.2")] public sealed class Plugin : BaseUnityPlugin { public const string PluginGuid = "lcoffice.v81compat.runtimepatch"; public const string PluginName = "LC Office v81 Compatibility Test"; public const string PluginVersion = "0.0.2"; private Harmony _harmony; internal static ConfigFile CompatConfig { get; private set; } private void Awake() { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown CompatConfig = ((BaseUnityPlugin)this).Config; ((BaseUnityPlugin)this).Logger.LogInfo((object)"=========================================="); ((BaseUnityPlugin)this).Logger.LogInfo((object)"[LCOfficeV81Compat] Compatibility plugin Awake reached."); ((BaseUnityPlugin)this).Logger.LogInfo((object)"[LCOfficeV81Compat] Beginning original Awake interception test."); ((BaseUnityPlugin)this).Logger.LogInfo((object)"=========================================="); try { _harmony = new Harmony("lcoffice.v81compat.runtimepatch"); ((BaseUnityPlugin)this).Logger.LogInfo((object)"[LCOfficeV81Compat] HarmonyX instance created successfully."); PatchOriginalLCOfficeAwake(); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("[LCOfficeV81Compat] Failed during Harmony interception setup:\n" + ex)); } } private void PatchOriginalLCOfficeAwake() { //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Expected O, but got Unknown ((BaseUnityPlugin)this).Logger.LogInfo((object)"[LCOfficeV81Compat] Searching for LCOffice.Plugin..."); Type type = AccessTools.TypeByName("LCOffice.Plugin"); if (type == null) { ((BaseUnityPlugin)this).Logger.LogError((object)"[LCOfficeV81Compat] Could not find type LCOffice.Plugin."); return; } ((BaseUnityPlugin)this).Logger.LogInfo((object)("[LCOfficeV81Compat] Found original plugin type: " + type.FullName)); MethodInfo methodInfo = AccessTools.Method(type, "Awake", (Type[])null, (Type[])null); if (methodInfo == null) { ((BaseUnityPlugin)this).Logger.LogError((object)"[LCOfficeV81Compat] Could not find LCOffice.Plugin.Awake()."); return; } ((BaseUnityPlugin)this).Logger.LogInfo((object)("[LCOfficeV81Compat] Found original Awake method: " + methodInfo)); MethodInfo methodInfo2 = AccessTools.Method(typeof(Plugin), "OriginalAwakePrefix", (Type[])null, (Type[])null); if (methodInfo2 == null) { ((BaseUnityPlugin)this).Logger.LogError((object)"[LCOfficeV81Compat] Could not resolve compatibility Prefix method."); return; } HarmonyMethod val = new HarmonyMethod(methodInfo2); _harmony.Patch((MethodBase)methodInfo, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ((BaseUnityPlugin)this).Logger.LogInfo((object)"[LCOfficeV81Compat] Harmony patch applied to original LCOffice Awake()."); } private static bool OriginalAwakePrefix() { ManualLogSource val = Logger.CreateLogSource("LCOfficeV81Compat"); val.LogWarning((object)"[LCOfficeV81Compat] Original LCOffice Awake intercepted."); if (!CompatBootstrap.Initialize()) { val.LogError((object)"[LCOfficeV81Compat] Compatibility bootstrap failed."); val.LogError((object)"[LCOfficeV81Compat] Original Awake will still be skipped to avoid known TypeLoadException."); return false; } val.LogInfo((object)"[LCOfficeV81Compat] Compatibility bootstrap succeeded."); val.LogWarning((object)"[LCOfficeV81Compat] Original LCOffice Awake skipped."); return false; } } }