Decompiled source of FishSlapper v1.0.0

FishSlapper.dll

Decompiled 15 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using FishNet.Connection;
using FishNet.Object;
using FishSlapper.Net;
using FishSlapper.Slap;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Steamworks;
using TMPro;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.InputSystem.Utilities;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("FishSlapper")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Azumatt")]
[assembly: AssemblyProduct("FishSlapper")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("CE328DD3-C686-4ADA-A12C-EEA94236929B")]
[assembly: AssemblyFileVersion("1.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[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;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class ExtensionMarkerAttribute : Attribute
	{
		public ExtensionMarkerAttribute(string name)
		{
		}
	}
}
namespace FishSlapper
{
	public static class KeyboardExtensions
	{
		[SpecialName]
		public sealed class <G>$8D1D3E80A18AA9715780B6CB7003B2F1
		{
			[SpecialName]
			public static class <M>$895AB635D4D087636CF1C26BA650BA11
			{
			}

			[ExtensionMarker("<M>$895AB635D4D087636CF1C26BA650BA11")]
			public bool IsKeyDown()
			{
				throw null;
			}

			[ExtensionMarker("<M>$895AB635D4D087636CF1C26BA650BA11")]
			public bool IsKeyHeld()
			{
				throw null;
			}

			[ExtensionMarker("<M>$895AB635D4D087636CF1C26BA650BA11")]
			public string? VanillaAction()
			{
				throw null;
			}
		}

		private static readonly Dictionary<KeyCode, Key> Keys = BuildKeyLookup();

		public static bool IsKeyDown(this KeyboardShortcut shortcut)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			KeyControl val = Control(((KeyboardShortcut)(ref shortcut)).MainKey);
			if (val != null && ((ButtonControl)val).wasPressedThisFrame)
			{
				return ((KeyboardShortcut)(ref shortcut)).Modifiers.All(IsHeld);
			}
			return false;
		}

		public static bool IsKeyHeld(this KeyboardShortcut shortcut)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			KeyControl val = Control(((KeyboardShortcut)(ref shortcut)).MainKey);
			if (val != null && ((ButtonControl)val).isPressed)
			{
				return ((KeyboardShortcut)(ref shortcut)).Modifiers.All(IsHeld);
			}
			return false;
		}

		public static string? VanillaAction(this KeyboardShortcut shortcut)
		{
			//IL_0002: 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_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			KeyControl val = Control(((KeyboardShortcut)(ref shortcut)).MainKey);
			if (val == null || !Object.op_Implicit((Object)(object)GameInfo._instance) || !Object.op_Implicit((Object)(object)GameInfo.Input) || !Object.op_Implicit((Object)(object)GameInfo.Input.actions))
			{
				return null;
			}
			foreach (InputAction action in GameInfo.Input.actions)
			{
				Enumerator<InputBinding> enumerator2 = action.bindings.GetEnumerator();
				try
				{
					while (enumerator2.MoveNext())
					{
						InputBinding current2 = enumerator2.Current;
						if (!((InputBinding)(ref current2)).isComposite && InputControlPath.Matches(((InputBinding)(ref current2)).effectivePath, (InputControl)(object)val))
						{
							return action.name;
						}
					}
				}
				finally
				{
					((IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose();
				}
			}
			return null;
		}

		private static KeyControl? Control(KeyCode code)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			Keyboard current = Keyboard.current;
			if (current == null || !Keys.TryGetValue(code, out var value))
			{
				return null;
			}
			return current[value];
		}

		private static bool IsHeld(KeyCode code)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			KeyControl val = Control(code);
			if (val != null)
			{
				return ((ButtonControl)val).isPressed;
			}
			return false;
		}

		private static Dictionary<KeyCode, Key> BuildKeyLookup()
		{
			//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_023a: Unknown result type (might be due to invalid IL or missing references)
			//IL_023f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0240: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<KeyCode, Key> dictionary = new Dictionary<KeyCode, Key>();
			foreach (KeyCode value in Enum.GetValues(typeof(KeyCode)))
			{
				string text = ((object)value/*cast due to .constrained prefix*/).ToString();
				if (text.StartsWith("Alpha"))
				{
					text = "Digit" + text.Substring(5);
				}
				else if (text.StartsWith("Keypad"))
				{
					text = "Numpad" + text.Substring(6);
				}
				else
				{
					string text2;
					switch (text)
					{
					case "Return":
						text2 = "Enter";
						break;
					case "LeftControl":
						text2 = "LeftCtrl";
						break;
					case "RightControl":
						text2 = "RightCtrl";
						break;
					case "LeftWindows":
					case "LeftCommand":
					case "LeftApple":
						text2 = "LeftMeta";
						break;
					case "RightWindows":
					case "RightCommand":
					case "RightApple":
						text2 = "RightMeta";
						break;
					case "BackQuote":
						text2 = "Backquote";
						break;
					case "Print":
						text2 = "PrintScreen";
						break;
					default:
						text2 = text;
						break;
					}
					text = text2;
				}
				if (Enum.TryParse<Key>(text, ignoreCase: true, out Key result) && (int)result != 0)
				{
					dictionary[value] = result;
				}
			}
			return dictionary;
		}
	}
	public enum Toggle
	{
		On = 1,
		Off = 0
	}
	public enum SlapButton
	{
		RightClick,
		LeftClick,
		None
	}
	public enum ValueMode
	{
		Multiply,
		Add
	}
	public enum SlapAnimation
	{
		Slap,
		Fist
	}
	public enum SoundMode
	{
		ReviveSlap,
		PunchHit,
		Off
	}
	public enum RuinMode
	{
		LoseTheSlaps,
		LoseOneSlap,
		DestroyIt
	}
	[BepInPlugin("Azumatt.FishSlapper", "FishSlapper", "1.0.0")]
	public class FishSlapperPlugin : BaseUnityPlugin
	{
		internal const string ModName = "FishSlapper";

		internal const string ModVersion = "1.0.0";

		internal const string Author = "Azumatt";

		private const string ModGUID = "Azumatt.FishSlapper";

		private const string ConfigFileName = "Azumatt.FishSlapper.cfg";

		private static readonly string ConfigFileFullPath;

		internal static readonly ManualLogSource FishSlapperLogger;

		private readonly Harmony harmony = new Harmony("Azumatt.FishSlapper");

		internal static ConfigEntry<Toggle> modEnabled;

		internal static ConfigEntry<SlapButton> slapButton;

		internal static ConfigEntry<KeyboardShortcut> slapKey;

		internal static ConfigEntry<Toggle> slapAnything;

		internal static ConfigEntry<int> maxSlaps;

		internal static ConfigEntry<float> slapCooldown;

		internal static ConfigEntry<SlapAnimation> slapAnimation;

		internal static ConfigEntry<Toggle> clipWrist;

		internal static ConfigEntry<float> contactOffset;

		internal static ConfigEntry<ValueMode> valueMode;

		internal static ConfigEntry<float> valuePerSlap;

		internal static ConfigEntry<float> maxMultiplier;

		internal static ConfigEntry<float> ruinChance;

		internal static ConfigEntry<Toggle> ruinRamps;

		internal static ConfigEntry<RuinMode> ruinMode;

		internal static ConfigEntry<Toggle> showPrompt;

		internal static ConfigEntry<string> promptText;

		internal static ConfigEntry<SoundMode> slapSound;

		internal static ConfigEntry<float> slapVolume;

		internal static ConfigEntry<Toggle> slapParticles;

		internal static ConfigEntry<float> slapShake;

		internal static ConfigEntry<Toggle> showNumbers;

		internal static ConfigEntry<Toggle> chatMessages;

		internal static bool IsEnabled
		{
			get
			{
				ConfigEntry<Toggle> val = modEnabled;
				if (val != null)
				{
					return val.Value == Toggle.On;
				}
				return false;
			}
		}

		public void Awake()
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Expected O, but got Unknown
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Expected O, but got Unknown
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Expected O, but got Unknown
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Expected O, but got Unknown
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Expected O, but got Unknown
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_021d: Expected O, but got Unknown
			//IL_02d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e0: Expected O, but got Unknown
			//IL_0329: Unknown result type (might be due to invalid IL or missing references)
			//IL_0333: Expected O, but got Unknown
			bool saveOnConfigSet = ((BaseUnityPlugin)this).Config.SaveOnConfigSet;
			((BaseUnityPlugin)this).Config.SaveOnConfigSet = false;
			modEnabled = config("1 - General", "Enabled", Toggle.On, "Turn the whole mod off without unloading it.");
			slapButton = config("2 - Slapping", "Slap Button", SlapButton.RightClick, "Right click is free while you hold a fish - Creature doesn't override Item.SecondaryInput. LeftClick fights PlayerEating, which binds PlayerLeftClick itself and starts eating any creature you hold, so you'll slap and chew at the same time.");
			slapKey = config<KeyboardShortcut>("2 - Slapping", "Slap Key", default(KeyboardShortcut), "Extra bind, works alongside the button. Empty by default. Vanilla owns WASD, QEFRZXCVB, 1-9, space, tab, shift, ctrl and escape - G H I J K L M N O P T U Y are the free letters.");
			slapAnything = config("2 - Slapping", "Slap Anything", Toggle.Off, "Off is your catch only. On lets you smack anything you can pick up. Dead players are never included, that one is the vanilla revive.");
			maxSlaps = config("2 - Slapping", "Max Slaps Per Fish", 5, new ConfigDescription("How many times one fish will take it. The host's number is the one that decides money.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			slapCooldown = config("2 - Slapping", "Slap Cooldown", 0.35f, new ConfigDescription("Seconds between swings. Your own swing speed still caps you.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), Array.Empty<object>()));
			slapAnimation = config("3 - Animation", "Slap Animation", SlapAnimation.Slap, "Slap drives your hand along DeadPlayerSlap, the clip and the trick the revive slap uses - it has no hand model of its own, it swings yours. Fist is the fallback, a plain swing bent sideways so it doesn't read as a jab.");
			clipWrist = config("3 - Animation", "Wrist From Clip", Toggle.On, "Slap only. On takes the hand's rotation from the clip too. Off leaves the wrist to vanilla, which is the one to try if the hand comes out twisted.");
			contactOffset = config("3 - Animation", "Contact Offset", 0.15f, new ConfigDescription("How far back toward you the hand lands, so it smacks the near side instead of reaching through.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			valueMode = config("4 - Value", "Value Mode", ValueMode.Multiply, "Multiply compounds every slap. Add stacks the same bonus flat each time.");
			valuePerSlap = config("4 - Value", "Value Per Slap", 1.25f, new ConfigDescription("1.25 is a 25% bump. Rides Item._bettingMultiplier, the same one the roulette table pays out with.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10f), Array.Empty<object>()));
			maxMultiplier = config("4 - Value", "Max Multiplier", 10f, new ConfigDescription("Ceiling on the whole multiplier, casino winnings included. 0 is no ceiling.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>()));
			ruinChance = config("5 - Risk", "Ruin Chance", 30f, new ConfigDescription("Percent chance a slap goes wrong. 0 turns the gamble off and every slap pays.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>()));
			ruinRamps = config("5 - Risk", "Ruin Chance Ramps", Toggle.On, "Scale the chance by how many slaps the fish has already taken. First one is free, the last one carries the whole chance.");
			ruinMode = config("5 - Risk", "Ruin Mode", RuinMode.LoseTheSlaps, "LoseTheSlaps backs out everything you slapped in, LoseOneSlap takes one step back, DestroyIt is the roulette rule.");
			showPrompt = config("6 - Prompt", "Show Slap Prompt", Toggle.On, "Put the slap binding on the held item line, next to the Inspect prompt the game already shows for a creature. Stays up for as long as you hold something slappable.");
			promptText = config("6 - Prompt", "Slap Prompt Text", "Slap", "The word in front of the button sprite. Not localized, so set it to whatever your language wants.");
			slapSound = config("7 - Feedback", "Slap Sound", SoundMode.ReviveSlap, "ReviveSlap is the AudioSequence off the DeadPlayer prefab, played at swing start the way the revive does. PunchHit is the game's FishPunchHit clip on contact instead.");
			slapVolume = config("7 - Feedback", "Slap Volume", 2f, new ConfigDescription("Scales whichever of the two you picked.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>()));
			slapParticles = config("7 - Feedback", "Slap Particles", Toggle.On, "Little blood puff where the hand lands.");
			slapShake = config("7 - Feedback", "Screen Shake", 150f, new ConfigDescription("Kick on your own view when you land one. 0 is off.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1000f), Array.Empty<object>()));
			showNumbers = config("7 - Feedback", "Show Value Numbers", Toggle.On, "Pop the money a slap gained or cost, read off the synced worth rather than guessed at. Rides the game's damage numbers, so it needs those turned on in the game's own settings.");
			chatMessages = config("7 - Feedback", "Chat Messages", Toggle.On, "Local chat line with the running total.");
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			harmony.PatchAll(executingAssembly);
			SetupWatcher();
			if (saveOnConfigSet)
			{
				((BaseUnityPlugin)this).Config.SaveOnConfigSet = saveOnConfigSet;
				((BaseUnityPlugin)this).Config.Save();
			}
		}

		private void Update()
		{
			Slapper.Update();
		}

		private void OnDestroy()
		{
			((BaseUnityPlugin)this).Config.Save();
		}

		private void SetupWatcher()
		{
			FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(Paths.ConfigPath, "Azumatt.FishSlapper.cfg");
			fileSystemWatcher.Changed += ReadConfigValues;
			fileSystemWatcher.Created += ReadConfigValues;
			fileSystemWatcher.Renamed += ReadConfigValues;
			fileSystemWatcher.IncludeSubdirectories = true;
			fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject;
			fileSystemWatcher.EnableRaisingEvents = true;
		}

		private void ReadConfigValues(object sender, FileSystemEventArgs e)
		{
			if (!File.Exists(ConfigFileFullPath))
			{
				return;
			}
			try
			{
				((BaseUnityPlugin)this).Config.Reload();
			}
			catch
			{
				FishSlapperLogger.LogError((object)"There was an issue loading your Azumatt.FishSlapper.cfg");
				FishSlapperLogger.LogError((object)"Please check your config entries for spelling and format!");
			}
		}

		private ConfigEntry<T> config<T>(string group, string name, T value, ConfigDescription description)
		{
			return ((BaseUnityPlugin)this).Config.Bind<T>(group, name, value, description);
		}

		private ConfigEntry<T> config<T>(string group, string name, T value, string description)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			return config(group, name, value, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()));
		}

		static FishSlapperPlugin()
		{
			string configPath = Paths.ConfigPath;
			char directorySeparatorChar = Path.DirectorySeparatorChar;
			ConfigFileFullPath = configPath + directorySeparatorChar + "Azumatt.FishSlapper.cfg";
			FishSlapperLogger = Logger.CreateLogSource("FishSlapper");
			modEnabled = null;
			slapButton = null;
			slapKey = null;
			slapAnything = null;
			maxSlaps = null;
			slapCooldown = null;
			slapAnimation = null;
			clipWrist = null;
			contactOffset = null;
			valueMode = null;
			valuePerSlap = null;
			maxMultiplier = null;
			ruinChance = null;
			ruinRamps = null;
			ruinMode = null;
			showPrompt = null;
			promptText = null;
			slapSound = null;
			slapVolume = null;
			slapParticles = null;
			slapShake = null;
			showNumbers = null;
			chatMessages = null;
		}
	}
	public static class Patches
	{
		[HarmonyPatch(typeof(Player), "InitializePlayer")]
		private static class OnLocalPlayerReady
		{
			private static bool started;

			private static void Postfix()
			{
				if (!started)
				{
					started = true;
					SlapHost.Register();
				}
			}
		}

		[HarmonyPatch(typeof(Server), "RpcReader___SendChatMessage___3264264606")]
		private static class CaptureChatSender
		{
			private static void Prefix(NetworkConnection __2)
			{
				ChatRpc.Sender = __2;
			}
		}

		[HarmonyPatch(typeof(Server), "RpcLogic___SendChatMessage___3264264606")]
		private static class SwallowOurRequests
		{
			private static bool Prefix(string __1)
			{
				return !ChatRpc.TryHandle(__1);
			}
		}

		[HarmonyPatch(typeof(OnlineChatManager), "RpcLogic___SendChatMessage___3264264606")]
		private static class HideRelayedRequests
		{
			private static bool Prefix(string __1)
			{
				return !ChatRpc.IsRequest(__1);
			}
		}

		[HarmonyPatch(typeof(PlayerPunching), "StartPunching")]
		private static class TagSlapSwings
		{
			private static void Prefix(PlayerPunching __instance, Transform target, int side)
			{
				Slapper.WindUpSlap(__instance, target, side);
			}

			private static void Postfix(PlayerPunching __instance, Transform target, int side)
			{
				Slapper.MarkPunch(__instance, target, side);
			}
		}

		[HarmonyPatch(typeof(PlayerPunching), "MoveAttack")]
		private static class ArcTheFist
		{
			private static void Postfix(PlayerPunching __instance, int side, Transform fist)
			{
				Slapper.OnMoveAttack(__instance, side, fist);
			}
		}

		[HarmonyPatch(typeof(PlayerPunching), "UpdateFist")]
		private static class DriveSlapHand
		{
			private static void Postfix(PlayerPunching __instance, int side)
			{
				Slapper.OnUpdateFist(__instance, side);
			}
		}

		[HarmonyPatch(typeof(PlayerPunching), "HitTarget")]
		private static class SlapInsteadOfPunch
		{
			private static bool Prefix(PlayerPunching __instance, int side)
			{
				return Slapper.OnHitTarget(__instance, side);
			}
		}

		[HarmonyPatch(typeof(ItemUI), "ShowSpecificItemInfo", new Type[]
		{
			typeof(HeldInfo),
			typeof(bool)
		})]
		private static class KeepSlapPromptUp
		{
			private static void Prefix(HeldInfo info, ref bool hideWithDelay)
			{
				if (Object.op_Implicit((Object)(object)Player.LocalPlayer) && SlapPrompt.KeepUp(info, Player.LocalPlayer.Holding.HeldItem))
				{
					hideWithDelay = false;
				}
			}
		}

		[HarmonyPatch(typeof(OnHitUI), "AddDamageNumber")]
		private static class MoneyNotDamage
		{
			private static void Postfix(OnHitUI __instance)
			{
				Slapper.OnDamageNumber(__instance);
			}
		}
	}
}
namespace FishSlapper.Slap
{
	internal static class SlapCounts
	{
		private static readonly Dictionary<Item, int> counts = new Dictionary<Item, int>();

		internal static int Get(Item item)
		{
			if (!counts.TryGetValue(item, out var value))
			{
				return 0;
			}
			return value;
		}

		internal static void Add(Item item)
		{
			counts[item] = Get(item) + 1;
			if (counts.Count > 64)
			{
				Prune();
			}
		}

		internal static void Clear()
		{
			counts.Clear();
		}

		private static void Prune()
		{
			List<Item> list = new List<Item>();
			foreach (KeyValuePair<Item, int> count in counts)
			{
				if (!Object.op_Implicit((Object)(object)count.Key))
				{
					list.Add(count.Key);
				}
			}
			foreach (Item item in list)
			{
				counts.Remove(item);
			}
		}
	}
	internal static class SlapPrompt
	{
		internal static void Refresh(Item held)
		{
			if (FishSlapperPlugin.showPrompt.Value == Toggle.Off || !Slapper.IsSlappable(held))
			{
				return;
			}
			ItemUI val = Ui();
			if (val?._curInfo != null)
			{
				TextMeshProUGUI itemInfoText = val._itemInfoText;
				string text = Prefix();
				if (Object.op_Implicit((Object)(object)itemInfoText) && text.Length != 0 && !((TMP_Text)itemInfoText).text.StartsWith(text, StringComparison.Ordinal))
				{
					((TMP_Text)itemInfoText).text = text + ((TMP_Text)itemInfoText).text;
				}
			}
		}

		internal static bool KeepUp(HeldInfo info, Item held)
		{
			if (FishSlapperPlugin.showPrompt.Value == Toggle.Off || !Slapper.IsSlappable(held))
			{
				return false;
			}
			if (Object.op_Implicit((Object)(object)LocalizationManager._instance))
			{
				return info == LocalizationManager.HeldCreatureInfo;
			}
			return false;
		}

		private static string Prefix()
		{
			string value = FishSlapperPlugin.promptText.Value;
			string text = Input();
			if (text.Length != 0)
			{
				return value + " (" + text + ")   ";
			}
			return "";
		}

		private unsafe static string Input()
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: 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_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			InputAction val = Slapper.SlapAction();
			string text = ((val == null) ? "" : (SpriteManager.InputToSpriteName(val, (InputSchemeSelection)0, -1) ?? ""));
			if (text.Length > 0)
			{
				return text;
			}
			KeyboardShortcut value = FishSlapperPlugin.slapKey.Value;
			KeyCode mainKey = ((KeyboardShortcut)(ref value)).MainKey;
			if ((int)mainKey != 0)
			{
				return ((object)(*(KeyCode*)(&mainKey))/*cast due to .constrained prefix*/).ToString();
			}
			return "";
		}

		private static ItemUI? Ui()
		{
			if (!Object.op_Implicit((Object)(object)PlayerUI._instance))
			{
				return null;
			}
			return PlayerUI._instance._itemUI;
		}
	}
	internal static class SlapSwing
	{
		private sealed class Rig
		{
			internal Transform? Anchor;

			internal Transform? Pivot;

			internal Animation? Anim;

			internal Vector3 Contact;
		}

		private const string Clip = "DeadPlayerSlap";

		private const float Windup = 0.4f;

		private const float Arc = 0.2f;

		private static readonly ConditionalWeakTable<PlayerPunching, Rig> Rigs = new ConditionalWeakTable<PlayerPunching, Rig>();

		private static bool warned;

		internal static bool Begin(PlayerPunching punching, Item item, Player slapper)
		{
			//IL_0080: 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_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: 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_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			if (FishSlapperPlugin.slapAnimation.Value != SlapAnimation.Slap || !Object.op_Implicit((Object)(object)slapper) || !Object.op_Implicit((Object)(object)slapper.CamObject))
			{
				return false;
			}
			Rig value = Rigs.GetValue(punching, (PlayerPunching _) => new Rig());
			if (!Object.op_Implicit((Object)(object)value.Anchor) && !Build(value))
			{
				return false;
			}
			Transform anchor = value.Anchor;
			anchor.SetParent(slapper.CamObject, false);
			anchor.rotation = slapper.CamObject.rotation;
			anchor.position = ((Component)item).transform.position - anchor.rotation * value.Contact - slapper.CamObject.forward * FishSlapperPlugin.contactOffset.Value;
			value.Anim.Play("DeadPlayerSlap");
			return true;
		}

		internal static void Drive(PlayerPunching punching, int side, float percent)
		{
			//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_005a: Unknown result type (might be due to invalid IL or missing references)
			if (Rigs.TryGetValue(punching, out Rig value) && Object.op_Implicit((Object)(object)value.Anim) && Object.op_Implicit((Object)(object)value.Pivot) && Sample(value, percent))
			{
				Transform fist = punching.GetFist(side);
				if (FishSlapperPlugin.clipWrist.Value == Toggle.On)
				{
					fist.SetPositionAndRotation(value.Pivot.position, value.Pivot.rotation);
				}
				else
				{
					fist.position = value.Pivot.position;
				}
			}
		}

		internal static void FistWindUp(PlayerPunching punching, int side)
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			Player player = punching._player;
			if (FishSlapperPlugin.slapAnimation.Value != SlapAnimation.Slap && Object.op_Implicit((Object)(object)player) && Object.op_Implicit((Object)(object)player.Hands) && Object.op_Implicit((Object)(object)player.CamObject))
			{
				punching.GetFist(side).position = player.Hands.CurDefaultHandPos(side == 0) + player.CamObject.right * (Sign(side) * 0.4f);
			}
		}

		internal static void FistArc(PlayerPunching punching, int side, Transform fist)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			Player player = punching._player;
			if (Object.op_Implicit((Object)(object)player) && Object.op_Implicit((Object)(object)player.CamObject))
			{
				float num = Mathf.Clamp01(punching._curAttackPercent[side]);
				fist.position += player.CamObject.right * (Sign(side) * 0.2f * Mathf.Sin(num * (float)Math.PI));
			}
		}

		private static float Sign(int side)
		{
			if (side != 0)
			{
				return -1f;
			}
			return 1f;
		}

		private static bool Sample(Rig rig, float percent)
		{
			AnimationState val = rig.Anim["DeadPlayerSlap"];
			if ((TrackedReference)(object)val == (TrackedReference)null)
			{
				return false;
			}
			val.enabled = true;
			val.weight = 1f;
			val.speed = 0f;
			val.time = Mathf.Clamp01(percent) * val.length;
			rig.Anim.Sample();
			return true;
		}

		private static bool Build(Rig rig)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			AnimationClip val = Source();
			if ((Object)(object)val == (Object)null)
			{
				Warn();
				return false;
			}
			GameObject val2 = new GameObject("FishSlapperSlapAnchor");
			GameObject val3 = new GameObject("DeadPlayerSlapPivot");
			val3.transform.SetParent(val2.transform, false);
			Animation val4 = val3.AddComponent<Animation>();
			val4.AddClip(val, "DeadPlayerSlap");
			val4.playAutomatically = false;
			val4.wrapMode = (WrapMode)8;
			rig.Anchor = val2.transform;
			rig.Pivot = val3.transform;
			rig.Anim = val4;
			val4.Play("DeadPlayerSlap");
			val4["DeadPlayerSlap"].speed = 0f;
			if (!Sample(rig, 1f))
			{
				Object.Destroy((Object)(object)val2);
				rig.Anchor = null;
				Warn();
				return false;
			}
			rig.Contact = val3.transform.localPosition;
			return true;
		}

		private static AnimationClip? Source()
		{
			if (!Object.op_Implicit((Object)(object)GameInfo._instance) || !Object.op_Implicit((Object)(object)GameInfo.DeadPlayerPrefab))
			{
				return null;
			}
			Animation slapHandAnim = GameInfo.DeadPlayerPrefab._slapHandAnim;
			if (!Object.op_Implicit((Object)(object)slapHandAnim))
			{
				return null;
			}
			return slapHandAnim.GetClip("DeadPlayerSlap");
		}

		private static void Warn()
		{
			if (!warned)
			{
				warned = true;
				FishSlapperPlugin.FishSlapperLogger.LogWarning((object)"Couldn't get DeadPlayerSlap off the DeadPlayer prefab. Falling back to the fist - set Slap Animation to Fist to shut this up.");
			}
		}
	}
	internal static class SlapHost
	{
		internal static void Register()
		{
			ChatRpc.Register("slap", OnSlap);
		}

		private static void OnSlap(Player from, string[] args)
		{
			Item heldItem = from.Holding.HeldItem;
			if (!Slapper.IsSlappable(heldItem) || ((Object)(object)heldItem.SyncedHolder != (Object)(object)from && (Object)(object)heldItem.Holder != (Object)(object)from))
			{
				return;
			}
			int num = SlapCounts.Get(heldItem);
			int value = FishSlapperPlugin.maxSlaps.Value;
			if (num < value)
			{
				SlapCounts.Add(heldItem);
				if (Ruined(num, value))
				{
					Ruin(heldItem, num);
					return;
				}
				float value2 = FishSlapperPlugin.valuePerSlap.Value;
				float num2 = ((FishSlapperPlugin.valueMode.Value == ValueMode.Multiply) ? (heldItem.BettingMultiplier * value2) : (heldItem.BettingMultiplier + (value2 - 1f)));
				float value3 = FishSlapperPlugin.maxMultiplier.Value;
				heldItem._bettingMultiplier.Value = ((value3 > 0f) ? Mathf.Min(num2, value3) : num2);
			}
		}

		private static bool Ruined(int done, int max)
		{
			float num = FishSlapperPlugin.ruinChance.Value;
			if (num <= 0f)
			{
				return false;
			}
			if (FishSlapperPlugin.ruinRamps.Value == Toggle.On && max > 1)
			{
				num *= (float)done / (float)(max - 1);
			}
			return Random.value * 100f < num;
		}

		private static void Ruin(Item item, int done)
		{
			float value = FishSlapperPlugin.valuePerSlap.Value;
			bool flag = FishSlapperPlugin.valueMode.Value == ValueMode.Multiply;
			switch (FishSlapperPlugin.ruinMode.Value)
			{
			case RuinMode.DestroyIt:
				item.DestroyItem((byte)0, byte.MaxValue);
				break;
			case RuinMode.LoseOneSlap:
				item._bettingMultiplier.Value = Mathf.Max(1f, flag ? (item.BettingMultiplier / Mathf.Max(value, 1.0001f)) : (item.BettingMultiplier - (value - 1f)));
				break;
			default:
				item._bettingMultiplier.Value = Mathf.Max(1f, flag ? (item.BettingMultiplier / Mathf.Pow(Mathf.Max(value, 1.0001f), (float)done)) : (item.BettingMultiplier - (float)done * (value - 1f)));
				break;
			}
		}
	}
	internal static class Slapper
	{
		private sealed class Swing
		{
			internal bool IsSlap;

			internal bool Landed;

			internal bool UsingClip;
		}

		internal const int RightSide = 0;

		private const int LeftSide = 1;

		private static readonly ConditionalWeakTable<PlayerPunching, Swing[]> swings = new ConditionalWeakTable<PlayerPunching, Swing[]>();

		private static float nextSlapTime;

		private static Item? watched;

		private static string watchedName = "";

		private static int watchedWorth;

		private static float feedbackUntil;

		private static float resultBy;

		private static string? pendingNumber;

		internal static void Update()
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.LocalPlayer;
			if (FishSlapperPlugin.IsEnabled && Object.op_Implicit((Object)(object)localPlayer))
			{
				if (ButtonPressed() || FishSlapperPlugin.slapKey.Value.IsKeyDown())
				{
					TrySlap(localPlayer);
				}
				WatchWorth(localPlayer);
				SlapPrompt.Refresh(localPlayer.Holding.HeldItem);
			}
		}

		internal static void TrySlap(Player player)
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: 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)
			if (!FishSlapperPlugin.IsEnabled)
			{
				return;
			}
			Item heldItem = player.Holding.HeldItem;
			if (!player.BlockInputs && IsSlappable(heldItem) && !(Time.time < nextSlapTime) && SlapCounts.Get(heldItem) < FishSlapperPlugin.maxSlaps.Value && Object.op_Implicit((Object)(object)player.Punching) && player.Punching.CanPunch())
			{
				int num = FreeSide(heldItem);
				Vector3 val = ((Component)heldItem).transform.position - player.CamObject.forward * FishSlapperPlugin.contactOffset.Value;
				player.Punching.StartPunching(((Component)heldItem).transform, num, true, ((Component)heldItem).transform.InverseTransformPoint(val));
				nextSlapTime = Time.time + FishSlapperPlugin.slapCooldown.Value;
				feedbackUntil = Time.time + 2f;
				if (!Object.op_Implicit((Object)(object)Server.Instance) || !((NetworkBehaviour)Server.Instance).IsServerInitialized)
				{
					SlapCounts.Add(heldItem);
				}
				ChatRpc.Send("slap");
				resultBy = Time.time + 0.75f;
			}
		}

		internal static bool IsSlappable(Item item)
		{
			if (!Object.op_Implicit((Object)(object)item) || item.IsDestroying || Object.op_Implicit((Object)(object)item.DeadPlayer))
			{
				return false;
			}
			if (FishSlapperPlugin.slapAnything.Value != Toggle.On)
			{
				return Object.op_Implicit((Object)(object)item.Creature);
			}
			return true;
		}

		private static int FreeSide(Item item)
		{
			return item.HandTransformsRight.Exists ? 1 : 0;
		}

		private static bool ButtonPressed()
		{
			InputAction val = SlapAction();
			if (val != null)
			{
				return val.WasPressedThisFrame();
			}
			return false;
		}

		internal static InputAction? SlapAction()
		{
			SlapButton value = FishSlapperPlugin.slapButton.Value;
			if (value == SlapButton.None || !Object.op_Implicit((Object)(object)GameInfo._instance) || !Object.op_Implicit((Object)(object)GameInfo.Input) || (Object)(object)GameInfo.Input.actions == (Object)null)
			{
				return null;
			}
			return GameInfo.Input.actions[(value == SlapButton.RightClick) ? "PlayerRightClick" : "PlayerLeftClick"];
		}

		private static Item? HeldTarget(Transform target)
		{
			Item val = (Object.op_Implicit((Object)(object)target) ? ItemManager.Get(target) : null);
			if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val.Holder))
			{
				return null;
			}
			return val;
		}

		private static Swing SwingFor(PlayerPunching punching, int side)
		{
			return swings.GetValue(punching, (PlayerPunching _) => new Swing[2]
			{
				new Swing(),
				new Swing()
			})[side];
		}

		internal static void MarkPunch(PlayerPunching punching, Transform target, int side)
		{
			Item val = HeldTarget(target);
			Swing swing = SwingFor(punching, side);
			swing.IsSlap = val != null;
			swing.Landed = false;
			swing.UsingClip = swing.IsSlap && SlapSwing.Begin(punching, val, punching._player);
			if (swing.IsSlap)
			{
				PlaySwingSound(val, punching._player);
			}
		}

		internal static void WindUpSlap(PlayerPunching punching, Transform target, int side)
		{
			if (HeldTarget(target) != null)
			{
				SlapSwing.FistWindUp(punching, side);
			}
		}

		internal static void OnMoveAttack(PlayerPunching punching, int side, Transform fist)
		{
			Swing swing = SwingFor(punching, side);
			if (swing != null && swing.IsSlap && !swing.UsingClip)
			{
				SlapSwing.FistArc(punching, side, fist);
			}
		}

		internal static void OnUpdateFist(PlayerPunching punching, int side)
		{
			if (SwingFor(punching, side).UsingClip && (punching._isAttacking[side] || punching._isReturning[side]))
			{
				SlapSwing.Drive(punching, side, punching._curAttackPercent[side]);
			}
		}

		internal static bool OnHitTarget(PlayerPunching punching, int side)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			Swing swing = SwingFor(punching, side);
			if (!swing.IsSlap)
			{
				return true;
			}
			if (swing.Landed)
			{
				return false;
			}
			swing.Landed = true;
			Player player = punching._player;
			if (!Object.op_Implicit((Object)(object)player))
			{
				return false;
			}
			Transform val = punching._curTarget[side];
			Vector3 point = (Object.op_Implicit((Object)(object)val) ? val.TransformPoint(punching._targetHitPoint[side]) : player.CamObject.position);
			PlayContactEffects(player, point);
			return false;
		}

		private static void PlaySwingSound(Item item, Player slapper)
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: 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_00a3: Expected O, but got Unknown
			if (FishSlapperPlugin.slapSound.Value == SoundMode.ReviveSlap && Object.op_Implicit((Object)(object)slapper))
			{
				AudioSequence val = ((Object.op_Implicit((Object)(object)GameInfo._instance) && Object.op_Implicit((Object)(object)GameInfo.DeadPlayerPrefab)) ? GameInfo.DeadPlayerPrefab._slapSounds : null);
				if (val?.Steps == null || val.Steps.Length == 0)
				{
					Thump(((Component)item).transform.position);
					return;
				}
				AudioSequenceManager.PlayPlayerSequence(new AudioSequence
				{
					Steps = val.Steps,
					Distance = val.Distance,
					Volume = val.Volume * FishSlapperPlugin.slapVolume.Value
				}, slapper, ((Component)item).gameObject);
			}
		}

		private static void PlayContactEffects(Player slapper, Vector3 point)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: 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_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			if (FishSlapperPlugin.slapSound.Value == SoundMode.PunchHit)
			{
				Thump(point);
			}
			if (FishSlapperPlugin.slapParticles.Value == Toggle.On)
			{
				ParticleManager.Play("BloodSmall", point, Vector3.up);
			}
			float value = FishSlapperPlugin.slapShake.Value;
			if (value > 0f && (Object)(object)slapper == (Object)(object)Player.LocalPlayer && Object.op_Implicit((Object)(object)slapper.ScreenShake))
			{
				slapper.ScreenShake.Shake(value, 1, default(Vector2));
			}
		}

		private static void Thump(Vector3 point)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			AudioManager.PlayClipAt("FishPunchHit", point, true, (AudioDistance)1, FishSlapperPlugin.slapVolume.Value, 0f);
		}

		private static void WatchWorth(Player player)
		{
			Item heldItem = player.Holding.HeldItem;
			if (watched != null && !Object.op_Implicit((Object)(object)watched))
			{
				if (Time.time <= feedbackUntil)
				{
					Announce(watchedName + "  " + Signed(-watchedWorth) + "  (gone)");
				}
				Watch(null);
			}
			else if (heldItem != watched)
			{
				Watch(heldItem);
			}
			else if (Object.op_Implicit((Object)(object)heldItem))
			{
				int totalWorth = heldItem.TotalWorth;
				int num = totalWorth - watchedWorth;
				watchedWorth = totalWorth;
				if (num != 0 && Time.time <= feedbackUntil)
				{
					resultBy = 0f;
					ShowMoney(heldItem, num, totalWorth);
					Announce($"{watchedName}  {Signed(num)}  (${totalWorth})");
				}
				else if (resultBy > 0f && Time.time > resultBy)
				{
					resultBy = 0f;
					Announce($"{watchedName}  no change  (${totalWorth})");
				}
			}
		}

		private static void Watch(Item? item)
		{
			watched = item;
			watchedName = (Object.op_Implicit((Object)(object)item) ? item.GetName() : "");
			watchedWorth = (Object.op_Implicit((Object)(object)item) ? item.TotalWorth : 0);
			resultBy = 0f;
		}

		private static string Signed(int amount)
		{
			if (amount >= 0)
			{
				return $"+${amount}";
			}
			return $"-${-amount}";
		}

		private static void ShowMoney(Item held, int diff, int worth)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			if (FishSlapperPlugin.showNumbers.Value != Toggle.Off)
			{
				pendingNumber = $"<size=150%>${worth}</size>\n<size=70%>{Signed(diff)}</size>";
				PlayerUI.AddDamageNumber(((Component)held).transform.position, diff, diff < 0);
				pendingNumber = null;
			}
		}

		internal static void OnDamageNumber(OnHitUI ui)
		{
			if (pendingNumber != null && DecalManager.UseDamageNumbers && ui._damageTexts.Count != 0)
			{
				TextMeshProUGUI obj = ui._damageTexts[ui._curDamageText];
				((TMP_Text)obj).richText = true;
				((TMP_Text)obj).text = pendingNumber;
			}
		}

		private static void Announce(string message)
		{
			if (FishSlapperPlugin.chatMessages.Value == Toggle.On)
			{
				ChatManager.ChatMessage(message);
			}
		}

		[Conditional("DEBUG")]
		private static void Log(string what)
		{
			FishSlapperPlugin.FishSlapperLogger.LogInfo((object)what);
		}
	}
}
namespace FishSlapper.Net
{
	internal static class ChatRpc
	{
		internal const string Prefix = "!FishSlapper ";

