using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization.Formatters.Binary; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using OpenTheNoor.Config; using OpenTheNoor.Managers; using Unity.Collections; using Unity.Netcode; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("OpenTheNoor")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("OpenTheNoor")] [assembly: AssemblyCopyright("Copyright © 2025")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("b58bef91-7e8e-4613-a41d-797b02584ab7")] [assembly: AssemblyFileVersion("1.1.6")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.1.6.0")] namespace OpenTheNoor.Patches { [HarmonyPatch(typeof(StartOfRound))] internal class StartOfRoundPatch { [HarmonyPostfix] [HarmonyPatch("Start")] private static void spawnNetManager(StartOfRound __instance) { if (((NetworkBehaviour)__instance).IsHost) { Object.Instantiate(OpenTheNoorBase.Instance.netManagerPrefab).GetComponent().Spawn(false); } } } } namespace OpenTheNoor.Managers { public class NetworkManagerOpenTheNoor : NetworkBehaviour { public static NetworkManagerOpenTheNoor Instance; private void Awake() { if ((Object)(object)Instance == (Object)null) { Instance = this; } } [ServerRpc(RequireOwnership = false)] public void MakeOpenTheNoorNoiseServerRpc(NetworkBehaviourReference __door) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) MakeOpenTheNoorNoiseClientRpc(__door); } [ClientRpc] public void MakeOpenTheNoorNoiseClientRpc(NetworkBehaviourReference __door) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) AudioSource doorLockSFX = ((DoorLock)NetworkBehaviourReference.op_Implicit(__door)).doorLockSFX; if ((Object)(object)doorLockSFX != (Object)null) { PlayerControllerBPatch.playOpenTheNoorNoise(doorLockSFX, OpenTheNoorBase.SoundFX.ToArray()); } } } } namespace OpenTheNoor.Config { [Serializable] public class Config : SyncedInstance { private const float VOLUME_DEFAULT = 0.5f; private const bool PLAY_FOR_ALL_PLAYERS_DEFAULT = true; private const float PLAY_SOUND_CHANCE_DEFAULT = 100f; public float VOLUME; public bool PLAY_FOR_ALL_PLAYERS; public float PLAY_SOUND_CHANCE; public Config(ConfigFile cfg) { InitInstance(this); VOLUME = cfg.Bind("ClientSide", "volume", 0.5f, "The volume that the sound will play at for you.").Value; PLAY_FOR_ALL_PLAYERS = cfg.Bind("ServerSide", "playForAllPlayers", true, "Play the sound for other players.\nThis will allow all players to hear the sound when another player attempts to open a door.").Value; PLAY_SOUND_CHANCE = cfg.Bind("ServerSide", "playSoundChance", 100f, "The percentage chance that the sound will play.").Value; } public static void RequestSync() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) if (!SyncedInstance.IsClient) { return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(SyncedInstance.IntSize, (Allocator)2, -1); try { SyncedInstance.MessageManager.SendNamedMessage("Kolton12O.OpenTheNoor_OnRequestConfigSync", 0uL, val, (NetworkDelivery)3); } finally { ((IDisposable)(FastBufferWriter)(ref val)).Dispose(); } } public static void OnRequestSync(ulong clientId, FastBufferReader _) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) if (!SyncedInstance.IsHost) { return; } OpenTheNoorBase.Instance.mls.LogInfo((object)$"Config sync request received from client: {clientId}"); byte[] array = SyncedInstance.SerializeToBytes(SyncedInstance.Instance); int num = array.Length; FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(num + SyncedInstance.IntSize, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe(ref num, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteBytesSafe(array, -1, 0); SyncedInstance.MessageManager.SendNamedMessage("Kolton12O.OpenTheNoor_OnReceiveConfigSync", clientId, val, (NetworkDelivery)3); } catch (Exception arg) { OpenTheNoorBase.Instance.mls.LogInfo((object)$"Error occurred syncing config with client: {clientId}\n{arg}"); } finally { ((IDisposable)(FastBufferWriter)(ref val)).Dispose(); } } public static void OnReceiveSync(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(SyncedInstance.IntSize)) { OpenTheNoorBase.Instance.mls.LogError((object)"Config sync error: Could not begin reading buffer."); return; } int num = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num, default(ForPrimitives)); if (!((FastBufferReader)(ref reader)).TryBeginRead(num)) { OpenTheNoorBase.Instance.mls.LogError((object)"Config sync error: Host could not sync."); return; } byte[] data = new byte[num]; ((FastBufferReader)(ref reader)).ReadBytesSafe(ref data, num, 0); SyncedInstance.SyncInstance(data); OpenTheNoorBase.Instance.mls.LogInfo((object)"Successfully synced config with host."); } } [Serializable] public class SyncedInstance { [NonSerialized] protected static int IntSize = 4; internal static CustomMessagingManager MessageManager => NetworkManager.Singleton.CustomMessagingManager; internal static bool IsClient => NetworkManager.Singleton.IsClient; internal static bool IsHost => NetworkManager.Singleton.IsHost; public static T Default { get; private set; } public static T Instance { get; private set; } public static bool Synced { get; internal set; } protected void InitInstance(T instance) { Default = instance; Instance = instance; IntSize = 4; } internal static void SyncInstance(byte[] data) { Instance = DeserializeFromBytes(data); Synced = true; } internal static void RevertSync() { Instance = Default; Synced = false; } public static byte[] SerializeToBytes(T val) { BinaryFormatter binaryFormatter = new BinaryFormatter(); using MemoryStream memoryStream = new MemoryStream(); try { binaryFormatter.Serialize(memoryStream, val); return memoryStream.ToArray(); } catch (Exception arg) { OpenTheNoorBase.Instance.mls.LogError((object)$"Error serializing instance: {arg}"); return null; } } public static T DeserializeFromBytes(byte[] data) { BinaryFormatter binaryFormatter = new BinaryFormatter(); using MemoryStream serializationStream = new MemoryStream(data); try { return (T)binaryFormatter.Deserialize(serializationStream); } catch (Exception arg) { OpenTheNoorBase.Instance.mls.LogError((object)$"Error deserializing instance: {arg}"); return default(T); } } } [HarmonyPatch(typeof(GameNetworkManager))] internal class GameNetworkManagerPatch { [HarmonyPostfix] [HarmonyPatch("Start")] private static void AddToPrefabs(ref GameNetworkManager __instance) { ((Component)__instance).GetComponent().AddNetworkPrefab(OpenTheNoorBase.Instance.netManagerPrefab); } [HarmonyPostfix] [HarmonyPatch(typeof(GameNetworkManager), "StartDisconnect")] public static void PlayerLeave() { SyncedInstance.RevertSync(); } } [HarmonyPatch(typeof(PlayerControllerB))] internal class PlayerControllerBPatch { [HarmonyPatch(typeof(PlayerControllerB), "Interact_performed")] [HarmonyPrefix] private static void onInteract(PlayerControllerB __instance) { //IL_0077: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)__instance.hoveringOverTrigger != (Object)null)) { return; } DoorLock componentInParent = ((Component)__instance.hoveringOverTrigger).GetComponentInParent(); if (!((Object)(object)componentInParent != (Object)null) || !componentInParent.isLocked) { return; } float num = Math.Max(0f, Math.Min(100f, SyncedInstance.Instance.PLAY_SOUND_CHANCE)); if (!(new Random().NextDouble() * 100.0 <= (double)num)) { return; } if (SyncedInstance.Instance.PLAY_FOR_ALL_PLAYERS) { NetworkManagerOpenTheNoor.Instance.MakeOpenTheNoorNoiseServerRpc(NetworkBehaviourReference.op_Implicit((NetworkBehaviour)(object)componentInParent)); return; } AudioSource doorLockSFX = componentInParent.doorLockSFX; if ((Object)(object)doorLockSFX != (Object)null) { playOpenTheNoorNoise(doorLockSFX, OpenTheNoorBase.SoundFX.ToArray()); } } [HarmonyPostfix] [HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")] public static void InitializeLocalPlayer() { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown if (SyncedInstance.IsHost) { SyncedInstance.MessageManager.RegisterNamedMessageHandler("Kolton12O.OpenTheNoor_OnRequestConfigSync", new HandleNamedMessageDelegate(Config.OnRequestSync)); SyncedInstance.Synced = true; } else { SyncedInstance.Synced = false; SyncedInstance.MessageManager.RegisterNamedMessageHandler("Kolton12O.OpenTheNoor_OnReceiveConfigSync", new HandleNamedMessageDelegate(Config.OnReceiveSync)); Config.RequestSync(); } } public static void playOpenTheNoorNoise(AudioSource __audioSource, AudioClip[] sounds) { RoundManager.PlayRandomClip(__audioSource, sounds, true, SyncedInstance.Default.VOLUME, 0, 1000); } } [BepInPlugin("Kolton12O.OpenTheNoor", "OpenTheNoor", "1.1.6")] public class OpenTheNoorBase : BaseUnityPlugin { public const string MOD_GUID = "Kolton12O.OpenTheNoor"; public const string MOD_NAME = "OpenTheNoor"; public const string MOD_VERSION = "1.1.6"; private readonly Harmony harmony = new Harmony("Kolton12O.OpenTheNoor"); public static OpenTheNoorBase Instance; internal ManualLogSource mls; internal static List SoundFX; internal static AssetBundle Bundle; public GameObject netManagerPrefab; public static Config Config { get; internal set; } private void Awake() { if ((Object)(object)Instance == (Object)null) { Instance = this; } mls = Logger.CreateLogSource("Kolton12O.OpenTheNoor"); Config = new Config(((BaseUnityPlugin)this).Config); Type[] types = Assembly.GetExecutingAssembly().GetTypes(); for (int i = 0; i < types.Length; i++) { MethodInfo[] methods = types[i].GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (methodInfo.GetCustomAttributes(typeof(RuntimeInitializeOnLoadMethodAttribute), inherit: false).Length != 0) { methodInfo.Invoke(null, null); } } } mls.LogInfo((object)"Open The Noor has awaken!"); Bundle = AssetBundle.LoadFromFile(((BaseUnityPlugin)Instance).Info.Location.TrimEnd("OpenTheNoor.dll".ToCharArray()) + "openthenoor"); SoundFX = new List(); if ((Object)(object)Bundle != (Object)null) { mls.LogInfo((object)"Successfully loaded asset bundle! :)"); netManagerPrefab = Bundle.LoadAsset("Assets/OpenTheNoor/NetworkManagerOpenTheNoor.prefab"); netManagerPrefab.AddComponent(); SoundFX = Bundle.LoadAllAssets().ToList(); } else { mls.LogError((object)"Failed to load asset bundle! :("); } harmony.PatchAll(); } } }