Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of TestAccountFixes v1.4.0
TestAccountFixes.dll
Decompiled 7 months agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using LethalCompanyInputUtils.Api; using Microsoft.CodeAnalysis; using MonoMod.Utils; using TMPro; using TestAccountCore; using TestAccountCore.Dependencies; using TestAccountCore.Dependencies.Compatibility; using TestAccountFixes.Core; using TestAccountFixes.Dependencies; using TestAccountFixes.Fixes; using TestAccountFixes.Fixes.ItemGrab.Compatibility; using Unity.Netcode; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.UIElements.Collections; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: IgnoresAccessChecksTo("AmazingAssets.TerrainToMesh")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: IgnoresAccessChecksTo("ClientNetworkTransform")] [assembly: IgnoresAccessChecksTo("com.olegknyazev.softmask")] [assembly: IgnoresAccessChecksTo("DissonanceVoip")] [assembly: IgnoresAccessChecksTo("EasyTextEffects")] [assembly: IgnoresAccessChecksTo("Facepunch Transport for Netcode for GameObjects")] [assembly: IgnoresAccessChecksTo("Facepunch.Steamworks.Win64")] [assembly: IgnoresAccessChecksTo("Unity.AI.Navigation")] [assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging")] [assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging.DocCodeExamples")] [assembly: IgnoresAccessChecksTo("Unity.Burst")] [assembly: IgnoresAccessChecksTo("Unity.Burst.Unsafe")] [assembly: IgnoresAccessChecksTo("Unity.Collections")] [assembly: IgnoresAccessChecksTo("Unity.Collections.LowLevel.ILSupport")] [assembly: IgnoresAccessChecksTo("Unity.InputSystem")] [assembly: IgnoresAccessChecksTo("Unity.InputSystem.ForUI")] [assembly: IgnoresAccessChecksTo("Unity.Jobs")] [assembly: IgnoresAccessChecksTo("Unity.Mathematics")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.Common")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.MetricTypes")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStats")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Component")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Configuration")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Implementation")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsReporting")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkProfiler.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkSolutionInterface")] [assembly: IgnoresAccessChecksTo("Unity.Netcode.Components")] [assembly: IgnoresAccessChecksTo("Unity.Netcode.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.Networking.Transport")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Csg")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.KdTree")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Poly2Tri")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Stl")] [assembly: IgnoresAccessChecksTo("Unity.Profiling.Core")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.ShaderLibrary")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Config.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary")] [assembly: IgnoresAccessChecksTo("Unity.Services.Authentication")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Analytics")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Configuration")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Device")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments.Internal")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Internal")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Networking")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Registration")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Scheduler")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Telemetry")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Threading")] [assembly: IgnoresAccessChecksTo("Unity.Services.QoS")] [assembly: IgnoresAccessChecksTo("Unity.Services.Relay")] [assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")] [assembly: IgnoresAccessChecksTo("Unity.Timeline")] [assembly: IgnoresAccessChecksTo("Unity.VisualEffectGraph.Runtime")] [assembly: IgnoresAccessChecksTo("UnityEngine.ARModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.NVIDIAModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.UI")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("TestAccount666.TestAccountFixes")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyDescription("All my fixes in one mod")] [assembly: AssemblyFileVersion("1.4.0.0")] [assembly: AssemblyInformationalVersion("1.4.0+625b0fa10adb75a9404e62eaf7729ba50325a21a")] [assembly: AssemblyProduct("TestAccountFixes")] [assembly: AssemblyTitle("TestAccount666.TestAccountFixes")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.4.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 TestAccountFixes { [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency("TestAccount666.TestAccountCore", "1.1.0")] [BepInPlugin("TestAccount666.TestAccountFixes", "TestAccountFixes", "1.4.0")] public class TestAccountFixes : BaseUnityPlugin { public static TestAccountFixes Instance { get; private set; } internal static ManualLogSource Logger { get; private set; } internal static Harmony? Harmony { get; set; } private void Awake() { Logger = ((BaseUnityPlugin)this).Logger; Instance = this; if (DependencyChecker.IsLobbyCompatibilityInstalled()) { Logger.LogInfo((object)"Found LobbyCompatibility Mod, initializing support :)"); LobbyCompatibilitySupport.Initialize("TestAccount666.TestAccountFixes", "1.4.0", (CompatibilityLevel)0, (VersionStrictness)2); } InstantiateFixes(); if (((BaseUnityPlugin)this).Config.Bind<bool>("General", "Print Config Entries On Startup", false, (ConfigDescription)null).Value) { PrintConfigEntries(); } Logger.LogInfo((object)"TestAccount666.TestAccountFixes v1.4.0 has loaded!"); } public void PrintConfigEntries() { Dictionary<string, string> configDictionary = new Dictionary<string, string>(); CollectionExtensions.Do<KeyValuePair<ConfigDefinition, ConfigEntryBase>>((IEnumerable<KeyValuePair<ConfigDefinition, ConfigEntryBase>>)((BaseUnityPlugin)this).Config, (Action<KeyValuePair<ConfigDefinition, ConfigEntryBase>>)delegate(KeyValuePair<ConfigDefinition, ConfigEntryBase> pair) { ConfigDefinition key = pair.Key; ConfigEntryBase value = pair.Value; if (value != null && !key.Key.Contains("Description")) { string text2 = $"{key.Section} -> {value.BoxedValue} ({value.DefaultValue})"; if (!configDictionary.TryGetValue(key.Key, out string value2)) { configDictionary.Add(key.Key, text2); } else { value2 = value2 + "\n" + text2; configDictionary.Remove(key.Key); configDictionary.Add(key.Key, value2); } } }); Logger.LogInfo((object)"Config entries:"); CollectionExtensions.Do<KeyValuePair<string, string>>((IEnumerable<KeyValuePair<string, string>>)configDictionary, (Action<KeyValuePair<string, string>>)delegate(KeyValuePair<string, string> pair) { Logger.LogInfo((object)"~~~~~~~~~~~~~~~~~~~~"); Logger.LogInfo((object)("Key: " + pair.Key)); Logger.LogInfo((object)" "); string[] array = pair.Value.Split("\n"); foreach (string text in array) { Logger.LogInfo((object)text); } Logger.LogInfo((object)"~~~~~~~~~~~~~~~~~~~~"); }); } private void InstantiateFixes() { Logger.LogInfo((object)"Loading fixes..."); Type fixType = typeof(Fix); IEnumerable<Type> enumerable = from type in Assembly.GetExecutingAssembly().GetTypes() where type != null where fixType.IsAssignableFrom(type) where type != fixType select type; foreach (Type item in enumerable) { Fix fix = item.GetConstructors()[0].Invoke(new object[1] { ((BaseUnityPlugin)this).Config }) as Fix; fix?.Awake(); Logger.LogInfo((object)("Loaded fix: " + fix?.fixName)); } Logger.LogInfo((object)"Loaded all fixes!"); } } public static class MyPluginInfo { public const string PLUGIN_GUID = "TestAccount666.TestAccountFixes"; public const string PLUGIN_NAME = "TestAccountFixes"; public const string PLUGIN_VERSION = "1.4.0"; } } namespace TestAccountFixes.Fixes { internal abstract class Fix { private readonly string _description; internal readonly string fixName; private ConfigEntry<bool> _sendDebugMessages = null; private ConfigEntry<bool> _fixEnabled = null; private ConfigEntry<LogLevel> _debugMessageLogLevel = null; private readonly bool _enabledByDefault; private Harmony? Harmony { get; set; } private static ManualLogSource Logger { get; set; } internal abstract void Awake(); protected Fix(ConfigFile configFile, string fixName, string description, bool enabledByDefault = true) { this.fixName = fixName; _enabledByDefault = enabledByDefault; _description = description; Logger = TestAccountFixes.Logger; InitializeConfig(configFile); } private void InitializeConfig(ConfigFile configFile) { _fixEnabled = configFile.Bind<bool>(fixName, "1. Enable Fix", _enabledByDefault, "If true, will enable the fix (Requires Restart, if changed via LethalConfig)"); _sendDebugMessages = configFile.Bind<bool>(fixName, "2. Send Debug Messages", false, "If true, will send additional information. Please turn this on, if you encounter any bugs."); _debugMessageLogLevel = configFile.Bind<LogLevel>(fixName, "3. Debug Message Log Level", LogLevel.NORMAL, "The higher the log level, the more spam. Only set this higher if asked."); configFile.Bind<string>(fixName, "4. Description", "This entry just exists to describe the fix", _description); } internal void Patch() { //IL_003f: 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) //IL_0046: Expected O, but got Unknown //IL_004b: Expected O, but got Unknown if (!_fixEnabled.Value) { LogDebug("Skipping this fix, as it is disabled"); return; } if (Harmony == null) { Harmony val = new Harmony("TestAccount666.TestAccountFixes-" + fixName); Harmony val2 = val; Harmony = val; } LogDebug("Patching..."); Type[] types = Assembly.GetExecutingAssembly().GetTypes(); foreach (Type type in types) { LogDebug("Got type: " + type.FullName, LogLevel.VERBOSE); LogDebug("Passes? " + type?.Namespace?.StartsWith(typeof(Fix).Namespace + "." + fixName), LogLevel.VERBOSE); if ((type?.Namespace?.StartsWith(typeof(Fix).Namespace + "." + fixName)).GetValueOrDefault()) { try { Harmony.PatchAll(type); } catch (TypeLoadException) { } } } LogDebug("Finished patching!"); } internal void Unpatch() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_0026: Expected O, but got Unknown if (Harmony == null) { Harmony val = new Harmony("TestAccount666.TestAccountFixes-" + fixName); Harmony val2 = val; Harmony = val; } Logger.LogDebug((object)"Unpatching..."); Harmony.UnpatchSelf(); Logger.LogDebug((object)"Finished unpatching!"); } internal void LogDebug(string message, LogLevel logLevel = LogLevel.NORMAL) { if (_sendDebugMessages.Value && logLevel <= _debugMessageLogLevel.Value) { Logger.LogInfo((object)$"[{logLevel}-Debug-{fixName}] {message}"); } } } } namespace TestAccountFixes.Fixes.SpiderWeb { public static class CobwebChecker { private static long _nextCheck; public static void HandleCobweb(PlayerControllerB playerControllerB) { PlayerControllerB localPlayerController = StartOfRound.Instance.localPlayerController; if ((Object)(object)playerControllerB != (Object)(object)localPlayerController) { SpiderWebFix.LogDebug(playerControllerB.playerUsername + " is not local player!", LogLevel.VERY_VERBOSE); return; } long currentTime = UnixTime.GetCurrentTime(); if (currentTime < _nextCheck) { SpiderWebFix.LogDebug($"Still on cooldown, current time '{currentTime}', next check '{_nextCheck}'", LogLevel.VERY_VERBOSE); return; } _nextCheck = currentTime + 1000; if (!IsPlayerValid(playerControllerB)) { SpiderWebFix.LogDebug(playerControllerB.playerUsername + " not valid, skipping...", LogLevel.VERY_VERBOSE); return; } List<SandSpiderWebTrap> activeCobwebs = FindActiveCobwebs(); if (!ShouldReleaseBasedOnCobwebs(activeCobwebs)) { SpiderWebFix.LogDebug("Found active cobwebs for " + playerControllerB.playerUsername + ", skipping..."); return; } if (!ShouldReleaseBasedOnZapGuns()) { SpiderWebFix.LogDebug("Found active zap guns for " + playerControllerB.playerUsername + ", skipping..."); return; } SpiderWebFix.LogDebug("Releasing " + playerControllerB.playerUsername + " from pesky cobwebs :>"); ReleasePlayer(activeCobwebs); } private static bool IsPlayerValid(PlayerControllerB playerControllerB) { if (StartOfRound.Instance == null) { SpiderWebFix.LogDebug("StartOfRound is null!", LogLevel.VERBOSE); return false; } PlayerControllerB localPlayerController = StartOfRound.Instance.localPlayerController; if (localPlayerController.isSinking) { SpiderWebFix.LogDebug(playerControllerB.playerUsername + " is sinking!", LogLevel.VERBOSE); return false; } if (localPlayerController.isMovementHindered > 0) { return true; } SpiderWebFix.LogDebug(playerControllerB.playerUsername + " is not hindered!", LogLevel.VERY_VERBOSE); return false; } private static List<SandSpiderWebTrap> FindActiveCobwebs() { SandSpiderWebTrap[] cobwebs = Object.FindObjectsOfType<SandSpiderWebTrap>(); if (cobwebs == null) { cobwebs = Array.Empty<SandSpiderWebTrap>(); } return (from cobwebTrap in cobwebs where cobwebs != null where cobwebTrap.hinderingLocalPlayer select cobwebTrap).ToList(); } private static bool ShouldReleaseBasedOnCobwebs(IReadOnlyCollection<SandSpiderWebTrap> activeCobwebs) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) if (LinqExtensions.None<SandSpiderWebTrap>((IEnumerable<SandSpiderWebTrap>)activeCobwebs)) { return true; } Vector3 localPlayerPosition = ((Component)StartOfRound.Instance.localPlayerController).transform.position; return LinqExtensions.None<SandSpiderWebTrap>(from cobweb in activeCobwebs let cobwebPosition = ((Component)cobweb).transform.position let distance = Vector3.Distance(localPlayerPosition, cobwebPosition) where !cobweb.webHasBeenBroken && distance < 10f select cobweb); } private static bool ShouldReleaseBasedOnZapGuns() { List<PatcherTool> list = new List<PatcherTool>(); PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; foreach (PlayerControllerB val in allPlayerScripts) { GrabbableObject[] itemSlots = val.ItemSlots; foreach (GrabbableObject val2 in itemSlots) { PatcherTool val3 = (PatcherTool)(object)((val2 is PatcherTool) ? val2 : null); if (val3 != null) { list.Add(val3); } } } return LinqExtensions.None<PlayerControllerB>(from zapGun in list where zapGun != null let shockableTransform = zapGun.shockedTargetScript.GetShockableTransform() let shockedPlayer = ((Component)shockableTransform).GetComponentInChildren<PlayerControllerB>() where shockedPlayer != null && (Object)(object)shockedPlayer != (Object)(object)StartOfRound.Instance.localPlayerController select shockedPlayer); } private static void ReleasePlayer(List<SandSpiderWebTrap> activeCobwebs) { PlayerControllerB localPlayerController = StartOfRound.Instance.localPlayerController; localPlayerController.isMovementHindered -= activeCobwebs.Count; if (localPlayerController.isMovementHindered < 0) { localPlayerController.isMovementHindered = 0; } foreach (SandSpiderWebTrap activeCobweb in activeCobwebs) { activeCobweb.hinderingLocalPlayer = false; activeCobweb.currentTrappedPlayer = null; localPlayerController.hinderedMultiplier /= 3.5f; } if (!(localPlayerController.hinderedMultiplier >= 1f)) { localPlayerController.hinderedMultiplier = 1f; } } } internal class SpiderWebFix : Fix { private const string DESCRIPTION = "The Spider Web Fix addresses issues related to cobweb interactions, specifically resolving instances where players may become trapped in non-existent cobwebs."; internal static ConfigEntry<bool> teleportCobwebs; private readonly ConfigFile _configFile; internal static SpiderWebFix Instance { get; private set; } public SpiderWebFix(ConfigFile configFile) { _configFile = configFile; base..ctor(configFile, "SpiderWeb", "The Spider Web Fix addresses issues related to cobweb interactions, specifically resolving instances where players may become trapped in non-existent cobwebs."); } internal override void Awake() { Instance = this; InitializeConfig(); Patch(); } private void InitializeConfig() { teleportCobwebs = _configFile.Bind<bool>(fixName, "5. Teleport Cobwebs", true, "If true, will teleport cobwebs somewhere else as soon as they are broken."); } internal new static void LogDebug(string message, LogLevel logLevel = LogLevel.NORMAL) { ((Fix)Instance).LogDebug(message, logLevel); } } } namespace TestAccountFixes.Fixes.SpiderWeb.Patches { [HarmonyPatch(typeof(PlayerControllerB))] public class PlayerControllerBPatch { [HarmonyPatch("LateUpdate")] [HarmonyPostfix] private static void UpdatePostfix(PlayerControllerB __instance) { CobwebChecker.HandleCobweb(__instance); } [HarmonyPatch("TeleportPlayer")] [HarmonyPostfix] private static void TeleportPlayerPostfix(PlayerControllerB __instance) { CobwebChecker.HandleCobweb(__instance); } } [HarmonyPatch(typeof(SandSpiderWebTrap))] public static class SandSpiderWebTrapPatch { [HarmonyPatch("Update")] [HarmonyPostfix] private static void TeleportBrokenCobwebs(SandSpiderWebTrap __instance) { //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) if (SpiderWebFix.teleportCobwebs.Value) { SpiderWebFix.LogDebug("Updating Cobweb...", LogLevel.VERY_VERBOSE); StartOfRound instance = StartOfRound.Instance; if ((instance == null || (!((NetworkBehaviour)instance).IsServer && !((NetworkBehaviour)instance).IsHost)) ? true : false) { SpiderWebFix.LogDebug("We're not host or StartOfRound is null, skipping...", LogLevel.VERY_VERBOSE); return; } if (__instance == null || !__instance.webHasBeenBroken) { SpiderWebFix.LogDebug("Cobweb is not broken, skipping...", LogLevel.VERY_VERBOSE); return; } ((Component)__instance).transform.position = Vector3.left * 10000f; __instance.webHasBeenBroken = false; ((Behaviour)__instance).enabled = false; SpiderWebFix.LogDebug("Teleporting pesky cobweb :>"); } } } } namespace TestAccountFixes.Fixes.SpiderDamage { internal class SpiderDamageFix : Fix { private const string DESCRIPTION = "The Spooder Damage \"Fix\" will adjust the amount of damage a spider deals."; private readonly ConfigFile _configFile; private ConfigEntry<int> _spooderDamageEntry; internal static SpiderDamageFix Instance { get; private set; } public SpiderDamageFix(ConfigFile configFile) { _configFile = configFile; _spooderDamageEntry = null; base..ctor(configFile, "SpiderDamage", "The Spooder Damage \"Fix\" will adjust the amount of damage a spider deals.", enabledByDefault: false); } internal override void Awake() { Instance = this; InitializeConfig(); Patch(); } private void InitializeConfig() { _spooderDamageEntry = _configFile.Bind<int>(fixName, "5. Spooder Damage", 20, "This will change the amount damage that spooders (aka spiders) deal. 90 is the vanilla value."); } public static int GetSpooderDamage() { return (Instance?._spooderDamageEntry?.Value).GetValueOrDefault(90); } internal new static void LogDebug(string message, LogLevel logLevel = LogLevel.NORMAL) { ((Fix)Instance).LogDebug(message, logLevel); } } } namespace TestAccountFixes.Fixes.SpiderDamage.Transpilers { [HarmonyPatch(typeof(SandSpiderAI))] public static class SandSpiderAITranspiler { [CompilerGenerated] private sealed class <AdjustSpooderDamageValue>d__0 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IEnumerator, IDisposable { private int <>1__state; private CodeInstruction <>2__current; private int <>l__initialThreadId; private IEnumerable<CodeInstruction> instructions; public IEnumerable<CodeInstruction> <>3__instructions; private IEnumerator<CodeInstruction> <>s__1; private CodeInstruction <codeInstruction>5__2; CodeInstruction IEnumerator<CodeInstruction>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <AdjustSpooderDamageValue>d__0(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || (uint)(num - 1) <= 1u) { try { } finally { <>m__Finally1(); } } <>s__1 = null; <codeInstruction>5__2 = null; <>1__state = -2; } private bool MoveNext() { //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Expected O, but got Unknown try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>s__1 = instructions.GetEnumerator(); <>1__state = -3; break; case 1: <>1__state = -3; break; case 2: <>1__state = -3; <codeInstruction>5__2 = null; break; } if (<>s__1.MoveNext()) { <codeInstruction>5__2 = <>s__1.Current; if (<codeInstruction>5__2.opcode != OpCodes.Ldc_I4_S) { <>2__current = <codeInstruction>5__2; <>1__state = 1; return true; } <>2__current = new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(SpiderDamageFix), "GetSpooderDamage", (Type[])null, (Type[])null)); <>1__state = 2; return true; } <>m__Finally1(); <>s__1 = null; return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<>s__1 != null) { <>s__1.Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<CodeInstruction> IEnumerable<CodeInstruction>.GetEnumerator() { <AdjustSpooderDamageValue>d__0 <AdjustSpooderDamageValue>d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; <AdjustSpooderDamageValue>d__ = this; } else { <AdjustSpooderDamageValue>d__ = new <AdjustSpooderDamageValue>d__0(0); } <AdjustSpooderDamageValue>d__.instructions = <>3__instructions; return <AdjustSpooderDamageValue>d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<CodeInstruction>)this).GetEnumerator(); } } [IteratorStateMachine(typeof(<AdjustSpooderDamageValue>d__0))] [HarmonyPatch("OnCollideWithPlayer")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> AdjustSpooderDamageValue(IEnumerable<CodeInstruction> instructions) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <AdjustSpooderDamageValue>d__0(-2) { <>3__instructions = instructions }; } } } namespace TestAccountFixes.Fixes.PlayerSpeed { internal class PlayerSpeedFix : Fix { private const string DESCRIPTION = "The PlayerSpeedFix fixes player's critical injured state while not actually being critically injured."; internal static PlayerSpeedFix Instance { get; private set; } public PlayerSpeedFix(ConfigFile configFile) : base(configFile, "PlayerSpeed", "The PlayerSpeedFix fixes player's critical injured state while not actually being critically injured.") { } internal override void Awake() { Instance = this; Patch(); } internal new static void LogDebug(string message, LogLevel logLevel = LogLevel.NORMAL) { ((Fix)Instance).LogDebug(message, logLevel); } } } namespace TestAccountFixes.Fixes.PlayerSpeed.Patches { [HarmonyPatch(typeof(PlayerControllerB))] public static class PlayerControllerBPatch { private static long _nextCheck; [HarmonyPatch("Update")] [HarmonyPrefix] private static void FixCriticallyInjuredState(PlayerControllerB __instance) { long currentTime = UnixTime.GetCurrentTime(); if (currentTime < _nextCheck) { PlayerSpeedFix.LogDebug($"Still on cooldown, current time '{currentTime}', next check '{_nextCheck}'", LogLevel.VERY_VERBOSE); return; } _nextCheck = currentTime + 1000; if (!__instance.criticallyInjured) { PlayerSpeedFix.LogDebug("Player " + __instance.playerUsername + " is not injured, skiping!", LogLevel.VERY_VERBOSE); return; } if (__instance.health < 20) { PlayerSpeedFix.LogDebug("Player " + __instance.playerUsername + " is not below 20HP!", LogLevel.VERY_VERBOSE); return; } PlayerSpeedFix.LogDebug("Fixing player " + __instance.playerUsername + "!"); __instance.criticallyInjured = false; } } } namespace TestAccountFixes.Fixes.ItemGrab { internal class ItemGrabFix : Fix { private const string DESCRIPTION = "Breaks the laws of physics to allow grabbing items behind InteractTriggers."; private readonly ConfigFile _configFile; internal static ItemGrabFixInputActions itemGrabFixInputActions; internal ConfigEntry<bool> allowItemGrabBeforeGameStart; internal static ItemGrabFix Instance { get; private set; } public ItemGrabFix(ConfigFile configFile) { _configFile = configFile; allowItemGrabBeforeGameStart = null; base..ctor(configFile, "ItemGrab", "Breaks the laws of physics to allow grabbing items behind InteractTriggers."); } internal override void Awake() { Instance = this; if (DependencyChecker.IsBetterItemHandlingInstalled()) { TestAccountFixes.Logger.LogInfo((object)"[ItemGrabFix] Found BetterItemHandling enabling support :)"); BetterItemHandlingSupport.Setup(); } itemGrabFixInputActions = new ItemGrabFixInputActions(); InitializeConfig(); Patch(); } private void InitializeConfig() { allowItemGrabBeforeGameStart = _configFile.Bind<bool>(fixName, "5. Allow Item Grab Before Game Start", false, "If set to true, will allow items to be grabbed before the game has started. This may cause desyncs."); } internal new static void LogDebug(string message, LogLevel logLevel = LogLevel.NORMAL) { ((Fix)Instance).LogDebug(message, logLevel); } } public class ItemGrabFixInputActions : LcInputActions { [InputAction("<Keyboard>/leftShift", Name = "NormalGrab")] public InputAction NormalGrabKey { get; set; } } } namespace TestAccountFixes.Fixes.ItemGrab.Patches { [HarmonyPatch(typeof(StartOfRound))] public static class GrabbableObjectPatch { [HarmonyPatch("Start")] [HarmonyPrefix] private static void SetGrabbableBeforeStart() { if (!ItemGrabFix.Instance.allowItemGrabBeforeGameStart.Value) { return; } foreach (Item items in StartOfRound.Instance.allItemsList.itemsList) { ItemGrabFix.LogDebug($"{items.itemName} can be grabbed? {items.canBeGrabbedBeforeGameStart}", LogLevel.VERBOSE); if (!items.canBeGrabbedBeforeGameStart) { ItemGrabFix.LogDebug(items.itemName + " can now be grabbed :)", LogLevel.VERBOSE); items.canBeGrabbedBeforeGameStart = true; } } } } [HarmonyPatch(typeof(PlayerControllerB))] public static class PlayerControllerBPatch { private static readonly int _GrabInvalidated = Animator.StringToHash("GrabInvalidated"); private static readonly int _GrabValidated = Animator.StringToHash("GrabValidated"); private static readonly int _CancelHolding = Animator.StringToHash("cancelHolding"); private static readonly int _Throw = Animator.StringToHash("Throw"); private static readonly Regex _DirtyInteractRegex = new Regex("Interact:<(Keyboard|Mouse)>/", RegexOptions.Compiled); [HarmonyPatch("SetHoverTipAndCurrentInteractTrigger")] [HarmonyPrefix] [HarmonyBefore(new string[] { "com.kodertech.TelevisionController", "com.kodertech.BoomboxController" })] public static bool BeforeSetHoverTipAndCurrentInteractTrigger(PlayerControllerB __instance) { return HandleSetHoverTipAndCurrentInteractTrigger(__instance); } private static bool HandleSetHoverTipAndCurrentInteractTrigger(PlayerControllerB playerControllerB) { if (ItemGrabFix.itemGrabFixInputActions.NormalGrabKey.IsPressed()) { return true; } if ((Object)(object)playerControllerB.hoveringOverTrigger != (Object)null && playerControllerB.hoveringOverTrigger.isBeingHeldByPlayer) { return true; } if (!IsLocalPlayer((Object)(object)playerControllerB) || playerControllerB.isGrabbingObjectAnimation) { return true; } if (!RaycastForObject(playerControllerB, out var hit)) { ClearTriggerAndTip(playerControllerB); return true; } if (playerControllerB.FirstEmptyItemSlot() == -1) { ((TMP_Text)playerControllerB.cursorTip).text = "Inventory full!"; return false; } GrabbableObject component = ((Component)((RaycastHit)(ref hit)).collider).GetComponent<GrabbableObject>(); if (component == null || !component.grabbable) { return true; } if (component == null || component.deactivated) { return true; } if ((Object)(object)component != (Object)null) { if (!ItemGrabFix.Instance.allowItemGrabBeforeGameStart.Value && !component.itemProperties.canBeGrabbedBeforeGameStart && !GameNetworkManager.Instance.gameHasStarted) { ((TMP_Text)playerControllerB.cursorTip).text = "(Cannot hold until ship has landed)"; return false; } playerControllerB.hoveringOverTrigger = null; } if ((Object)(object)component != (Object)null && !string.IsNullOrEmpty(component.customGrabTooltip)) { ((TMP_Text)playerControllerB.cursorTip).text = component.customGrabTooltip; return false; } string interactKey = GetInteractKey(); ((TMP_Text)playerControllerB.cursorTip).text = "Grab : [" + interactKey + "]"; ((Behaviour)playerControllerB.cursorIcon).enabled = true; playerControllerB.cursorIcon.sprite = playerControllerB.grabItemIcon; return false; } [HarmonyPatch("Interact_performed")] [HarmonyPostfix] public static void Interact_performed(PlayerControllerB __instance, ref CallbackContext context) { if (!ItemGrabFix.itemGrabFixInputActions.NormalGrabKey.IsPressed() && (!((Object)(object)__instance.hoveringOverTrigger != (Object)null) || !__instance.hoveringOverTrigger.isBeingHeldByPlayer) && ((((NetworkBehaviour)__instance).IsOwner && __instance.isPlayerControlled && (__instance == null || !((NetworkBehaviour)__instance).IsServer || __instance.isHostPlayerObject)) || __instance.isTestingPlayer) && ((CallbackContext)(ref context)).performed) { BeginGrabObject(__instance); } } private static void BeginGrabObject(PlayerControllerB instance) { //IL_0216: Unknown result type (might be due to invalid IL or missing references) ItemGrabFixHook.OnPreBeforeGrabObject(instance, null); if (!IsLocalPlayer((Object)(object)instance) || !RaycastForObject(instance, out var hit)) { return; } GrabbableObject component = ((Component)((RaycastHit)(ref hit)).collider).GetComponent<GrabbableObject>(); ItemGrabFixHook.OnBeforeGrabObject(instance, component); if ((Object)(object)component == (Object)null || instance.inSpecialInteractAnimation || instance.isGrabbingObjectAnimation || component.isHeld || component.isPocketed) { return; } NetworkObject networkObject = ((NetworkBehaviour)component).NetworkObject; if ((Object)(object)networkObject == (Object)null || !networkObject.IsSpawned || component == null || !component.grabbable || component == null || component.deactivated || (!ItemGrabFix.Instance.allowItemGrabBeforeGameStart.Value && !component.itemProperties.canBeGrabbedBeforeGameStart && !GameNetworkManager.Instance.gameHasStarted)) { return; } try { component.InteractItem(); } catch (Exception ex) { Extensions.LogDetailed(ex, (string)null); } if (!instance.twoHanded && component.grabbable && instance.FirstEmptyItemSlot() != -1) { ResetAnimators(instance); instance.currentlyGrabbingObject = component; instance.SetSpecialGrabAnimationBool(true, (GrabbableObject)null); instance.isGrabbingObjectAnimation = true; ((Behaviour)instance.cursorIcon).enabled = false; ((TMP_Text)instance.cursorTip).text = ""; instance.twoHanded = component.itemProperties.twoHanded; instance.carryWeight += Mathf.Clamp(component.itemProperties.weight - 1f, 0f, 10f); instance.grabObjectAnimationTime = ((component.itemProperties.grabAnimationTime <= 0f) ? 0.4f : component.itemProperties.grabAnimationTime); if (!instance.isTestingPlayer) { instance.GrabObjectServerRpc(NetworkObjectReference.op_Implicit(networkObject)); } instance.grabObjectCoroutine = ((MonoBehaviour)instance).StartCoroutine(instance.GrabObject()); ItemGrabFixHook.OnAfterGrabObject(instance, component); } } private static bool IsLocalPlayer(Object player) { return player == (Object)(object)StartOfRound.Instance.localPlayerController; } private static bool RaycastForObject(PlayerControllerB player, out RaycastHit hit) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //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_0021: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: 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) if ((Object)(object)player == (Object)null || (Object)(object)player.gameplayCamera == (Object)null) { hit = default(RaycastHit); return false; } Transform transform = ((Component)player.gameplayCamera).transform; Vector3 position = transform.position; Vector3 forward = transform.forward; Ray val = default(Ray); ((Ray)(ref val))..ctor(position, forward); if (!Physics.Raycast(val, ref hit, player.grabDistance, player.grabbableObjectsMask | 0x100 | 0x2000000 | 0x1000) || !((Component)((RaycastHit)(ref hit)).collider).CompareTag("PhysicsProp")) { return false; } if (IsInteractableObjectHit(val, player, hit)) { return false; } return !IsDoorHit(val, player, hit); } private static bool PerformRaycastAndCheckConditions(Ray ray, PlayerControllerB player, RaycastHit grabbableObjectHit, bool checkDoor = true) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) RaycastHit val = default(RaycastHit); if (!Physics.Raycast(ray, ref val, player.grabDistance, 512)) { return false; } DoorLock component = ((Component)((RaycastHit)(ref val)).collider).GetComponent<DoorLock>(); if (checkDoor) { if ((Object)(object)component == (Object)null) { return false; } } else if ((Object)(object)component != (Object)null) { return false; } BoxCollider[] components = ((Component)((RaycastHit)(ref val)).collider).gameObject.GetComponents<BoxCollider>(); BoxCollider[] array = components; RaycastHit val3 = default(RaycastHit); foreach (BoxCollider val2 in array) { if (Object.op_Implicit((Object)(object)val2) && !((Collider)val2).isTrigger) { Vector3 size = val2.size; val2.size = new Vector3(0f, size.y, size.z); bool flag = ((Collider)val2).Raycast(ray, ref val3, player.grabDistance); val2.size = size; if (flag) { return ((RaycastHit)(ref val3)).distance < ((RaycastHit)(ref grabbableObjectHit)).distance; } } } return false; } private static bool IsDoorHit(Ray ray, PlayerControllerB player, RaycastHit grabbableObjectHit) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) return PerformRaycastAndCheckConditions(ray, player, grabbableObjectHit); } private static bool IsInteractableObjectHit(Ray ray, PlayerControllerB player, RaycastHit grabbableObjectHit) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) return PerformRaycastAndCheckConditions(ray, player, grabbableObjectHit, checkDoor: false); } private static void ClearTriggerAndTip(PlayerControllerB playerControllerB) { ((Behaviour)playerControllerB.cursorIcon).enabled = false; ((TMP_Text)playerControllerB.cursorTip).text = ""; if ((Object)(object)playerControllerB.hoveringOverTrigger != (Object)null) { playerControllerB.previousHoveringOverTrigger = playerControllerB.hoveringOverTrigger; } playerControllerB.hoveringOverTrigger = null; } private static void ResetAnimators(PlayerControllerB playerControllerB) { Animator playerBodyAnimator = playerControllerB.playerBodyAnimator; playerBodyAnimator.SetBool(_GrabInvalidated, false); playerBodyAnimator.SetBool(_GrabValidated, false); playerBodyAnimator.SetBool(_CancelHolding, false); playerBodyAnimator.ResetTrigger(_Throw); } private static string GetInteractKey() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) InputAction val = IngamePlayerSettings.Instance.playerInput.actions.FindAction("Interact", false); InputBinding val2 = val.bindings[0]; string input = ((object)(InputBinding)(ref val2)).ToString(); return _DirtyInteractRegex.Replace(input, "").ToUpper(); } } } namespace TestAccountFixes.Fixes.ItemGrab.Compatibility { public static class BetterItemHandlingSupport { private static Assembly? _betterItemHandlingAssembly; private static Type? _playerControllerBPatchesType; private static MethodInfo? _beginGrabObjectPrefixMethod; private static MethodInfo? _beginGrabObjectPostfixMethod; public static void Setup() { ItemGrabFixHook.BeforeGrabObject += BeforeBeginGrabObject; ItemGrabFixHook.AfterGrabObject += AfterBeginGrabObject; } private static void BeforeBeginGrabObject(GrabObjectEventArgs grabObjectEventArgs) { if (FindBetterItemHandlingAssembly() && FindPlayerControllerPatchType() && FindBeginGrabObjectPrefixMethod()) { _beginGrabObjectPrefixMethod?.Invoke(null, new object[1] { grabObjectEventArgs.playerControllerB }); } } private static void AfterBeginGrabObject(GrabObjectEventArgs grabObjectEventArgs) { if (FindBetterItemHandlingAssembly() && FindPlayerControllerPatchType() && FindBeginGrabObjectPostfixMethod()) { _beginGrabObjectPostfixMethod?.Invoke(null, new object[1] { grabObjectEventArgs.playerControllerB }); } } private static bool FindBetterItemHandlingAssembly() { if (_betterItemHandlingAssembly != null) { return true; } Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { if (assembly.FullName.ToLower().Contains("betteritemhandling")) { _betterItemHandlingAssembly = assembly; break; } } if (_betterItemHandlingAssembly != null) { return true; } TestAccountFixes.Logger.LogError((object)"[ItemGrabFix] Couldn't find BetterItemHandling assembly!"); return false; } private static bool FindPlayerControllerPatchType() { if ((object)_playerControllerBPatchesType != null) { return true; } _playerControllerBPatchesType = (from type in AccessTools.GetTypesFromAssembly(_betterItemHandlingAssembly) where type.FullName == "BetterItemHandling.Patches.PlayerControllerBPatches" select type).FirstOrDefault(); if ((object)_playerControllerBPatchesType != null) { return true; } TestAccountFixes.Logger.LogError((object)"[ItemGrabFix] Couldn't find BetterItemHandling PlayerControllerBPatches type!"); return false; } private static bool FindBeginGrabObjectPrefixMethod() { if ((object)_beginGrabObjectPrefixMethod != null) { return true; } _beginGrabObjectPrefixMethod = AccessTools.DeclaredMethod(_playerControllerBPatchesType, "BeginGrabObjectPrefix", new Type[1] { typeof(PlayerControllerB) }, (Type[])null); if ((object)_beginGrabObjectPrefixMethod != null) { return true; } TestAccountFixes.Logger.LogError((object)"[ItemGrabFix] Couldn't find BetterItemHandling BeginGrabObjectPrefix method!"); return false; } private static bool FindBeginGrabObjectPostfixMethod() { if ((object)_beginGrabObjectPostfixMethod != null) { return true; } _beginGrabObjectPostfixMethod = AccessTools.DeclaredMethod(_playerControllerBPatchesType, "BeginGrabObjectPostfix", new Type[1] { typeof(PlayerControllerB) }, (Type[])null); if ((object)_beginGrabObjectPostfixMethod != null) { return true; } TestAccountFixes.Logger.LogError((object)"[ItemGrabFix] Couldn't find BetterItemHandling BeginGrabObjectPostfix method!"); return false; } } public class GrabObjectEventArgs : EventArgs { public readonly PlayerControllerB playerControllerB; public GrabbableObject? grabbableObject; public GrabObjectEventArgs(PlayerControllerB playerControllerB, GrabbableObject? grabbableObject) { this.playerControllerB = playerControllerB; this.grabbableObject = grabbableObject; base..ctor(); } } public static class ItemGrabFixHook { public delegate void GrabObjectEvent(GrabObjectEventArgs args); public static event GrabObjectEvent PreBeforeGrabObject; public static event GrabObjectEvent BeforeGrabObject; public static event GrabObjectEvent AfterGrabObject; internal static void OnPreBeforeGrabObject(PlayerControllerB playerControllerB, GrabbableObject? grabbableObject) { ItemGrabFix.LogDebug("OnPreBeforeGrabObject!", LogLevel.VERBOSE); ItemGrabFixHook.PreBeforeGrabObject?.Invoke(new GrabObjectEventArgs(playerControllerB, grabbableObject)); ItemGrabFix.LogDebug("PreBeforeGrabObject?" + (ItemGrabFixHook.PreBeforeGrabObject != null), LogLevel.VERBOSE); } internal static void OnBeforeGrabObject(PlayerControllerB playerControllerB, GrabbableObject? grabbableObject) { ItemGrabFix.LogDebug("OnBeforeGrabObject!", LogLevel.VERBOSE); ItemGrabFixHook.BeforeGrabObject?.Invoke(new GrabObjectEventArgs(playerControllerB, grabbableObject)); ItemGrabFix.LogDebug("BeforeGrabObject?" + (ItemGrabFixHook.BeforeGrabObject != null), LogLevel.VERBOSE); } internal static void OnAfterGrabObject(PlayerControllerB playerControllerB, GrabbableObject? grabbableObject) { ItemGrabFix.LogDebug("OnAfterGrabObject!", LogLevel.VERBOSE); ItemGrabFixHook.AfterGrabObject?.Invoke(new GrabObjectEventArgs(playerControllerB, grabbableObject)); ItemGrabFix.LogDebug("AfterGrabObject? " + (ItemGrabFixHook.AfterGrabObject != null), LogLevel.VERBOSE); } } } namespace TestAccountFixes.Fixes.ItemGrab.Compatibility.Patches { [HarmonyPatch(typeof(MenuManager))] public static class MenuManagerPatch { [HarmonyPatch("Start")] [HarmonyPostfix] public static void CheckForGrabObjectPatches() { MethodInfo methodInfo = AccessTools.DeclaredMethod(typeof(PlayerControllerB), "BeginGrabObject", (Type[])null, (Type[])null); CheckForPatches(methodInfo); MethodInfo methodInfo2 = AccessTools.DeclaredMethod(typeof(PlayerControllerB), "SetHoverTipAndCurrentInteractTrigger", (Type[])null, (Type[])null); CheckForPatches(methodInfo2); } private static void CheckForPatches(MethodInfo methodInfo) { Patches patchInfo = Harmony.GetPatchInfo((MethodBase)methodInfo); if (patchInfo == null) { return; } List<Patch> list = new List<Patch>(); IEnumerable<Patch> finalizers = patchInfo.Finalizers; list.AddRange(finalizers ?? Enumerable.Empty<Patch>()); finalizers = patchInfo.Postfixes; list.AddRange(finalizers ?? Enumerable.Empty<Patch>()); finalizers = patchInfo.Prefixes; list.AddRange(finalizers ?? Enumerable.Empty<Patch>()); finalizers = patchInfo.Transpilers; list.AddRange(finalizers ?? Enumerable.Empty<Patch>()); finalizers = patchInfo.ILManipulators; list.AddRange(finalizers ?? Enumerable.Empty<Patch>()); list.RemoveAll((Patch patch) => (patch?.owner)?.StartsWith("TestAccount666.TestAccountFixes") ?? true); if (list.Count <= 0) { return; } TestAccountFixes.Logger.LogWarning((object)new StringBuilder().Append("[GrabItemFix] Detected mods patching the ").Append(methodInfo.DeclaringType?.FullName ?? "null").Append("#") .Append(methodInfo.Name) .Append(" method!")); TestAccountFixes.Logger.LogWarning((object)"[GrabItemFix] This could be an issue!"); TestAccountFixes.Logger.LogWarning((object)"[GrabItemFix] Please report any issues!"); HashSet<string> hashSet = new HashSet<string>(); foreach (Patch item in list) { hashSet.Add(item.owner); } TestAccountFixes.Logger.LogWarning((object)"[GrabItemFix] Mods that might not work as expected:"); TestAccountFixes.Logger.LogWarning((object)"[GrabItemFix] ~~~~ Start of list ~~~~"); foreach (string item2 in hashSet) { TestAccountFixes.Logger.LogWarning((object)("[GrabItemFix] " + item2)); } TestAccountFixes.Logger.LogWarning((object)"[GrabItemFix] ~~~~ End of list ~~~~"); TestAccountFixes.Logger.LogWarning((object)"[GrabItemFix] Keep in mind... Just because a mod is listed here, doesn't mean it will cause issues!"); } } } namespace TestAccountFixes.Fixes.DogSound { internal class DogSoundFix : Fix { private const string DESCRIPTION = "Fixes inconsistency with eyeless dogs, such as their inability to detect shotgun blasts."; internal static ConfigEntry<bool> fixSilentSprint; internal static ConfigEntry<bool> chatIsLoudActually; private readonly ConfigFile _configFile; internal static DogSoundFix Instance { get; private set; } public DogSoundFix(ConfigFile configFile) { _configFile = configFile; base..ctor(configFile, "DogSound", "Fixes inconsistency with eyeless dogs, such as their inability to detect shotgun blasts."); } internal override void Awake() { Instance = this; InitializeConfig(); Patch(); } private void InitializeConfig() { fixSilentSprint = _configFile.Bind<bool>(fixName, "5. Fix Silent Sprint", true, "If true, will fix the silent sprint bug"); chatIsLoudActually = _configFile.Bind<bool>(fixName, "6. Chat is loud actually", false, "If true, chat will be loud. Dogs will be able to hear you sending chat messages"); } internal new static void LogDebug(string message, LogLevel logLevel = LogLevel.NORMAL) { ((Fix)Instance).LogDebug(message, logLevel); } } public class SprintChecker : MonoBehaviour { internal enum PlayerState { WALK, CROUCH, SPRINT } private const int SWITCH_THRESHOLD = 6; private const float SWITCH_TIME_FRAME = 1f; internal PlayerState currentState = PlayerState.WALK; private float _lastCheckTime; private Vector3 _lastPosition; private PlayerState _previousState = PlayerState.WALK; private int _switchCount; private static PlayerState GetPlayerState(PlayerControllerB playerControllerB) { //IL_0012: 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_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) PlayerState result = PlayerState.WALK; AnimatorStateInfo currentAnimatorStateInfo; bool num; if (!((NetworkBehaviour)playerControllerB).IsOwner) { currentAnimatorStateInfo = playerControllerB.playerBodyAnimator.GetCurrentAnimatorStateInfo(0); num = ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).IsTag("Sprinting"); } else { num = playerControllerB.isSprinting; } if (num) { result = PlayerState.SPRINT; } bool num2; if (!((NetworkBehaviour)playerControllerB).IsOwner) { currentAnimatorStateInfo = playerControllerB.playerBodyAnimator.GetCurrentAnimatorStateInfo(0); num2 = ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).IsTag("crouching"); } else { num2 = playerControllerB.isCrouching; } if (num2) { result = PlayerState.CROUCH; } return result; } private static void AlertDoggos(PlayerControllerB playerControllerB) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) DogSoundFix.LogDebug("[SilentSprint3] " + playerControllerB.playerUsername + " is alerting doggos!"); bool flag = playerControllerB.isInHangarShipRoom && StartOfRound.Instance.hangarDoorsClosed; playerControllerB.PlayFootstepSound(); RoundManager.Instance.PlayAudibleNoise(((Component)playerControllerB).transform.position, 13f, 0.6f, 0, flag, 8); } internal void CheckForRapidStateChange(PlayerControllerB playerControllerB) { //IL_0036: 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) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) _previousState = currentState; currentState = GetPlayerState(playerControllerB); if (currentState != _previousState) { Vector3 position = ((Component)playerControllerB).transform.position; bool flag = (double)Vector3.Distance(position, _lastPosition) <= 0.001; _lastPosition = position; DogSoundFix.LogDebug($"[SilentSprint3] {playerControllerB.playerUsername}: Switch from {_previousState} to {currentState} detected!", LogLevel.VERY_VERBOSE); _switchCount++; if (_switchCount >= 6 && !flag) { AlertDoggos(playerControllerB); } if (!(Time.time - _lastCheckTime < 1f)) { DogSoundFix.LogDebug("[SilentSprint3] " + playerControllerB.playerUsername + ": Threshold expired!", LogLevel.VERY_VERBOSE); _switchCount = 0; _lastCheckTime = Time.time; } } } } } namespace TestAccountFixes.Fixes.DogSound.Patches { [HarmonyPatch(typeof(HUDManager))] public static class HUDManagerPatch { [HarmonyPatch("AddTextToChatOnServer")] [HarmonyPostfix] private static void MakeChatLoud(int playerId) { //IL_00b2: Unknown result type (might be due to invalid IL or missing references) if (DogSoundFix.chatIsLoudActually.Value) { if (!((NetworkBehaviour)StartOfRound.Instance).IsHost && !((NetworkBehaviour)StartOfRound.Instance).IsServer) { DogSoundFix.LogDebug("We're not host, skipping...", LogLevel.VERY_VERBOSE); return; } if (StartOfRound.Instance.inShipPhase) { DogSoundFix.LogDebug("We're in ship phase, skipping...", LogLevel.VERY_VERBOSE); return; } if (playerId <= -1) { DogSoundFix.LogDebug("Invalid player id, or system message, skipping...", LogLevel.VERBOSE); return; } PlayerControllerB val = StartOfRound.Instance.allPlayerScripts[playerId]; bool flag = val.isInHangarShipRoom && StartOfRound.Instance.hangarDoorsClosed; RoundManager.Instance.PlayAudibleNoise(((Component)val).transform.position, 15f, 0.6f, 1, flag, 666); DogSoundFix.LogDebug("Loud chat message!", LogLevel.VERY_VERBOSE); } } } [HarmonyPatch(typeof(PlayerControllerB))] public static class PlayerControllerBPatch { [HarmonyPatch("PlayJumpAudio")] [HarmonyPostfix] private static void AlertDoggosBySprintJumping(PlayerControllerB __instance) { //IL_00a2: Unknown result type (might be due to invalid IL or missing references) if (!DogSoundFix.fixSilentSprint.Value) { return; } if (!((NetworkBehaviour)__instance).IsHost) { DogSoundFix.LogDebug("[SilentSprint4] We're not host, skipping..."); return; } SprintChecker sprintChecker = ((Component)__instance).gameObject.GetComponent<SprintChecker>() ?? ((Component)__instance).gameObject.AddComponent<SprintChecker>(); if (sprintChecker.currentState == SprintChecker.PlayerState.SPRINT) { DogSoundFix.LogDebug("[SilentSprint4] " + __instance.playerUsername + " is alerting doggos!"); bool flag = __instance.isInHangarShipRoom && StartOfRound.Instance.hangarDoorsClosed; RoundManager.Instance.PlayAudibleNoise(((Component)__instance).transform.position, 13f, 0.6f, 0, flag, 8); } } [HarmonyPatch("Start")] [HarmonyPostfix] private static void AddCheckForSilentSprint(PlayerControllerB __instance) { if (!DogSoundFix.fixSilentSprint.Value) { return; } if (!((NetworkBehaviour)__instance).IsHost) { DogSoundFix.LogDebug("[SilentSprint1] We're not host, skipping..."); return; } PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; foreach (PlayerControllerB val in allPlayerScripts) { if (val != null && Object.op_Implicit((Object)(object)val) && ((Component)val).gameObject.GetComponent<SprintChecker>() == null) { ((Component)val).gameObject.AddComponent<SprintChecker>(); } } } [HarmonyPatch("Update")] [HarmonyPostfix] private static void CheckForSilentSprint(PlayerControllerB __instance) { if (!DogSoundFix.fixSilentSprint.Value) { return; } if (!((NetworkBehaviour)__instance).IsHost) { DogSoundFix.LogDebug("[SilentSprint2] We're not host, skipping...", LogLevel.VERY_VERBOSE); return; } PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; foreach (PlayerControllerB val in allPlayerScripts) { if (val != null && Object.op_Implicit((Object)(object)val)) { SprintChecker sprintChecker = ((Component)val).gameObject.GetComponent<SprintChecker>() ?? ((Component)val).gameObject.AddComponent<SprintChecker>(); sprintChecker.CheckForRapidStateChange(val); } } } } [HarmonyPatch(typeof(ShotgunItem))] public static class ShotgunPatch { [HarmonyPatch("ShootGunServerRpc")] [HarmonyPostfix] private static void ShootGunServerRpcPostfix(ShotgunItem __instance, Vector3 shotgunPosition) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) HandleShotgunNoise(__instance, 50f, 6f, shotgunPosition); } [HarmonyPatch("ItemInteractLeftRight")] [HarmonyPostfix] private static void ItemInteractLeftRightPostfix(ShotgunItem __instance) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) HandleShotgunNoise(__instance); } [HarmonyPatch("ReloadGunEffectsServerRpc")] [HarmonyPostfix] private static void ReloadGunEffectsServerRpcPostfix(ShotgunItem __instance, bool start) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) bool ignore = start; HandleShotgunNoise(__instance, 4f, 0.5f, default(Vector3), ignore); } private static void HandleShotgunNoise(ShotgunItem shotgunItem, float noiseRange = 4f, float noiseLoudness = 0.5f, Vector3 shotgunPosition = default(Vector3), bool ignore = false) { //IL_0052: 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) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) if (!((NetworkBehaviour)StartOfRound.Instance).IsHost) { DogSoundFix.LogDebug("[Shotgun] We're not host, skipping...", LogLevel.VERBOSE); return; } if (ignore) { DogSoundFix.LogDebug("[Shotgun] Ignoring this shot...", LogLevel.VERBOSE); return; } bool flag = ((GrabbableObject)shotgunItem).isInShipRoom && StartOfRound.Instance.hangarDoorsClosed; if (shotgunPosition == default(Vector3)) { if (((GrabbableObject)shotgunItem).playerHeldBy != null) { shotgunPosition = ((Component)((GrabbableObject)shotgunItem).playerHeldBy).transform.position; } if (shotgunItem.heldByEnemy != null) { shotgunPosition = ((Component)shotgunItem.heldByEnemy).transform.position; } } RoundManager.Instance.PlayAudibleNoise(shotgunPosition, noiseRange, noiseLoudness, 1, flag, 666); DogSoundFix.LogDebug("[Shotgun] Alerting doggos!", LogLevel.VERBOSE); } } } namespace TestAccountFixes.Fixes.AutomaticInventory { internal class AutomaticInventoryFix : Fix { [CompilerGenerated] private sealed class <>c__DisplayClass8_0 { public ManualInventoryFixInputActions manualInventoryFixInputActions; internal bool <RegisterManualInventoryFixKey>b__0() { bool flag = manualInventoryFixInputActions.ManualInventoryFixKey != null; LogDebug($"Manual Inventory Fix Key registered? {flag}", LogLevel.VERY_VERBOSE); if (!flag) { return false; } LogDebug("Manual Inventory Fix Key registered!"); manualInventoryFixInputActions.ManualInventoryFixKey.performed += ReverseThrowingObject; return true; } } [CompilerGenerated] private sealed class <RegisterManualInventoryFixKey>d__8 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public ManualInventoryFixInputActions manualInventoryFixInputActions; private <>c__DisplayClass8_0 <>8__1; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <RegisterManualInventoryFixKey>d__8(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>8__1 = null; <>1__state = -2; } private bool MoveNext() { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>8__1 = new <>c__DisplayClass8_0(); <>8__1.manualInventoryFixInputActions = manualInventoryFixInputActions; LogDebug("Registering Manual Inventory Fix Key..."); <>2__current = (object)new WaitUntil((Func<bool>)delegate { bool flag = <>8__1.manualInventoryFixInputActions.ManualInventoryFixKey != null; LogDebug($"Manual Inventory Fix Key registered? {flag}", LogLevel.VERY_VERBOSE); if (!flag) { return false; } LogDebug("Manual Inventory Fix Key registered!"); <>8__1.manualInventoryFixInputActions.ManualInventoryFixKey.performed += ReverseThrowingObject; return true; }); <>1__state = 1; return true; case 1: <>1__state = -1; return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private const string DESCRIPTION = "Tries to fix inventory issues without user input."; private readonly ConfigFile _configFile; internal static AutomaticInventoryFix Instance { get; private set; } public AutomaticInventoryFix(ConfigFile configFile) { _configFile = configFile; base..ctor(configFile, "AutomaticInventory", "Tries to fix inventory issues without user input."); } internal override void Awake() { Instance = this; Patch(); if (DependencyChecker.IsInventoryFixPluginInstalled()) { LogDebug("InventoryFixPlugin is installed! Not registering the manual inventory fix key!"); return; } ManualInventoryFixInputActions manualInventoryFixInputActions = new ManualInventoryFixInputActions(); ((MonoBehaviour)TestAccountFixes.Instance).StartCoroutine(RegisterManualInventoryFixKey(manualInventoryFixInputActions)); } [IteratorStateMachine(typeof(<RegisterManualInventoryFixKey>d__8))] private static IEnumerator RegisterManualInventoryFixKey(ManualInventoryFixInputActions manualInventoryFixInputActions) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <RegisterManualInventoryFixKey>d__8(0) { manualInventoryFixInputActions = manualInventoryFixInputActions }; } private static void ReverseThrowingObject(CallbackContext context) { if (((CallbackContext)(ref context)).performed && Object.op_Implicit((Object)(object)StartOfRound.Instance)) { PlayerControllerB localPlayerController = StartOfRound.Instance.localPlayerController; if (Object.op_Implicit((Object)(object)localPlayerController) && localPlayerController != null && !localPlayerController.inTerminalMenu && !localPlayerController.isTypingChat) { localPlayerController.throwingObject = !localPlayerController.throwingObject; HUDManager.Instance.DisplayTip("TestAccountFixes", "Manual Inventory Fix triggered", true, false, "LC_Tip1"); LogDebug("Manual fix was triggered! ThrowingObject? " + localPlayerController.throwingObject); } } } internal new static void LogDebug(string message, LogLevel logLevel = LogLevel.NORMAL) { ((Fix)Instance).LogDebug(message, logLevel); } } public class ManualInventoryFixInputActions : LcInputActions { [InputAction(/*Could not decode attribute arguments.*/)] public InputAction? ManualInventoryFixKey { get; set; } } } namespace TestAccountFixes.Fixes.AutomaticInventory.Patches { [HarmonyPatch(typeof(PlayerControllerB))] public static class PlayerControllerBFinalizer { [HarmonyPatch("SetObjectAsNoLongerHeld")] [HarmonyFinalizer] public static Exception SetObjectAsNoLongerHeldFinalizer(Exception __exception, GrabbableObject dropObject, Vector3 targetFloorPosition) { //IL_00df: Unknown result type (might be due to invalid IL or missing references) AutomaticInventoryFix.LogDebug("[NoLongerHeld] Exception? " + (__exception != null), LogLevel.VERY_VERBOSE); if (__exception == null) { return null; } AutomaticInventoryFix.LogDebug("Caught Exception from PlayerControllerB#SetObjectAsNoLongerHeld method!"); Extensions.LogDetailed(__exception, (string)null); AutomaticInventoryFix.LogDebug("More Information:"); AutomaticInventoryFix.LogDebug("dropObject null? " + ((Object)(object)dropObject == (Object)null)); AutomaticInventoryFix.LogDebug("targetFloorPosition null? " + false); if ((Object)(object)dropObject == (Object)null) { return null; } AutomaticInventoryFix.LogDebug("transform null? " + ((Object)(object)((Component)dropObject).transform == (Object)null)); if ((Object)(object)((Component)dropObject).transform == (Object)null) { return null; } _ = ((Component)dropObject).transform.position; AutomaticInventoryFix.LogDebug("transform position null? " + false); AutomaticInventoryFix.LogDebug("transform parent null? " + ((Object)(object)((Component)dropObject).transform.parent == (Object)null)); return null; } } [HarmonyPatch(typeof(PlayerControllerB))] public static class PlayerControllerBPatch { private static long _throwTimeoutTime; private static long _grabTimeoutTime; private static NetworkObject? _thrownObject; private static readonly int _CancelHoldingHash = Animator.StringToHash("cancelHolding"); [HarmonyPatch("Update")] [HarmonyPostfix] private static void AfterUpdate(PlayerControllerB __instance) { if (!__instance.isPlayerControlled || __instance.isPlayerDead) { return; } try { ThrowObjectCheck(__instance); } catch (Exception ex) { Extensions.LogDetailed(ex, (string)null); } try { GrabObjectCheck(__instance); } catch (Exception ex2) { Extensions.LogDetailed(ex2, (string)null); } } [HarmonyPatch("DiscardHeldObject")] [HarmonyPrefix] private static void DiscardHeldObjectPrefix(PlayerControllerB __instance, NetworkObject parentObjectTo) { if (__instance != null && ((NetworkBehaviour)__instance).IsOwner) { GrabbableObject currentlyHeldObjectServer = __instance.currentlyHeldObjectServer; NetworkObject component = ((Component)currentlyHeldObjectServer).GetComponent<NetworkObject>(); NetworkObject val = parentObjectTo ?? component; if (val != null) { long currentTime = UnixTime.GetCurrentTime(); AutomaticInventoryFix.LogDebug("Detected throw! Setting timeout..."); _throwTimeoutTime = currentTime + 1000; _thrownObject = val; } } } private static void ThrowObjectCheck(PlayerControllerB player) { //IL_007d: Unknown result type (might be due to invalid IL or missing references) if (_throwTimeoutTime <= 0) { return; } if (player.hasThrownObject) { _throwTimeoutTime = 0L; return; } long currentTime = UnixTime.GetCurrentTime(); if (_throwTimeoutTime <= currentTime) { AutomaticInventoryFix.LogDebug("Detected throw lasting longer than 1 second, giving up..."); player.throwingObject = false; player.playerBodyAnimator.SetBool(_CancelHoldingHash, false); _throwTimeoutTime = 0L; if (_thrownObject != null) { player.GrabObjectServerRpc(NetworkObjectReference.op_Implicit(_thrownObject)); } } } private static void GrabObjectCheck(PlayerControllerB player) { GrabbableObject currentlyGrabbingObject = player.currentlyGrabbingObject; if (currentlyGrabbingObject == null) { _grabTimeoutTime = 0L; return; } if (player.grabbedObjectValidated) { _grabTimeoutTime = 0L; return; } long currentTime = UnixTime.GetCurrentTime(); if (_grabTimeoutTime <= 0) { AutomaticInventoryFix.LogDebug("Detected grab! Setting timeout..."); _grabTimeoutTime = currentTime + 1000; } else { if (_grabTimeoutTime > currentTime) { return; } AutomaticInventoryFix.LogDebug("Detected grab lasting longer than 1 second, giving up..."); player.grabInvalidated = true; player.currentlyGrabbingObject = null; if (!((Object)(object)currentlyGrabbingObject.parentObject != (Object)(object)player.localItemHolder)) { if (currentlyGrabbingObject.playerHeldBy != null) { currentlyGrabbingObject.parentObject = currentlyGrabbingObject.playerHeldBy.serverItemHolder; } else if (currentlyGrabbingObject.isInShipRoom || currentlyGrabbingObject.isInElevator) { currentlyGrabbingObject.parentObject = StartOfRound.Instance.elevatorTransform; } else { currentlyGrabbingObject.parentObject = null; } } } } } } namespace TestAccountFixes.Dependencies { internal static class DependencyChecker { private static readonly Dictionary<string, bool> _DependencyDictionary = new Dictionary<string, bool>(); internal static bool IsLobbyCompatibilityInstalled() { return DependencyChecker.IsLobbyCompatibilityInstalled(); } internal static bool IsBetterItemHandlingInstalled() { return IsInstalled("Yan01h.BetterItemHandling"); } internal static bool IsInventoryFixPluginInstalled() { return IsInstalled("Dokge.InventoryFixPlugin"); } private static bool IsInstalled(string key) { string key2 = key; if (_DependencyDictionary.ContainsKey(key2)) { return DictionaryExtensions.Get<string, bool>((IDictionary<string, bool>)_DependencyDictionary, key2, false); } bool flag = Chainloader.PluginInfos.Values.Any((PluginInfo metadata) => metadata.Metadata.GUID.Contains(key2)); _DependencyDictionary.Add(key2, flag); return flag; } } } namespace TestAccountFixes.Core { public enum LogLevel { NORMAL, VERBOSE, VERY_VERBOSE } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }