Decompiled source of Big Scratch v1.0.2

BWScratch.dll

Decompiled 12 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using Mirror;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("BWScratch")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.2.0")]
[assembly: AssemblyInformationalVersion("1.0.2")]
[assembly: AssemblyProduct("BWScratch")]
[assembly: AssemblyTitle("BWScratch")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.2.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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 BWScratch
{
	public enum ScratchHand
	{
		Right,
		Left
	}
	public enum EyeLook
	{
		Keep,
		Circle,
		Line,
		Wobbly,
		Sleeping,
		Squint,
		Ring,
		Dead,
		SmallCircle,
		Square,
		ThickRing,
		Spiral
	}
	public enum EyeMode
	{
		Random,
		Fixed
	}
	[BepInPlugin("bigwalk.scratch", "Big Scratch", "1.0.2")]
	public class ScratchPlugin : BasePlugin
	{
		public const string Guid = "bigwalk.scratch";

		public const string Name = "Big Scratch";

		public const string Ver = "1.0.2";

		internal static ManualLogSource L;

		internal static ConfigEntry<KeyCode> KeyScratch;

		internal static ConfigEntry<ScratchHand> Hand;

		internal static ConfigEntry<bool> BlockWhileHolding;

		internal static ConfigEntry<bool> HoldOtherArm;

		internal static ConfigEntry<bool> WakeUp;

		internal static ConfigEntry<bool> ShareWithOthers;

		internal static ConfigEntry<bool> ShowOthers;

		internal static ConfigEntry<float> HandAngle;

		internal static ConfigEntry<float> HandElevation;

		internal static ConfigEntry<float> Press;

		internal static ConfigEntry<float> ElbowAngle;

		internal static ConfigEntry<float> ElbowElevation;

		internal static ConfigEntry<float> ElbowRadius;

		internal static ConfigEntry<float> Amp;

		internal static ConfigEntry<float> Hz;

		internal static ConfigEntry<float> Direction;

		internal static ConfigEntry<float> BlendIn;

		internal static ConfigEntry<float> BlendOut;

		internal static ConfigEntry<float> MaxReach;

		internal static ConfigEntry<bool> FaceEyes;

		internal static ConfigEntry<EyeMode> FaceMode;

		internal static ConfigEntry<float> WildChance;

		internal static ConfigEntry<EyeLook> LeftEye;

		internal static ConfigEntry<EyeLook> RightEye;

		internal static ConfigEntry<bool> Rhythm;

		internal static ConfigEntry<EyeLook> RhythmEye;

		internal static ConfigEntry<int> RhythmEvery;

		internal static ConfigEntry<bool> ScratchOthers;

		internal static ConfigEntry<float> AimAngle;

		internal static ConfigEntry<float> Range;

		internal static ConfigEntry<float> Reach;

		internal static ConfigEntry<bool> Startle;

		internal static ConfigEntry<float> StartleSeconds;

		internal static ConfigEntry<bool> StartleSound;

		internal static ConfigEntry<bool> ReactEyes;

		internal static ConfigEntry<bool> DebugMarker;

		internal static ConfigEntry<bool> DebugLog;

		public override void Load()
		{
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Expected O, but got Unknown
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Expected O, but got Unknown
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Expected O, but got Unknown
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Expected O, but got Unknown
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Expected O, but got Unknown
			//IL_024b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Expected O, but got Unknown
			//IL_0288: Unknown result type (might be due to invalid IL or missing references)
			//IL_0292: Expected O, but got Unknown
			//IL_02c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cf: Expected O, but got Unknown
			//IL_0302: Unknown result type (might be due to invalid IL or missing references)
			//IL_030c: Expected O, but got Unknown
			//IL_033f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0349: Expected O, but got Unknown
			//IL_037c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0386: Expected O, but got Unknown
			//IL_03b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c3: Expected O, but got Unknown
			//IL_0436: Unknown result type (might be due to invalid IL or missing references)
			//IL_0440: Expected O, but got Unknown
			//IL_04e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f1: Expected O, but got Unknown
			//IL_0544: Unknown result type (might be due to invalid IL or missing references)
			//IL_054e: Expected O, but got Unknown
			//IL_0581: Unknown result type (might be due to invalid IL or missing references)
			//IL_058b: Expected O, but got Unknown
			//IL_05be: Unknown result type (might be due to invalid IL or missing references)
			//IL_05c8: Expected O, but got Unknown
			//IL_061b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0625: Expected O, but got Unknown
			//IL_06e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_06e7: Expected O, but got Unknown
			//IL_080d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0814: Expected O, but got Unknown
			//IL_0846: Unknown result type (might be due to invalid IL or missing references)
			L = ((BasePlugin)this).Log;
			KeyScratch = ((BasePlugin)this).Config.Bind<KeyCode>("Keys", "Scratch", (KeyCode)39, "Hold to scratch.");
			Hand = ((BasePlugin)this).Config.Bind<ScratchHand>("General", "Hand", ScratchHand.Right, "Which hand scratches.");
			BlockWhileHolding = ((BasePlugin)this).Config.Bind<bool>("General", "BlockWhileHolding", true, "Do not scratch while holding a prop or a player.");
			HoldOtherArm = ((BasePlugin)this).Config.Bind<bool>("General", "HoldOtherArm", true, "Keep the other arm in its normal pose while scratching (otherwise the game leaves it hanging behind you).");
			WakeUp = ((BasePlugin)this).Config.Bind<bool>("General", "WakeUp", true, "Scratching counts as activity: wakes you up if asleep and keeps you awake while held.");
			ShareWithOthers = ((BasePlugin)this).Config.Bind<bool>("Network", "ShareWithOthers", true, "Let other players who also have this mod see you scratch (sent inside the game's own echo sync; players without the mod are unaffected).");
			ShowOthers = ((BasePlugin)this).Config.Bind<bool>("Network", "ShowOthers", true, "Show other players' scratches when they have the mod.");
			HandAngle = ((BasePlugin)this).Config.Bind<float>("Hand", "Angle", 30f, new ConfigDescription("Where on the bum, in degrees: 0 = straight back, 90 = fully on the scratching side.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-30f, 120f), Array.Empty<object>()));
			HandElevation = ((BasePlugin)this).Config.Bind<float>("Hand", "Elevation", 25f, new ConfigDescription("Height on the bum, in degrees: 0 = centre height, 45 = upper back, -45 = lower back.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-80f, 80f), Array.Empty<object>()));
			Press = ((BasePlugin)this).Config.Bind<float>("Hand", "Press", 0.35f, new ConfigDescription("How far the hand sinks into the bum: 0 = just touching, 1 = hand centre on the surface.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			ElbowAngle = ((BasePlugin)this).Config.Bind<float>("Elbow", "Angle", 80f, new ConfigDescription("Elbow direction, degrees: 0 = straight back, 90 = out to the side.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-30f, 150f), Array.Empty<object>()));
			ElbowElevation = ((BasePlugin)this).Config.Bind<float>("Elbow", "Elevation", 37f, new ConfigDescription("Elbow height, degrees above the bum centre.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-60f, 80f), Array.Empty<object>()));
			ElbowRadius = ((BasePlugin)this).Config.Bind<float>("Elbow", "Radius", 2f, new ConfigDescription("Elbow distance from the bum centre, as a multiple of the bum surface distance.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 2.5f), Array.Empty<object>()));
			Amp = ((BasePlugin)this).Config.Bind<float>("Motion", "Amplitude", 0.035f, new ConfigDescription("Rub amplitude in metres.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.15f), Array.Empty<object>()));
			Hz = ((BasePlugin)this).Config.Bind<float>("Motion", "Speed", 4f, new ConfigDescription("Rubs per second.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 12f), Array.Empty<object>()));
			Direction = ((BasePlugin)this).Config.Bind<float>("Motion", "Direction", 20f, new ConfigDescription("Rub direction, degrees: 0 = up and down, 90 = side to side.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 90f), Array.Empty<object>()));
			BlendIn = ((BasePlugin)this).Config.Bind<float>("Motion", "BlendIn", 0.3f, new ConfigDescription("Seconds for the hand to travel to the bum.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 1.5f), Array.Empty<object>()));
			BlendOut = ((BasePlugin)this).Config.Bind<float>("Motion", "BlendOut", 0.35f, new ConfigDescription("Seconds for the hand to travel back.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 1.5f), Array.Empty<object>()));
			MaxReach = ((BasePlugin)this).Config.Bind<float>("Motion", "MaxReach", 0.55f, new ConfigDescription("Max shoulder-to-hand distance, metres.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 1f), Array.Empty<object>()));
			FaceEyes = ((BasePlugin)this).Config.Bind<bool>("Face", "Eyes", true, "Change the eyes while scratching (also what other players with the mod see).");
			FaceMode = ((BasePlugin)this).Config.Bind<EyeMode>("Face", "Mode", EyeMode.Random, "Random = each press draws a look from a curated set; Fixed = always the LeftEye/RightEye/Rhythm settings below.");
			WildChance = ((BasePlugin)this).Config.Bind<float>("Face", "WildChance", 0.2f, new ConfigDescription("Random mode: chance that a press draws any combination at all (Dead and Sleeping included) instead of a curated look.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			LeftEye = ((BasePlugin)this).Config.Bind<EyeLook>("Face", "LeftEye", EyeLook.Squint, "Fixed mode: left eye while scratching. Keep = the game's own eyes.");
			RightEye = ((BasePlugin)this).Config.Bind<EyeLook>("Face", "RightEye", EyeLook.Squint, "Fixed mode: right eye while scratching. Keep = the game's own eyes.");
			Rhythm = ((BasePlugin)this).Config.Bind<bool>("Face", "Rhythm", true, "Fixed mode: wink in time with the rubbing, the eyes taking turns showing RhythmEye.");
			RhythmEye = ((BasePlugin)this).Config.Bind<EyeLook>("Face", "RhythmEye", EyeLook.Line, "Fixed mode: the look the winking eye takes.");
			RhythmEvery = ((BasePlugin)this).Config.Bind<int>("Face", "RhythmEvery", 1, new ConfigDescription("Fixed mode: swap the winking eye every this many rubs.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 4), Array.Empty<object>()));
			ScratchOthers = ((BasePlugin)this).Config.Bind<bool>("Others", "ScratchOthers", true, "Scratch another player's bum instead of your own when you look at them from close by.");
			AimAngle = ((BasePlugin)this).Config.Bind<float>("Others", "AimAngle", 20f, new ConfigDescription("How precisely you must look at the other player (any part of them), degrees from the centre of the screen.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 60f), Array.Empty<object>()));
			Range = ((BasePlugin)this).Config.Bind<float>("Others", "Range", 1f, new ConfigDescription("Max distance from your shoulder to their bum, metres.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 2f), Array.Empty<object>()));
			Reach = ((BasePlugin)this).Config.Bind<float>("Others", "Reach", 0.8f, new ConfigDescription("How far the arm may stretch when scratching someone else, metres.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.3f, 1.5f), Array.Empty<object>()));
			Startle = ((BasePlugin)this).Config.Bind<bool>("Others", "Startle", true, "The scratched player's eyes go startled (the game's snatched look, SmallCircle) when the scratch starts, before the random reaction.");
			StartleSeconds = ((BasePlugin)this).Config.Bind<float>("Others", "StartleSeconds", 0.6f, new ConfigDescription("How long the startled eyes last, seconds.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>()));
			StartleSound = ((BasePlugin)this).Config.Bind<bool>("Others", "StartleSound", true, "Play the game's snatched-reaction sound at the scratched player when the scratch starts.");
			ReactEyes = ((BasePlugin)this).Config.Bind<bool>("Others", "ReactEyes", true, "The scratched player's eyes show a random reaction while being scratched.");
			DebugMarker = ((BasePlugin)this).Config.Bind<bool>("Debug", "Marker", false, "Show small spheres at the hand (grey) and elbow (dark) targets.");
			DebugLog = ((BasePlugin)this).Config.Bind<bool>("Debug", "Log", false, "Log the first frames of each scratch, all network frames and the game's own eye changes.");
			try
			{
				ClassInjector.RegisterTypeInIl2Cpp<ScratchBehaviour>();
				((BasePlugin)this).AddComponent<ScratchBehaviour>();
			}
			catch (Exception ex)
			{
				L.LogError((object)("[BWScratch] AddComponent failed: " + ex));
			}
			Harmony val = new Harmony("bigwalk.scratch");
			try
			{
				val.PatchAll(typeof(ArmsLateUpdatePatch));
			}
			catch (Exception ex2)
			{
				L.LogError((object)("[BWScratch] Harmony patch (arms) failed: " + ex2));
			}
			try
			{
				val.PatchAll(typeof(SplineRefreshPatch));
			}
			catch (Exception ex3)
			{
				L.LogError((object)("[BWScratch] Harmony patch (spline) failed: " + ex3));
			}
			try
			{
				val.PatchAll(typeof(EchoCommandPatch));
			}
			catch (Exception ex4)
			{
				L.LogError((object)("[BWScratch] Harmony patch (echo) failed - sharing will not work: " + ex4));
			}
			try
			{
				val.PatchAll(typeof(EyeMoodPatch));
			}
			catch (Exception ex5)
			{
				L.LogError((object)("[BWScratch] Harmony patch (eyes) failed - eyes will not change: " + ex5));
			}
			try
			{
				val.PatchAll(typeof(SnatchReactPatch));
			}
			catch (Exception ex6)
			{
				L.LogWarning((object)("[BWScratch] Harmony patch (snatch log) failed: " + ex6));
			}
			ManualLogSource l = L;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(203, 23, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[BWScratch] ");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>("1.0.2");
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" loaded. Hold ");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<KeyCode>(KeyScratch.Value);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" to scratch with the ");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<ScratchHand>(Hand.Value);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" hand. share=");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<bool>(ShareWithOthers.Value);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" show=");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<bool>(ShowOthers.Value);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" eyes=");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<bool>(FaceEyes.Value);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" mode=");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<EyeMode>(FaceMode.Value);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" wild=");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<float>(WildChance.Value, "0.00");
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" (fixed: ");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<EyeLook>(LeftEye.Value);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("/");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<EyeLook>(RightEye.Value);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", rhythm=");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<bool>(Rhythm.Value);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" ");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<EyeLook>(RhythmEye.Value);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" every ");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(RhythmEvery.Value);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("); ");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(ScratchFace.Curated.Length);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" curated looks; others=");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<bool>(ScratchOthers.Value);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" aim=");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<float>(AimAngle.Value, "0");
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("deg range=");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<float>(Range.Value, "0.00");
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("m reach=");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<float>(Reach.Value, "0.00");
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("m startle=");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<bool>(Startle.Value);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" ");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<float>(StartleSeconds.Value, "0.0");
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("s sound=");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<bool>(StartleSound.Value);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" reactEyes=");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<bool>(ReactEyes.Value);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" (");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(ScratchFace.Reactions.Length);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" reactions)");
			}
			l.LogInfo(val2);
		}
	}
	[HarmonyPatch(typeof(PlayerArms), "LateUpdate")]
	internal static class ArmsLateUpdatePatch
	{
		private static void Prefix(PlayerArms __instance)
		{
			try
			{
				ScratchBehaviour.BeforeArmsLateUpdate(__instance);
			}
			catch (Exception ex)
			{
				ScratchBehaviour.Once("armspre", "[BWScratch] arms prefix error: " + ex);
			}
		}

		private static void Postfix(PlayerArms __instance)
		{
			try
			{
				ScratchBehaviour.AfterArmsLateUpdate(__instance);
			}
			catch (Exception ex)
			{
				ScratchBehaviour.Once("arms", "[BWScratch] arms postfix error: " + ex);
			}
		}
	}
	[HarmonyPatch(typeof(LimbSpline), "Refresh")]
	internal static class SplineRefreshPatch
	{
		private static void Postfix(LimbSpline __instance)
		{
			try
			{
				ScratchBehaviour.AfterSplineRefresh(__instance);
			}
			catch (Exception ex)
			{
				ScratchBehaviour.Once("refresh", "[BWScratch] refresh postfix error: " + ex);
			}
		}
	}
	[HarmonyPatch(typeof(PlayerNetworking), "CmdSetEchoAmount")]
	internal static class EchoCommandPatch
	{
		private static void Prefix(PlayerNetworking __instance, ref float __0)
		{
			try
			{
				__0 = ScratchNet.OnOutgoingEcho(__instance, __0);
			}
			catch (Exception ex)
			{
				ScratchBehaviour.Once("echopre", "[BWScratch] echo prefix error: " + ex);
			}
		}
	}
	[HarmonyPatch(typeof(PlayerEyes), "SetEyeMood", new Type[]
	{
		typeof(PlayerEyeMood),
		typeof(PlayerEyeMood)
	})]
	internal static class EyeMoodPatch
	{
		private static void Prefix(PlayerEyes __instance, ref PlayerEyeMood __0, ref PlayerEyeMood __1)
		{
			try
			{
				ScratchFace.OnSetEyeMood(__instance, ref __0, ref __1);
			}
			catch (Exception ex)
			{
				ScratchBehaviour.Once("eyepre", "[BWScratch] eye prefix error: " + ex);
			}
		}
	}
	[HarmonyPatch(typeof(PlayerHands), "ReactSnatched")]
	internal static class SnatchReactPatch
	{
		private static void Postfix(PlayerHands __instance)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected O, but got Unknown
			try
			{
				if (!ScratchPlugin.DebugLog.Value)
				{
					return;
				}
				string text = "?";
				try
				{
					PlayerCharacter playerCharacter = __instance.playerCharacter;
					if ((Object)(object)playerCharacter != (Object)null)
					{
						text = ScratchBehaviour.NameOf(playerCharacter);
					}
				}
				catch
				{
				}
				ManualLogSource l = ScratchPlugin.L;
				bool flag = default(bool);
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(77, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[BWScratch] eyes ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(text);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": snatch reaction played f");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(Time.frameCount);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" (watch the next 'game set' lines)");
				}
				l.LogInfo(val);
			}
			catch (Exception ex)
			{
				ScratchBehaviour.Once("snatchlog", "[BWScratch] snatch log error: " + ex);
			}
		}
	}
	internal static class Wire
	{
		public const int Magic = 5;

		public const int Mask = 65535;

		public static int Pack(int id, int val)
		{
			int num = ((id & 0xF) << 5) | (val & 0x1F);
			return 0xA000 | (Check(num) << 9) | num;
		}

		private static int Check(int body)
		{
			int num = body * 40503 + 23505;
			int num2 = num ^ (num >> 7);
			return (num2 ^ (num2 >> 3)) & 0xF;
		}

		public static bool Unpack(int frame, out int id, out int val)
		{
			frame &= 0xFFFF;
			id = 0;
			val = 0;
			if (frame >> 13 != 5)
			{
				return false;
			}
			int num = frame & 0x1FF;
			if (((frame >> 9) & 0xF) != Check(num))
			{
				return false;
			}
			id = (num >> 5) & 0xF;
			val = num & 0x1F;
			return true;
		}

		public static int FrameOf(float v)
		{
			if (float.IsNaN(v) || float.IsInfinity(v))
			{
				return 0;
			}
			return BitConverter.SingleToInt32Bits(v) & 0xFFFF;
		}

		public static float Base(float v)
		{
			if (float.IsNaN(v) || float.IsInfinity(v))
			{
				return v;
			}
			return BitConverter.Int32BitsToSingle(BitConverter.SingleToInt32Bits(v) & -65536);
		}

		public static float Encode(float v, int frame)
		{
			if (float.IsNaN(v) || float.IsInfinity(v))
			{
				return v;
			}
			int num = BitConverter.SingleToInt32Bits(v);
			int num2 = num & -65536;
			if ((num & 0x7F800000) == 0)
			{
				num2 = (num & int.MinValue) | 0x35800000;
				return BitConverter.Int32BitsToSingle(num2 | (frame & 0xFFFF));
			}
			int num3 = num2 | (frame & 0xFFFF);
			if ((num3 & 0x7FFFFFFF) > (num & 0x7FFFFFFF) && (num2 & 0x7FFFFFFF) >= 65536)
			{
				num3 = (num2 - 65536) | (frame & 0xFFFF);
			}
			return BitConverter.Int32BitsToSingle(num3);
		}
	}
	internal struct Pose
	{
		public bool left;

		public float handAngle;

		public float handElev;

		public float press;

		public float elbowAngle;

		public float elbowElev;

		public float elbowRadius;

		public float amp;

		public float hz;

		public float dir;

		public int look;

		public int eyeL;

		public int eyeR;

		public bool rhythm;

		public int rhythmEye;

		public int rhythmEvery;

		public const int LookNone = 0;

		public const int LookCustom = 31;

		private static readonly float[] Min = new float[14]
		{
			0f, -30f, -80f, 0f, -30f, -60f, 1f, 0f, 0.5f, 0f,
			0f, 0f, 0f, 0f
		};

		private static readonly float[] Max = new float[14]
		{
			0f, 120f, 80f, 1f, 150f, 80f, 2.5f, 0.15f, 12f, 90f,
			0f, 0f, 0f, 0f
		};

		private static readonly bool[] Raw = new bool[14]
		{
			false, false, false, false, false, false, false, false, false, false,
			true, true, true, true
		};

		public const int ParamCount = 13;

		public bool HasEyes
		{
			get
			{
				if (look != 0)
				{
					if (eyeL == 0 && eyeR == 0)
					{
						if (rhythm)
						{
							return rhythmEye != 0;
						}
						return false;
					}
					return true;
				}
				return false;
			}
		}

		public string EyesText => $"{eyeL}/{eyeR}" + ((rhythm && rhythmEye != 0) ? $" + {rhythmEye} every {rhythmEvery}" : "") + ((look == 0) ? " (none)" : ((look == 31) ? " (custom)" : $" (#{look - 1})"));

		public int[] EyeIds
		{
			get
			{
				if (look == 31)
				{
					return new int[4] { 10, 11, 12, 13 };
				}
				return new int[1] { 10 };
			}
		}

		public static Pose FromConfig()
		{
			bool value = ScratchPlugin.FaceEyes.Value;
			Pose result = new Pose
			{
				left = (ScratchPlugin.Hand.Value == ScratchHand.Left),
				handAngle = ScratchPlugin.HandAngle.Value,
				handElev = ScratchPlugin.HandElevation.Value,
				press = ScratchPlugin.Press.Value,
				elbowAngle = ScratchPlugin.ElbowAngle.Value,
				elbowElev = ScratchPlugin.ElbowElevation.Value,
				elbowRadius = ScratchPlugin.ElbowRadius.Value,
				amp = ScratchPlugin.Amp.Value,
				hz = ScratchPlugin.Hz.Value,
				dir = ScratchPlugin.Direction.Value,
				look = 0
			};
			if (value)
			{
				result.look = 31;
				result.eyeL = (int)ScratchPlugin.LeftEye.Value;
				result.eyeR = (int)ScratchPlugin.RightEye.Value;
				result.rhythm = ScratchPlugin.Rhythm.Value;
				result.rhythmEye = (int)ScratchPlugin.RhythmEye.Value;
				result.rhythmEvery = Mathf.Clamp(ScratchPlugin.RhythmEvery.Value, 1, 4);
			}
			return result;
		}

		public void SetEyes(EyeCombo c)
		{
			eyeL = c.l;
			eyeR = c.r;
			rhythm = c.rhythm;
			rhythmEye = c.rhythmEye;
			rhythmEvery = Mathf.Clamp(c.every, 1, 4);
			look = ((c.index >= 0 && c.index + 1 < 31) ? (c.index + 1) : 31);
		}

		public void ClearEyes()
		{
			look = 0;
			eyeL = (eyeR = 0);
			rhythm = false;
			rhythmEye = 0;
		}

		public float Get(int id)
		{
			return id switch
			{
				1 => handAngle, 
				2 => handElev, 
				3 => press, 
				4 => elbowAngle, 
				5 => elbowElev, 
				6 => elbowRadius, 
				7 => amp, 
				8 => hz, 
				9 => dir, 
				10 => look, 
				11 => (eyeL & 0xF) | (((rhythmEvery - 1) & 1) << 4), 
				12 => (eyeR & 0xF) | (((rhythmEvery - 1 >> 1) & 1) << 4), 
				13 => (rhythm ? 16 : 0) | (rhythmEye & 0xF), 
				_ => 0f, 
			};
		}

		public void Set(int id, float v)
		{
			int num = (int)v;
			switch (id)
			{
			case 1:
				handAngle = v;
				break;
			case 2:
				handElev = v;
				break;
			case 3:
				press = v;
				break;
			case 4:
				elbowAngle = v;
				break;
			case 5:
				elbowElev = v;
				break;
			case 6:
				elbowRadius = v;
				break;
			case 7:
				amp = v;
				break;
			case 8:
				hz = v;
				break;
			case 9:
				dir = v;
				break;
			case 10:
				if (num >= 1 && num < 31 && num - 1 < ScratchFace.Curated.Length)
				{
					SetEyes(ScratchFace.Curated[num - 1]);
				}
				else if (num == 31)
				{
					look = 31;
				}
				else
				{
					ClearEyes();
				}
				break;
			case 11:
				eyeL = Look(num & 0xF);
				rhythmEvery = ((rhythmEvery - 1) & 2) + ((num >> 4) & 1) + 1;
				break;
			case 12:
				eyeR = Look(num & 0xF);
				rhythmEvery = ((rhythmEvery - 1) & 1) + (((num >> 4) & 1) << 1) + 1;
				break;
			case 13:
				rhythm = (num & 0x10) != 0;
				rhythmEye = Look(num & 0xF);
				break;
			}
		}

		private static int Look(float v)
		{
			int num = (int)v;
			if (num < 0 || num > 11)
			{
				return 0;
			}
			return num;
		}

		public static int Quantise(int id, float v)
		{
			if (Raw[id])
			{
				return Mathf.Clamp(Mathf.RoundToInt(v), 0, 31);
			}
			return Mathf.Clamp(Mathf.RoundToInt(Mathf.InverseLerp(Min[id], Max[id], v) * 31f), 0, 31);
		}

		public static float Dequantise(int id, int q)
		{
			if (Raw[id])
			{
				return Mathf.Clamp(q, 0, 31);
			}
			return Mathf.Lerp(Min[id], Max[id], (float)Mathf.Clamp(q, 0, 31) / 31f);
		}
	}
	internal struct EyeCombo
	{
		public int l;

		public int r;

		public bool rhythm;

		public int rhythmEye;

		public int every;

		public string name;

		public int index;

		public EyeCombo(string name, EyeLook l, EyeLook r, EyeLook rhythmEye = EyeLook.Keep, int every = 1)
		{
			this.name = name;
			this.l = (int)l;
			this.r = (int)r;
			rhythm = rhythmEye != EyeLook.Keep;
			this.rhythmEye = (int)rhythmEye;
			this.every = every;
			index = -1;
		}
	}
	internal static class ScratchFace
	{
		private static readonly Dictionary<IntPtr, PlayerState> _byEyes;

		private static int _gameLogLines;

		private const int MaxGameLogLines = 120;

		private static readonly Random Rng;

		private static int _lastCurated;

		internal static EyeCombo EyesShut;

		internal static readonly EyeCombo[] Curated;

		internal static readonly EyeCombo[] Reactions;

		static ScratchFace()
		{
			_byEyes = new Dictionary<IntPtr, PlayerState>();
			Rng = new Random();
			_lastCurated = -1;
			Curated = new EyeCombo[14]
			{
				new EyeCombo("squint", EyeLook.Squint, EyeLook.Squint),
				new EyeCombo("eyes shut", EyeLook.Line, EyeLook.Line),
				new EyeCombo("dizzy", EyeLook.Spiral, EyeLook.Spiral),
				new EyeCombo("wobbly", EyeLook.Wobbly, EyeLook.Wobbly),
				new EyeCombo("wide", EyeLook.Ring, EyeLook.Ring),
				new EyeCombo("pinpoint", EyeLook.SmallCircle, EyeLook.SmallCircle),
				new EyeCombo("wink right", EyeLook.Circle, EyeLook.Line),
				new EyeCombo("wink left", EyeLook.Line, EyeLook.Circle),
				new EyeCombo("squint wink right", EyeLook.Squint, EyeLook.Line),
				new EyeCombo("squint wink left", EyeLook.Line, EyeLook.Squint),
				new EyeCombo("squint, winking in rhythm", EyeLook.Squint, EyeLook.Squint, EyeLook.Line),
				new EyeCombo("winking in rhythm", EyeLook.Circle, EyeLook.Circle, EyeLook.Line, 2),
				new EyeCombo("wide, winking in rhythm", EyeLook.Ring, EyeLook.Ring, EyeLook.Line, 2),
				new EyeCombo("dizzy, squinting in rhythm", EyeLook.Spiral, EyeLook.Spiral, EyeLook.Squint)
			};
			Reactions = new EyeCombo[11]
			{
				new EyeCombo("startled", EyeLook.SmallCircle, EyeLook.SmallCircle),
				new EyeCombo("wide", EyeLook.Ring, EyeLook.Ring),
				new EyeCombo("very wide", EyeLook.ThickRing, EyeLook.ThickRing),
				new EyeCombo("dizzy", EyeLook.Spiral, EyeLook.Spiral),
				new EyeCombo("wobbly", EyeLook.Wobbly, EyeLook.Wobbly),
				new EyeCombo("squint", EyeLook.Squint, EyeLook.Squint),
				new EyeCombo("eyes shut", EyeLook.Line, EyeLook.Line),
				new EyeCombo("wink right", EyeLook.Circle, EyeLook.Line),
				new EyeCombo("wink left", EyeLook.Line, EyeLook.Circle),
				new EyeCombo("winking in rhythm", EyeLook.Circle, EyeLook.Circle, EyeLook.Line, 2),
				new EyeCombo("wide, winking in rhythm", EyeLook.Ring, EyeLook.Ring, EyeLook.Line)
			};
			for (int i = 0; i < Curated.Length; i++)
			{
				Curated[i].index = i;
			}
			EyesShut = Curated[1];
			if (EyesShut.name != "eyes shut")
			{
				EyesShut = new EyeCombo("eyes shut", EyeLook.Line, EyeLook.Line);
			}
		}

		public static uint Seed(uint scratcher, uint victim, int nonce)
		{
			int num = ((int)scratcher * -1640531535) ^ (((int)victim + -1640531527) * -2048144777) ^ ((nonce & 0x1F) * -1028477379);
			int num2 = (num ^ (num >>> 15)) * -2048144777;
			return (uint)(num2 ^ (num2 >>> 13));
		}

		public static EyeCombo Reaction(uint seed)
		{
			return Reactions[seed % (uint)Reactions.Length];
		}

		public static EyeCombo Draw()
		{
			if (Rng.NextDouble() < (double)ScratchPlugin.WildChance.Value)
			{
				bool flag = Rng.Next(2) == 0;
				return new EyeCombo
				{
					name = "wild",
					l = Rng.Next(1, 12),
					r = Rng.Next(1, 12),
					rhythm = flag,
					rhythmEye = (flag ? Rng.Next(1, 12) : 0),
					every = Rng.Next(1, 4),
					index = -1
				};
			}
			int num = Rng.Next(Curated.Length);
			if (Curated.Length > 1 && num == _lastCurated)
			{
				num = (num + 1 + Rng.Next(Curated.Length - 1)) % Curated.Length;
			}
			_lastCurated = num;
			return Curated[num];
		}

		private static PlayerEyeMood Mood(int look)
		{
			return (PlayerEyeMood)(look - 1);
		}

		private static void Rhythm(ref int l, ref int r, int eye, int every, float start, float hz)
		{
			if (eye != 0 && !(hz <= 0f))
			{
				if (((int)Mathf.Floor(Mathf.Max(0f, Time.time - start) * hz / (float)Mathf.Max(1, every)) & 1) == 0)
				{
					l = eye;
				}
				else
				{
					r = eye;
				}
			}
		}

		public static bool Wants(PlayerState st, out int l, out int r)
		{
			l = (r = 0);
			float unscaledTime = Time.unscaledTime;
			if (ScratchPlugin.ReactEyes.Value && unscaledTime - st.scratchedLast < 0.3f)
			{
				if (unscaledTime < st.startleUntil)
				{
					l = (r = 8);
					return true;
				}
				EyeCombo reaction = st.reaction;
				l = reaction.l;
				r = reaction.r;
				if (reaction.rhythm)
				{
					Rhythm(ref l, ref r, reaction.rhythmEye, reaction.every, st.scratchedStart, st.scratchedHz);
				}
				if (l == 0)
				{
					return r != 0;
				}
				return true;
			}
			if (!st.held)
			{
				return false;
			}
			Pose pose = st.pose;
			l = pose.eyeL;
			r = pose.eyeR;
			if (pose.rhythm)
			{
				Rhythm(ref l, ref r, pose.rhythmEye, pose.rhythmEvery, st.startTime, pose.hz);
			}
			if (l == 0)
			{
				return r != 0;
			}
			return true;
		}

		public static void OnSetEyeMood(PlayerEyes eyes, ref PlayerEyeMood left, ref PlayerEyeMood right)
		{
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Expected O, but got Unknown
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Expected I4, but got Unknown
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Expected I4, but got Unknown
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			if (eyes == null)
			{
				return;
			}
			IntPtr pointer = ((Il2CppObjectBase)eyes).Pointer;
			if (!_byEyes.TryGetValue(pointer, out var value) || value == null)
			{
				PlayerCharacter val = null;
				try
				{
					val = eyes.playerCharacter;
				}
				catch
				{
				}
				if ((Object)(object)val == (Object)null)
				{
					return;
				}
				PlayerNetworking pn = null;
				try
				{
					pn = val.playerNetworking;
				}
				catch
				{
				}
				value = ScratchBehaviour.StateFor(val, pn);
				_byEyes[pointer] = value;
			}
			int num = (int)left;
			int num2 = (int)right;
			if (num != value.gameEyeL || num2 != value.gameEyeR)
			{
				value.gameEyeL = num;
				value.gameEyeR = num2;
				if (ScratchPlugin.DebugLog.Value && _gameLogLines < 120)
				{
					_gameLogLines++;
					string text = "?";
					try
					{
						PlayerAnimatables animatables = eyes.playerCharacter.animatables;
						if ((Object)(object)animatables != (Object)null)
						{
							text = (animatables.overrideDefaultEyeMood ? $"anim({animatables.eyeMood})" : "no");
						}
					}
					catch
					{
					}
					ManualLogSource l = ScratchPlugin.L;
					bool flag = default(bool);
					BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(49, 6, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[BWScratch] eyes ");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(value.name);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": game set L=");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<PlayerEyeMood>(left);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" R=");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<PlayerEyeMood>(right);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" animOverride=");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(text);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" f");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(Time.frameCount);
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>((_gameLogLines == 120) ? " (last eye log line)" : "");
					}
					l.LogInfo(val2);
				}
			}
			int l2;
			int r;
			bool flag2 = Wants(value, out l2, out r);
			if (flag2)
			{
				if (l2 != 0)
				{
					left = (PlayerEyeMood)(int)Mood(l2);
				}
				if (r != 0)
				{
					right = (PlayerEyeMood)(int)Mood(r);
				}
			}
			if (flag2 != value.eyesOverriding)
			{
				value.eyesOverriding = flag2;
				if (ScratchPlugin.DebugLog.Value)
				{
					ScratchPlugin.L.LogInfo((object)(flag2 ? $"[BWScratch] eyes {value.name}: override on L={left} R={right} (game wanted {num}/{num2}) f{Time.frameCount}" : $"[BWScratch] eyes {value.name}: override off, back to {left}/{right} f{Time.frameCount}"));
				}
			}
		}
	}
	internal class PlayerState
	{
		public bool held;

		public float weight;

		public Pose pose = Pose.FromConfig();

		public int framesLogged;

		public float startTime;

		public int lastRaw = int.MinValue;

		public int validFrames;

		public float lastValidTime;

		public bool rxScratching;

		public string name = "?";

		public int gameEyeL = -1;

		public int gameEyeR = -1;

		public bool eyesOverriding;

		public PlayerCharacter pc;

		public PlayerNetworking pn;

		public uint netId;

		public int lastSeenFrame = -1;

		public bool targetOther;

		public int targetNetLow = -1;

		public int nonce;

		public bool nonceReady;

		public PlayerState victim;

		public float scratchedLast = -999f;

		public float scratchedStart;

		public float scratchedHz = 4f;

		public float startleUntil;

		public EyeCombo reaction;

		public string scratchedBy = "";
	}
	internal static class ScratchNet
	{
		private static int _heldFrame = Wire.Pack(0, 0);

		private static readonly Queue<int> _tx = new Queue<int>();

		private static float _nextTx;

		private static float _nextKeepalive;

		private static int _seq;

		private static bool _wasHeld;

		private static float _lastSent = float.NaN;

		private static float _lastSentTime;

		private static int _verified;

		private static int _corrupted;

		private static float _gameEcho = float.NaN;

		private static bool _sending;

		public const float KeepaliveSeconds = 0.4f;

		public const float TimeoutSeconds = 2f;

		private static bool _txOther;

		private static int _txNetLow = -1;

		private static int _txNonce = -1;

		private static int StateFrame(bool scratching, bool left, bool other)
		{
			_seq = (_seq + 1) & 3;
			int val = (scratching ? 16 : 0) | (left ? 8 : 0) | (_seq << 1) | (other ? 1 : 0);
			return Wire.Pack(0, val);
		}

		private static void EnqueueTarget(PlayerState st)
		{
			if (st.targetOther)
			{
				_tx.Enqueue(Wire.Pack(14, st.targetNetLow & 0x1F));
				_tx.Enqueue(Wire.Pack(15, st.nonce & 0x1F));
			}
		}

		public static void Update(PlayerNetworking pn, PlayerState st)
		{
			//IL_04fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0504: Expected O, but got Unknown
			//IL_032e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0335: Expected O, but got Unknown
			if ((Object)(object)pn == (Object)null)
			{
				return;
			}
			bool held = st.held;
			Pose pose = st.pose;
			float unscaledTime = Time.unscaledTime;
			if (!ScratchPlugin.ShareWithOthers.Value)
			{
				if (_tx.Count > 0)
				{
					_tx.Clear();
				}
				_wasHeld = held;
				return;
			}
			bool flag = st.targetOther != _txOther || (st.targetOther && (st.targetNetLow != _txNetLow || st.nonce != _txNonce));
			if (held && !_wasHeld)
			{
				_tx.Clear();
				_tx.Enqueue(StateFrame(scratching: true, pose.left, st.targetOther));
				EnqueueTarget(st);
				int[] eyeIds = pose.EyeIds;
				foreach (int id in eyeIds)
				{
					_tx.Enqueue(Wire.Pack(id, Pose.Quantise(id, pose.Get(id))));
				}
				for (int j = 1; j <= 9; j++)
				{
					_tx.Enqueue(Wire.Pack(j, Pose.Quantise(j, pose.Get(j))));
				}
				_nextTx = 0f;
			}
			else if (!held && _wasHeld)
			{
				_tx.Clear();
				_tx.Enqueue(StateFrame(scratching: false, pose.left, other: false));
				_nextTx = 0f;
			}
			else if (held && flag)
			{
				int[] array = _tx.ToArray();
				_tx.Clear();
				_tx.Enqueue(StateFrame(scratching: true, pose.left, st.targetOther));
				EnqueueTarget(st);
				int[] eyeIds = pose.EyeIds;
				foreach (int id2 in eyeIds)
				{
					_tx.Enqueue(Wire.Pack(id2, Pose.Quantise(id2, pose.Get(id2))));
				}
				eyeIds = array;
				foreach (int num in eyeIds)
				{
					Wire.Unpack(num, out var id3, out var _);
					if (id3 >= 1 && id3 <= 9)
					{
						_tx.Enqueue(num);
					}
				}
				_nextTx = 0f;
			}
			_wasHeld = held;
			_txOther = st.targetOther;
			_txNetLow = st.targetNetLow;
			_txNonce = st.nonce;
			if (held && _tx.Count == 0 && unscaledTime >= _nextKeepalive)
			{
				_tx.Enqueue(StateFrame(scratching: true, pose.left, st.targetOther));
			}
			bool flag2 = default(bool);
			if (!float.IsNaN(_lastSent) && unscaledTime - _lastSentTime > 0.6f)
			{
				int num2 = Wire.FrameOf(pn.echoAmount);
				if (num2 == (BitConverter.SingleToInt32Bits(_lastSent) & 0xFFFF))
				{
					_verified++;
				}
				else
				{
					_corrupted++;
				}
				if (ScratchPlugin.DebugLog.Value && _verified + _corrupted <= 12)
				{
					ManualLogSource l = ScratchPlugin.L;
					BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(73, 6, ref flag2);
					if (flag2)
					{
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[BWScratch] tx readback: sent frame 0x");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(BitConverter.SingleToInt32Bits(_lastSent) & 0xFFFF, "X4");
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" synced 0x");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(num2, "X4");
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" ");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>((num2 == (BitConverter.SingleToInt32Bits(_lastSent) & 0xFFFF)) ? "OK" : "CORRUPTED");
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" (ok ");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(_verified);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", bad ");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(_corrupted);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(") echoAmount=");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<float>(pn.echoAmount, "R");
					}
					l.LogInfo(val2);
				}
				_lastSent = float.NaN;
			}
			if (_tx.Count <= 0 || !(unscaledTime >= _nextTx))
			{
				return;
			}
			_heldFrame = _tx.Dequeue();
			float num3 = (float.IsNaN(_gameEcho) ? Wire.Base(pn.echoAmount) : _gameEcho);
			try
			{
				_sending = true;
				pn.CmdSetEchoAmount(num3);
			}
			catch (Exception ex)
			{
				ScratchBehaviour.Once("cmdecho", "[BWScratch] CmdSetEchoAmount failed: " + ex.Message);
			}
			finally
			{
				_sending = false;
			}
			float num4 = 0.15f;
			try
			{
				num4 = Mathf.Max(((NetworkBehaviour)pn).syncInterval, 0.1f) + 0.05f;
			}
			catch
			{
			}
			_nextTx = unscaledTime + num4;
			if (_tx.Count == 0)
			{
				_nextKeepalive = unscaledTime + 0.4f;
			}
			if (ScratchPlugin.DebugLog.Value)
			{
				Wire.Unpack(_heldFrame, out var id4, out var val3);
				ManualLogSource l2 = ScratchPlugin.L;
				BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(59, 6, ref flag2);
				if (flag2)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[BWScratch] tx frame id=");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(id4);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" val=");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(val3);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" (0x");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(_heldFrame, "X4");
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(") base=");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<float>(num3, "R");
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" interval=");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<float>(num4, "0.00");
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("s queued=");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(_tx.Count);
				}
				l2.LogInfo(val2);
			}
		}

		public static float OnOutgoingEcho(PlayerNetworking pn, float value)
		{
			if (!ScratchPlugin.ShareWithOthers.Value)
			{
				return value;
			}
			try
			{
				if ((Object)(object)pn == (Object)null || !((NetworkBehaviour)pn).isLocalPlayer)
				{
					return value;
				}
			}
			catch
			{
				return value;
			}
			if (!_sending)
			{
				_gameEcho = value;
			}
			float result = (_lastSent = Wire.Encode(value, _heldFrame));
			_lastSentTime = Time.unscaledTime;
			return result;
		}

		public static void Receive(PlayerNetworking pn, PlayerState st)
		{
			//IL_03b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ba: Expected O, but got Unknown
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Expected O, but got Unknown
			//IL_0475: Unknown result type (might be due to invalid IL or missing references)
			//IL_047c: Expected O, but got Unknown
			//IL_0319: Unknown result type (might be due to invalid IL or missing references)
			//IL_0320: Expected O, but got Unknown
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Expected O, but got Unknown
			float echoAmount;
			try
			{
				echoAmount = pn.echoAmount;
			}
			catch
			{
				return;
			}
			int num = Wire.FrameOf(echoAmount);
			float unscaledTime = Time.unscaledTime;
			if (st.name.StartsWith("PlayerCharacter") && (Time.frameCount & 0x7F) == 0)
			{
				try
				{
					string username = pn.username;
					if (!string.IsNullOrEmpty(username))
					{
						st.name = username;
					}
				}
				catch
				{
				}
			}
			bool flag5 = default(bool);
			if (num != st.lastRaw)
			{
				st.lastRaw = num;
				if (Wire.Unpack(num, out var id, out var val))
				{
					st.validFrames++;
					st.lastValidTime = unscaledTime;
					if (id == 0)
					{
						bool flag = (val & 0x10) != 0;
						bool flag2 = (val & 8) != 0;
						bool flag3 = flag && (val & 1) != 0;
						bool flag4 = flag && (!st.rxScratching || flag3 != st.targetOther);
						if ((flag != st.rxScratching || flag3 != st.targetOther) && ScratchPlugin.DebugLog.Value)
						{
							ManualLogSource l = ScratchPlugin.L;
							BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(36, 5, ref flag5);
							if (flag5)
							{
								((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[BWScratch] rx ");
								((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(st.name);
								((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": scratch ");
								((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(flag ? "START" : "STOP");
								((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" (");
								((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(flag2 ? "Left" : "Right");
								((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(flag3 ? ", someone else" : "");
								((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(") frames=");
								((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(st.validFrames);
							}
							l.LogInfo(val2);
						}
						bool num2 = flag && !st.rxScratching;
						st.rxScratching = flag;
						st.pose.left = flag2;
						st.targetOther = flag3;
						if (!flag3 || flag4)
						{
							st.targetNetLow = -1;
							st.nonceReady = false;
						}
						if (num2)
						{
							st.pose.ClearEyes();
						}
					}
					else if (id <= 13)
					{
						st.pose.Set(id, Pose.Dequantise(id, val));
						if (ScratchPlugin.DebugLog.Value && (st.validFrames <= 40 || id == 10))
						{
							ManualLogSource l2 = ScratchPlugin.L;
							BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(26, 4, ref flag5);
							if (flag5)
							{
								((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[BWScratch] rx ");
								((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(st.name);
								((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": param ");
								((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(id);
								((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" = ");
								((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<float>(st.pose.Get(id), "0.###");
								((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>((id >= 10) ? (" eyes " + st.pose.EyesText) : "");
							}
							l2.LogInfo(val2);
						}
					}
					else
					{
						switch (id)
						{
						case 14:
							if (val != st.targetNetLow)
							{
								st.nonceReady = false;
							}
							st.targetNetLow = val;
							if (ScratchPlugin.DebugLog.Value)
							{
								ManualLogSource l3 = ScratchPlugin.L;
								BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(35, 2, ref flag5);
								if (flag5)
								{
									((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[BWScratch] rx ");
									((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(st.name);
									((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": target netId%32 = ");
									((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(val);
								}
								l3.LogInfo(val2);
							}
							break;
						case 15:
							st.nonce = val;
							st.nonceReady = true;
							break;
						}
					}
				}
				else if (ScratchPlugin.DebugLog.Value && st.validFrames == 0 && st.framesLogged < 3)
				{
					st.framesLogged++;
					ManualLogSource l4 = ScratchPlugin.L;
					BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(75, 3, ref flag5);
					if (flag5)
					{
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[BWScratch] rx ");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(st.name);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": echo 0x");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(num, "X4");
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" is not a frame (no mod, or plain echo) echoAmount=");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<float>(echoAmount, "R");
					}
					l4.LogInfo(val2);
				}
			}
			st.held = st.rxScratching && st.validFrames >= 2 && unscaledTime - st.lastValidTime < 2f;
			if (!st.rxScratching || st.held || !(unscaledTime - st.lastValidTime >= 2f))
			{
				return;
			}
			st.rxScratching = false;
			if (ScratchPlugin.DebugLog.Value)
			{
				ManualLogSource l5 = ScratchPlugin.L;
				BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(34, 1, ref flag5);
				if (flag5)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[BWScratch] rx ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(st.name);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": scratch timed out");
				}
				l5.LogInfo(val2);
			}
		}
	}
	public class ScratchBehaviour : MonoBehaviour
	{
		private class ArmRec
		{
			public int refreshFrame = -1;

			public int refreshes;

			public Vector3 firstHand;

			public Vector3 firstElbow;

			public int preFrame = -1;

			public Vector3 preHand;

			public Vector3 preElbow;
		}

		private class Cache
		{
			public Renderer bum;

			public MeshFilter bumMf;

			public Bounds bumLocal;

			public bool hasLocal;

			public Transform pelvis;

			public float handR = 0.06f;
		}

		private static readonly HashSet<string> _once = new HashSet<string>();

		private static bool _keyHeld;

		private static int _activation;

		private static EyeCombo _drawn;

		private static readonly Dictionary<int, ArmRec> _recs = new Dictionary<int, ArmRec>();

		private static readonly Dictionary<int, Cache> _cache = new Dictionary<int, Cache>();

		private static readonly Dictionary<int, PlayerState> _states = new Dictionary<int, PlayerState>();

		private static GameObject _markerHand;

		private static GameObject _markerElbow;

		private static int _nonce;

		public ScratchBehaviour(IntPtr ptr)
			: base(ptr)
		{
		}

		internal static void Once(string key, string msg)
		{
			if (_once.Add(key))
			{
				ScratchPlugin.L.LogWarning((object)msg);
			}
		}

		private void Update()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Expected O, but got Unknown
			try
			{
				bool key = Input.GetKey(ScratchPlugin.KeyScratch.Value);
				bool flag = default(bool);
				if (key && !_keyHeld)
				{
					_activation++;
					if (ScratchPlugin.DebugLog.Value)
					{
						ManualLogSource l = ScratchPlugin.L;
						BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(32, 3, ref flag);
						if (flag)
						{
							((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[BWScratch] scratch #");
							((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(_activation);
							((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" START (");
							((BepInExLogInterpolatedStringHandler)val).AppendFormatted<ScratchHand>(ScratchPlugin.Hand.Value);
							((BepInExLogInterpolatedStringHandler)val).AppendLiteral(") f");
							((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(Time.frameCount);
						}
						l.LogInfo(val);
					}
				}
				else if (!key && _keyHeld && ScratchPlugin.DebugLog.Value)
				{
					ManualLogSource l2 = ScratchPlugin.L;
					BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(28, 2, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[BWScratch] scratch #");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(_activation);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" STOP f");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(Time.frameCount);
					}
					l2.LogInfo(val);
				}
				_keyHeld = key;
			}
			catch (Exception ex)
			{
				Once("update", "[BWScratch] Update error: " + ex);
			}
		}

		private static bool IsLocal(PlayerNetworking pn)
		{
			try
			{
				return (Object)(object)pn != (Object)null && ((NetworkBehaviour)pn).isLocalPlayer;
			}
			catch
			{
				return false;
			}
		}

		private static bool IsHolding(PlayerCharacter pc)
		{
			try
			{
				return pc.hands != null && pc.hands.isHoldingSomething;
			}
			catch
			{
				return false;
			}
		}

		private static void KeepAwake(PlayerCharacter pc, PlayerState st)
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			try
			{
				PlayerSleeper sleeper = pc.sleeper;
				if (sleeper == null)
				{
					Once("nosleeper", "[BWScratch] PlayerCharacter.sleeper is null, cannot wake");
					return;
				}
				bool flag = false;
				try
				{
					flag = sleeper.localIsSleeping;
				}
				catch
				{
				}
				sleeper.RecordAction();
				if (flag && ScratchPlugin.DebugLog.Value && st.weight <= 0f)
				{
					ManualLogSource l = ScratchPlugin.L;
					bool flag2 = default(bool);
					BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(62, 1, ref flag2);
					if (flag2)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[BWScratch] was asleep, RecordAction() called (timeTilSleep=");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(sleeper.timeTilSleep, "0.#");
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("s)");
					}
					l.LogInfo(val);
				}
			}
			catch (Exception ex)
			{
				Once("wake", "[BWScratch] wake error: " + ex.Message);
			}
		}

		private static PlayerState State(PlayerCharacter pc, PlayerNetworking pn)
		{
			int instanceID = ((Object)pc).GetInstanceID();
			if (!_states.TryGetValue(instanceID, out var value))
			{
				value = new PlayerState();
				try
				{
					value.name = (((Object)(object)pn != (Object)null && !string.IsNullOrEmpty(pn.username)) ? pn.username : ((Object)pc).name);
				}
				catch
				{
					value.name = ((Object)pc).name;
				}
				_states[instanceID] = value;
			}
			return value;
		}

		internal static PlayerState StateFor(PlayerCharacter pc, PlayerNetworking pn)
		{
			return State(pc, pn);
		}

		internal static string NameOf(PlayerCharacter pc)
		{
			try
			{
				if (_states.TryGetValue(((Object)pc).GetInstanceID(), out var value))
				{
					return value.name;
				}
				PlayerNetworking playerNetworking = pc.playerNetworking;
				string text = (((Object)(object)playerNetworking != (Object)null) ? playerNetworking.username : null);
				return string.IsNullOrEmpty(text) ? ((Object)pc).name : text;
			}
			catch
			{
				return "?";
			}
		}

		private static ArmRec Rec(LimbSpline s)
		{
			int instanceID = ((Object)s).GetInstanceID();
			if (!_recs.TryGetValue(instanceID, out var value))
			{
				value = new ArmRec();
				_recs[instanceID] = value;
			}
			return value;
		}

		internal static void AfterSplineRefresh(LimbSpline s)
		{
			//IL_0055: 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)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)s == (Object)null || !_recs.TryGetValue(((Object)s).GetInstanceID(), out var value))
			{
				return;
			}
			int frameCount = Time.frameCount;
			if (value.refreshFrame != frameCount)
			{
				value.refreshFrame = frameCount;
				value.refreshes = 0;
				Transform endTransform = s.endTransform;
				Transform handleTransform = s.handleTransform;
				if ((Object)(object)endTransform != (Object)null)
				{
					value.firstHand = endTransform.position;
				}
				if ((Object)(object)handleTransform != (Object)null)
				{
					value.firstElbow = handleTransform.position;
				}
			}
			value.refreshes++;
		}

		internal static void BeforeArmsLateUpdate(PlayerArms arms)
		{
			if (arms != null)
			{
				Capture(arms.rightArmLimbSpline, arms.rightHand);
				Capture(arms.leftArmLimbSpline, arms.leftHand);
			}
		}

		private static void Capture(LimbSpline s, Transform hand)
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: 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_0062: 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)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)s == (Object)null))
			{
				ArmRec armRec = Rec(s);
				armRec.preFrame = Time.frameCount;
				Transform handleTransform = s.handleTransform;
				Transform val = (((Object)(object)hand != (Object)null) ? hand : s.endTransform);
				armRec.preHand = (((Object)(object)val != (Object)null) ? val.position : Vector3.zero);
				armRec.preElbow = (((Object)(object)handleTransform != (Object)null) ? handleTransform.position : Vector3.zero);
			}
		}

		private static void RestPose(ArmRec rec, Vector3 curHand, Vector3 curElbow, out Vector3 hand, out Vector3 elbow, out string src)
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: 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_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			int frameCount = Time.frameCount;
			if (rec != null && rec.refreshFrame == frameCount)
			{
				hand = rec.firstHand;
				elbow = rec.firstElbow;
				src = "refresh1";
			}
			else if (rec != null && rec.preFrame == frameCount)
			{
				hand = rec.preHand;
				elbow = rec.preElbow;
				src = "prefix";
			}
			else
			{
				hand = curHand;
				elbow = curElbow;
				src = "current";
			}
		}

		private static Cache GetCache(PlayerCharacter pc, Transform hand)
		{
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			int instanceID = ((Object)pc).GetInstanceID();
			if (_cache.TryGetValue(instanceID, out var value) && (Object)(object)value.bum != (Object)null)
			{
				return value;
			}
			value = new Cache();
			try
			{
				Transform val = ((pc.registry != null) ? pc.registry.armUprightBone : null);
				value.pelvis = (((Object)(object)val != (Object)null) ? val.parent : null);
				Il2CppArrayBase<Renderer> componentsInChildren = ((Component)pc).GetComponentsInChildren<Renderer>(true);
				foreach (Renderer item in componentsInChildren)
				{
					if ((Object)(object)item != (Object)null && ((Object)((Component)item).gameObject).name == "BodyBall_LOD0 - bottom")
					{
						value.bum = item;
						break;
					}
				}
				if ((Object)(object)value.bum == (Object)null)
				{
					foreach (Renderer item2 in componentsInChildren)
					{
						if ((Object)(object)item2 != (Object)null && ((Object)((Component)item2).gameObject).name.Contains("bottom") && ((Object)((Component)item2).gameObject).name.Contains("LOD0"))
						{
							value.bum = item2;
							break;
						}
					}
				}
				if ((Object)(object)value.bum != (Object)null)
				{
					value.bumMf = ((Component)value.bum).GetComponent<MeshFilter>();
					Mesh val2 = (((Object)(object)value.bumMf != (Object)null) ? value.bumMf.sharedMesh : null);
					if ((Object)(object)val2 != (Object)null)
					{
						value.bumLocal = val2.bounds;
						value.hasLocal = true;
					}
				}
				if ((Object)(object)hand != (Object)null)
				{
					Renderer componentInChildren = ((Component)hand).GetComponentInChildren<Renderer>(true);
					if ((Object)(object)componentInChildren != (Object)null)
					{
						Bounds bounds = componentInChildren.bounds;
						float num = (((Bounds)(ref bounds)).extents.x + ((Bounds)(ref bounds)).extents.y + ((Bounds)(ref bounds)).extents.z) / 3f;
						if (num > 0.01f && num < 0.3f)
						{
							value.handR = num;
						}
					}
				}
			}
			catch (Exception ex)
			{
				Once("cache", "[BWScratch] cache error: " + ex.Message);
			}
			_cache[instanceID] = value;
			return value;
		}

		private static Vector3 BumCentre(Cache c, Transform root)
		{
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//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_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)c.bum == (Object)null)
			{
				if (!((Object)(object)c.pelvis != (Object)null))
				{
					return root.position + Vector3.up * 0.68f;
				}
				return c.pelvis.position;
			}
			try
			{
				if (c.hasLocal)
				{
					return ((Component)c.bum).transform.TransformPoint(((Bounds)(ref c.bumLocal)).center);
				}
				Bounds bounds = c.bum.bounds;
				return ((Bounds)(ref bounds)).center;
			}
			catch
			{
				return root.position + Vector3.up * 0.68f;
			}
		}

		private static float SurfaceDist(Cache c, Vector3 d)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: 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_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: 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_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: 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_00b8: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)c.bum == (Object)null || !c.hasLocal)
			{
				return 0.29f;
			}
			try
			{
				Vector3 val = ((Component)c.bum).transform.InverseTransformVector(d);
				Vector3 extents = ((Bounds)(ref c.bumLocal)).extents;
				float num = 0f;
				if (extents.x > 1E-05f)
				{
					num += val.x / extents.x * (val.x / extents.x);
				}
				if (extents.y > 1E-05f)
				{
					num += val.y / extents.y * (val.y / extents.y);
				}
				if (extents.z > 1E-05f)
				{
					num += val.z / extents.z * (val.z / extents.z);
				}
				if (num < 1E-08f)
				{
					return 0.29f;
				}
				float num2 = 1f / Mathf.Sqrt(num);
				if (num2 < 0.05f || num2 > 1.5f)
				{
					return 0.29f;
				}
				return num2;
			}
			catch
			{
				return 0.29f;
			}
		}

		private static Vector3 KeepOutside(Cache c, Vector3 p, Vector3 centre, float extra)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: 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)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: 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_003d: Unknown result type (might be due to invalid IL or missing references)
			//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_003a: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = p - centre;
			float num = ((Vector3)(ref val)).magnitude;
			if (num < 0.0001f)
			{
				val = Vector3.back;
				num = 1f;
			}
			Vector3 val2 = val / num;
			float num2 = SurfaceDist(c, val2) + extra;
			if (!(num < num2))
			{
				return p;
			}
			return centre + val2 * num2;
		}

		internal static void AfterArmsLateUpdate(PlayerArms arms)
		{
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Expected O, but got Unknown
			if (arms == null)
			{
				return;
			}
			PlayerCharacter playerCharacter = arms.playerCharacter;
			if ((Object)(object)playerCharacter == (Object)null)
			{
				return;
			}
			PlayerNetworking val = null;
			try
			{
				val = playerCharacter.playerNetworking;
			}
			catch
			{
			}
			bool flag = IsLocal(val);
			PlayerState playerState = State(playerCharacter, val);
			playerState.pc = playerCharacter;
			playerState.pn = val;
			playerState.lastSeenFrame = Time.frameCount;
			try
			{
				if ((Object)(object)val != (Object)null)
				{
					playerState.netId = ((NetworkBehaviour)val).netId;
				}
			}
			catch
			{
			}
			bool flag2 = IsHolding(playerCharacter);
			if (flag)
			{
				bool flag3 = _keyHeld && !(ScratchPlugin.BlockWhileHolding.Value && flag2);
				Pose pose = Pose.FromConfig();
				if (ScratchPlugin.FaceEyes.Value && ScratchPlugin.FaceMode.Value == EyeMode.Random)
				{
					if (flag3 && !playerState.held)
					{
						_drawn = ScratchFace.Draw();
						if (ScratchPlugin.DebugLog.Value)
						{
							Pose pose2 = pose;
							pose2.SetEyes(_drawn);
							ManualLogSource l = ScratchPlugin.L;
							bool flag4 = default(bool);
							BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(28, 2, ref flag4);
							if (flag4)
							{
								((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[BWScratch] eyes: drew '");
								((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(_drawn.name);
								((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("' = ");
								((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(pose2.EyesText);
							}
							l.LogInfo(val2);
						}
					}
					pose.SetEyes(_drawn);
				}
				PlayerState playerState2 = playerState.victim;
				if (flag3)
				{
					playerState2 = null;
					if (ScratchPlugin.ScratchOthers.Value)
					{
						try
						{
							playerState2 = PickTarget(playerCharacter, playerState, arms, pose.left);
						}
						catch (Exception ex)
						{
							Once("pick", "[BWScratch] target pick error: " + ex);
						}
					}
					if (playerState2 != playerState.victim)
					{
						if (playerState2 != null)
						{
							playerState.nonce = ++_nonce & 0x1F;
						}
						if (ScratchPlugin.DebugLog.Value)
						{
							ScratchPlugin.L.LogInfo((object)((playerState2 != null) ? $"[BWScratch] target: {playerState2.name} (netId {playerState2.netId}, nonce {playerState.nonce}) f{Time.frameCount}" : $"[BWScratch] target: own bum f{Time.frameCount}"));
						}
					}
				}
				playerState.victim = playerState2;
				playerState.targetOther = flag3 && playerState2 != null;
				playerState.targetNetLow = (playerState.targetOther ? ((int)(playerState2.netId & 0x1F)) : (-1));
				if (playerState.targetOther && ScratchPlugin.FaceEyes.Value)
				{
					pose.SetEyes(ScratchFace.EyesShut);
				}
				playerState.held = flag3;
				playerState.pose = pose;
				if (playerState.held && ScratchPlugin.WakeUp.Value)
				{
					KeepAwake(playerCharacter, playerState);
				}
				try
				{
					ScratchNet.Update(val, playerState);
				}
				catch (Exception ex2)
				{
					Once("tx", "[BWScratch] tx error: " + ex2);
				}
			}
			else
			{
				if (!ScratchPlugin.ShowOthers.Value || (Object)(object)val == (Object)null)
				{
					playerState.held = false;
					playerState.weight = 0f;
					return;
				}
				ScratchNet.Receive(val, playerState);
				if (flag2)
				{
					playerState.held = false;
				}
				if (playerState.held)
				{
					playerState.victim = (playerState.targetOther ? ResolveVictim(playerState) : null);
					if (playerState.targetOther && playerState.victim == null)
					{
						playerState.held = false;
					}
				}
			}
			bool num = playerState.weight > 0f;
			float num2 = (playerState.held ? ScratchPlugin.BlendIn.Value : ScratchPlugin.BlendOut.Value);
			playerState.weight = Mathf.MoveTowards(playerState.weight, playerState.held ? 1f : 0f, Time.deltaTime / Mathf.Max(0.01f, num2));
			if (!num && playerState.weight > 0f)
			{
				playerState.framesLogged = 0;
				playerState.startTime = Time.unscaledTime;
			}
			if (playerState.weight <= 0f)
			{
				playerState.victim = null;
				if (flag && (Object)(object)_markerHand != (Object)null)
				{
					_markerHand.SetActive(false);
					if ((Object)(object)_markerElbow != (Object)null)
					{
						_markerElbow.SetActive(false);
					}
				}
			}
			else
			{
				PoseArm(arms, playerCharacter, playerState, flag, flag2);
				if (playerState.held && playerState.victim != null)
				{
					MarkScratched(playerState.victim, playerState);
				}
			}
		}

		private static PlayerState PickTarget(PlayerCharacter pc, PlayerState st, PlayerArms arms, bool left)
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0251: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Expected O, but got Unknown
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			Transform val = null;
			try
			{
				val = pc.cameraTransform;
			}
			catch
			{
			}
			if ((Object)(object)val == (Object)null)
			{
				Camera main = Camera.main;
				if ((Object)(object)main != (Object)null)
				{
					val = ((Component)main).transform;
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			LimbSpline val2 = (left ? arms.leftArmLimbSpline : arms.rightArmLimbSpline);
			Vector3 val3 = (((Object)(object)val2 != (Object)null && (Object)(object)val2.startTransform != (Object)null) ? val2.startTransform.position : val.position);
			float value = ScratchPlugin.AimAngle.Value;
			float value2 = ScratchPlugin.Range.Value;
			PlayerState result = null;
			float num = 999f;
			bool flag3 = default(bool);
			foreach (KeyValuePair<int, PlayerState> state in _states)
			{
				PlayerState value3 = state.Value;
				if (value3 == st || (Object)(object)value3.pc == (Object)null || Time.frameCount - value3.lastSeenFrame > 5)
				{
					continue;
				}
				Vector3 val4;
				try
				{
					val4 = BumCentre(GetCache(value3.pc, null), RootOf(value3.pc));
				}
				catch
				{
					continue;
				}
				float num2 = Vector3.Distance(val4, val3);
				float num3 = Vector3.Angle(val.forward, val4 - val.position);
				try
				{
					Transform val5 = ((value3.pc.registry != null) ? value3.pc.registry.headBone : null);
					Vector3 val6 = (((Object)(object)val5 != (Object)null) ? val5.position : (val4 + Vector3.up * 0.6f));
					num3 = Mathf.Min(num3, Vector3.Angle(val.forward, val6 - val.position));
					num3 = Mathf.Min(num3, Vector3.Angle(val.forward, (val6 + val4) * 0.5f - val.position));
				}
				catch
				{
				}
				bool flag = value3 == st.victim;
				bool flag2 = ((!flag) ? (num2 < value2 && num3 < value) : (num2 < value2 * 1.3f && num3 < value * 2.5f));
				if (ScratchPlugin.DebugLog.Value && st.held && !flag && (Time.frameCount & 0x1F) == 0)
				{
					ManualLogSource l = ScratchPlugin.L;
					BepInExInfoLogInterpolatedStringHandler val7 = new BepInExInfoLogInterpolatedStringHandler(62, 6, ref flag3);
					if (flag3)
					{
						((BepInExLogInterpolatedStringHandler)val7).AppendLiteral("[BWScratch] aim check ");
						((BepInExLogInterpolatedStringHandler)val7).AppendFormatted<string>(value3.name);
						((BepInExLogInterpolatedStringHandler)val7).AppendLiteral(": angle=");
						((BepInExLogInterpolatedStringHandler)val7).AppendFormatted<float>(num3, "0");
						((BepInExLogInterpolatedStringHandler)val7).AppendLiteral("deg (limit ");
						((BepInExLogInterpolatedStringHandler)val7).AppendFormatted<float>(value, "0");
						((BepInExLogInterpolatedStringHandler)val7).AppendLiteral(") dist=");
						((BepInExLogInterpolatedStringHandler)val7).AppendFormatted<float>(num2, "0.00");
						((BepInExLogInterpolatedStringHandler)val7).AppendLiteral("m (limit ");
						((BepInExLogInterpolatedStringHandler)val7).AppendFormatted<float>(value2, "0.00");
						((BepInExLogInterpolatedStringHandler)val7).AppendLiteral(") -> ");
						((BepInExLogInterpolatedStringHandler)val7).AppendFormatted<string>(flag2 ? "target" : "no");
					}
					l.LogInfo(val7);
				}
				if (flag2)
				{
					if (flag)
					{
						return value3;
					}
					if (num3 < num)
					{
						result = value3;
						num = num3;
					}
				}
			}
			return result;
		}

		private static PlayerState ResolveVictim(PlayerState st)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: 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 (st.targetNetLow < 0 || !st.nonceReady || (Object)(object)st.pc == (Object)null)
			{
				return null;
			}
			Vector3 position;
			try
			{
				position = ((Component)st.pc).transform.position;
			}
			catch
			{
				return null;
			}
			PlayerState playerState = null;
			float num = 3f;
			foreach (KeyValuePair<int, PlayerState> state in _states)
			{
				PlayerState value = state.Value;
				if (value != st && !((Object)(object)value.pc == (Object)null) && Time.frameCount - value.lastSeenFrame <= 5 && (value.netId & 0x1F) == (uint)st.targetNetLow)
				{
					float num2;
					try
					{
						num2 = Vector3.Distance(((Component)value.pc).transform.position, position);
					}
					catch
					{
						continue;
					}
					if (num2 < num)
					{
						num = num2;
						playerState = value;
					}
				}
			}
			if (playerState == null && ScratchPlugin.DebugLog.Value)
			{
				Once("novictim" + st.name + st.targetNetLow, $"[BWScratch] rx {st.name}: no player with netId%32={st.targetNetLow} nearby, scratching own bum instead");
			}
			return playerState;
		}

		private static Transform RootOf(PlayerCharacter pc)
		{
			try
			{
				if (pc.registry != null && (Object)(object)pc.registry.root != (Object)null)
				{
					return pc.registry.root;
				}
			}
			catch
			{
			}
			return ((Component)pc).transform;
		}

		private static void MarkScratched(PlayerState v, PlayerState s)
		{
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Expected O, but got Unknown
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			float unscaledTime = Time.unscaledTime;
			if (unscaledTime - v.scratchedLast > 0.5f)
			{
				uint num = ScratchFace.Seed(s.netId, v.netId, s.nonce);
				v.reaction = ScratchFace.Reaction(num);
				v.scratchedStart = Time.time;
				v.scratchedHz = s.pose.hz;
				v.scratchedBy = s.name;
				bool flag = ScratchPlugin.Startle.Value && ScratchPlugin.StartleSeconds.Value > 0f;
				v.startleUntil = (flag ? (unscaledTime + ScratchPlugin.StartleSeconds.Value) : unscaledTime);
				bool flag2 = false;
				if (ScratchPlugin.StartleSound.Value && (Object)(object)v.pc != (Object)null)
				{
					try
					{
						PlayerAudioReferences playerAudio = v.pc.playerAudio;
						AudioRandomContainer val = (((Object)(object)playerAudio != (Object)null) ? playerAudio.snatchReactionSound : null);
						if ((Object)(object)val != (Object)null)
						{
							flag2 = (Object)(object)val.Play(Vector3.zero, (Object)(object)v.pc, (IAudioRTPCXProvider)null, true, v.pc.kernal, 0.0, -1f, (AudioClip)null, (FuncOneOut<XAxisType, float, bool>)null, (List<IAudioVolume>)null, (Func<AudioRandomContainer, int>)null) != (Object)null;
						}
						else
						{
							Once("nosnd", "[BWScratch] snatchReactionSound not found, no startle sound");
						}
					}
					catch (Exception ex)
					{
						Once("snd", "[BWScratch] startle sound failed: " + ex.Message);
					}
				}
				if (ScratchPlugin.DebugLog.Value)
				{
					ManualLogSource l = ScratchPlugin.L;
					bool flag3 = default(bool);
					BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(75, 8, ref flag3);
					if (flag3)
					{
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[BWScratch] react ");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(v.name);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": scratched by ");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(s.name);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", eyes '");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(v.reaction.name);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("' startle=");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<bool>(flag);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" sound=");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<bool>(flag2);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" seed=0x");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<uint>(num, "X8");
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" nonce=");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(s.nonce);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" f");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(Time.frameCount);
					}
					l.LogInfo(val2);
				}
			}
			v.scratchedLast = unscaledTime;
			if (ScratchPlugin.WakeUp.Value && IsLocal(v.pn) && (Object)(object)v.pc != (Object)null)
			{
				KeepAwake(v.pc, v);
			}
		}

		private static void PoseArm(PlayerArms arms, PlayerCharacter pc, PlayerState st, bool local, bool holding)
		{
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0912: Unknown result type (might be due to invalid IL or missing references)
			//IL_0919: Expected O, but got Unknown
			//IL_03b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0303: Unknown result type (might be due to invalid IL or missing references)
			//IL_0305: Unknown result type (might be due to invalid IL or missing references)
			//IL_0307: Unknown result type (might be due to invalid IL or missing references)
			//IL_030b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0315: Unknown result type (might be due to invalid IL or missing references)
			//IL_031a: Unknown result type (might be due to invalid IL or missing references)
			//IL_031f: Unknown result type (might be due to invalid IL or missing references)
			//IL_033d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0346: Unknown result type (might be due to invalid IL or missing references)
			//IL_034b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0354: Unknown result type (might be due to invalid IL or missing references)
			//IL_0359: Unknown result type (might be due to invalid IL or missing references)
			//IL_0365: Unknown result type (might be due to invalid IL or missing references)
			//IL_036a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0373: Unknown result type (might be due to invalid IL or missing references)
			//IL_0378: Unknown result type (might be due to invalid IL or missing references)
			//IL_037d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0381: Unknown result type (might be due to invalid IL or missing references)
			//IL_0386: Unknown result type (might be due to invalid IL or missing references)
			//IL_0388: Unknown result type (might be due to invalid IL or missing references)
			//IL_038a: Unknown result type (might be due to invalid IL or missing references)
			//IL_038e: Unknown result type (might be due to invalid IL or missing references)
			//IL_039c: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0400: Unknown result type (might be due to invalid IL or missing references)
			//IL_0405: Unknown result type (might be due to invalid IL or missing references)
			//IL_040a: Unknown result type (might be due to invalid IL or missing references)
			//IL_040e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0413: Unknown result type (might be due to invalid IL or missing references)
			//IL_0415: Unknown result type (might be due to invalid IL or missing references)
			//IL_0417: Unknown result type (might be due to invalid IL or missing references)
			//IL_041b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0425: Unknown result type (might be due to invalid IL or missing references)
			//IL_042a: Unknown result type (might be due to invalid IL or missing references)
			//IL_042f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0431: Unknown result type (might be due to invalid IL or missing references)
			//IL_0433: Unknown result type (might be due to invalid IL or missing references)
			//IL_0435: Unknown result type (might be due to invalid IL or missing references)
			//IL_0437: Unknown result type (might be due to invalid IL or missing references)
			//IL_0441: Unknown result type (might be due to invalid IL or missing references)
			//IL_0446: Unknown result type (might be due to invalid IL or missing references)
			//IL_044b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0452: Unknown result type (might be due to invalid IL or missing references)
			//IL_0457: Unknown result type (might be due to invalid IL or missing references)
			//IL_045c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0463: Unknown result type (might be due to invalid IL or missing references)
			//IL_0468: Unknown result type (might be due to invalid IL or missing references)
			//IL_046d: Unknown result type (might be due to invalid IL or missing references)
			//IL_03de: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_04bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_04df: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0501: Unknown result type (might be due to invalid IL or missing references)
			//IL_0506: Unknown result type (might be due to invalid IL or missing references)
			//IL_051e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0523: Unknown result type (might be due to invalid IL or missing references)
			//IL_0528: Unknown result type (might be due to invalid IL or missing references)
			//IL_052a: Unknown result type (might be due to invalid IL or missing references)
			//IL_052c: Unknown result type (might be due to invalid IL or missing references)
			//IL_052e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0533: Unknown result type (might be due to invalid IL or missing references)
			//IL_0535: Unknown result type (might be due to invalid IL or missing references)
			//IL_0537: Unknown result type (might be due to invalid IL or missing references)
			//IL_053e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0543: Unknown result type (might be due to invalid IL or missing references)
			//IL_0548: Unknown result type (might be due to invalid IL or missing references)
			//IL_054a: Unknown result type (might be due to invalid IL or missing references)
			//IL_054c: Unknown result type (might be due to invalid IL or missing references)
			//IL_054e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0553: Unknown result type (might be due to invalid IL or missing references)
			//IL_0646: Unknown result type (might be due to invalid IL or missing references)
			//IL_0648: Unknown result type (might be due to invalid IL or missing references)
			//IL_064c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0653: Unknown result type (might be due to invalid IL or missing references)
			//IL_0655: Unknown result type (might be due to invalid IL or missing references)
			//IL_065c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0661: Unknown result type (might be due to invalid IL or missing references)
			//IL_0634: Unknown result type (might be due to invalid IL or missing references)
			//IL_0636: Unknown result type (might be due to invalid IL or missing references)
			//IL_0638: Unknown result type (might be due to invalid IL or missing references)
			//IL_0578: Unknown result type (might be due to invalid IL or missing references)
			//IL_057d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0581: Unknown result type (might be due to invalid IL or missing references)
			//IL_0586: Unknown result type (might be due to invalid IL or missing references)
			//IL_0592: Unknown result type (might be due to invalid IL or missing references)
			//IL_0594: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_05be: Unknown result type (might be due to invalid IL or missing references)
			//IL_05c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_05c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_05c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_05cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_05d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_05d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_05d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_05da: Unknown result type (might be due to invalid IL or missing references)
			//IL_05df: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_05fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0560: Unknown result type (might be due to invalid IL or missing references)
			//IL_0564: Unknown result type (might be due to invalid IL or missing references)
			//IL_056b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0570: Unknown result type (might be due to invalid IL or missing references)
			//IL_0575: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b8f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b96: Expected O, but got Unknown
			//IL_06a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c40: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c55: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0217: Unknown result type (might be due to invalid IL or missing references)
			//IL_06ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_071b: Unknown result type (might be due to invalid IL or missing references)
			//IL_06db: Unknown result type (might be due to invalid IL or missing references)
			//IL_09a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_09b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_09e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_09f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a0b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a0d: Unk