using 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("DissonanceVoip")]
[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.3.5.0")]
[assembly: AssemblyInformationalVersion("1.3.5+373f6f1445f0e35e6c7470b5fac93ea58a7d3914")]
[assembly: AssemblyProduct("TestAccountFixes")]
[assembly: AssemblyTitle("TestAccount666.TestAccountFixes")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.3.5.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.3.5")]
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.3.5", (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.3.5 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.3.5";
}
}
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
{
[HarmonyPatch("OnCollideWithPlayer")]
[HarmonyTranspiler]
private static IEnumerable<CodeInstruction> AdjustSpooderDamageValue(IEnumerable<CodeInstruction> instructions)
{
foreach (CodeInstruction codeInstruction in instructions)
{
if (codeInstruction.opcode != OpCodes.Ldc_I4_S)
{
yield return codeInstruction;
}
else
{
yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(SpiderDamageFix), "GetSpooderDamage", (Type[])null, (Type[])null));
}
}
}
}
}
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
{
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));
}
private static IEnumerator RegisterManualInventoryFixKey(ManualInventoryFixInputActions manualInventoryFixInputActions)
{
ManualInventoryFixInputActions manualInventoryFixInputActions2 = manualInventoryFixInputActions;
yield return (object)new WaitUntil((Func<bool>)(() => manualInventoryFixInputActions2.ManualInventoryFixKey != null));
manualInventoryFixInputActions2.ManualInventoryFixKey.performed += ReverseThrowingObject;
}
private static void ReverseThrowingObject(CallbackContext context)
{
if (((CallbackContext)(ref context)).performed && StartOfRound.Instance != null)
{
PlayerControllerB localPlayerController = StartOfRound.Instance.localPlayerController;
if (localPlayerController != null)
{
localPlayerController.throwingObject = !localPlayerController.throwingObject;
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)
{
}
}
}