using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Numerics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using CSync.Extensions; using CSync.Lib; using EntranceIntangibility.patch; using GameNetcodeStuff; using HarmonyLib; using Microsoft.CodeAnalysis; using Unity.Netcode; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("qwcan")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+16ee622a592f9e8e1997eebbe2551cc594dc6ddc")] [assembly: AssemblyProduct("EntranceIntagibility")] [assembly: AssemblyTitle("EntranceIntangibility")] [assembly: AssemblyVersion("1.0.0.0")] [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.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace EntranceIntangibility { public class EntranceConfig : SyncedConfig2 { [SyncedEntryField] public SyncedEntry IntangibilityDuration; public EntranceConfig(ConfigFile configFile) : base("EntranceIntangibility") { IntangibilityDuration = SyncedBindingExtensions.BindSyncedEntry(configFile, "Settings", "IntangibilityDuration", 2.5f, "How long the player is intangible for after entering or leaving the facility, in seconds."); ConfigManager.Register((SyncedConfig2)this); } } [BepInPlugin("EntranceIntangibility", "EntranceIntangibility", "1.2.0")] [BepInDependency("com.sigurd.csync", "5.0.1")] public class Plugin : BaseUnityPlugin { public const string GUID = "EntranceIntangibility"; private readonly Harmony _harmony = new Harmony("EntranceIntangibility"); internal static EntranceConfig Config; public Dictionary LastEnteredDoor = new Dictionary(); public static Plugin Instance { get; set; } public static ManualLogSource Log => ((BaseUnityPlugin)Instance).Logger; public Plugin() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown Instance = this; } private void Awake() { Config = new EntranceConfig(((BaseUnityPlugin)this).Config); Log.LogInfo((object)"Applying patches..."); ApplyPluginPatch(); Log.LogInfo((object)"Patches applied"); } public bool IsIntangible(int playerObj) { if (!LastEnteredDoor.TryGetValue(playerObj, out var value)) { return false; } return (float)(DateTimeOffset.Now.ToUnixTimeMilliseconds() - value) < Config.IntangibilityDuration.Value * 1000f; } private void ApplyPluginPatch() { _harmony.PatchAll(typeof(EnemyAIPatch)); _harmony.PatchAll(typeof(PlayerControllerPatch)); _harmony.PatchAll(typeof(EntranceTeleportPatch)); _harmony.PatchAll(typeof(ShipTeleporterPatch)); _harmony.PatchAll(typeof(NutcrackerAIPatch)); _harmony.PatchAll(typeof(NetworkPatch)); } } } namespace EntranceIntangibility.patch { [HarmonyPatch(typeof(EnemyAI))] public class EnemyAIPatch { [HarmonyPostfix] [HarmonyPatch("PlayerIsTargetable")] private static void PlayerIsTargetablePatch(EnemyAI __instance, PlayerControllerB playerScript, ref bool __result) { if (Plugin.Instance.IsIntangible((int)playerScript.playerClientId)) { __result = false; } } [HarmonyPostfix] [HarmonyPatch("GetAllPlayersInLineOfSight")] private static void GetAllPlayersInLineOfSightPostfixPatch(EnemyAI __instance, float width, int range, Transform eyeObject, float proximityCheck, ref PlayerControllerB[] __result) { __result = __result?.Where((PlayerControllerB player) => !Plugin.Instance.IsIntangible((int)player.playerClientId)).ToArray(); } [HarmonyPostfix] [HarmonyPatch("CheckLineOfSightForPlayer")] private static void CheckLineOfSightForPlayerPostfixPatch(EnemyAI __instance, float width, int range, int proximityAwareness, ref PlayerControllerB __result) { if (Object.op_Implicit((Object)(object)__result) && Plugin.Instance.IsIntangible((int)__result.playerClientId)) { __result = null; } } [HarmonyPostfix] [HarmonyPatch("CheckLineOfSightForClosestPlayer")] private static void CheckLineOfSightForClosestPlayerPostfixPatch(EnemyAI __instance, float width, int range, int proximityAwareness, ref PlayerControllerB __result) { if (Object.op_Implicit((Object)(object)__result) && Plugin.Instance.IsIntangible((int)__result.playerClientId)) { __result = null; } } } [HarmonyPatch(typeof(EntranceTeleport))] public class EntranceTeleportPatch { [HarmonyPatch("TeleportPlayerClientRpc")] [HarmonyPrefix] private static void TeleportPlayerClientRpcPatch(EntranceTeleport __instance, int playerObj) { Plugin.Log.LogInfo((object)$"Player {playerObj} entered the facility (ClientRPC), giving them intangibility for {Plugin.Config.IntangibilityDuration.Value} seconds: {DateTimeOffset.Now.ToUnixTimeMilliseconds()}"); Plugin.Instance.LastEnteredDoor[playerObj] = DateTimeOffset.Now.ToUnixTimeMilliseconds(); } [HarmonyPatch("TeleportPlayerServerRpc")] [HarmonyPrefix] private static void TeleportPlayerServerRpcPatch(EntranceTeleport __instance, int playerObj) { Plugin.Log.LogInfo((object)$"Player {playerObj} entered the facility (ServerRPC), giving them intangibility for {Plugin.Config.IntangibilityDuration.Value} seconds: {DateTimeOffset.Now.ToUnixTimeMilliseconds()}"); Plugin.Instance.LastEnteredDoor[playerObj] = DateTimeOffset.Now.ToUnixTimeMilliseconds(); } } public class NetworkPatch { [HarmonyPatch(typeof(NetworkManager))] internal static class NetworkPrefabPatch2 { [HarmonyPostfix] [HarmonyPatch("SetSingleton")] private static void RegisterPrefab() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("EntranceIntangibility Prefab"); ((Object)val).hideFlags = (HideFlags)(((Object)val).hideFlags | 0x3D); Object.DontDestroyOnLoad((Object)(object)val); NetworkObject obj = val.AddComponent(); FieldInfo field = typeof(NetworkObject).GetField("GlobalObjectIdHash", BindingFlags.Instance | BindingFlags.NonPublic); field.SetValue(obj, GetHash("EntranceIntangibility")); NetworkManager.Singleton.PrefabHandler.AddNetworkPrefab(val); static uint GetHash(string value) { return value?.Aggregate(17u, (uint current, char c) => (current * 31) ^ c) ?? 0; } } } } [HarmonyPatch(typeof(NutcrackerEnemyAI))] public class NutcrackerAIPatch { [HarmonyPostfix] [HarmonyPatch("CheckLineOfSightForLocalPlayer")] private static void CheckLineOfSightForLocalPlayerPostfixPatch(NutcrackerEnemyAI __instance, ref bool __result) { if (__result && Plugin.Instance.IsIntangible((int)GameNetworkManager.Instance.localPlayerController.playerClientId)) { __result = false; } } } [HarmonyPatch(typeof(PlayerControllerB))] public class PlayerControllerPatch { [HarmonyPrefix] [HarmonyPatch("DamagePlayer")] private static bool DamagePlayerPrefixPatch(PlayerControllerB __instance, int damageNumber, CauseOfDeath causeOfDeath, bool fallDamage, Vector3 force) { if (Plugin.Instance.IsIntangible((int)__instance.playerClientId)) { return false; } return true; } [HarmonyPostfix] [HarmonyPatch("AllowPlayerDeath")] private static void AllowPlayerDeathPatch(PlayerControllerB __instance, ref bool __result) { if (Plugin.Instance.IsIntangible((int)__instance.playerClientId)) { __result = false; } } } [HarmonyPatch(typeof(ShipTeleporter))] public class ShipTeleporterPatch { [HarmonyPostfix] [HarmonyPatch(typeof(ShipTeleporter), "TeleportPlayerOutWithInverseTeleporter")] private static void SetTeleportPlayerOutWithInverseTeleporter(ShipTeleporter __instance, ref int playerObj) { Plugin.Log.LogInfo((object)$"Player {playerObj} inverse teleported, giving them intangibility for {Plugin.Config.IntangibilityDuration.Value} seconds: {DateTimeOffset.Now.ToUnixTimeMilliseconds()}"); Plugin.Instance.LastEnteredDoor[playerObj] = DateTimeOffset.Now.ToUnixTimeMilliseconds(); } } }