Decompiled source of ShipWindows v1.11.0
ShipWindows.dll
Decompiled 2 weeks ago
The result has been truncated due to the large size, download it to view full contents!
#define DEBUG using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Serialization.Formatters.Binary; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Threading; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using LobbyCompatibility.Enums; using LobbyCompatibility.Features; using Microsoft.CodeAnalysis; using ShipColors.Events; using ShipWindows.Compatibility; using ShipWindows.Components; using ShipWindows.EnemyPatches; using ShipWindows.MiscPatches; using ShipWindows.Networking; using ShipWindows.Utilities; using Unity.Collections; using Unity.Netcode; using UnityEngine; using UnityEngine.Events; using UnityEngine.Networking; using UnityEngine.Rendering; using UnityEngine.Rendering.HighDefinition; using UnityEngine.SceneManagement; using UnityEngine.Serialization; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: IgnoresAccessChecksTo("CelestialTint")] [assembly: IgnoresAccessChecksTo("ShipColors")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("TestAccount666.ShipWindows")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyDescription("Adds glass windows to the ship so you can see what's going on outside.")] [assembly: AssemblyFileVersion("1.11.0.0")] [assembly: AssemblyInformationalVersion("1.11.0+30147a8f71ed84abb7611e842f8ac6c1338ba7ea")] [assembly: AssemblyProduct("ShipWindows")] [assembly: AssemblyTitle("TestAccount666.ShipWindows")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.11.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.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] [Microsoft.CodeAnalysis.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] [Microsoft.CodeAnalysis.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 ShipWindows { public class ShipWindowDef { public int baseCost; public int id; public GameObject prefab; public int unlockableID; private ShipWindowDef(int id, GameObject prefab, int baseCost) { this.id = id; this.prefab = prefab; this.baseCost = baseCost; } public static ShipWindowDef Register(int id, int baseCost) { ShipWindows.Logger.LogInfo((object)$"Registering window prefab: Window {id}"); GameObject val = ShipWindows.mainAssetBundle.LoadAsset<GameObject>($"Assets/LethalCompany/Mods/plugins/ShipWindows/SpawnWindow{id}.prefab"); val.AddComponent<ShipWindowSpawner>().id = id; NetworkManager.Singleton.AddNetworkPrefab(val); return new ShipWindowDef(id, val, baseCost); } } [BepInIncompatibility("veri.lc.shipwindow")] [CompatibleDependency("mborsh.WiderShipMod", typeof(ShipMods))] [CompatibleDependency("MelanieMelicious.2StoryShip", typeof(ShipMods))] [CompatibleDependency("darmuh.ShipColors", "0.1.0", typeof(ShipColors))] [CompatibleDependency("CelestialTint", "1.0.1", typeof(CelestialTint))] [CompatibleDependency("LethalExpansion", typeof(LethalExpansion))] [CompatibleDependency("com.github.lethalmods.lethalexpansioncore", typeof(LethalExpansion))] [CompatibleDependency("BMX.LobbyCompatibility", typeof(LobbyCompatibility))] [BepInPlugin("TestAccount666.ShipWindows", "ShipWindows", "1.11.0")] public class ShipWindows : BaseUnityPlugin { public static AssetBundle mainAssetBundle = null; public static GameObject? windowSwitchPrefab; public static readonly Dictionary<int, ShipWindowDef> WindowRegistry = new Dictionary<int, ShipWindowDef>(); public static GameObject? spaceProps = null; public static GameObject? outsideSkybox; public static readonly Material?[] DoorMaterials = (Material?[])(object)new Material[2]; private static Coroutine? _windowCoroutine; public static ShipWindows Instance { get; private set; } = null; internal static ManualLogSource Logger { get; private set; } = null; internal static Harmony? Harmony { get; private set; } private void Awake() { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown Logger = ((BaseUnityPlugin)this).Logger; Instance = this; if (Harmony == null) { Harmony = new Harmony("TestAccount666.ShipWindows"); } WindowConfig.InitializeConfig(((BaseUnityPlugin)this).Config); if (!WindowConfig.enableWindow1.Value && !WindowConfig.enableWindow2.Value && !WindowConfig.enableWindow3.Value && !WindowConfig.enableWindow4.Value) { Logger.LogWarning((object)"All windows are disabled. Please enable any window in your settings for this mod to have any effect."); return; } Logger.LogInfo((object)("\nCurrent settings:\n" + $" Vanilla Mode: {WindowConfig.vanillaMode.Value}\n" + $" Shutters: {WindowConfig.enableShutter.Value}\n" + $" Hide Space Props: {WindowConfig.hideSpaceProps.Value}\n" + $" Space Sky: {WindowConfig.spaceOutsideSetting.Value}\n" + $" Bottom Lights: {WindowConfig.disableUnderLights.Value}\n" + $" Posters: {WindowConfig.dontMovePosters.Value}\n" + $" Sky Rotation: {WindowConfig.skyboxRotateSpeed.Value}\n" + $" Sky Resolution: {WindowConfig.skyboxResolution.Value}\n" + $" Windows Unlockable: {WindowConfig.windowsUnlockable.Value}\n" + $" Window 1 Enabled: {WindowConfig.enableWindow1.Value}\n" + $" Window 2 Enabled: {WindowConfig.enableWindow2.Value}\n" + $" Window 3 Enabled: {WindowConfig.enableWindow3.Value}\n" + $" Window 4 Enabled: {WindowConfig.enableWindow4.Value}\n")); if (!LoadAssetBundle()) { Logger.LogError((object)"Failed to load asset bundle! Abort mission!"); return; } try { InitializeNetcode(); } catch (Exception ex) { Logger.LogError((object)"Something went wrong with the netcode patcher!"); Logger.LogError((object)ex); return; } new WindowState(); Harmony.PatchAll(typeof(ShipWindows)); Harmony.PatchAll(typeof(Unlockables)); Harmony.PatchAll(typeof(EnemyAICollisionDetectPatch)); Harmony.PatchAll(typeof(EnemyMeshPatch)); if (WindowConfig.changeLightSwitchTip.Value) { Harmony.PatchAll(typeof(LightSwitchPatch)); } Harmony.PatchAll(typeof(DepositItemsDeskPatch)); Harmony.PatchAll(typeof(ShipBuildModeManagerPatch)); CompatibleDependencyAttribute.Init((BaseUnityPlugin)(object)this); ShipWindow4K.TryToLoad(); ((MonoBehaviour)this).StartCoroutine(SoundLoader.LoadAudioClips()); WindowConfig.glassMaterial.SettingChanged += delegate { ShipReplacer.ReplaceGlassMaterial(); }; Logger.LogInfo((object)"Loaded successfully!"); } private static bool LoadAssetBundle() { Logger.LogInfo((object)"Loading ShipWindow AssetBundle..."); string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); Debug.Assert(directoryName != null, "assemblyLocation != null"); mainAssetBundle = AssetBundle.LoadFromFile(Path.Combine(directoryName, "ship_window")); return (Object)(object)mainAssetBundle != (Object)null; } private static GameObject FindOrThrow(string name) { GameObject val = GameObject.Find(name); if (!Object.op_Implicit((Object)(object)val)) { throw new Exception("Could not find " + name + "! Wrong scene?"); } return val; } private static int GetWindowBaseCost(int id) { if (1 == 0) { } int result = id switch { 1 => WindowConfig.window1Cost.Value, 2 => WindowConfig.window2Cost.Value, 3 => WindowConfig.window3Cost.Value, 4 => WindowConfig.window4Cost.Value, _ => 60, }; if (1 == 0) { } return result; } public static bool IsWindowEnabled(int id) { if (1 == 0) { } bool result = id switch { 1 => WindowConfig.enableWindow1.Value, 2 => WindowConfig.enableWindow2.Value, 3 => WindowConfig.enableWindow3.Value, 4 => WindowConfig.enableWindow4.Value, _ => false, }; if (1 == 0) { } return result; } public static bool IsWindowDefaultUnlocked(int id) { if (1 == 0) { } bool result = id switch { 1 => WindowConfig.defaultWindow1.Value, 2 => WindowConfig.defaultWindow2.Value, 3 => WindowConfig.defaultWindow3.Value, 4 => WindowConfig.defaultWindow4.Value, _ => false, }; if (1 == 0) { } return result; } private static void RegisterWindows() { for (int i = 1; i <= 4; i++) { if (IsWindowEnabled(i)) { ShipWindowDef value = ShipWindowDef.Register(i, GetWindowBaseCost(i)); WindowRegistry.Add(i, value); } } } private static void AddStars() { if (CelestialTint.Enabled) { return; } GameObject val = GameObject.Find("Systems/Rendering"); GameObject val2 = GameObject.Find("Systems/Rendering/StarsSphere"); switch (WindowConfig.spaceOutsideSetting.Value) { case SpaceOutside.OTHER_MODS: break; case SpaceOutside.SPACE_HDRI: { if ((Object)(object)val == (Object)null) { throw new Exception("Could not find Systems/Rendering. Wrong scene?"); } GameObject val4 = mainAssetBundle.LoadAsset<GameObject>("Assets/LethalCompany/Mods/plugins/ShipWindows/UniverseVolume.prefab"); outsideSkybox = Object.Instantiate<GameObject>(val4, val.transform); ((Renderer)val2.GetComponent<MeshRenderer>()).enabled = false; outsideSkybox.AddComponent<SpaceSkybox>(); if ((Object)(object)ShipWindow4K.Skybox4K != (Object)null) { outsideSkybox.GetComponent<SpaceSkybox>()?.SetSkyboxTexture(ShipWindow4K.Skybox4K); } break; } case SpaceOutside.BLACK_AND_STARS: { if ((Object)(object)val2 == (Object)null) { throw new Exception("Could not find vanilla Stars Sphere. Wrong scene?"); } if ((Object)(object)val == (Object)null) { throw new Exception("Could not find Systems/Rendering. Wrong scene?"); } GameObject val3 = mainAssetBundle.LoadAsset<GameObject>("Assets/LethalCompany/Mods/plugins/ShipWindows/StarsSphereLarge.prefab"); if ((Object)(object)val3 == (Object)null) { throw new Exception("Could not load star sphere large prefab!"); } outsideSkybox = Object.Instantiate<GameObject>(val3, val.transform); ((Renderer)val2.GetComponent<MeshRenderer>()).enabled = false; outsideSkybox.AddComponent<SpaceSkybox>(); break; } default: throw new ArgumentOutOfRangeException(WindowConfig.spaceOutsideSetting.Value.ToString() + " is not a valid option!"); } } private static void HideSpaceProps() { if (!CelestialTint.Enabled && WindowConfig.hideSpaceProps.Value) { GameObject val = GameObject.Find("Environment/SpaceProps"); if (val != null) { val.SetActive(false); } } } private static void HideMiscMeshes() { GameObject val = GameObject.Find("notSpawnedPlatform"); GameObject val2 = GameObject.Find("notSpawnedPlatform (1)"); MeshRenderer val3 = ((val != null) ? val.GetComponent<MeshRenderer>() : null); MeshRenderer val4 = ((val2 != null) ? val2.GetComponent<MeshRenderer>() : null); if ((Object)(object)val3 != (Object)null) { ((Renderer)val3).enabled = false; } if ((Object)(object)val4 != (Object)null) { ((Renderer)val4).enabled = false; } } public static void OpenWindowDelayed(float delay) { if (_windowCoroutine != null) { ((MonoBehaviour)StartOfRound.Instance).StopCoroutine(_windowCoroutine); } _windowCoroutine = ((MonoBehaviour)StartOfRound.Instance).StartCoroutine(OpenWindowCoroutine(delay)); } public static void OpenWindowOnCondition(Func<bool> conditionPredicate) { if (_windowCoroutine != null) { ((MonoBehaviour)StartOfRound.Instance).StopCoroutine(_windowCoroutine); } _windowCoroutine = ((MonoBehaviour)StartOfRound.Instance).StartCoroutine(OpenWindowOnConditionCoroutine(conditionPredicate)); } private static IEnumerator OpenWindowCoroutine(float delay) { Logger.LogInfo((object)("Opening window in " + delay + " seconds...")); yield return (object)new WaitForSeconds(delay); WindowState.Instance.SetWindowState(closed: false, locked: false, WindowConfig.playShutterVoiceLinesOnTransitions.Value); _windowCoroutine = null; } private static IEnumerator OpenWindowOnConditionCoroutine(Func<bool> conditionPredicate) { Logger.LogInfo((object)("Opening window when " + conditionPredicate?.ToString() + " is true")); yield return (object)new WaitUntil(conditionPredicate); WindowState.Instance.SetWindowState(closed: false, locked: false, WindowConfig.playShutterVoiceLinesOnTransitions.Value); _windowCoroutine = null; } private static void HandleWindowSync() { WindowState.Instance.ReceiveSync(); } [HarmonyPostfix] [HarmonyPatch(typeof(GameNetworkManager), "Start")] private static void AddPrefabsToNetwork() { if (!WindowConfig.vanillaMode.Value) { if (WindowConfig.enableShutter.Value) { GameObject val = mainAssetBundle.LoadAsset<GameObject>("Assets/LethalCompany/Mods/plugins/ShipWindows/WindowShutterSwitch.prefab"); val.AddComponent<ShipWindowShutterSwitch>(); NetworkManager.Singleton.AddNetworkPrefab(val); windowSwitchPrefab = val; } RegisterWindows(); } } [HarmonyPrefix] [HarmonyPatch(typeof(StartOfRound), "ChangeLevelServerRpc")] private static void LockWindowsWhileRouting(int levelID) { if (WindowConfig.shuttersHideMoonTransitions.Value) { SelectableLevel[] array = StartOfRound.Instance.levels; if (array == null) { array = Array.Empty<SelectableLevel>(); } SelectableLevel val = array.Where((SelectableLevel level) => (Object)(object)level != (Object)null).FirstOrDefault((Func<SelectableLevel, bool>)((SelectableLevel selectableLevel) => selectableLevel.levelID == levelID)); if (!((Object)(object)val == (Object)null)) { WindowState.Instance.SetWindowState(closed: true, locked: true, WindowConfig.playShutterVoiceLinesOnTransitions.Value); OpenWindowDelayed(val.timeToArrive + 2.5f); } } } [HarmonyPrefix] [HarmonyPatch(typeof(Terminal), "Awake")] private static void AddWindowsToUnlockables(Terminal __instance) { try { if (!WindowConfig.windowsUnlockable.Value || WindowConfig.vanillaMode.Value) { return; } foreach (KeyValuePair<int, ShipWindowDef> item in WindowRegistry) { int unlockableID = Unlockables.AddWindowToUnlockables(__instance, item.Value); item.Value.unlockableID = unlockableID; } } catch (Exception arg) { Logger.LogError((object)$"Error occurred registering window unlockables...\n{arg}"); } } [HarmonyPostfix] [HarmonyPatch(typeof(StartOfRound), "Awake")] private static void SpawnShutterSwitch() { try { if (!WindowConfig.vanillaMode.Value && WindowConfig.enableShutter.Value) { Unlockables.AddSwitchToUnlockables(); ((MonoBehaviour)StartOfRound.Instance).StartCoroutine(ShipReplacer.WaitAndCheckSwitch()); } ShipReplacer.debounceReplace = false; } catch (Exception ex) { Logger.LogError((object)ex); } } [HarmonyPostfix] [HarmonyPatch(typeof(StartOfRound), "Start")] private static void InitializeWindows() { try { if (!WindowConfig.windowsUnlockable.Value || WindowConfig.vanillaMode.Value) { ShipReplacer.ReplaceShip(); } AddStars(); HideSpaceProps(); HideMiscMeshes(); } catch (Exception ex) { Logger.LogError((object)ex); } } [HarmonyPostfix] [HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")] private static void OnPlayerConnect() { NetworkHandler.RegisterMessages(); NetworkHandler.WindowSyncReceivedEvent += HandleWindowSync; if (!NetworkHandler.IsHost) { NetworkHandler.RequestWindowSync(); } } [HarmonyPostfix] [HarmonyPatch(typeof(GameNetworkManager), "StartDisconnect")] private static void OnPlayerDisconnect() { NetworkHandler.UnregisterMessages(); NetworkHandler.WindowSyncReceivedEvent -= HandleWindowSync; } [HarmonyPostfix] [HarmonyPatch(typeof(StartOfRound), "LateUpdate")] private static void FollowPlayer() { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) if (!CelestialTint.Enabled && !((Object)(object)outsideSkybox == (Object)null)) { if (StartOfRound.Instance.suckingPlayersOutOfShip) { outsideSkybox.transform.position = ((Component)GameNetworkManager.Instance.localPlayerController).transform.position; } else { outsideSkybox.transform.localPosition = Vector3.zero; } } } [HarmonyPostfix] [HarmonyPatch(typeof(StartMatchLever), "PullLeverAnim")] private static void CloseAndLockWindows(bool leverPulled) { if (leverPulled) { WindowState.Instance.SetWindowState(closed: true, locked: true, WindowConfig.playShutterVoiceLinesOnTransitions.Value); } } [HarmonyPostfix] [HarmonyPatch(typeof(RoundManager), "FinishGeneratingNewLevelClientRpc")] private static void OpenWindowAfterLevelGeneration() { WindowState.Instance.SetVolumeState(active: false); OpenWindowOnCondition(() => StartOfRound.Instance.shipDoorsEnabled && !StartOfRound.Instance.inShipPhase); } [HarmonyPostfix] [HarmonyPatch(typeof(StartOfRound), "ShipHasLeft")] private static void OpenWindowAfterShipLeave() { WindowState.Instance.SetWindowState(closed: true, locked: true, WindowConfig.playShutterVoiceLinesOnTransitions.Value); OpenWindowOnCondition(() => StartOfRound.Instance.inShipPhase); } [HarmonyPostfix] [HarmonyPatch(typeof(StartOfRound), "ResetShip")] private static void CheckForKeptSpawners() { ((MonoBehaviour)StartOfRound.Instance).StartCoroutine(ShipReplacer.CheckForKeptSpawners()); } [HarmonyPostfix] [HarmonyPatch(typeof(RoundManager), "DespawnPropsAtEndOfRound")] private static void Patch_DespawnProps() { if (CelestialTint.Enabled) { return; } try { switch (WindowConfig.spaceOutsideSetting.Value) { case SpaceOutside.SPACE_HDRI: case SpaceOutside.BLACK_AND_STARS: { float volumeRotation = (float)(StartOfRound.Instance.gameStats?.daysSpent).GetValueOrDefault(1) * 80f; WindowState.Instance.SetVolumeRotation(volumeRotation); WindowState.Instance.SetVolumeState(active: true); break; } default: throw new ArgumentOutOfRangeException(WindowConfig.spaceOutsideSetting.Value.ToString() + " is not a valid option!"); case SpaceOutside.OTHER_MODS: break; } GameObject val = GameObject.Find("Environment/SpaceProps"); if (!((Object)(object)val == (Object)null) && WindowConfig.hideSpaceProps.Value) { val.SetActive(false); } } catch (Exception ex) { Logger.LogError((object)ex); } } private static void InitializeNetcode() { Type[] types = Assembly.GetExecutingAssembly().GetTypes(); Type[] array = types; foreach (Type type in array) { MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic); MethodInfo[] array2 = methods; foreach (MethodInfo methodInfo in array2) { object[] customAttributes = methodInfo.GetCustomAttributes(typeof(RuntimeInitializeOnLoadMethodAttribute), inherit: false); if (customAttributes.Length != 0) { methodInfo.Invoke(null, null); } } } } } public enum SpaceOutside { OTHER_MODS, SPACE_HDRI, BLACK_AND_STARS } public static class WindowConfig { public static ConfigEntry<bool> vanillaMode; public static ConfigEntry<WindowMaterial> glassMaterial; public static ConfigEntry<bool> enableShutter; public static ConfigEntry<bool> shuttersHideMoonTransitions; public static ConfigEntry<bool> hideSpaceProps; public static ConfigEntry<SpaceOutside> spaceOutsideSetting; public static ConfigEntry<bool> disableUnderLights; public static ConfigEntry<bool> dontMovePosters; public static ConfigEntry<float> skyboxRotateSpeed; public static ConfigEntry<int> skyboxResolution; public static ConfigEntry<bool> windowsUnlockable; public static ConfigEntry<int> window1Cost; public static ConfigEntry<int> window2Cost; public static ConfigEntry<int> window3Cost; public static ConfigEntry<int> window4Cost; public static ConfigEntry<bool> enableWindow1; public static ConfigEntry<bool> enableWindow2; public static ConfigEntry<bool> enableWindow3; public static ConfigEntry<bool> enableWindow4; public static ConfigEntry<bool> defaultWindow1; public static ConfigEntry<bool> defaultWindow2; public static ConfigEntry<bool> defaultWindow3; public static ConfigEntry<bool> defaultWindow4; public static ConfigEntry<bool> changeLightSwitchTip; public static ConfigEntry<bool> enableShutterVoiceLines; public static ConfigEntry<bool> playShutterVoiceLinesOnTransitions; public static ConfigEntry<bool> enableShutterSwitchScanNode; public static ConfigEntry<bool> makeWesleySellAudioRare; public static ConfigEntry<bool> enableWesleySellAudio; public static ConfigEntry<bool> celestialTintOverrideSpace; public static ConfigEntry<bool> enableEnemyFix; public static ConfigEntry<bool> allowEnemyTriggerThroughWindows; public static void InitializeConfig(ConfigFile configFile) { //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Expected O, but got Unknown vanillaMode = configFile.Bind<bool>("General", "VanillaMode", false, "Enable this to preserve vanilla network compatability. This will disable unlockables and the shutter toggle switch. (default = false)"); glassMaterial = configFile.Bind<WindowMaterial>("General", "WindowMaterial", WindowMaterial.NO_REFRACTION_IRIDESCENCE, "Defines what material will be used for the glass. Iridescence will give you some nice rainbow colors. They are more visible with Refraction, but Refraction breaks some VFX."); enableShutter = configFile.Bind<bool>("General", "EnableWindowShutter", true, "Enable the window shutter to hide transitions between space and the current moon. (default = true)"); shuttersHideMoonTransitions = configFile.Bind<bool>("Misc", "Shutters hide moon transitions", true, "If set to true, will close the window shutters when routing to a new moon.Disabling this will look weird, if CelestialTint isn't installed."); hideSpaceProps = configFile.Bind<bool>("General", "HideSpaceProps", false, "Should the planet and moon outside the ship be hidden?"); spaceOutsideSetting = configFile.Bind<SpaceOutside>("General", "SpaceOutside", SpaceOutside.SPACE_HDRI, "Set this value to control how the outside space looks."); disableUnderLights = configFile.Bind<bool>("General", "DisableUnderLights", false, "Disable the flood lights added under the ship if you have the floor window enabled."); dontMovePosters = configFile.Bind<bool>("General", "DontMovePosters", false, "Don't move the poster that blocks the second window if set to true."); skyboxRotateSpeed = configFile.Bind<float>("General", "RotateSpaceSkybox", 0.1f, new ConfigDescription("Sets the rotation speed of the space skybox for visual effect. Requires 'SpaceOutside' to be set to 1 or 2.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-1f, 1f), Array.Empty<object>())); skyboxResolution = configFile.Bind<int>("General", "SkyboxResolution", 0, "OBSOLETE: Download [Ship Windows 4K Skybox] from the Thunderstore to enable!"); windowsUnlockable = configFile.Bind<bool>("General", "WindowsUnlockable", true, "Adds the windows to the terminal as ship upgrades. Set this to false and use below settings to have them enabled by default."); window1Cost = configFile.Bind<int>("General", "Window1Cost", 60, "The base cost of the window behind the terminal / right of the switch."); window2Cost = configFile.Bind<int>("General", "Window2Cost", 60, "The base cost of the window across from the terminal / left of the switch."); window3Cost = configFile.Bind<int>("General", "Window3Cost", 100, "The base cost of the large floor window."); window4Cost = configFile.Bind<int>("General", "Window4Cost", 75, "The base cost of the door windows."); enableWindow1 = configFile.Bind<bool>("General", "EnableWindow1", true, "Enable the window to the right of the switch, behind the terminal."); enableWindow2 = configFile.Bind<bool>("General", "EnableWindow2", true, "Enable the window to the left of the switch, across from the first window."); enableWindow3 = configFile.Bind<bool>("General", "EnableWindow3", true, "Enable the large floor window."); enableWindow4 = configFile.Bind<bool>("General", "EnableWindow4", true, "Enable the door windows."); defaultWindow1 = configFile.Bind<bool>("General", "UnlockWindow1", true, "If set as unlockable, start the game with window to the right of the switch unlocked already."); defaultWindow2 = configFile.Bind<bool>("General", "UnlockWindow2", false, "If set as unlockable, start the game with window across from the terminal unlocked already."); defaultWindow3 = configFile.Bind<bool>("General", "UnlockWindow3", false, "If set as unlockable, start the game with the floor window unlocked already."); defaultWindow4 = configFile.Bind<bool>("General", "UnlockWindow4", false, "If set as unlockable, start the game with the door windows unlocked already."); changeLightSwitchTip = configFile.Bind<bool>("Misc", "Change light switch tool tip", true, "If set to true, will change the tool tip for the light switch to match the shutter's tool tip."); enableShutterVoiceLines = configFile.Bind<bool>("Misc", "Enable Wesley shutter voice lines", true, "If set to true, will load and use Wesley's voice lines for opening/closing the window shutters."); playShutterVoiceLinesOnTransitions = configFile.Bind<bool>("Misc", "Play Wesley shutter voice lines on transitions", true, "If set to true, will play the voice lines, if opening/closing the window shutters is caused by a transition."); enableShutterSwitchScanNode = configFile.Bind<bool>("Misc", "Enable Shutter Switch scan node", true, "If set to true, will enable the scan node for the shutter switch."); makeWesleySellAudioRare = configFile.Bind<bool>("Misc", "Make Wesley Sell Audio Rare", false, "If set to true, will add the wesley sell audio to the rare audio list."); enableWesleySellAudio = configFile.Bind<bool>("Misc", "Enable Wesley Sell Audio", true, "If set to true, will add the wesley sell audio to the audio list."); allowEnemyTriggerThroughWindows = configFile.Bind<bool>("Misc", "Allow Enemy Trigger Through Windows", true, "If set to true, will allow you to trigger enemies through windows. Will also allow enemies to see you through windows. Does not have any effect on vanilla mode."); celestialTintOverrideSpace = configFile.Bind<bool>("Other Mods", "CelestialTintOverrideSpace", false, "If Celestial Tint is installed, override the skybox. Only effective if skybox is set to Space HDRRI Volume."); enableEnemyFix = configFile.Bind<bool>("Fixes", "Enable Enemy Fix", true, "If set to true, will add a check to enemy's ai to prevent them from killing you through the windows. Enabling this might cause some issues though."); } } public enum WindowMaterial { NO_REFRACTION, NO_REFRACTION_IRIDESCENCE, REFRACTION, REFRACTION_IRIDESCENCE } public static class MyPluginInfo { public const string PLUGIN_GUID = "TestAccount666.ShipWindows"; public const string PLUGIN_NAME = "ShipWindows"; public const string PLUGIN_VERSION = "1.11.0"; } } namespace ShipWindows.Utilities { internal static class ObjectReplacer { private static readonly Dictionary<GameObject?, ReplaceInfo> _ReplacedObjects = new Dictionary<GameObject, ReplaceInfo>(); internal static readonly List<ReplacedMeshInfo> ReplacedMeshes = new List<ReplacedMeshInfo>(); internal static readonly List<ReplacedMaterialInfo> ReplacedMaterials = new List<ReplacedMaterialInfo>(); public static void ReplaceMaterial(GameObject fromObj, GameObject toObj) { try { MeshRenderer component = fromObj.GetComponent<MeshRenderer>(); MeshRenderer component2 = toObj.GetComponent<MeshRenderer>(); if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component2)) { ((Renderer)component2).material = ((Renderer)component).material; ((Renderer)component2).materials = ((Renderer)component).materials; ((Renderer)component2).sharedMaterial = ((Renderer)component).sharedMaterial; ((Renderer)component2).sharedMaterials = ((Renderer)component).sharedMaterials; } } catch (Exception arg) { ShipWindows.Logger.LogError((object)$"Could not replace object material:\n{arg}"); } } public static GameObject Replace(GameObject original, GameObject prefab) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) ShipWindows.Logger.LogInfo((object)("Replacing object " + ((Object)original).name + " with " + ((Object)prefab).name + "...")); GameObject val = Object.Instantiate<GameObject>(prefab, original.transform.parent); val.transform.position = original.transform.position; val.transform.rotation = original.transform.rotation; string name = ((Object)original).name; ((Object)original).name = name + " (Old)"; ((Object)val).name = name; val.SetActive(true); original.SetActive(false); ReplaceInfo replaceInfo = default(ReplaceInfo); replaceInfo.name = name; replaceInfo.original = original; replaceInfo.replacement = val; ReplaceInfo value = replaceInfo; _ReplacedObjects[original] = value; return val; } public static void RestoreMeshes() { foreach (ReplacedMeshInfo item in ReplacedMeshes.ToList()) { MeshFilter meshFilter = item.meshFilter; meshFilter.mesh = item.original; meshFilter.sharedMesh = item.original; ReplacedMeshes.Remove(item); } } public static void RestoreMaterials() { foreach (ReplacedMaterialInfo item in ReplacedMaterials.ToList()) { MeshRenderer meshRenderer = item.meshRenderer; ((Renderer)meshRenderer).material = item.original; ((Renderer)meshRenderer).sharedMaterial = item.original; ((Renderer)meshRenderer).materials = item.originals; ((Renderer)meshRenderer).sharedMaterials = item.originals; ReplacedMaterials.Remove(item); } } public static void Restore(GameObject original) { try { if (_ReplacedObjects.TryGetValue(original, out var value)) { ShipWindows.Logger.LogInfo((object)("Restoring object " + value.name + "...")); GameObject? original2 = value.original; if (original2 != null) { original2.SetActive(true); } if ((Object)(object)value.original != (Object)null) { ((Object)value.original).name = value.name; } Object.DestroyImmediate((Object)(object)value.replacement); _ReplacedObjects.Remove(original); } } catch (Exception) { ShipWindows.Logger.LogWarning((object)("GameObject replacement info not found for: " + (((Object)(object)original != (Object)null) ? ((Object)original).name : "Invalid GameObject") + "! Not replaced?")); } } } internal record struct ReplacedMeshInfo { public MeshFilter meshFilter; public Mesh original; public Mesh replacement; } internal record struct ReplacedMaterialInfo { public MeshRenderer meshRenderer; public Material original; public Material replacement; public Material[] originals; public Material[] replacements; public bool Equals(ReplacedMaterialInfo other) { return (Object)(object)meshRenderer == (Object)(object)other.meshRenderer && (Object)(object)original == (Object)(object)other.original && (Object)(object)replacement == (Object)(object)other.replacement && originals.SequenceEqual(other.originals) && replacements.SequenceEqual(other.replacements); } public override int GetHashCode() { return HashCode.Combine<MeshRenderer, Material, Material, Material[], Material[]>(meshRenderer, original, replacement, originals, replacements); } } internal struct ReplaceInfo { public string name; public GameObject? original; public GameObject replacement; } internal static class ShipReplacer { public static bool debounceReplace; public static GameObject? vanillaShipInside; public static GameObject? newShipInside; public static GameObject? switchInstance; private static GameObject? FindOrThrow(string name) { GameObject val = GameObject.Find(name); if (!Object.op_Implicit((Object)(object)val)) { throw new Exception("Could not find " + name + "! Wrong scene?"); } return val; } private static string GetShipAssetName() { if (WindowConfig.windowsUnlockable.Value && !WindowConfig.vanillaMode.Value) { ShipWindowSpawner[] source = Object.FindObjectsByType<ShipWindowSpawner>((FindObjectsSortMode)0); bool flag = (Object)(object)source.FirstOrDefault((ShipWindowSpawner spawner) => spawner.id == 1) != (Object)null; bool flag2 = (Object)(object)source.FirstOrDefault((ShipWindowSpawner spawner) => spawner.id == 2) != (Object)null; bool flag3 = (Object)(object)source.FirstOrDefault((ShipWindowSpawner spawner) => spawner.id == 3) != (Object)null; return $"ShipInsideWithWindow{(flag ? 1 : 0)}{(flag2 ? 1 : 0)}{(flag3 ? 1 : 0)}"; } bool value = WindowConfig.enableWindow1.Value; bool value2 = WindowConfig.enableWindow2.Value; bool value3 = WindowConfig.enableWindow3.Value; return $"ShipInsideWithWindow{(value ? 1 : 0)}{(value2 ? 1 : 0)}{(value3 ? 1 : 0)}"; } private static void AddWindowScripts(GameObject ship) { //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Expected O, but got Unknown GameObject val = GameObject.Find("Environment/HangarShip/AnimatedShipDoor/HangarDoorLeft (1)/WindowsLeft(Clone)"); if ((Object)(object)val != (Object)null && (Object)(object)val.GetComponent<ShipWindow>() == (Object)null) { ShipWindow shipWindow = val.AddComponent<ShipWindow>(); shipWindow.id = 4; } GameObject val2 = GameObject.Find("Environment/HangarShip/AnimatedShipDoor/HangarDoorRight (1)/WindowsRight(Clone)"); if ((Object)(object)val2 != (Object)null && (Object)(object)val2.GetComponent<ShipWindow>() == (Object)null) { ShipWindow shipWindow2 = val2.AddComponent<ShipWindow>(); shipWindow2.id = 4; } Transform val3 = ship.transform.Find("WindowContainer"); if ((Object)(object)val3 == (Object)null) { return; } foreach (Transform item in val3) { Transform val4 = item; if (!((Object)(object)((Component)val4).gameObject.GetComponent<ShipWindow>() != (Object)null)) { string name = ((Object)((Component)val4).gameObject).name; if (int.TryParse(name[name.Length - 1].ToString(), out var result)) { ((Component)val4).gameObject.AddComponent<ShipWindow>().id = result; } } } } public static void ReplaceDebounced(bool replace) { if (WindowConfig.windowsUnlockable.Value && !WindowConfig.vanillaMode.Value && !debounceReplace) { debounceReplace = true; ((MonoBehaviour)StartOfRound.Instance).StartCoroutine(ReplacementCoroutine(replace)); } } private static IEnumerator ReplacementCoroutine(bool replace) { yield return null; debounceReplace = false; if (replace) { ReplaceShip(); } else { RestoreShip(); } } private static string GetMaterialName(this WindowMaterial separator) { if (1 == 0) { } string result = separator switch { WindowMaterial.NO_REFRACTION => "GlassNoRefraction", WindowMaterial.NO_REFRACTION_IRIDESCENCE => "GlassNoRefractionIridescence", WindowMaterial.REFRACTION => "GlassWithRefraction", WindowMaterial.REFRACTION_IRIDESCENCE => "GlassWithRefractionIridescence", _ => throw new ArgumentOutOfRangeException("separator", separator, null), }; if (1 == 0) { } return result; } internal static void ReplaceGlassMaterial() { if (!((Object)(object)newShipInside == (Object)null)) { ReplaceGlassMaterial(newShipInside); } } private static void ReplaceGlassMaterial(GameObject shipPrefab) { WindowMaterial value = WindowConfig.glassMaterial.Value; ShipWindows.Logger.LogInfo((object)$"Replacing material glass material with: {value}"); Material val = ShipWindows.mainAssetBundle.LoadAsset<Material>("Assets/LethalCompany/Mods/plugins/ShipWindows/Materials/" + value.GetMaterialName() + ".mat"); if ((Object)(object)val == (Object)null) { throw new NullReferenceException($"Couldn't find glass material {value} ({value.GetMaterialName()})!"); } Transform obj = shipPrefab.transform.Find("WindowContainer/Window1/Glass"); MeshRenderer val2 = ((obj != null) ? ((Component)obj).GetComponent<MeshRenderer>() : null); Transform obj2 = shipPrefab.transform.Find("WindowContainer/Window2/Glass"); MeshRenderer val3 = ((obj2 != null) ? ((Component)obj2).GetComponent<MeshRenderer>() : null); Transform obj3 = shipPrefab.transform.Find("WindowContainer/Window3"); MeshRenderer val4 = ((obj3 != null) ? ((Component)obj3).GetComponent<MeshRenderer>() : null); List<MeshRenderer> list = new List<MeshRenderer>(); GameObject val5 = GameObject.Find("Environment/HangarShip/AnimatedShipDoor/HangarDoorLeft (1)/WindowsLeft(Clone)/WindowFront"); GameObject val6 = GameObject.Find("Environment/HangarShip/AnimatedShipDoor/HangarDoorLeft (1)/WindowsLeft(Clone)/WindowBack"); GameObject val7 = GameObject.Find("Environment/HangarShip/AnimatedShipDoor/HangarDoorRight (1)/WindowsRight(Clone)/WindowFront"); GameObject val8 = GameObject.Find("Environment/HangarShip/AnimatedShipDoor/HangarDoorRight (1)/WindowsRight(Clone)/WindowBack"); list.Add((val5 != null) ? val5.GetComponent<MeshRenderer>() : null); list.Add((val6 != null) ? val6.GetComponent<MeshRenderer>() : null); list.Add((val7 != null) ? val7.GetComponent<MeshRenderer>() : null); list.Add((val8 != null) ? val8.GetComponent<MeshRenderer>() : null); if ((Object)(object)val2 != (Object)null) { ((Renderer)val2).material = val; } if ((Object)(object)val3 != (Object)null) { ((Renderer)val3).material = val; } if ((Object)(object)val4 != (Object)null) { ((Renderer)val4).material = val; } foreach (MeshRenderer item in list.OfType<MeshRenderer>()) { ((Renderer)item).material = val; } } public static void ReplaceShip() { try { if ((Object)(object)newShipInside != (Object)null && (Object)(object)vanillaShipInside != (Object)null) { ObjectReplacer.Restore(vanillaShipInside); } vanillaShipInside = FindOrThrow("Environment/HangarShip/ShipInside"); string shipAssetName = GetShipAssetName(); GameObject val = ShipWindows.mainAssetBundle.LoadAsset<GameObject>("Assets/LethalCompany/Mods/plugins/ShipWindows/Ships/" + shipAssetName + ".prefab"); if ((Object)(object)val == (Object)null) { if (!shipAssetName.Equals("ShipInsideWithWindow000")) { throw new Exception("Could not load requested ship replacement! " + shipAssetName); } val = vanillaShipInside; } ShipWindowSpawner[] source = Object.FindObjectsByType<ShipWindowSpawner>((FindObjectsSortMode)0); bool flag = (Object)(object)source.FirstOrDefault((ShipWindowSpawner spawner) => spawner.id == 4) != (Object)null; bool flag2 = (!WindowConfig.windowsUnlockable.Value || WindowConfig.vanillaMode.Value) && WindowConfig.enableWindow4.Value; if (flag || flag2) { SpawnDoorWindows(); } AddWindowScripts(val); ReplaceGlassMaterial(val); newShipInside = ObjectReplacer.Replace(vanillaShipInside, val); if (ShipColors.Enabled) { ShipColors.RefreshColors(); } ((MonoBehaviour)StartOfRound.Instance).StartCoroutine(WaitAndCheckSwitch()); WindowState.Instance.SetWindowState(WindowState.Instance.windowsClosed, WindowState.Instance.windowsLocked, playVoiceLine: false); } catch (Exception arg) { ShipWindows.Logger.LogError((object)$"Failed to replace ShipInside! \n{arg}"); } } private static void SpawnDoorWindows() { GameObject val = GameObject.Find("Environment/HangarShip/AnimatedShipDoor"); BoxCollider[] componentsInChildren = val.GetComponentsInChildren<BoxCollider>(); BoxCollider[] array = componentsInChildren; foreach (BoxCollider val2 in array) { if (componentsInChildren != null) { ((Collider)val2).isTrigger = true; } } ReplaceDoor(val, "Left"); ReplaceDoor(val, "Right"); } private static void ReplaceDoor(GameObject shipDoors, string side) { ShipWindows.Logger.LogInfo((object)("Replacing ship door: " + side)); Transform val = shipDoors.transform.Find("HangarDoor" + side + " (1)"); if (Object.op_Implicit((Object)(object)((Component)val).transform.Find("Windows" + side))) { return; } MeshFilter component = ((Component)val).gameObject.GetComponent<MeshFilter>(); Mesh val2 = ShipWindows.mainAssetBundle.LoadAsset<Mesh>("Assets/LethalCompany/Mods/plugins/ShipWindows/ShipDoor/ShipDoor" + side + ".asset"); ShipWindows.Logger.LogInfo((object)("Got new mesh? " + ((Object)(object)val2 != (Object)null))); MeshRenderer component2 = ((Component)val).gameObject.GetComponent<MeshRenderer>(); for (int i = 0; i < ShipWindows.DoorMaterials.Length; i++) { Material val3 = ShipWindows.DoorMaterials[i]; if (!((Object)(object)val3 != (Object)null)) { val3 = ShipWindows.mainAssetBundle.LoadAsset<Material>($"Assets/LethalCompany/Mods/plugins/ShipWindows/Materials/HangarShipDoor{i + 1}.mat"); if ((Object)(object)val3 == (Object)null) { ShipWindows.Logger.LogError((object)$"Couldn't find ship door material '{i}'!"); return; } ShipWindows.DoorMaterials[i] = val3; } } Material[] doorMaterials = ShipWindows.DoorMaterials; ObjectReplacer.ReplacedMaterials.Add(new ReplacedMaterialInfo { meshRenderer = component2, original = ((Renderer)component2).material, replacement = doorMaterials[0], originals = ((Renderer)component2).materials, replacements = doorMaterials }); ObjectReplacer.ReplacedMeshes.Add(new ReplacedMeshInfo { meshFilter = component, original = component.mesh, replacement = val2 }); component.mesh = val2; component.sharedMesh = val2; MeshCollider val4 = ((Component)val).gameObject.AddComponent<MeshCollider>(); val4.sharedMesh = component.sharedMesh; ((Renderer)component2).material = doorMaterials[0]; ((Renderer)component2).materials = doorMaterials; ((Renderer)component2).sharedMaterial = doorMaterials[0]; ((Renderer)component2).sharedMaterials = doorMaterials; GameObject val5 = ShipWindows.mainAssetBundle.LoadAsset<GameObject>("Assets/LethalCompany/Mods/plugins/ShipWindows/ShipDoor/Windows" + side + ".prefab"); Object.Instantiate<GameObject>(val5, val); } public static void SpawnSwitch() { ShipWindowShutterSwitch shipWindowShutterSwitch = Object.FindFirstObjectByType<ShipWindowShutterSwitch>(); if ((Object)(object)shipWindowShutterSwitch != (Object)null) { switchInstance = ((Component)shipWindowShutterSwitch).gameObject; return; } ShipWindows.Logger.LogInfo((object)"Spawning shutter switch..."); if (!((Object)(object)ShipWindows.windowSwitchPrefab == (Object)null) && (NetworkManager.Singleton.IsHost || NetworkManager.Singleton.IsServer)) { switchInstance = Object.Instantiate<GameObject>(ShipWindows.windowSwitchPrefab); switchInstance.GetComponent<NetworkObject>().Spawn(false); } } public static void CheckShutterSwitch() { NetworkManager singleton = NetworkManager.Singleton; if (singleton != null && !singleton.IsHost && !singleton.IsServer) { return; } ShipWindow[] array = Object.FindObjectsByType<ShipWindow>((FindObjectsSortMode)0); if (array == null) { array = Array.Empty<ShipWindow>(); } if (array.Length != 0) { if ((Object)(object)switchInstance == (Object)null) { SpawnSwitch(); } else { switchInstance.SetActive(true); } } else if (!((Object)(object)switchInstance == (Object)null)) { NetworkObject component = switchInstance.GetComponent<NetworkObject>(); if ((Object)(object)component != (Object)null) { component.Despawn(true); } Object.Destroy((Object)(object)switchInstance); switchInstance = null; } } public static IEnumerator WaitAndCheckSwitch() { yield return null; CheckShutterSwitch(); } public static void RestoreShip() { if (!((Object)(object)newShipInside == (Object)null)) { if ((Object)(object)vanillaShipInside == (Object)null) { throw new NullReferenceException("vanillaShipInside == null?!"); } ObjectReplacer.RestoreMaterials(); ObjectReplacer.RestoreMeshes(); ObjectReplacer.Restore(vanillaShipInside); ((MonoBehaviour)StartOfRound.Instance).StartCoroutine(WaitAndCheckSwitch()); newShipInside = null; } } public static IEnumerator CheckForKeptSpawners() { yield return (object)new WaitForSeconds(2f); ShipWindowSpawner[] windows = Object.FindObjectsByType<ShipWindowSpawner>((FindObjectsSortMode)0); if (windows.Length != 0) { ReplaceDebounced(replace: true); } } } internal static class ShipWindow4K { private static readonly DirectoryInfo _BaseDirectory = new DirectoryInfo(Assembly.GetExecutingAssembly().Location); public static AssetBundle? TextureBundle { get; private set; } public static Texture? Skybox4K { get; private set; } public static bool TryToLoad() { if ((Object)(object)Skybox4K != (Object)null) { return true; } try { string text = _BaseDirectory.Parent?.Parent?.FullName; Debug.Assert(text != null, "pluginsFolder != null"); string[] files = Directory.GetFiles(text, "ship_window_4k", SearchOption.AllDirectories); int num = 0; if (num < files.Length) { string fileName = files[num]; FileInfo fileInfo = new FileInfo(fileName); if (!fileInfo.Extension.Equals(".old")) { if (TextureBundle == null) { TextureBundle = AssetBundle.LoadFromFile(fileInfo.FullName); } Object[] array = TextureBundle.LoadAllAssets(); if (array == null) { array = Array.Empty<Object>(); } Skybox4K = (Texture?)((array.Length != 0) ? /*isinst with value type is only supported in some contexts*/: null); if ((Object)(object)Skybox4K == (Object)null) { throw new NullReferenceException("Texture not present"); } ShipWindows.Logger.LogDebug((object)("Found 4K skybox texture! " + ((Object)(object)Skybox4K != (Object)null))); return true; } } } catch (Exception arg) { ShipWindows.Logger.LogError((object)$"Failed to find and load 4K skybox AssetBundle!\n{arg}"); return false; } ShipWindows.Logger.LogDebug((object)"Did not locate 4K skybox bundle."); return false; } } public static class SoundLoader { public static readonly AudioClip[] CommonSellCounterLines = (AudioClip[])(object)new AudioClip[1]; public static readonly AudioClip[] RareSellCounterLines = (AudioClip[])(object)new AudioClip[1]; public static readonly AudioClip[] VoiceLines = (AudioClip[])(object)new AudioClip[2]; public static IEnumerator LoadAudioClips() { string assemblyDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); Debug.Assert(assemblyDirectory != null, "assemblyDirectory != null"); string audioPath = Path.Combine(assemblyDirectory, "sounds"); audioPath = (Directory.Exists(audioPath) ? audioPath : Path.Combine(assemblyDirectory)); ShipWindows.Logger.LogInfo((object)"Loading Wesley voice lines..."); string voiceLinesAudioPath2 = Path.Combine(audioPath, "voicelines"); voiceLinesAudioPath2 = (Directory.Exists(voiceLinesAudioPath2) ? voiceLinesAudioPath2 : Path.Combine(audioPath)); LoadShutterCloseClip(voiceLinesAudioPath2); LoadShutterOpenClip(voiceLinesAudioPath2); if (WindowConfig.enableWesleySellAudio.Value) { LoadSellCounterClips(voiceLinesAudioPath2); } yield break; } private static void LoadShutterOpenClip(string voiceLinesAudioPath) { string text = Path.Combine(voiceLinesAudioPath, "ShutterOpen.wav"); string fileName = Path.GetFileName(text); Uri filePath = new Uri(text); string text2 = fileName; AudioClip val = LoadAudioClipFromFile(filePath, text2.Substring(0, text2.Length - 4)); if ((Object)(object)val == (Object)null) { ShipWindows.Logger.LogError((object)"Failed to load voice line 'ShutterOpen'!"); ShipWindows.Logger.LogError((object)("Path: " + voiceLinesAudioPath)); } else { VoiceLines[0] = val; ShipWindows.Logger.LogInfo((object)("Loaded line '" + ((Object)val).name + "'!")); } } private static void LoadShutterCloseClip(string voiceLinesAudioPath) { string text = Path.Combine(voiceLinesAudioPath, "ShutterClose.wav"); string fileName = Path.GetFileName(text); Uri filePath = new Uri(text); string text2 = fileName; AudioClip val = LoadAudioClipFromFile(filePath, text2.Substring(0, text2.Length - 4)); if ((Object)(object)val == (Object)null) { ShipWindows.Logger.LogError((object)"Failed to load voice line 'ShutterClose'!"); ShipWindows.Logger.LogError((object)("Path: " + voiceLinesAudioPath)); } else { VoiceLines[1] = val; ShipWindows.Logger.LogInfo((object)("Loaded line '" + ((Object)val).name + "'!")); } } private static void LoadSellCounterClips(string voiceLinesAudioPath) { string text = Path.Combine(voiceLinesAudioPath, "SellCounter1.wav"); string fileName = Path.GetFileName(text); Uri filePath = new Uri(text); string text2 = fileName; AudioClip val = LoadAudioClipFromFile(filePath, text2.Substring(0, text2.Length - 4)); if ((Object)(object)val == (Object)null) { ShipWindows.Logger.LogError((object)"Failed to load voice line 'SellCounter1'!"); ShipWindows.Logger.LogError((object)("Path: " + voiceLinesAudioPath)); return; } if (WindowConfig.makeWesleySellAudioRare.Value) { RareSellCounterLines[0] = val; } else { CommonSellCounterLines[0] = val; } ShipWindows.Logger.LogInfo((object)("Loaded line '" + ((Object)val).name + "'!")); } private static AudioClip? LoadAudioClipFromFile(Uri filePath, string name) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Invalid comparison between Unknown and I4 UnityWebRequest audioClip = UnityWebRequestMultimedia.GetAudioClip(filePath, (AudioType)20); try { UnityWebRequestAsyncOperation val = audioClip.SendWebRequest(); while (!((AsyncOperation)val).isDone) { Thread.Sleep(100); } if ((int)audioClip.result != 1) { ShipWindows.Logger.LogError((object)("Failed to load AudioClip: " + audioClip.error)); return null; } AudioClip content = DownloadHandlerAudioClip.GetContent(audioClip); ((Object)content).name = name; return content; } finally { ((IDisposable)audioClip)?.Dispose(); } } } internal class Unlockables { private class WindowUnlockable { public string name = null; public int price; } public static Dictionary<int, string> windowNames = new Dictionary<int, string> { [1] = "Right Window", [2] = "Left Window", [3] = "Floor Window", [4] = "Door Window" }; public static Dictionary<int, string> windowInfo = new Dictionary<int, string> { [1] = "\nAdds a window to the right of the ship's control panel, behind the terminal.\n\n", [2] = "\nAdds a window to the left of the ship's control panel.\n\n", [3] = "\nAdds a window to the floor of the ship.\n\n", [4] = "\nAdds windows to the door of the ship.\n\n" }; private static readonly Dictionary<int, WindowUnlockable> _WindowUnlockables = new Dictionary<int, WindowUnlockable>(); [HarmonyPrefix] [HarmonyPatch(typeof(Terminal), "TextPostProcess")] private static void Patch_TextPostProcess(ref string modifiedDisplayText, TerminalNode node) { try { if (modifiedDisplayText.Contains("[buyableItemsList]") && modifiedDisplayText.Contains("[unlockablesSelectionList]")) { int index = modifiedDisplayText.IndexOf(":"); modifiedDisplayText = _WindowUnlockables.Reverse().Where<KeyValuePair<int, WindowUnlockable>>(delegate(KeyValuePair<int, WindowUnlockable> unlock) { KeyValuePair<int, WindowUnlockable> keyValuePair2 = unlock; return !ShipWindows.IsWindowDefaultUnlocked(keyValuePair2.Key); }).Select(delegate(KeyValuePair<int, WindowUnlockable> unlock) { KeyValuePair<int, WindowUnlockable> keyValuePair = unlock; string name = keyValuePair.Value.name; keyValuePair = unlock; return $"\n* {name} // Price: ${keyValuePair.Value.price}"; }) .Aggregate(modifiedDisplayText, (string current, string upgradeLine) => current.Insert(index + 1, upgradeLine)); } } catch (Exception ex) { ShipWindows.Logger.LogError((object)ex); } } private static TerminalKeyword CreateKeyword(string word, TerminalKeyword defaultVerb) { TerminalKeyword val = ScriptableObject.CreateInstance<TerminalKeyword>(); ((Object)val).name = word; val.word = word; val.isVerb = false; val.accessTerminalObjects = false; val.defaultVerb = defaultVerb; return val; } public static int AddWindowToUnlockables(Terminal terminal, ShipWindowDef def) { //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Expected O, but got Unknown //IL_0369: Unknown result type (might be due to invalid IL or missing references) //IL_036e: Unknown result type (might be due to invalid IL or missing references) //IL_03a3: Unknown result type (might be due to invalid IL or missing references) //IL_03ac: Expected O, but got Unknown //IL_03ae: Unknown result type (might be due to invalid IL or missing references) //IL_03b3: Unknown result type (might be due to invalid IL or missing references) //IL_03e8: Unknown result type (might be due to invalid IL or missing references) //IL_03f1: Expected O, but got Unknown //IL_0493: Unknown result type (might be due to invalid IL or missing references) //IL_0498: Unknown result type (might be due to invalid IL or missing references) //IL_04a0: Unknown result type (might be due to invalid IL or missing references) //IL_04ad: Expected O, but got Unknown //IL_04cc: Unknown result type (might be due to invalid IL or missing references) //IL_04d1: Unknown result type (might be due to invalid IL or missing references) //IL_04d9: Unknown result type (might be due to invalid IL or missing references) //IL_04e6: Expected O, but got Unknown if (!windowNames.TryGetValue(def.id, out string name)) { name = $"Window {def.id}"; } ShipWindows.Logger.LogInfo((object)("Adding " + name + " to unlockables...")); UnlockablesList unlockablesList = StartOfRound.Instance.unlockablesList; int num = unlockablesList.unlockables.FindIndex((UnlockableItem unlockable) => unlockable.unlockableName == name); if (!_WindowUnlockables.ContainsKey(def.id)) { _WindowUnlockables.Add(def.id, new WindowUnlockable { name = name, price = def.baseCost }); } int num2; if (num != -1) { num2 = num; } else { TerminalKeyword val = terminal.terminalNodes.allKeywords.First((TerminalKeyword keyword) => keyword.word == "buy"); TerminalNode result = val.compatibleNouns[0].result.terminalOptions[1].result; TerminalKeyword val2 = terminal.terminalNodes.allKeywords.First((TerminalKeyword keyword) => keyword.word == "info"); TerminalKeyword val3 = CreateKeyword(name.ToLowerInvariant().Replace(" ", "") ?? "", val); UnlockableItem item = new UnlockableItem { unlockableName = name, spawnPrefab = true, alwaysInStock = true, prefabObject = def.prefab, unlockableType = 1, IsPlaceable = false, maxNumber = 1, canBeStored = false, alreadyUnlocked = ShipWindows.IsWindowDefaultUnlocked(def.id) }; unlockablesList.unlockables.Capacity++; unlockablesList.unlockables.Add(item); num2 = unlockablesList.unlockables.FindIndex((UnlockableItem unlockable) => unlockable.unlockableName == name); ShipWindows.Logger.LogInfo((object)$"{name} added to unlockable list at index {num2}"); TerminalNode val4 = ScriptableObject.CreateInstance<TerminalNode>(); ((Object)val4).name = name.Replace(" ", "-") + "BuyNode2"; val4.displayText = "Ordered " + name + "! Your new balance is [playerCredits].\n\nPlease clean the windows at the end of your contract.\n\n"; val4.clearPreviousText = true; val4.maxCharactersToType = 15; val4.buyItemIndex = -1; val4.shipUnlockableID = num2; val4.buyUnlockable = true; val4.creatureName = name; val4.isConfirmationNode = false; val4.itemCost = def.baseCost; TerminalNode val5 = ScriptableObject.CreateInstance<TerminalNode>(); ((Object)val5).name = name.Replace(" ", "-") + "BuyNode1"; val5.displayText = "You have requested to order " + name + ".\nTotal cost of item: [totalCost].\n\nPlease CONFIRM or DENY.\n\n"; val5.clearPreviousText = true; val5.maxCharactersToType = 15; val5.shipUnlockableID = num2; val5.itemCost = def.baseCost; val5.creatureName = name; val5.overrideOptions = true; val5.terminalOptions = (CompatibleNoun[])(object)new CompatibleNoun[2] { new CompatibleNoun { noun = terminal.terminalNodes.allKeywords.First((TerminalKeyword keyword2) => keyword2.word == "confirm"), result = val4 }, new CompatibleNoun { noun = terminal.terminalNodes.allKeywords.First((TerminalKeyword keyword2) => keyword2.word == "deny"), result = result } }; string valueOrDefault = windowInfo.GetValueOrDefault(def.id, "[No information about this object was found.]\n"); TerminalNode val6 = ScriptableObject.CreateInstance<TerminalNode>(); ((Object)val6).name = name.Replace(" ", "-") + "InfoNode"; val6.displayText = valueOrDefault; val6.clearPreviousText = true; val6.maxCharactersToType = 25; List<TerminalKeyword> list = terminal.terminalNodes.allKeywords.ToList(); list.Add(val3); terminal.terminalNodes.allKeywords = list.ToArray(); List<CompatibleNoun> list2 = val.compatibleNouns.ToList(); list2.Add(new CompatibleNoun { noun = val3, result = val5 }); val.compatibleNouns = list2.ToArray(); List<CompatibleNoun> list3 = val2.compatibleNouns.ToList(); list3.Add(new CompatibleNoun { noun = val3, result = val6 }); val2.compatibleNouns = list3.ToArray(); ShipWindows.Logger.LogInfo((object)("Registered terminal nodes for " + name)); } return num2; } public static int AddSwitchToUnlockables() { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Expected O, but got Unknown UnlockablesList unlockablesList = StartOfRound.Instance.unlockablesList; int num = unlockablesList.unlockables.FindIndex((UnlockableItem unlockable) => unlockable.unlockableName == "Shutter Switch"); int num2; if (num != -1) { num2 = num; } else { UnlockableItem item = new UnlockableItem { unlockableName = "Shutter Switch", spawnPrefab = false, unlockableType = 1, IsPlaceable = true, maxNumber = 1, canBeStored = false, alreadyUnlocked = true }; unlockablesList.unlockables.Capacity++; unlockablesList.unlockables.Add(item); num2 = unlockablesList.unlockables.FindIndex((UnlockableItem unlockable) => unlockable.unlockableName == "Shutter Switch"); } if (Object.op_Implicit((Object)(object)ShipWindows.windowSwitchPrefab)) { PlaceableShipObject componentInChildren = ShipWindows.windowSwitchPrefab.GetComponentInChildren<PlaceableShipObject>(); componentInChildren.unlockableID = num2; } ShipWindows.Logger.LogInfo((object)$"Added shutter switch to unlockables list at ID {num2}"); return num2; } } } namespace ShipWindows.Networking { [Serializable] internal class NetworkHandler { public delegate void OnWindowSwitchToggled(); public delegate void OnWindowSyncReceive(); [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__ReceiveWindowSync; public static HandleNamedMessageDelegate <1>__ReceiveWindowSwitchUsed_Server; public static HandleNamedMessageDelegate <2>__ReceiveWindowSwitchUsed_Client; public static HandleNamedMessageDelegate <3>__ReceiveWindowSyncRequest; } internal static CustomMessagingManager MessageManager => NetworkManager.Singleton.CustomMessagingManager; internal static bool IsClient => NetworkManager.Singleton.IsClient; internal static bool IsHost => NetworkManager.Singleton.IsHost; public static event OnWindowSyncReceive WindowSyncReceivedEvent; public static event OnWindowSwitchToggled WindowSwitchToggledEvent; public static void RegisterMessages() { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Expected O, but got Unknown //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Expected O, but got Unknown ShipWindows.Logger.LogInfo((object)"Registering network message handlers..."); CustomMessagingManager messageManager = MessageManager; object obj = <>O.<0>__ReceiveWindowSync; if (obj == null) { HandleNamedMessageDelegate val = ReceiveWindowSync; <>O.<0>__ReceiveWindowSync = val; obj = (object)val; } messageManager.RegisterNamedMessageHandler("ShipWindow_WindowSyncResponse", (HandleNamedMessageDelegate)obj); CustomMessagingManager messageManager2 = MessageManager; object obj2 = <>O.<1>__ReceiveWindowSwitchUsed_Server; if (obj2 == null) { HandleNamedMessageDelegate val2 = ReceiveWindowSwitchUsed_Server; <>O.<1>__ReceiveWindowSwitchUsed_Server = val2; obj2 = (object)val2; } messageManager2.RegisterNamedMessageHandler("ShipWindow_WindowSwitchUsed", (HandleNamedMessageDelegate)obj2); CustomMessagingManager messageManager3 = MessageManager; object obj3 = <>O.<2>__ReceiveWindowSwitchUsed_Client; if (obj3 == null) { HandleNamedMessageDelegate val3 = ReceiveWindowSwitchUsed_Client; <>O.<2>__ReceiveWindowSwitchUsed_Client = val3; obj3 = (object)val3; } messageManager3.RegisterNamedMessageHandler("ShipWindow_WindowSwitchUsedBroadcast", (HandleNamedMessageDelegate)obj3); if (IsHost) { CustomMessagingManager messageManager4 = MessageManager; object obj4 = <>O.<3>__ReceiveWindowSyncRequest; if (obj4 == null) { HandleNamedMessageDelegate val4 = ReceiveWindowSyncRequest; <>O.<3>__ReceiveWindowSyncRequest = val4; obj4 = (object)val4; } messageManager4.RegisterNamedMessageHandler("ShipWindow_WindowSyncRequest", (HandleNamedMessageDelegate)obj4); } } public static void UnregisterMessages() { ShipWindows.Logger.LogInfo((object)"Unregistering network message handlers..."); MessageManager.UnregisterNamedMessageHandler("ShipWindow_WindowSyncResponse"); MessageManager.UnregisterNamedMessageHandler("ShipWindow_WindowSyncRequest"); MessageManager.UnregisterNamedMessageHandler("ShipWindow_WindowSwitchUsed"); MessageManager.UnregisterNamedMessageHandler("ShipWindow_WindowSwitchUsedBroadcast"); } public static void WindowSwitchUsed(bool currentState) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(1, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref currentState, default(ForPrimitives)); MessageManager.SendNamedMessage("ShipWindow_WindowSwitchUsed", 0uL, val, (NetworkDelivery)3); } finally { ((IDisposable)(FastBufferWriter)(ref val)).Dispose(); } } public static void ReceiveWindowSwitchUsed_Server(ulong clientId, FastBufferReader reader) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) bool flag = default(bool); ((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref flag, default(ForPrimitives)); FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(1, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref flag, default(ForPrimitives)); MessageManager.SendNamedMessageToAll("ShipWindow_WindowSwitchUsedBroadcast", val, (NetworkDelivery)3); } finally { ((IDisposable)(FastBufferWriter)(ref val)).Dispose(); } } public static void ReceiveWindowSwitchUsed_Client(ulong _, FastBufferReader reader) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) bool flag = default(bool); ((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref flag, default(ForPrimitives)); WindowState.Instance.SetWindowState(!flag, WindowState.Instance.windowsLocked); } private static void ReceiveWindowSyncRequest(ulong clientId, FastBufferReader reader) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) if (!IsHost) { return; } byte[] array = SerializeToBytes(WindowState.Instance); int num = array.Length; FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(num + 4, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref num, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteBytesSafe(array, -1, 0); MessageManager.SendNamedMessage("ShipWindow_WindowSyncResponse", clientId, val, (NetworkDelivery)3); } catch (Exception arg) { ShipWindows.Logger.LogError((object)$"Error occurred sending window sync message:\n{arg}"); } finally { ((IDisposable)(FastBufferWriter)(ref val)).Dispose(); } } public static void RequestWindowSync() { //IL_0035: Unknown result type (might be due to invalid IL or missing references) if (!IsClient) { return; } ShipWindows.Logger.LogInfo((object)"Requesting WindowState sync..."); FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(1, (Allocator)2, -1); try { MessageManager.SendNamedMessage("ShipWindow_WindowSyncRequest", 0uL, val, (NetworkDelivery)3); } finally { ((IDisposable)(FastBufferWriter)(ref val)).Dispose(); } } public static void ReceiveWindowSync(ulong _, FastBufferReader reader) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) if (!((FastBufferReader)(ref reader)).TryBeginRead(4)) { ShipWindows.Logger.LogError((object)"Failed to read window sync message"); return; } int num = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref num, default(ForPrimitives)); if (!((FastBufferReader)(ref reader)).TryBeginRead(num)) { ShipWindows.Logger.LogError((object)"Window sync failed."); return; } ShipWindows.Logger.LogInfo((object)"Receiving WindowState sync message..."); byte[] data = new byte[num]; ((FastBufferReader)(ref reader)).ReadBytesSafe(ref data, num, 0); WindowState instance = DeserializeFromBytes<WindowState>(data); WindowState.Instance = instance; NetworkHandler.WindowSyncReceivedEvent?.Invoke(); } public static byte[] SerializeToBytes(object val) { BinaryFormatter binaryFormatter = new BinaryFormatter(); using MemoryStream memoryStream = new MemoryStream(); try { binaryFormatter.Serialize(memoryStream, val); return memoryStream.ToArray(); } catch (Exception arg) { ShipWindows.Logger.LogError((object)$"Error serializing object: \n{arg}"); return null; } } public static T DeserializeFromBytes<T>(byte[] data) { BinaryFormatter binaryFormatter = new BinaryFormatter(); using MemoryStream serializationStream = new MemoryStream(data); try { return (T)binaryFormatter.Deserialize(serializationStream); } catch (Exception arg) { ShipWindows.Logger.LogError((object)$"Error deserializing object: \n{arg}"); return default(T); } } } [Serializable] internal class WindowState { [FormerlySerializedAs("WindowsClosed")] public bool windowsClosed; [FormerlySerializedAs("WindowsLocked")] public bool windowsLocked; [FormerlySerializedAs("VolumeActive")] public bool volumeActive = true; [FormerlySerializedAs("VolumeRotation")] public float volumeRotation; public static WindowState Instance { get; set; } public WindowState() { Instance = this; } public void SetWindowState(bool closed, bool locked, bool playVoiceLine = true) { if (WindowConfig.enableShutter.Value) { ShipWindow[] array = Object.FindObjectsByType<ShipWindow>((FindObjectsSortMode)0); if (playVoiceLine && array.Length != 0) { PlayVoiceLine(closed ? 1 : 0); } ShipWindow[] array2 = array; foreach (ShipWindow shipWindow in array2) { shipWindow.SetClosed(closed); } windowsClosed = closed; windowsLocked = locked; } } public static void PlayVoiceLine(int clipIndex) { if (WindowConfig.enableShutterVoiceLines.Value) { ShipWindows.Logger.LogDebug((object)("Playing clip: " + clipIndex)); AudioClip clip = SoundLoader.VoiceLines[clipIndex]; AudioSource speakerAudioSource = StartOfRound.Instance.speakerAudioSource; speakerAudioSource.PlayOneShot(StartOfRound.Instance.disableSpeakerSFX); speakerAudioSource.clip = clip; speakerAudioSource.Play(); } } public void SetVolumeState(bool active) { GameObject outsideSkybox = ShipWindows.outsideSkybox; if (outsideSkybox != null) { outsideSkybox.SetActive(active); } volumeActive = active; } public void SetVolumeRotation(float rotation) { SpaceSkybox.Instance?.SetRotation(rotation); volumeRotation = rotation; } public void ReceiveSync() { ShipWindows.Logger.LogInfo((object)"Receiving window sync message..."); SetWindowState(windowsClosed, windowsLocked, playVoiceLine: false); SetVolumeState(volumeActive); SetVolumeRotation(volumeRotation); } } } namespace ShipWindows.MiscPatches { [HarmonyPatch(typeof(DepositItemsDesk))] public static class DepositItemsDeskPatch { [HarmonyPatch("Start")] [HarmonyPostfix] private static void AddVoiceLines(DepositItemsDesk __instance) { List<AudioClip> list = __instance.rareMicrophoneAudios.ToList(); list.AddRange(SoundLoader.RareSellCounterLines); list.RemoveAll((AudioClip clip) => (Object)(object)clip == (Object)null); __instance.rareMicrophoneAudios = list.ToArray(); List<AudioClip> list2 = __instance.microphoneAudios.ToList(); list2.AddRange(SoundLoader.CommonSellCounterLines); list2.RemoveAll((AudioClip clip) => (Object)(object)clip == (Object)null); __instance.microphoneAudios = list2.ToArray(); } } [HarmonyPatch(typeof(AutoParentToShip))] public class LightSwitchPatch { [HarmonyPatch("Awake")] [HarmonyPostfix] private static void ConstructorPostfix(AutoParentToShip __instance) { string text = ((__instance != null) ? ((Object)__instance).name : null) ?? ""; if (text.Equals("LightSwitchContainer")) { InteractTrigger val = ((__instance != null) ? ((Component)__instance).GetComponentInChildren<InteractTrigger>() : null); if (!((Object)(object)val == (Object)null) && val.hoverTip.Equals("Switch lights : [LMB]")) { val.hoverTip = "Toggle lights : [LMB]"; } } } } [HarmonyPatch(typeof(ShipBuildModeManager))] public static class ShipBuildModeManagerPatch { [HarmonyPatch("Awake")] [HarmonyPostfix] private static void ChangeLayerMasks(ShipBuildModeManager __instance) { __instance.placementMask |= 0x10000000; __instance.placementMaskAndBlockers |= 0x10000000; __instance.placeableShipObjectsMask |= 0x10000000; } } } namespace ShipWindows.EnemyPatches { [HarmonyPatch(typeof(EnemyAICollisionDetect))] public static class EnemyAICollisionDetectPatch { [HarmonyPatch("OnTriggerStay")] [HarmonyPrefix] private static bool CanCollide(EnemyAI ___mainScript, ref Collider other) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown if (!WindowConfig.enableEnemyFix.Value) { return true; } PlayerControllerB component = ((Component)other).gameObject.GetComponent<PlayerControllerB>(); PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController; if ((Object)(object)component != (Object)(object)localPlayerController) { return true; } bool flag = ___mainScript.isInsidePlayerShip == localPlayerController.isInHangarShipRoom; if (!flag) { other = new Collider(); } return flag; } } public static class EnemyMeshPatch { [HarmonyPatch(typeof(StartOfRound), "SetPlayerSafeInShip")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> EnableAllEnemyMeshes(IEnumerable<CodeInstruction> instructions) { ShipWindows.Logger.LogDebug((object)"Searching for start: ldfld bool StartOfRound::hangarDoorsClosed"); ShipWindows.Logger.LogDebug((object)"Searching for end: ret NULL"); List<CodeInstruction> list = instructions.ToList(); int num = -1; int num2 = -1; for (int i = 0; i < list.Count; i++) { CodeInstruction val = list[i]; if (num == -1 && ((object)val).ToString().Equals("ldfld bool StartOfRound::hangarDoorsClosed")) { num = i - 1; } else if (((object)val).ToString().Equals("ret NULL")) { num2 = i; break; } } if (num == -1 || num2 == -1) { ShipWindows.Logger.LogFatal((object)"Couldn't find instructions to remove!"); ShipWindows.Logger.LogFatal((object)("Start: " + num)); ShipWindows.Logger.LogFatal((object)("End: " + num2)); ShipWindows.Logger.LogFatal((object)"Please report this error!"); return list; } ShipWindows.Logger.LogDebug((object)("Found start at: " + num)); ShipWindows.Logger.LogDebug((object)("Found end at: " + num2)); list.RemoveRange(num, num2 - num); return list; } [HarmonyPatch(typeof(EnemyAI), "Start")] [HarmonyPostfix] private static void EnableEnemyMesh(EnemyAI __instance) { EnableEnemyMeshGeneric(__instance); } [HarmonyPatch(typeof(MaskedPlayerEnemy), "Start")] [HarmonyPostfix] private static void EnableEnemyMesh(MaskedPlayerEnemy __instance) { EnableEnemyMeshGeneric((EnemyAI)(object)__instance); } private static void EnableEnemyMeshGeneric(EnemyAI enemyAI) { enemyAI.EnableEnemyMesh(true, false); } } } namespace ShipWindows.Components { [AddComponentMenu("TestAccount666/ShipWindows/CelestialTintSkyboxRotator")] public class CelestialTintSkyboxRotator : MonoBehaviour { [SerializeField] private Volume? skyVolume; private PhysicallyBasedSky? _sky; private void Update() { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)skyVolume == (Object)null || !Object.op_Implicit((Object)(object)skyVolume)) { return; } if ((Object)(object)_sky == (Object)null) { skyVolume.profile.TryGet<PhysicallyBasedSky>(ref _sky); return; } if (((VolumeParameter<Vector3>)(object)_sky.spaceRotation).value.y > 360f) { Vector3Parameter spaceRotation = _sky.spaceRotation; ((VolumeParameter<Vector3>)(object)spaceRotation).value = ((VolumeParameter<Vector3>)(object)spaceRotation).value - new Vector3(0f, 360f, 0f); } if (((VolumeParameter<Vector3>)(object)_sky.spaceRotation).value.y < 0f) { Vector3Parameter spaceRotation2 = _sky.spaceRotation; ((VolumeParameter<Vector3>)(object)spaceRotation2).value = ((VolumeParameter<Vector3>)(object)spaceRotation2).value + new Vector3(0f, 360f, 0f); } Vector3Parameter spaceRotation3 = _sky.spaceRotation; ((VolumeParameter<Vector3>)(object)spaceRotation3).value = ((VolumeParameter<Vector3>)(object)spaceRotation3).value + new Vector3(0f, Time.deltaTime * WindowConfig.skyboxRotateSpeed.Value, 0f); } } public class CustomAnimatedObjectTrigger : AnimatedObjectTrigger { private static readonly int _OnAnimatorHash = Animator.StringToHash("on"); public void TriggerAnimation() { if (base.triggerByChance) { ((AnimatedObjectTrigger)this).InitializeRandomSeed(); if ((double)base.triggerRandom.Next(100) >= (double)base.chancePercent) { return; } } if (base.isBool) { Debug.Log((object)$"Triggering animated object trigger bool: setting to {!base.boolValue}"); base.boolValue = !base.boolValue; if ((Object)(object)base.triggerAnimator != (Object)null) { base.triggerAnimator.SetBool(base.animationString, base.boolValue); } if ((Object)(object)base.triggerAnimatorB != (Object)null) { base.triggerAnimatorB.SetBool(_OnAnimatorHash, base.boolValue); } } else if ((Object)(object)base.triggerAnimator != (Object)null) { base.triggerAnimator.SetTrigger(base.animationString); } ((AnimatedObjectTrigger)this).SetParticleBasedOnBoolean(); ((AnimatedObjectTrigger)this).PlayAudio(base.boolValue, false); base.localPlayerTriggered = true; if (base.isBool) { ((UnityEvent<bool>)(object)base.onTriggerBool).Invoke(base.boolValue); ((AnimatedObjectTrigger)this).UpdateAnimServerRpc(base.boolValue, false, (int)StartOfRound.Instance.localPlayerController.playerClientId); } else { ((AnimatedObjectTrigger)this).UpdateAnimTriggerServerRpc(); } } } [AddComponentMenu("TestAccount666/ShipWindows/ShipWindow")] public class ShipWindow : MonoBehaviour { public static string[] window3DisabledList = new string[2] { "UnderbellyMachineParts", "NurbsPath.001" }; public int id; private GameObject? _oldPostersObject; private static readonly int _ClosedId = Animator.StringToHash("Closed"); public void Start() { OnStart(); } public void OnDestroy() { switch (id) { case 1: break; case 2: ObjectReplacer.Restore(_oldPostersObject); break; case 3: { string[] array = window3DisabledList; foreach (string text in array) { GameObject val = GameObject.Find("Environment/HangarShip/" + text); if (val != null) { val.gameObject.SetActive(true); } } break; } } } public void SetClosed(bool closed) { Animator component = ((Component)this).GetComponent<Animator>(); if (component != null) { component.SetBool(_ClosedId, closed); } } public void OnStart() { switch (id) { case 1: break; case 2: { if (WindowConfig.dontMovePosters.Value || ShipMods.Enabled) { break; } GameObject val3 = ShipWindows.mainAssetBundle.LoadAsset<GameObject>("Assets/LethalCompany/Mods/plugins/ShipWindows/ShipPosters.prefab"); if (!((Object)(object)val3 == (Object)null)) { GameObject? newShipInside2 = ShipReplacer.newShipInside; Transform val4 = ((newShipInside2 != null) ? newShipInside2.transform.parent.Find("Plane.001") : null); if (!((Object)(object)val4 == (Object)null)) { _oldPostersObject = ((Component)val4).gameObject; GameObject toObj = ObjectReplacer.Replace(_oldPostersObject, val3); ObjectReplacer.ReplaceMaterial(_oldPostersObject, toObj); } } break; } case 3: { string[] array = window3DisabledList; foreach (string text in array) { GameObject val = GameObject.Find("Environment/HangarShip/" + text); if (val != null) { val.gameObject.SetActive(false); } } if (WindowConfig.disableUnderLights.Value) { GameObject? newShipInside = ShipReplacer.newShipInside; Transform val2 = ((newShipInside != null) ? newShipInside.transform.Find("WindowContainer/Window3/Lights") : null); if (val2 != null) { ((Component)val2).gameObject.SetActive(false); } } break; } case 4: break; } } } [AddComponentMenu("TestAccount666/ShipWindows/ShipWindowShutterSwitch")] public class ShipWindowShutterSwitch : NetworkBehaviour { public InteractTrigger? interactTrigger; public Animator? animator; private static readonly int _OnHash = Animator.StringToHash("on"); private bool _destroy; [SerializeField] private GameObject? scanNodeObject; public override void OnNetworkSpawn() { if (!_destroy) { ((NetworkBehaviour)this).OnNetworkSpawn(); ((MonoBehaviour)this).StartCoroutine(AddSwitchListener()); ((MonoBehaviour)this).StartCoroutine(UpdateScanNodeOnce()); ((MonoBehaviour)this).StartCoroutine(SyncInteractable()); } } public override void OnNetworkDespawn() { _destroy = true; ((NetworkBehaviour)this).OnNetworkDespawn(); } public override void OnDestroy() { _destroy = true; ((NetworkBehaviour)this).OnDestroy(); } private IEnumerator AddSwitchListener() { yield return (object)new WaitUntil((Func<bool>)(() => (Object)(object)interactTrigger != (Object)null)); ((UnityEvent<PlayerControllerB>)(object)interactTrigger?.onInteract).AddListener((UnityAction<PlayerControllerB>)PlayerUsedSwitch); ShipWindows.Logger.LogDebug((object)"Added listener! :)"); } private IEnumerator SyncInteractable() { bool currentlyLocked = WindowState.Instance.windowsLocked; yield return (object)new WaitUntil((Func<bool>)(() => _destroy || WindowState.Instance.windowsLocked != currentlyLocked)); if (_destroy) { yield break; } yield return (object)new WaitUntil((Func<bool>)(() => _destroy || (Object)(object)interactTrigger != (Object)null)); if (!_destroy) { if ((Object)(object)interactTrigger == (Object)null) { throw new Exception("Could not find InteractTrigger!"); } interactTrigger.interactable = !WindowState.Instance.windowsLocked; ((MonoBehaviour)this).StartCoroutine(SyncInteractable()); } } public void PlayerUsedSwitch(PlayerControllerB playerControllerB) { if (!((Object)(object)animator == (Object)null)) { bool @bool = animator.GetBool(_OnHash); NetworkHandler.WindowSwitchUsed(@bool); UpdateScanNode(); } } private IEnumerator UpdateScanNodeOnce() { yield return (object)new WaitUntil((Func<bool>)(() => (Object)(object)scanNodeObject != (Object)null)); ShipWindows.Logger.LogDebug((object)"Updating Scan Node! :>"); UpdateScanNode(); } private void UpdateScanNode() { if ((Object)(object)scanNodeObject == (Object)null) { ShipWindows.Logger.LogError((object)"Couldn't find ScanNode object for ShutterSwitch???"); } else if (scanNodeObject.activeSelf != WindowConfig.enableShutterSwitchScanNode.Value) { scanNodeObject.SetActive(WindowConfig.enableShutterSwitchScanNode.Value); } } } [AddComponentMenu("TestAccount666/ShipWindows/ShipWindowSpawner")] public class ShipWindowSpawner : MonoBehaviour { [FormerlySerializedAs("ID")] public int id; public void Start() { OnStart(); } public void OnDestroy() { ShipReplacer.ReplaceDebounced(replace: false); } public void OnStart() { ShipReplacer.ReplaceDebounced(replace: true); } } [AddComponentMenu("TestAccount666/ShipWindows/ SpaceSkybox")] public class SpaceSkybox : MonoBehaviour { private HDRISky? _sky; private Transform? _starSphere; public static SpaceSkybox Instance { get; private set; } public void Awake() { Instance = this; } public void Start() { switch (WindowConfig.spaceOutsideSetting.Value) { case SpaceOutside.OTHER_MODS: break; case SpaceOutside.SPACE_HDRI: { Volume component = ((Component)this).GetComponent<Volume>(); if (component != null) { VolumeProfile profile = component.profile; if (profile != null) { profile.TryGet<HDRISky>(ref _sky); } } break; } case SpaceOutside.BLACK_AND_STARS: _starSphere = ((Component)this).transform; break; default: throw new ArgumentOutOfRangeException(WindowConfig.spaceOutsideSetting.Value.ToString() + " is not a valid option!"); } } public void Update() { //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) switch (WindowConfig.spaceOutsideSetting.Value) { case SpaceOutside.OTHER_MODS: break; case SpaceOutside.SPACE_HDRI: if (!((Object)(object)_sky == (Object)null)) { ClampedFloatParameter rotation = ((SkySettings)_sky).rotation; ((VolumeParameter<float>)(object)rotation).value = ((VolumeParameter<float>)(object)rotation).value + Time.deltaTime * WindowConfig.skyboxRotateSpeed.Value; if (((VolumeParameter<float>)(object)((SkySettings)_sky).rotation).value >= 360f) { ((VolumeParameter<float>)(object)((SkySettings)_sky).rotation).value = 0f; } WindowState.Instance.volumeRotation = ((VolumeParameter<float>)(object)((SkySettings)_sky).rotation).value; } break; case SpaceOutside.BLACK_AND_STARS: if (!((Object)(object)_starSphere == (Object)null)) { _starSphere.Rotate(Vector3.forward * (Time.deltaTime * WindowConfig.skyboxRotateSpeed.Value)); WindowState.Instance.volumeRotation = _starSphere.eulerAngles.y; } break; default: throw new ArgumentOutOfRangeException(WindowConfig.spaceOutsideSetting.Value.ToString() + " is not a valid option!"); } } public void SetRotation(float r) { //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) switch (WindowConfig.spaceOutsideSetting.Value) { case SpaceOutside.OTHER_MODS: break; case SpaceOutside.SPACE_HDRI: if (!((Object)(object)_sky == (Object)null)) { float num = r % 360f; if (num < 0f) { num += 360f; } ((VolumeParameter<float>)(object)((SkySettings)_sky).rotation).value = num; WindowState.Instance.volumeRotation = ((VolumeParameter<float>)(object)((SkySettings)_sky).rotation).value; } break; case SpaceOutside.BLACK_AND_STARS: if (!((Object)(object)_starSphere == (Object)null)) { _starSphere.rotation = Quaternion.identity; _starSphere.Rotate(Vector3.forward * r); WindowState.Instance.volumeRotation = _starSphere.eulerAngles.y; } break; default: throw new ArgumentOutOfRangeException(WindowConfig.spaceOutsideSetting.Value.ToString() + " is not a valid option!"); } } public void SetSkyboxTexture(Texture? skybox) { switch (WindowConfig.spaceOutsideSetting.Value) { case SpaceOutside.OTHER_MODS: break; case SpaceOutside.SPACE_HDRI: if (!((Object)(object)_sky == (Object)null)) { ((VolumeParameter<Texture>)(object)_sky.hdriSky).value = skybox; } break; case SpaceOutside.BLACK_AND_STARS: break; default: throw new ArgumentOutOfRangeException(WindowConfig.spaceOutsideSetting.Value.ToString() + " is not a valid option!"); } } } public class WindowLayerManager : MonoBehaviour { private void Start() { if (WindowConfig.vanillaMode.Value) { SetLayer(enemySeeThrough: false); } else { WindowConfig.allowEnemyTriggerThroughWindows.SettingChanged += UpdateLayer; } } private void OnDestroy() { WindowConfig.allowEnemyTriggerThroughWindows.SettingChanged -= UpdateLayer; } private void UpdateLayer(object o, EventArgs eventArgs) { SetLayer(WindowConfig.allowEnemyTriggerThroughWindows.Value); } private void SetLayer(bool enemySeeThrough) { ((Component)this).gameObject.layer = (enemySeeThrough ? 28 : 8); } } } namespace ShipWindows.Compatibility { internal static class CelestialTint { private static GameObject? _skyGameObject; private static bool _checkFor4K = true; public static bool Enabled { get; private set; } private static bool Initialize() { if (Enabled) { return false; } Enabled = true; if (WindowConfig.celestialTintOverrideSpace.Value && WindowConfig.spaceOutsideSetting.Value != SpaceOutside.SPACE_HDRI) { ShipWindows.Logger.LogFatal((object)"You have 'CelestialTintOverrideSpace' activated, but 'SpaceOutside' is not set to 'SPACE_HDRI'. This will do nothing!"); return true; } WindowConfig.celestialTintOverrideSpace.SettingChanged += delegate { CheckSceneState(); }; SceneManager.sceneLoaded += delegate { if (!((Object)(object)StartOfRound.Instance == (Object)null)) { ((MonoBehaviour)StartOfRound.Instance).StartCoroutine(CheckSceneStateDelayed()); } }; SceneManager.sceneUnloaded += delegate { if (!((Object)(object)StartOfRound.Instance == (Object)null)) { ((MonoBehaviour)StartOfRound.Instance).StartCoroutine(CheckSceneStateDelayed()); } }; return true; } [HarmonyPatch(typeof(CelestialTint), "CheckSceneState")] [HarmonyPostfix] private static void CelestialTintCheckSceneState() { CheckSceneState(); } private static IEnumerator CheckSceneStateDelayed() { yield return (object)new WaitForEndOfFrame(); yield return (object)new WaitForEndOfFrame(); CheckSceneState(); } private static void CheckSceneState() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) if (!WindowConfig.celestialTintOverrideSpace.Value) { DestroySkyOverride(); return; } if (SceneManager.sceneCount == 1) { Scene activeScene = SceneManager.GetActiveScene(); if (((Scene)(ref activeScene)).name == "SampleSceneRelay") { LoadSkyOverride(); return; } } DestroySkyOverride(); } private static void DestroySkyOverride() { if (!((Object)(object)_skyGameObject == (Object)null)) { Object.Destroy((Object)(object)_skyGameObject); _skyGameObject = null; } } private static void LoadSkyOverride() { if ((Object)(object)_skyGameObject != (Object)null) { DestroySkyOverride(); } GameObject val = ShipWindows.mainAssetBundle.LoadAsset<GameObject>("Assets/LethalCompany/Mods/plugins/ShipWindows/CelestialTint/CelestialTintSkyOverridePrefab.prefab"); _skyGameObject = Object.Instantiate<GameObject>(val); GameObject val2 = GameObject.Find("Systems/Rendering/StarsSphere"); if ((Object)(object)val2 != (Object)null && Object.op_Implicit((Object)(object)val2)) { val2.SetActive(false); } CheckFor4KTexture(); if ((Object)(object)ShipWindow4K.Skybox4K == (Object)null) { ShipWindows.Logger.LogDebug((object)"Did not find Skybox4k! (This is not an error, unless you installed the 4k extension!)"); } else { OverrideSpaceEmissionTexture(); } } private static void OverrideSpaceEmissionTexture() { ShipWindows.Logger.LogDebug((object)"Overriding texture now!"); if ((Object)(object)_skyGameObject == (Object)null) { ShipWindows.Logger.LogDebug((object)"Nevermind!"); return; } Volume component = _skyGameObject.GetComponent<Volume>(); PhysicallyBasedSky val = default(PhysicallyBasedSky); component.profile.TryGet<PhysicallyBasedSky>(ref val); if ((Object)(object)val == (Object)null) { ShipWindows.Logger.LogError((object)"Couldn't find PhysicallyBasedSky in celestial tint sky override!"); return; } ((VolumeParameter<Texture>)(object)val.spaceEmissionTexture).value = ShipWindow4K.Skybox4K; ShipWindows.Logger.LogDebug((object)"Loaded 4k Skybox!"); } private static void CheckFor4KTexture() { if (_checkFor4K) { _checkFor4K = false; ShipWindow4K.TryToLoad(); } } } internal class CompatibleDependencyAttribute : BepInDependency { public Type handler; public Version? versionRequired; public CompatibleDependencyAttribute(string guid, Type handlerType) : base(guid, (DependencyFlags)2) { handler = handlerType; } public CompatibleDependencyAttribute(string guid, string versionRequired, Type handlerType) : base(guid, (DependencyFlags)2) { handler = handlerType; this.versionRequired = new Version(versionRequired); } public static void Init(BaseUnityPlugin source) { IEnumerable<CompatibleDependencyAttribute> customAttributes = ((MemberInfo)((object)source).GetType()).GetCustomAttributes<CompatibleDependencyAttribute>(); foreach (CompatibleDependencyAttribute item in customAttributes) { if (!Chainloader.PluginInfos.TryGetValue(((BepInDependency)item).DependencyGUID, out var value)) { continue; } if (item.versionRequired != null && item.versionRequired.CompareTo(value.Metadata.Version) > 0) { ShipWindows.Logger.LogInfo((object)$"Found compatible mod, but it does not meet version requirements: {((BepInDependency)item).DependencyGUID} {value.Metadata.Version}"); continue; } ShipWindows.Logger.LogInfo((object)$"Found compatible mod: {((BepInDependency)item).DependencyGUID} {value.Metadata.Version}"); if (!(bool)item.handler.GetMethod("Initialize", BindingFlags.Static | BindingFlags.NonPublic)?.Invoke(null, null)) { ShipWindows.Logger.LogInfo((object)$"Found compatible mod, but patches have already been applied: {((BepInDependency)item).DependencyGUID} {value.Metadata.Version}"); continue; } Harmony? harmony = ShipWindows.Harmony; if (harmony != null) { harmony.PatchAll(item.handler); } item.handler = null; } } } internal static class LethalExpansion { public static bool Enabled { get; private set; } private static bool Initialize() { if (Enabled) { return false; } Enabled = true; return true; } [HarmonyPostfix] [HarmonyPatch(typeof(StartOfRound), "Start")] private static void Patch_RoundStart() { //IL_003c: Unknown result type (might be due to invalid IL or missing references) if (Enabled) { GameObject val = GameObject.Find("terrainfixer"); if (!((Object)(object)val == (Object)null)) { val.transform.position = new Vector3(0f, -5000f, 0f); } } } } public class LobbyCompatibility { public static bool Enabled { get; private set; } private static bool Initialize() { if (Enabled) { return false; } Enabled = true; ShipWindows.Logger.LogInfo((object)"Found LobbyCompatibility Mod, initializing support :)"); PluginHelper.RegisterPlugin("TestAccount666.ShipWindows", new Version("1.11.0"), (CompatibilityLevel)((!WindowConfig.vanillaMode.Value) ? 2 : 0), (VersionStrictness)2); return true; } } internal static class ShipColors { public static bool Enabled { get; private set; } private static bool Initialize() { if (Enabled) { return false; } Enabled = true; return true; } public static void RefreshColors() { Subscribers.StartCustomizer(); } } public class ShipMods { public static bool Enabled { get; private set; } private static bool Initialize() { if (Enabled) { return false; } Enabled = true; return true; } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(stri