		private static readonly Dictionary<string, Action<Player, string[]>> handlers = new Dictionary<string, Action<Player, string[]>>(StringComparer.Ordinal);

		internal static NetworkConnection? Sender;

		internal static void Register(string command, Action<Player, string[]> onHost)
		{
			handlers[command] = onHost;
		}

		internal static void Send(string command, params string[] args)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)Server.Instance))
			{
				if (((NetworkBehaviour)Server.Instance).IsServerInitialized)
				{
					Run(Player.LocalPlayer, command, args);
				}
				else
				{
					Server.Instance.SendChatMessage(SteamUser.GetSteamID().m_SteamID, "!FishSlapper " + command + ((args.Length != 0) ? (" " + string.Join(" ", args)) : ""));
				}
			}
		}

		internal static bool IsRequest(string? message)
		{
			return message?.StartsWith("!FishSlapper ", StringComparison.Ordinal) ?? false;
		}

		internal static bool TryHandle(string message)
		{
			Player val = TakeSender();
			if (!IsRequest(message))
			{
				return false;
			}
			if (!FishSlapperPlugin.IsEnabled)
			{
				return true;
			}
			string[] array = message.Substring("!FishSlapper ".Length).Split(new char[1] { ' ' });
			string[] array2 = new string[array.Length - 1];
			Array.Copy(array, 1, array2, 0, array2.Length);
			Run(val, array[0], array2);
			return true;
		}

		private static Player? TakeSender()
		{
			NetworkConnection sender = Sender;
			Sender = null;
			if (sender == (NetworkConnection)null)
			{
				return null;
			}
			foreach (Player player in PlayerManager.Players)
			{
				if (((NetworkBehaviour)player).Owner == sender)
				{
					return player;
				}
			}
			return null;
		}

		private static void Run(Player? from, string command, string[] args)
		{
			if (!Object.op_Implicit((Object)(object)Server.Instance) || !((NetworkBehaviour)Server.Instance).IsServerInitialized || !handlers.TryGetValue(command, out Action<Player, string[]> value) || !Object.op_Implicit((Object)(object)from))
			{
				return;
			}
			try
			{
				value(from, args);
			}
			catch (Exception arg)
			{
				FishSlapperPlugin.FishSlapperLogger.LogError((object)$"'{command}' blew up handling {args.Length} args: {arg}");
			}
		}
	}
}