Decompiled source of Better How To Fish v1.0.3

BepInEx/plugins/GiantFish/GiantFish.dll

Decompiled 2 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using FishNet;
using FishNet.Broadcast;
using FishNet.Connection;
using FishNet.Managing;
using FishNet.Object;
using FishNet.Object.Synchronizing;
using FishNet.Serializing;
using FishNet.Transporting;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.Rendering;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("GiantFish")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.3.0")]
[assembly: AssemblyInformationalVersion("1.0.3")]
[assembly: AssemblyProduct("GiantFish")]
[assembly: AssemblyTitle("GiantFish")]
[assembly: AssemblyVersion("1.0.3.0")]
[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 GiantFishMod
{
	internal static class CatchNotification
	{
		private static GameObject _currentCard;

		private static RenderTexture _currentTexture;

		private static readonly FieldInfo InventoryCameraField = AccessTools.Field(typeof(PlayerInventory), "_inventoryCamera");

		private static readonly FieldInfo ItemSlotsField = AccessTools.Field(typeof(PlayerInventory), "_itemSlots");

		private static readonly FieldInfo SlotFilterField = AccessTools.Field(typeof(InventorySlot), "_filter");

		private static readonly FieldInfo SlotRendererField = AccessTools.Field(typeof(InventorySlot), "_renderer");

		private static readonly FieldInfo SlotImageField = AccessTools.Field(typeof(InventorySlot), "_itemImage");

		public static void Show(MonoBehaviour runner, Creature creature, string catcherName)
		{
			Cleanup();
			Transform fXCanvasTrans = PlayerUI.FXCanvasTrans;
			if (!((Object)(object)fXCanvasTrans == (Object)null))
			{
				_currentCard = BuildCard(fXCanvasTrans, creature, catcherName);
				runner.StartCoroutine(AnimateCard(_currentCard));
			}
		}

		private static GameObject BuildCard(Transform parent, Creature creature, string catcherName)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Expected O, but got Unknown
			//IL_0058: 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_0068: 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_007d: 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_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: 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_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: 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_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0230: 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_0259: Unknown result type (might be due to invalid IL or missing references)
			//IL_0288: Unknown result type (might be due to invalid IL or missing references)
			//IL_0297: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0333: Unknown result type (might be due to invalid IL or missing references)
			//IL_0342: Unknown result type (might be due to invalid IL or missing references)
			//IL_035c: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_03dd: 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_042b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0430: Unknown result type (might be due to invalid IL or missing references)
			//IL_043d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0443: Unknown result type (might be due to invalid IL or missing references)
			//IL_0448: Unknown result type (might be due to invalid IL or missing references)
			//IL_0449: Unknown result type (might be due to invalid IL or missing references)
			//IL_0453: Unknown result type (might be due to invalid IL or missing references)
			//IL_0454: Unknown result type (might be due to invalid IL or missing references)
			//IL_045e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0469: Unknown result type (might be due to invalid IL or missing references)
			//IL_047d: 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_04b1: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("GiantFishCatchCard", new Type[4]
			{
				typeof(RectTransform),
				typeof(CanvasGroup),
				typeof(Image),
				typeof(Outline)
			});
			val.transform.SetParent(parent, false);
			RectTransform val2 = (RectTransform)val.transform;
			val2.anchorMin = new Vector2(0.5f, 1f);
			val2.anchorMax = new Vector2(0.5f, 1f);
			val2.pivot = new Vector2(0.5f, 1f);
			val2.anchoredPosition = new Vector2(0f, -28f);
			val2.sizeDelta = new Vector2(460f, 148f);
			((Graphic)val.GetComponent<Image>()).color = new Color(0.018f, 0.048f, 0.075f, 0.96f);
			Outline component = val.GetComponent<Outline>();
			((Shadow)component).effectColor = new Color(0.18f, 0.82f, 0.88f, 0.72f);
			((Shadow)component).effectDistance = new Vector2(2f, -2f);
			AddPanel(val.transform, "TopAccent", new Vector2(0f, 0f), new Vector2(460f, 4f), new Color(0.18f, 0.82f, 0.88f, 1f));
			AddPanel(val.transform, "PreviewPanel", new Vector2(-166f, -20f), new Vector2(112f, 108f), new Color(0.045f, 0.105f, 0.14f, 0.94f), out var panelTransform);
			AddText(val.transform, "CaptureLabel", "NUEVA CAPTURA", new Vector2(42f, -14f), new Vector2(272f, 20f), 11f, (FontStyles)1, new Color(0.62f, 0.75f, 0.81f), (TextAlignmentOptions)513);
			AddText(val.transform, "Size", $"×{FishSizeRuntime.GetDisplaySize(creature):0.00}", new Vector2(42f, -33f), new Vector2(272f, 36f), 29f, (FontStyles)1, new Color(0.38f, 0.94f, 1f), (TextAlignmentOptions)513);
			AddText(val.transform, "Catcher", "PESCADO POR  ·  " + catcherName, new Vector2(42f, -72f), new Vector2(272f, 22f), 14f, (FontStyles)1, Color.white, (TextAlignmentOptions)513);
			AddPanel(val.transform, "Divider", new Vector2(42f, -99f), new Vector2(272f, 1f), new Color(0.18f, 0.82f, 0.88f, 0.35f), out var _);
			int num = (((Object)(object)creature != (Object)null) ? ((Item)creature).TotalWorth : 0);
			AddText(val.transform, "SaleValue", $"VALOR DE VENTA  ·  ${num:N0}", new Vector2(42f, -108f), new Vector2(272f, 22f), 14f, (FontStyles)1, new Color(0.96f, 0.76f, 0.28f), (TextAlignmentOptions)513);
			Player catcherForCreature = RodUpgradeSystem.GetCatcherForCreature(creature);
			int level = RodUpgradeSystem.GetLevel(catcherForCreature);
			AddText(val.transform, "RodBonuses", $"CAÑA {level}  ·  SUERTE {RodUpgradeSystem.GetLuck(catcherForCreature)}  ·  " + $"VEL. +{level * 5}%  ·  VENTA +{RodUpgradeSystem.GetSaleBonus(catcherForCreature)}%", new Vector2(42f, -130f), new Vector2(272f, 16f), 9.5f, (FontStyles)1, new Color(0.62f, 0.75f, 0.81f), (TextAlignmentOptions)513);
			GameObject val3 = new GameObject("FishPreview", new Type[2]
			{
				typeof(RectTransform),
				typeof(RawImage)
			});
			val3.transform.SetParent(panelTransform, false);
			RectTransform val4 = (RectTransform)val3.transform;
			val4.anchorMin = Vector2.zero;
			val4.anchorMax = Vector2.one;
			val4.offsetMin = new Vector2(6f, 6f);
			val4.offsetMax = new Vector2(-6f, -6f);
			_currentTexture = BuildFishPreview(creature, out var previewUv);
			RawImage component2 = val3.GetComponent<RawImage>();
			component2.texture = (Texture)(object)_currentTexture;
			component2.uvRect = previewUv;
			val.transform.localScale = Vector3.zero;
			return val;
		}

		private static GameObject AddPanel(Transform parent, string objectName, Vector2 position, Vector2 size, Color color, out Transform panelTransform)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			//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_004a: 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)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: 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_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: 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_0092: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(objectName, new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			val.transform.SetParent(parent, false);
			RectTransform val2 = (RectTransform)val.transform;
			val2.anchorMin = new Vector2(0.5f, 1f);
			val2.anchorMax = new Vector2(0.5f, 1f);
			val2.pivot = new Vector2(0.5f, 1f);
			val2.anchoredPosition = position;
			val2.sizeDelta = size;
			Image component = val.GetComponent<Image>();
			((Graphic)component).color = color;
			((Graphic)component).raycastTarget = false;
			panelTransform = val.transform;
			return val;
		}

		private static GameObject AddPanel(Transform parent, string objectName, Vector2 position, Vector2 size, Color color)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			Transform panelTransform;
			return AddPanel(parent, objectName, position, size, color, out panelTransform);
		}

		private static void AddText(Transform parent, string objectName, string value, Vector2 position, Vector2 size, float fontSize, FontStyles style, Color color, TextAlignmentOptions alignment = (TextAlignmentOptions)514)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: 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_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			TextMeshProUGUI val;
			if ((Object)(object)PlayerUI.CanvasTextPrefab != (Object)null)
			{
				val = Object.Instantiate<TextMeshProUGUI>(PlayerUI.CanvasTextPrefab, parent);
				((Object)((Component)val).gameObject).name = objectName;
			}
			else
			{
				GameObject val2 = new GameObject(objectName, new Type[2]
				{
					typeof(RectTransform),
					typeof(TextMeshProUGUI)
				});
				val2.transform.SetParent(parent, false);
				val = val2.GetComponent<TextMeshProUGUI>();
			}
			RectTransform rectTransform = ((TMP_Text)val).rectTransform;
			rectTransform.anchorMin = new Vector2(0.5f, 1f);
			rectTransform.anchorMax = new Vector2(0.5f, 1f);
			rectTransform.pivot = new Vector2(0.5f, 1f);
			rectTransform.anchoredPosition = position;
			rectTransform.sizeDelta = size;
			((TMP_Text)val).text = value;
			((TMP_Text)val).fontSize = fontSize;
			((TMP_Text)val).fontStyle = style;
			((Graphic)val).color = color;
			((TMP_Text)val).alignment = alignment;
			((TMP_Text)val).textWrappingMode = (TextWrappingModes)0;
			((Graphic)val).raycastTarget = false;
		}

		private static RenderTexture BuildFishPreview(Creature creature, out Rect previewUv)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0304: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Expected O, but got Unknown
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Expected O, but got Unknown
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Expected O, but got Unknown
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Expected O, but got Unknown
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_022b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			//IL_0242: Unknown result type (might be due to invalid IL or missing references)
			//IL_0247: Unknown result type (might be due to invalid IL or missing references)
			//IL_026a: Unknown result type (might be due to invalid IL or missing references)
			//IL_027c: Unknown result type (might be due to invalid IL or missing references)
			//IL_028d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0298: Unknown result type (might be due to invalid IL or missing references)
			previewUv = new Rect(0f, 0f, 1f, 1f);
			Player localPlayer = Player.LocalPlayer;
			if ((Object)(object)localPlayer == (Object)null || (Object)(object)localPlayer.Inventory == (Object)null)
			{
				Plugin.Instance?.LogPreviewWarning("Local inventory was unavailable for the catch preview.");
				return null;
			}
			PlayerInventory inventory = localPlayer.Inventory;
			Camera val = (Camera)InventoryCameraField.GetValue(inventory);
			List<InventorySlot> list = (List<InventorySlot>)ItemSlotsField.GetValue(inventory);
			if ((Object)(object)val == (Object)null || list == null)
			{
				Plugin.Instance?.LogPreviewWarning("Inventory camera or slots were unavailable for the catch preview.");
				return null;
			}
			InventorySlot val2 = null;
			MeshFilter val3 = null;
			Renderer val4 = null;
			RawImage val5 = null;
			foreach (InventorySlot item in list)
			{
				if (!((Object)(object)item == (Object)null))
				{
					MeshFilter val6 = (MeshFilter)SlotFilterField.GetValue(item);
					Renderer val7 = (Renderer)SlotRendererField.GetValue(item);
					RawImage val8 = (RawImage)SlotImageField.GetValue(item);
					if ((Object)(object)val6 != (Object)null && (Object)(object)val7 != (Object)null && (Object)(object)val8 != (Object)null)
					{
						val2 = item;
						val3 = val6;
						val4 = val7;
						val5 = val8;
						break;
					}
				}
			}
			RenderTexture targetTexture = val.targetTexture;
			Mesh val9 = ((creature.IsDrip && (Object)(object)((Item)creature).DripMesh != (Object)null) ? ((Item)creature).DripMesh : ((Item)creature).Mesh);
			if ((Object)(object)val2 == (Object)null || (Object)(object)targetTexture == (Object)null || (Object)(object)val9 == (Object)null)
			{
				Plugin.Instance?.LogPreviewWarning("Inventory preview resources were incomplete for " + ((Item)creature).GetName() + ".");
				return null;
			}
			previewUv = val5.uvRect;
			RenderTexture val10 = new RenderTexture(((Texture)targetTexture).width, ((Texture)targetTexture).height, targetTexture.depth, targetTexture.format)
			{
				name = "GiantFishCatchPreview",
				antiAliasing = Mathf.Max(1, targetTexture.antiAliasing)
			};
			val10.Create();
			Mesh sharedMesh = val3.sharedMesh;
			Vector3 localPosition = ((Component)val3).transform.localPosition;
			Quaternion localRotation = ((Component)val3).transform.localRotation;
			Vector3 localScale = ((Component)val3).transform.localScale;
			bool enabled = val4.enabled;
			bool fog = RenderSettings.fog;
			try
			{
				val3.sharedMesh = val9;
				((Component)val3).transform.localPosition = ((Item)creature).InventoryMeshPos;
				((Component)val3).transform.localEulerAngles = ((Item)creature).InventoryMeshRot;
				((Component)val3).transform.localScale = Vector3.one * ((Item)creature).InventoryMeshScale;
				val4.enabled = true;
				RenderSettings.fog = false;
				val.targetTexture = val10;
				val.Render();
				return val10;
			}
			finally
			{
				val.targetTexture = targetTexture;
				RenderSettings.fog = fog;
				val4.enabled = enabled;
				val3.sharedMesh = sharedMesh;
				((Component)val3).transform.localPosition = localPosition;
				((Component)val3).transform.localRotation = localRotation;
				((Component)val3).transform.localScale = localScale;
			}
		}

		private static IEnumerator AnimateCard(GameObject card)
		{
			CanvasGroup group = card.GetComponent<CanvasGroup>();
			float elapsed = 0f;
			while (elapsed < 0.28f && (Object)(object)card != (Object)null)
			{
				elapsed += Time.unscaledDeltaTime;
				float num = Mathf.Clamp01(elapsed / 0.28f);
				float num2 = 1f - Mathf.Pow(1f - num, 3f);
				card.transform.localScale = Vector3.one * num2;
				yield return null;
			}
			yield return (object)new WaitForSecondsRealtime(4.5f);
			elapsed = 0f;
			while (elapsed < 0.6f && (Object)(object)card != (Object)null)
			{
				elapsed += Time.unscaledDeltaTime;
				group.alpha = 1f - Mathf.Clamp01(elapsed / 0.6f);
				yield return null;
			}
			if ((Object)(object)card == (Object)(object)_currentCard)
			{
				Cleanup();
			}
		}

		private static void Cleanup()
		{
			if ((Object)(object)_currentCard != (Object)null)
			{
				Object.Destroy((Object)(object)_currentCard);
			}
			if ((Object)(object)_currentTexture != (Object)null)
			{
				_currentTexture.Release();
				Object.Destroy((Object)(object)_currentTexture);
			}
			_currentCard = null;
			_currentTexture = null;
		}
	}
	internal static class CreatureHealthBarSystem
	{
		private static float _nextScan;

		public static void Tick()
		{
			if (!(Time.unscaledTime < _nextScan) && !((Object)(object)Player.LocalPlayer == (Object)null))
			{
				_nextScan = Time.unscaledTime + 1.5f;
				Creature[] array = Object.FindObjectsByType<Creature>();
				for (int i = 0; i < array.Length; i++)
				{
					Attach(array[i]);
				}
			}
		}

		public static void Attach(Creature creature)
		{
			if (!((Object)(object)creature == (Object)null) && !(creature is Bird) && !(((object)creature).GetType().Name == "Albatross") && !((Object)(object)((Component)creature).GetComponent<CreatureHealthBar>() != (Object)null))
			{
				((Component)creature).gameObject.AddComponent<CreatureHealthBar>();
			}
		}

		public static void Shutdown()
		{
			CreatureHealthBar[] array = Object.FindObjectsByType<CreatureHealthBar>();
			foreach (CreatureHealthBar creatureHealthBar in array)
			{
				if ((Object)(object)creatureHealthBar != (Object)null)
				{
					Object.Destroy((Object)(object)creatureHealthBar);
				}
			}
		}
	}
	internal sealed class CreatureHealthBar : MonoBehaviour
	{
		private Creature _creature;

		private GameObject _root;

		private Image _fill;

		private TextMeshProUGUI _numbers;

		private Renderer[] _renderers;

		private float _nextRendererRefresh;

		private Bounds _bounds;

		private void Awake()
		{
			_creature = ((Component)this).GetComponent<Creature>();
			_renderers = ((Component)this).GetComponentsInChildren<Renderer>(true);
		}

		private void LateUpdate()
		{
			//IL_0084: 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_0163: 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_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Unknown result type (might be due to invalid IL or missing references)
			//IL_0298: Unknown result type (might be due to invalid IL or missing references)
			//IL_027d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0262: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_creature == (Object)null || ((Object)(object)_root == (Object)null && !TryCreate()))
			{
				return;
			}
			Player localPlayer = Player.LocalPlayer;
			Camera val = (((Object)(object)localPlayer != (Object)null) ? localPlayer.CurCam : Camera.main);
			if ((Object)(object)val == (Object)null)
			{
				_root.SetActive(false);
				return;
			}
			int num = Mathf.Max(1, _creature.MaxHp);
			int num2 = Mathf.Clamp(_creature.Hp, 0, num);
			float num3 = Vector3.Distance(((Component)val).transform.position, ((Component)this).transform.position);
			bool flag = num2 < num || (Object)(object)((Item)_creature).AttachedRod != (Object)null;
			bool flag2 = _renderers == null || _renderers.Length == 0 || _renderers.Any((Renderer renderer) => (Object)(object)renderer != (Object)null && renderer.isVisible);
			bool flag3 = num2 > 0 && flag2 && num3 <= (flag ? 28f : 12f);
			_root.SetActive(flag3);
			if (flag3)
			{
				if (Time.unscaledTime >= _nextRendererRefresh)
				{
					_renderers = ((Component)this).GetComponentsInChildren<Renderer>(true);
					_nextRendererRefresh = Time.unscaledTime + 1.5f;
				}
				RefreshBounds();
				float num4 = Mathf.Clamp(((Bounds)(ref _bounds)).extents.y + 0.28f, 0.45f, 4.5f);
				_root.transform.position = new Vector3(((Bounds)(ref _bounds)).center.x, ((Bounds)(ref _bounds)).max.y + num4 * 0.18f, ((Bounds)(ref _bounds)).center.z);
				_root.transform.rotation = ((Component)val).transform.rotation;
				float num5 = Mathf.Clamp(num3 * 0.00032f, 0.0024f, 0.0075f);
				_root.transform.localScale = Vector3.one * num5;
				float num6 = (float)num2 / (float)num;
				_fill.fillAmount = num6;
				((Graphic)_fill).color = ((num6 > 0.55f) ? new Color(0.22f, 0.86f, 0.42f, 0.96f) : ((num6 > 0.25f) ? new Color(1f, 0.7f, 0.16f, 0.96f) : new Color(0.95f, 0.2f, 0.18f, 0.96f)));
				((TMP_Text)_numbers).text = num2 + " / " + num;
			}
		}

		private bool TryCreate()
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//IL_0063: 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_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)PlayerUI.CanvasTextPrefab == (Object)null)
			{
				return false;
			}
			_root = new GameObject("GiantFishHealthBar", new Type[2]
			{
				typeof(RectTransform),
				typeof(Canvas)
			});
			Canvas component = _root.GetComponent<Canvas>();
			component.renderMode = (RenderMode)2;
			component.sortingOrder = 45;
			((RectTransform)_root.transform).sizeDelta = new Vector2(230f, 42f);
			SetRect(CreateImage(_root.transform, "Shadow", new Color(0f, 0f, 0f, 0.72f)).GetComponent<RectTransform>(), Vector2.zero, Vector2.one, new Vector2(-5f, -5f), new Vector2(5f, 5f));
			GameObject obj = CreateImage(_root.transform, "Track", new Color(0.035f, 0.055f, 0.065f, 0.96f));
			SetRect(obj.GetComponent<RectTransform>(), Vector2.zero, Vector2.one, new Vector2(2f, 2f), new Vector2(-2f, -2f));
			GameObject val = CreateImage(obj.transform, "Fill", Color.green);
			SetRect(val.GetComponent<RectTransform>(), Vector2.zero, Vector2.one, new Vector2(4f, 4f), new Vector2(-4f, -4f));
			_fill = val.GetComponent<Image>();
			_fill.type = (Type)3;
			_fill.fillMethod = (FillMethod)0;
			_fill.fillOrigin = 0;
			_numbers = Object.Instantiate<TextMeshProUGUI>(PlayerUI.CanvasTextPrefab, _root.transform);
			((Object)((Component)_numbers).gameObject).name = "HealthNumbers";
			SetRect(((TMP_Text)_numbers).rectTransform, Vector2.zero, Vector2.one, Vector2.zero, Vector2.zero);
			((TMP_Text)_numbers).fontSize = 24f;
			((TMP_Text)_numbers).fontStyle = (FontStyles)1;
			((TMP_Text)_numbers).alignment = (TextAlignmentOptions)514;
			((Graphic)_numbers).color = Color.white;
			((TMP_Text)_numbers).textWrappingMode = (TextWrappingModes)0;
			((Graphic)_numbers).raycastTarget = false;
			return true;
		}

		private void RefreshBounds()
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			Renderer val = ((IEnumerable<Renderer>)_renderers).FirstOrDefault((Func<Renderer, bool>)((Renderer renderer) => (Object)(object)renderer != (Object)null && renderer.enabled));
			if ((Object)(object)val == (Object)null)
			{
				_bounds = new Bounds(((Component)this).transform.position, Vector3.one);
				return;
			}
			_bounds = val.bounds;
			Renderer[] renderers = _renderers;
			foreach (Renderer val2 in renderers)
			{
				if ((Object)(object)val2 != (Object)null && val2.enabled)
				{
					((Bounds)(ref _bounds)).Encapsulate(val2.bounds);
				}
			}
		}

		private static GameObject CreateImage(Transform parent, string name, Color color)
		{
			//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_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: 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: Expected O, but got Unknown
			GameObject val = new GameObject(name, new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			val.transform.SetParent(parent, false);
			((Graphic)val.GetComponent<Image>()).color = color;
			((Graphic)val.GetComponent<Image>()).raycastTarget = false;
			return val;
		}

		private static void SetRect(RectTransform rect, Vector2 anchorMin, Vector2 anchorMax, Vector2 offsetMin, Vector2 offsetMax)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			rect.anchorMin = anchorMin;
			rect.anchorMax = anchorMax;
			rect.offsetMin = offsetMin;
			rect.offsetMax = offsetMax;
		}

		private void OnDestroy()
		{
			if ((Object)(object)_root != (Object)null)
			{
				Object.Destroy((Object)(object)_root);
			}
		}
	}
	internal static class FishSizeRuntime
	{
		private static readonly FieldInfo WeightField = AccessTools.Field(typeof(Item), "_syncedRandomWeight");

		private static readonly FieldInfo HpField = AccessTools.Field(typeof(Creature), "_hp");

		private static readonly FieldInfo SkipWeightField = AccessTools.Field(typeof(Creature), "_skipRandomizedWeight");

		public static float GetSize(Creature creature)
		{
			if (!IsScalableCatch(creature))
			{
				return 1f;
			}
			return Mathf.Clamp(((SyncVar<float>)WeightField.GetValue(creature)).Value, 1f, 25f);
		}

		public static bool IsScalableCatch(Creature creature)
		{
			if ((Object)(object)creature == (Object)null || creature is Bird || ((object)creature).GetType().Name == "Albatross")
			{
				return false;
			}
			FishScaleState component = ((Component)creature).GetComponent<FishScaleState>();
			if (!IsBoss(creature) && !((Object)(object)((Item)creature).AttachedRod != (Object)null))
			{
				if ((Object)(object)component != (Object)null)
				{
					if (!component.WasHooked)
					{
						return component.LoadedFromSave;
					}
					return true;
				}
				return false;
			}
			return true;
		}

		public static bool IsBoss(Creature creature)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Invalid comparison between Unknown and I4
			if ((Object)(object)creature != (Object)null)
			{
				return (int)creature.BossType > 0;
			}
			return false;
		}

		public static float GetDisplaySize(Creature creature)
		{
			if ((Object)(object)creature == (Object)null)
			{
				return 1f;
			}
			return Mathf.Clamp(GetRawWeight(creature), 1f, 25f);
		}

		public static float GetRawWeight(Creature creature)
		{
			return ((SyncVar<float>)WeightField.GetValue(creature)).Value;
		}

		public static void SetSize(Creature creature, float size)
		{
			size = Mathf.Clamp(size, 1f, 25f);
			((SyncVar<float>)WeightField.GetValue(creature)).Value = size;
		}

		public static bool SkipsRandomWeight(Creature creature)
		{
			return (bool)SkipWeightField.GetValue(creature);
		}

		public static void RefillHealth(Creature creature)
		{
			SyncVar<int> val = (SyncVar<int>)HpField.GetValue(creature);
			if (val.Value > 0)
			{
				val.Value = creature.MaxHp;
			}
		}

		public static void MarkLoadedFromSave(Creature creature)
		{
			GetOrCreateState(creature).LoadedFromSave = true;
		}

		public static void RecordCatcher(Creature creature, FishingRod rod)
		{
			if (!((Object)(object)creature == (Object)null) && !((Object)(object)rod == (Object)null))
			{
				FishScaleState orCreateState = GetOrCreateState(creature);
				orCreateState.WasHooked = true;
				orCreateState.CatcherRod = rod;
				Player val = (((Object)(object)((Item)rod).SyncedHolder != (Object)null) ? ((Item)rod).SyncedHolder : ((Item)rod).Holder);
				if ((Object)(object)val != (Object)null)
				{
					orCreateState.Catcher = val;
					orCreateState.CatcherName = val.SteamName;
				}
				if (InstanceFinder.IsServerStarted && !orCreateState.LuckRollApplied && !orCreateState.LoadedFromSave && !IsBoss(creature))
				{
					SetSize(creature, SizeDistribution.Roll(((NetworkBehaviour)creature).ObjectId, RodUpgradeSystem.GetLuck(val)));
					orCreateState.LuckRollApplied = true;
					RefillHealth(creature);
					ApplyVisualScale(creature);
					Plugin.Instance?.LogLuckRoll(creature, val, RodUpgradeSystem.GetLuck(val));
				}
			}
		}

		public static bool TryClaimBossInitialRefill(Creature creature)
		{
			if ((Object)(object)creature == (Object)null || !IsBoss(creature))
			{
				return false;
			}
			FishScaleState orCreateState = GetOrCreateState(creature);
			if (orCreateState.BossHealthInitialized)
			{
				return false;
			}
			orCreateState.BossHealthInitialized = true;
			return true;
		}

		public static bool IsDead(Creature creature)
		{
			if ((Object)(object)creature == (Object)null)
			{
				return false;
			}
			return ((SyncVar<int>)HpField.GetValue(creature)).Value <= 0;
		}

		public static bool TryClaimLocalNotification(Creature creature, out string catcherName)
		{
			catcherName = string.Empty;
			if ((Object)(object)creature == (Object)null)
			{
				return false;
			}
			FishScaleState component = ((Component)creature).GetComponent<FishScaleState>();
			if ((Object)(object)component == (Object)null || component.NotificationShown || (Object)(object)component.CatcherRod == (Object)null)
			{
				return false;
			}
			Player val = component.Catcher;
			if ((Object)(object)val == (Object)null)
			{
				val = (((Object)(object)((Item)component.CatcherRod).SyncedHolder != (Object)null) ? ((Item)component.CatcherRod).SyncedHolder : ((Item)component.CatcherRod).Holder);
			}
			Player localPlayer = Player.LocalPlayer;
			if (!((Object)(object)val != (Object)null) || ((!((Object)(object)localPlayer != (Object)null) || !((Object)(object)val == (Object)(object)localPlayer)) && !((NetworkBehaviour)val).Owner.IsLocalClient))
			{
				return false;
			}
			component.NotificationShown = true;
			catcherName = ((!string.IsNullOrWhiteSpace(component.CatcherName)) ? component.CatcherName : (((Object)(object)val != (Object)null) ? val.SteamName : localPlayer.SteamName));
			return true;
		}

		public static bool WasLoadedFromSave(Creature creature)
		{
			FishScaleState component = ((Component)creature).GetComponent<FishScaleState>();
			if ((Object)(object)component != (Object)null)
			{
				return component.LoadedFromSave;
			}
			return false;
		}

		public static void ApplyVisualScale(Creature creature)
		{
			//IL_0017: 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)
			if (IsScalableCatch(creature))
			{
				FishScaleState orCreateState = GetOrCreateState(creature);
				((Component)creature).transform.localScale = orCreateState.OriginalScale * GetSize(creature);
			}
		}

		private static FishScaleState GetOrCreateState(Creature creature)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			FishScaleState component = ((Component)creature).GetComponent<FishScaleState>();
			if ((Object)(object)component != (Object)null)
			{
				return component;
			}
			component = ((Component)creature).gameObject.AddComponent<FishScaleState>();
			component.OriginalScale = ((Component)creature).transform.localScale;
			return component;
		}

		public static int ScaledInt(int original, Creature creature)
		{
			double value = (double)original * (double)GetSize(creature);
			return (int)Math.Min(2147483647.0, Math.Max(1.0, Math.Round(value, MidpointRounding.AwayFromZero)));
		}
	}
	internal sealed class FishScaleState : MonoBehaviour
	{
		public Vector3 OriginalScale;

		public bool LoadedFromSave;

		public bool WasHooked;

		public FishingRod CatcherRod;

		public Player Catcher;

		public string CatcherName;

		public bool NotificationShown;

		public bool RankingSubmitted;

		public string RankingEntryId;

		public bool RankingAnnouncementSent;

		public bool LuckRollApplied;

		public bool BossHealthInitialized;

		private Creature _creature;

		private void Awake()
		{
			//IL_0013: 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)
			_creature = ((Component)this).GetComponent<Creature>();
			OriginalScale = ((Component)this).transform.localScale;
		}

		private void LateUpdate()
		{
			//IL_001d: 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_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0059: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_creature == (Object)null) && FishSizeRuntime.IsScalableCatch(_creature))
			{
				Vector3 val = OriginalScale * FishSizeRuntime.GetSize(_creature);
				Vector3 val2 = ((Component)this).transform.localScale - val;
				if (((Vector3)(ref val2)).sqrMagnitude > 1E-06f)
				{
					((Component)this).transform.localScale = val;
				}
			}
		}
	}
	[HarmonyPatch(typeof(Creature), "OnStartServer")]
	internal static class CreatureStartServerPatch
	{
		private static void Prefix(Creature __instance, out byte __state)
		{
			__state = 0;
			if (!FishSizeRuntime.IsScalableCatch(__instance) || (FishSizeRuntime.SkipsRandomWeight(__instance) && !FishSizeRuntime.IsBoss(__instance)))
			{
				return;
			}
			if (FishSizeRuntime.IsBoss(__instance) && !FishSizeRuntime.WasLoadedFromSave(__instance))
			{
				__state = 3;
			}
			else if (Math.Abs(FishSizeRuntime.GetRawWeight(__instance) - 1f) < 0.0001f)
			{
				if (FishSizeRuntime.WasLoadedFromSave(__instance))
				{
					FishSizeRuntime.SetSize(__instance, 1.0001f);
					__state = 2;
				}
				else
				{
					__state = 1;
				}
			}
		}

		private static void Postfix(Creature __instance, byte __state)
		{
			if (!FishSizeRuntime.IsScalableCatch(__instance) || (FishSizeRuntime.SkipsRandomWeight(__instance) && !FishSizeRuntime.IsBoss(__instance)))
			{
				return;
			}
			switch (__state)
			{
			case 1:
			case 3:
				FishSizeRuntime.SetSize(__instance, SizeDistribution.Roll(((NetworkBehaviour)__instance).ObjectId, RodUpgradeSystem.GetLuckForCreature(__instance)));
				break;
			case 2:
				FishSizeRuntime.SetSize(__instance, 1f);
				break;
			default:
				if (FishSizeRuntime.GetRawWeight(__instance) < 1f)
				{
					FishSizeRuntime.SetSize(__instance, 1f);
				}
				break;
			}
			FishSizeRuntime.RefillHealth(__instance);
			if (FishSizeRuntime.IsBoss(__instance))
			{
				Plugin.Instance?.ScheduleBossHealthRefill(__instance);
			}
			FishSizeRuntime.ApplyVisualScale(__instance);
			Plugin.Instance?.LogCatchSize(__instance);
			RankingManager.RecordCatch(__instance);
		}
	}
	[HarmonyPatch(typeof(Creature), "get_MaxHp")]
	internal static class CreatureMaxHpPatch
	{
		private static void Postfix(Creature __instance, ref int __result)
		{
			if (FishSizeRuntime.IsScalableCatch(__instance))
			{
				__result = FishSizeRuntime.ScaledInt(__result, __instance);
			}
		}
	}
	[HarmonyPatch(typeof(Creature), "OnStartClient")]
	internal static class CreatureStartClientPatch
	{
		private static void Postfix(Creature __instance)
		{
			FishSizeRuntime.ApplyVisualScale(__instance);
			CreatureHealthBarSystem.Attach(__instance);
		}
	}
	[HarmonyPatch(typeof(Creature), "LoadFromSave")]
	internal static class CreatureLoadFromSavePatch
	{
		private static void Prefix(Creature __instance)
		{
			if ((Object)(object)__instance != (Object)null && !(__instance is Bird) && ((object)__instance).GetType().Name != "Albatross")
			{
				FishSizeRuntime.MarkLoadedFromSave(__instance);
			}
		}

		private static void Postfix(Creature __instance)
		{
			if (FishSizeRuntime.IsScalableCatch(__instance) && FishSizeRuntime.GetRawWeight(__instance) < 1f)
			{
				FishSizeRuntime.SetSize(__instance, 1f);
			}
			FishSizeRuntime.ApplyVisualScale(__instance);
		}
	}
	[HarmonyPatch(typeof(AttackingFish), "DamageOnCollision")]
	internal static class AttackingFishDamagePatch
	{
		private static readonly FieldInfo DamageField = AccessTools.Field(typeof(AttackingFish), "_onHitDamage");

		private static void Prefix(AttackingFish __instance, out int __state)
		{
			__state = (int)DamageField.GetValue(__instance);
			DamageField.SetValue(__instance, FishSizeRuntime.ScaledInt(__state, (Creature)(object)__instance));
		}

		private static Exception Finalizer(AttackingFish __instance, int __state, Exception __exception)
		{
			DamageField.SetValue(__instance, __state);
			return __exception;
		}
	}
	[HarmonyPatch(typeof(BowheadWhale), "DamageOnCollision")]
	internal static class BowheadWhaleSizeDamagePatch
	{
		private static readonly FieldInfo DamageField = AccessTools.Field(typeof(AttackingFish), "_onHitDamage");

		private static void Prefix(BowheadWhale __instance, out int __state)
		{
			__state = (int)DamageField.GetValue(__instance);
			DamageField.SetValue(__instance, FishSizeRuntime.ScaledInt(__state, (Creature)(object)__instance));
		}

		private static Exception Finalizer(BowheadWhale __instance, int __state, Exception __exception)
		{
			DamageField.SetValue(__instance, __state);
			return __exception;
		}
	}
	[HarmonyPatch(typeof(Pufferfish), "OnCollisionEnter")]
	internal static class PufferfishSizeDamagePatch
	{
		private static readonly FieldInfo DamageField = AccessTools.Field(typeof(Pufferfish), "_onHitDamage");

		private static void Prefix(Pufferfish __instance, out int __state)
		{
			__state = (int)DamageField.GetValue(__instance);
			DamageField.SetValue(__instance, FishSizeRuntime.ScaledInt(__state, (Creature)(object)__instance));
		}

		private static Exception Finalizer(Pufferfish __instance, int __state, Exception __exception)
		{
			DamageField.SetValue(__instance, __state);
			return __exception;
		}
	}
	[HarmonyPatch(typeof(Item), "OnAttachedRodChange")]
	internal static class CatchOwnershipPatch
	{
		private static void Postfix(Item __instance, FishingRod next)
		{
			if ((Object)(object)__instance != (Object)null && (Object)(object)__instance.Creature != (Object)null && (Object)(object)next != (Object)null)
			{
				FishSizeRuntime.RecordCatcher(__instance.Creature, next);
				FishSizeRuntime.ApplyVisualScale(__instance.Creature);
			}
		}
	}
	[HarmonyPatch(typeof(Creature), "OnDeath")]
	internal static class CatchDeathNotificationPatch
	{
		private static void Postfix(Creature __instance)
		{
			if (!RankedCatchAnnouncement.WasAnnounced(((NetworkBehaviour)__instance).ObjectId) && (Object)(object)Plugin.Instance != (Object)null && FishSizeRuntime.TryClaimLocalNotification(__instance, out var catcherName))
			{
				Plugin.Instance.ShowCatchCard(__instance, catcherName);
			}
		}
	}
	[HarmonyPatch(typeof(Creature), "ServerChangeHp")]
	internal static class CatchRankingPatch
	{
		private static void Postfix(Creature __instance)
		{
			try
			{
				if (FishSizeRuntime.IsDead(__instance))
				{
					RankingManager.RecordCatch(__instance);
					RankingManager.AnnounceRankedDeath(__instance);
				}
			}
			catch (Exception exception)
			{
				Plugin.Instance?.LogRankingError("death hook", exception);
			}
		}
	}
	[HarmonyPatch(typeof(MoneyManager), "SellItem")]
	internal static class RodSaleContextPatch
	{
		private static void Prefix(object[] __args)
		{
			RodSaleBonusRuntime.Begin(__args?.OfType<Player>().FirstOrDefault() ?? Player.LocalPlayer);
		}

		private static Exception Finalizer(Exception __exception)
		{
			RodSaleBonusRuntime.End();
			return __exception;
		}
	}
	[HarmonyPatch(typeof(Item), "get_TotalWorth")]
	internal static class RodSaleWorthPatch
	{
		private static void Postfix(ref int __result)
		{
			__result = RodSaleBonusRuntime.Apply(__result);
		}
	}
	[BepInPlugin("com.reysher.howtofish.giantfish", "Better How to Fish", "1.0.3")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.reysher.howtofish.giantfish";

		public const string PluginName = "Better How to Fish";

		public const string PluginVersion = "1.0.3";

		private Harmony _harmony;

		internal static Plugin Instance { get; private set; }

		private void Awake()
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			Instance = this;
			RankingManager.Initialize(((BaseUnityPlugin)this).Config);
			RodUpgradeSystem.Initialize(((BaseUnityPlugin)this).Config);
			_harmony = new Harmony("com.reysher.howtofish.giantfish");
			_harmony.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Better How to Fish 1.0.3 loaded.");
		}

		private void Update()
		{
			RankingManager.Tick();
			RodUpgradeSystem.Tick();
			CreatureHealthBarSystem.Tick();
		}

		private void OnDestroy()
		{
			RankingManager.Shutdown();
			RodUpgradeSystem.Shutdown();
			CreatureHealthBarSystem.Shutdown();
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			Instance = null;
		}

		internal void ShowCatchCard(Creature creature, string catcherName)
		{
			CatchNotification.Show((MonoBehaviour)(object)this, creature, catcherName);
			SizeRewardNotification.Show((MonoBehaviour)(object)this, FishSizeRuntime.GetDisplaySize(creature));
		}

		internal void ShowGlobalRankedCatch(Creature creature, string catcherName, float size, bool isLocalCatcher)
		{
			CatchNotification.Show((MonoBehaviour)(object)this, creature, catcherName);
			if (isLocalCatcher)
			{
				SizeRewardNotification.Show((MonoBehaviour)(object)this, size);
			}
		}

		internal void LogPreviewWarning(string message)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)message);
		}

		internal void LogCatchSize(Creature creature)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"Scaled catch {((Item)creature).GetName()} to x{FishSizeRuntime.GetDisplaySize(creature):0.00}.");
		}

		internal void LogRankingError(string operation, Exception exception)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)$"Ranking {operation} failed safely: {exception}");
		}

		internal void LogRankingHudCreated()
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Ranking HUD created on its independent overlay canvas.");
		}

		internal void LogLuckRoll(Creature creature, Player catcher, int luck)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)(string.Format("Applied catcher luck {0} for {1}: ", luck, ((catcher != null) ? catcher.SteamName : null) ?? "Pescador") + $"{((Item)creature).GetName()} rolled x{FishSizeRuntime.GetDisplaySize(creature):0.00}."));
		}

		internal void LogUpgradePurchase(Player player, int cost, int newLevel)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)(string.Format("Server charged ${0} to {1} ", cost, ((player != null) ? player.SteamName : null) ?? "Pescador") + $"and applied rod upgrade level {newLevel}."));
		}

		internal void ScheduleBossHealthRefill(Creature creature)
		{
			((MonoBehaviour)this).StartCoroutine(RefillBossHealthAfterInitialization(creature));
		}

		private static IEnumerator RefillBossHealthAfterInitialization(Creature creature)
		{
			yield return null;
			yield return null;
			if ((Object)(object)creature != (Object)null && FishSizeRuntime.TryClaimBossInitialRefill(creature))
			{
				FishSizeRuntime.RefillHealth(creature);
			}
		}
	}
	internal static class RankedCatchAnnouncement
	{
		private static readonly Dictionary<int, float> AnnouncedObjects = new Dictionary<int, float>();

		public static void Receive(RankedCatchBroadcast message)
		{
			if (!((Object)(object)Plugin.Instance == (Object)null) && !WasAnnounced(message.ObjectId))
			{
				AnnouncedObjects[message.ObjectId] = Time.unscaledTime + 12f;
				((MonoBehaviour)Plugin.Instance).StartCoroutine(ShowWhenAvailable(message));
			}
		}

		public static bool WasAnnounced(int objectId)
		{
			if (!AnnouncedObjects.TryGetValue(objectId, out var value))
			{
				return false;
			}
			if (Time.unscaledTime <= value)
			{
				return true;
			}
			AnnouncedObjects.Remove(objectId);
			return false;
		}

		private static IEnumerator ShowWhenAvailable(RankedCatchBroadcast message)
		{
			float deadline = Time.unscaledTime + 2f;
			Creature creature = null;
			while ((Object)(object)creature == (Object)null && Time.unscaledTime < deadline)
			{
				Creature[] array = Object.FindObjectsByType<Creature>();
				foreach (Creature val in array)
				{
					if ((Object)(object)val != (Object)null && ((NetworkBehaviour)val).ObjectId == message.ObjectId)
					{
						creature = val;
						break;
					}
				}
				if ((Object)(object)creature == (Object)null)
				{
					yield return null;
				}
			}
			if (!((Object)(object)creature == (Object)null) && !((Object)(object)Plugin.Instance == (Object)null))
			{
				Player localPlayer = Player.LocalPlayer;
				bool isLocalCatcher = (Object)(object)localPlayer != (Object)null && message.CatcherId != 0L && localPlayer.SteamID == message.CatcherId;
				Plugin.Instance.ShowGlobalRankedCatch(creature, string.IsNullOrWhiteSpace(message.CatcherName) ? "Pescador" : message.CatcherName, message.Size, isLocalCatcher);
			}
		}
	}
	internal static class RankingHud
	{
		private static readonly Color Cyan = new Color(0.18f, 0.82f, 0.88f, 1f);

		private static readonly Color Muted = new Color(0.66f, 0.75f, 0.8f, 1f);

		private static readonly Color[] MedalColors = (Color[])(object)new Color[3]
		{
			new Color(1f, 0.72f, 0.22f, 1f),
			new Color(0.73f, 0.8f, 0.86f, 1f),
			new Color(0.8f, 0.48f, 0.27f, 1f)
		};

		private static GameObject _root;

		private static GameObject _canvasRoot;

		private static readonly TextMeshProUGUI[] RowNames = (TextMeshProUGUI[])(object)new TextMeshProUGUI[3];

		private static readonly TextMeshProUGUI[] RowSizes = (TextMeshProUGUI[])(object)new TextMeshProUGUI[3];

		private static string _lastSignature = string.Empty;

		public static void EnsureVisible(IReadOnlyList<RankingEntry> entries)
		{
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			TextMeshProUGUI canvasTextPrefab;
			try
			{
				canvasTextPrefab = PlayerUI.CanvasTextPrefab;
			}
			catch
			{
				return;
			}
			if ((Object)(object)Player.LocalPlayer == (Object)null || (Object)(object)canvasTextPrefab == (Object)null)
			{
				return;
			}
			if ((Object)(object)_root == (Object)null || (Object)(object)_canvasRoot == (Object)null)
			{
				Destroy();
				Build();
			}
			string text = BuildSignature(entries);
			if (text == _lastSignature)
			{
				return;
			}
			for (int i = 0; i < 3; i++)
			{
				bool flag = entries != null && i < entries.Count;
				string text2 = (flag ? (entries[i].PlayerName ?? "Pescador") : "Sin captura");
				if (text2.Length > 18)
				{
					text2 = text2.Substring(0, 17) + "…";
				}
				((TMP_Text)RowNames[i]).text = text2;
				((Graphic)RowNames[i]).color = (Color)(flag ? Color.white : new Color(Muted.r, Muted.g, Muted.b, 0.65f));
				((TMP_Text)RowSizes[i]).text = (flag ? $"×{entries[i].Size:0.00}" : "—");
				((Graphic)RowSizes[i]).color = (Color)(flag ? Cyan : new Color(Muted.r, Muted.g, Muted.b, 0.65f));
			}
			_lastSignature = text;
		}

		public static void Destroy()
		{
			if ((Object)(object)_canvasRoot != (Object)null)
			{
				Object.Destroy((Object)(object)_canvasRoot);
			}
			_root = null;
			_canvasRoot = null;
			for (int i = 0; i < 3; i++)
			{
				RowNames[i] = null;
				RowSizes[i] = null;
			}
			_lastSignature = string.Empty;
		}

		private static void Build()
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Expected O, but got Unknown
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Expected O, but got Unknown
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: 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_0113: 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_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Unknown result type (might be due to invalid IL or missing references)
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0264: Unknown result type (might be due to invalid IL or missing references)
			//IL_0273: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_031e: 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_0323: 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_0355: Unknown result type (might be due to invalid IL or missing references)
			//IL_035a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0376: Unknown result type (might be due to invalid IL or missing references)
			//IL_0385: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0406: 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_0440: 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_0476: Unknown result type (might be due to invalid IL or missing references)
			//IL_0485: Unknown result type (might be due to invalid IL or missing references)
			//IL_0490: Unknown result type (might be due to invalid IL or missing references)
			_canvasRoot = new GameObject("GiantFishRankingCanvas", new Type[3]
			{
				typeof(RectTransform),
				typeof(Canvas),
				typeof(CanvasScaler)
			});
			Canvas component = _canvasRoot.GetComponent<Canvas>();
			component.renderMode = (RenderMode)0;
			component.sortingOrder = 5000;
			CanvasScaler component2 = _canvasRoot.GetComponent<CanvasScaler>();
			component2.uiScaleMode = (ScaleMode)1;
			component2.referenceResolution = new Vector2(1920f, 1080f);
			component2.screenMatchMode = (ScreenMatchMode)0;
			component2.matchWidthOrHeight = 0.5f;
			_root = new GameObject("GiantFishRankingHud", new Type[3]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(Outline)
			});
			_root.transform.SetParent(_canvasRoot.transform, false);
			RectTransform val = (RectTransform)_root.transform;
			val.anchorMin = new Vector2(1f, 1f);
			val.anchorMax = new Vector2(1f, 1f);
			val.pivot = new Vector2(1f, 1f);
			val.anchoredPosition = new Vector2(-28f, -28f);
			val.sizeDelta = new Vector2(390f, 218f);
			Image component3 = _root.GetComponent<Image>();
			((Graphic)component3).color = new Color(0.018f, 0.048f, 0.075f, 0.94f);
			((Graphic)component3).raycastTarget = false;
			Outline component4 = _root.GetComponent<Outline>();
			((Shadow)component4).effectColor = new Color(Cyan.r, Cyan.g, Cyan.b, 0.72f);
			((Shadow)component4).effectDistance = new Vector2(2f, -2f);
			AddPanel(_root.transform, "TopAccent", new Vector2(0f, 0f), new Vector2(390f, 5f), Cyan);
			AddPanel(_root.transform, "TitleMarker", new Vector2(18f, -18f), new Vector2(4f, 39f), Cyan);
			AddText(_root.transform, "Title", "MAYORES CAPTURAS", new Vector2(34f, -13f), new Vector2(330f, 27f), 19f, (FontStyles)1, Color.white, (TextAlignmentOptions)513);
			AddText(_root.transform, "Subtitle", "RÉCORDS DE LA PARTIDA", new Vector2(34f, -39f), new Vector2(330f, 20f), 11f, (FontStyles)1, Muted, (TextAlignmentOptions)513);
			for (int i = 0; i < 3; i++)
			{
				float num = -72f - (float)i * 46f;
				Color color = ((i == 0) ? new Color(0.07f, 0.16f, 0.2f, 0.92f) : new Color(0.045f, 0.105f, 0.14f, 0.86f));
				Transform transform = AddPanel(_root.transform, $"RankRow{i + 1}", new Vector2(18f, num), new Vector2(354f, 38f), color).transform;
				AddPanel(transform, "RankBadge", new Vector2(0f, 0f), new Vector2(38f, 38f), new Color(MedalColors[i].r, MedalColors[i].g, MedalColors[i].b, 0.2f));
				AddText(transform, "Rank", (i + 1).ToString(), new Vector2(0f, -3f), new Vector2(38f, 31f), 18f, (FontStyles)1, MedalColors[i], (TextAlignmentOptions)514);
				RowNames[i] = AddText(transform, "Player", "Sin captura", new Vector2(50f, -3f), new Vector2(210f, 31f), 17f, (FontStyles)0, Color.white, (TextAlignmentOptions)513);
				RowSizes[i] = AddText(transform, "Size", "—", new Vector2(266f, -3f), new Vector2(72f, 31f), 18f, (FontStyles)1, Cyan, (TextAlignmentOptions)516);
			}
			Plugin.Instance?.LogRankingHudCreated();
		}

		private static GameObject AddPanel(Transform parent, string name, Vector2 position, Vector2 size, Color color)
		{
			//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_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: 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_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: 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_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: 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_009f: Expected O, but got Unknown
			GameObject val = new GameObject(name, new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			val.transform.SetParent(parent, false);
			RectTransform val2 = (RectTransform)val.transform;
			val2.anchorMin = new Vector2(0f, 1f);
			val2.anchorMax = new Vector2(0f, 1f);
			val2.pivot = new Vector2(0f, 1f);
			val2.anchoredPosition = position;
			val2.sizeDelta = size;
			Image component = val.GetComponent<Image>();
			((Graphic)component).color = color;
			((Graphic)component).raycastTarget = false;
			return val;
		}

		private static TextMeshProUGUI AddText(Transform parent, string name, string value, Vector2 position, Vector2 size, float fontSize, FontStyles style, Color color, TextAlignmentOptions alignment)
		{
			//IL_0028: 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_0052: 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_0063: 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_0082: 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)
			TextMeshProUGUI obj = Object.Instantiate<TextMeshProUGUI>(PlayerUI.CanvasTextPrefab, parent);
			((Object)((Component)obj).gameObject).name = name;
			RectTransform rectTransform = ((TMP_Text)obj).rectTransform;
			rectTransform.anchorMin = new Vector2(0f, 1f);
			rectTransform.anchorMax = new Vector2(0f, 1f);
			rectTransform.pivot = new Vector2(0f, 1f);
			rectTransform.anchoredPosition = position;
			rectTransform.sizeDelta = size;
			((TMP_Text)obj).text = value;
			((TMP_Text)obj).fontSize = fontSize;
			((TMP_Text)obj).fontStyle = style;
			((Graphic)obj).color = color;
			((TMP_Text)obj).alignment = alignment;
			((TMP_Text)obj).textWrappingMode = (TextWrappingModes)0;
			((Graphic)obj).raycastTarget = false;
			return obj;
		}

		private static string BuildSignature(IReadOnlyList<RankingEntry> entries)
		{
			StringBuilder stringBuilder = new StringBuilder();
			for (int i = 0; i < 3; i++)
			{
				if (entries != null && i < entries.Count)
				{
					stringBuilder.Append(entries[i].PlayerName).Append('|').Append(entries[i].Size.ToString("0.00"));
				}
				stringBuilder.Append(';');
			}
			return stringBuilder.ToString();
		}
	}
	internal struct RankingBroadcast : IBroadcast
	{
		public string Payload;
	}
	internal struct RankedCatchBroadcast : IBroadcast
	{
		public int ObjectId;

		public float Size;

		public ulong CatcherId;

		public string CatcherName;
	}
	internal sealed class RankingEntry
	{
		public string World;

		public string PlayerId;

		public string PlayerName;

		public float Size;
	}
	internal static class RankingManager
	{
		private static readonly List<RankingEntry> AllEntries = new List<RankingEntry>();

		private static readonly List<RankingEntry> CurrentEntries = new List<RankingEntry>();

		private static ConfigEntry<string> _savedData;

		private static NetworkManager _registeredNetworkManager;

		private static string _currentWorld = string.Empty;

		private static bool _serializersReady;

		private static bool _initialized;

		private static bool _wasServerStarted;

		private static float _nextBroadcastTime;

		public static void Initialize(ConfigFile config)
		{
			if (!_initialized)
			{
				_savedData = config.Bind<string>("Ranking", "Records", string.Empty, "Persistent Giant Fish records. This value is managed by the mod.");
				LoadSavedData();
				SetupSerializers();
				_initialized = true;
			}
		}

		public static void Tick()
		{
			EnsureNetworkRegistration();
			bool isServerStarted = InstanceFinder.IsServerStarted;
			if (isServerStarted)
			{
				SelectCurrentWorld();
				if (!_wasServerStarted || Time.unscaledTime >= _nextBroadcastTime)
				{
					BroadcastCurrent();
					_nextBroadcastTime = Time.unscaledTime + 4f;
				}
			}
			_wasServerStarted = isServerStarted;
			RankingHud.EnsureVisible(CurrentEntries);
		}

		public static void Shutdown()
		{
			if ((Object)(object)_registeredNetworkManager != (Object)null)
			{
				try
				{
					_registeredNetworkManager.ClientManager.UnregisterBroadcast<RankingBroadcast>((Action<RankingBroadcast, Channel>)OnRankingBroadcast);
					_registeredNetworkManager.ClientManager.UnregisterBroadcast<RankedCatchBroadcast>((Action<RankedCatchBroadcast, Channel>)OnRankedCatchBroadcast);
				}
				catch
				{
				}
			}
			_registeredNetworkManager = null;
			_wasServerStarted = false;
			RankingHud.Destroy();
		}

		public static void RecordCatch(Creature creature)
		{
			try
			{
				RecordCatchInternal(creature);
			}
			catch (Exception exception)
			{
				Plugin.Instance?.LogRankingError("record", exception);
			}
		}

		private static void RecordCatchInternal(Creature creature)
		{
			if (!_initialized || !InstanceFinder.IsServerStarted || (Object)(object)creature == (Object)null)
			{
				return;
			}
			FishScaleState component = ((Component)creature).GetComponent<FishScaleState>();
			if ((Object)(object)component == (Object)null || !component.WasHooked || component.RankingSubmitted)
			{
				return;
			}
			component.RankingSubmitted = true;
			Player val = component.Catcher;
			if ((Object)(object)val == (Object)null && (Object)(object)component.CatcherRod != (Object)null)
			{
				val = (((Object)(object)((Item)component.CatcherRod).SyncedHolder != (Object)null) ? ((Item)component.CatcherRod).SyncedHolder : ((Item)component.CatcherRod).Holder);
			}
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			SelectCurrentWorld();
			float displaySize = FishSizeRuntime.GetDisplaySize(creature);
			string text = ((val.SteamID != 0L) ? val.SteamID.ToString(CultureInfo.InvariantCulture) : ("connection-" + ((NetworkBehaviour)val).OwnerId.ToString(CultureInfo.InvariantCulture)));
			string playerName = (string.IsNullOrWhiteSpace(val.SteamName) ? "Pescador" : val.SteamName.Trim());
			RankingEntry rankingEntry = new RankingEntry();
			rankingEntry.World = _currentWorld;
			rankingEntry.PlayerId = text + "-" + DateTime.UtcNow.Ticks.ToString(CultureInfo.InvariantCulture) + "-" + ((NetworkBehaviour)creature).ObjectId.ToString(CultureInfo.InvariantCulture);
			rankingEntry.PlayerName = playerName;
			rankingEntry.Size = displaySize;
			RankingEntry rankingEntry2 = rankingEntry;
			AllEntries.Add(rankingEntry2);
			component.RankingEntryId = rankingEntry2.PlayerId;
			foreach (RankingEntry item in (from e in AllEntries
				where e != null && e.World == _currentWorld
				orderby e.Size descending
				select e).Skip(50).ToList())
			{
				AllEntries.Remove(item);
			}
			RefreshCurrentEntries();
			SaveData();
			BroadcastCurrent();
		}

		public static void AnnounceRankedDeath(Creature creature)
		{
			try
			{
				if (!_initialized || !InstanceFinder.IsServerStarted || (Object)(object)creature == (Object)null)
				{
					return;
				}
				FishScaleState state = ((Component)creature).GetComponent<FishScaleState>();
				if ((Object)(object)state == (Object)null || state.RankingAnnouncementSent || string.IsNullOrEmpty(state.RankingEntryId))
				{
					return;
				}
				SelectCurrentWorld();
				RankingEntry rankingEntry = CurrentEntries.FirstOrDefault((RankingEntry e) => e.PlayerId == state.RankingEntryId);
				if (rankingEntry != null)
				{
					Player val = state.Catcher;
					if ((Object)(object)val == (Object)null && (Object)(object)state.CatcherRod != (Object)null)
					{
						val = (((Object)(object)((Item)state.CatcherRod).SyncedHolder != (Object)null) ? ((Item)state.CatcherRod).SyncedHolder : ((Item)state.CatcherRod).Holder);
					}
					state.RankingAnnouncementSent = true;
					RankedCatchBroadcast rankedCatchBroadcast = new RankedCatchBroadcast
					{
						ObjectId = ((NetworkBehaviour)creature).ObjectId,
						Size = rankingEntry.Size,
						CatcherId = (((Object)(object)val != (Object)null) ? val.SteamID : 0),
						CatcherName = rankingEntry.PlayerName
					};
					if (InstanceFinder.IsClientStarted)
					{
						RankedCatchAnnouncement.Receive(rankedCatchBroadcast);
					}
					InstanceFinder.ServerManager.Broadcast<RankedCatchBroadcast>(rankedCatchBroadcast, true, (Channel)0);
				}
			}
			catch (Exception exception)
			{
				Plugin.Instance?.LogRankingError("global announcement", exception);
			}
		}

		public static void BroadcastCurrent()
		{
			try
			{
				BroadcastCurrentInternal();
			}
			catch (Exception exception)
			{
				Plugin.Instance?.LogRankingError("broadcast", exception);
			}
		}

		private static void BroadcastCurrentInternal()
		{
			if (_initialized && InstanceFinder.IsServerStarted && !((Object)(object)InstanceFinder.ServerManager == (Object)null))
			{
				SelectCurrentWorld();
				InstanceFinder.ServerManager.Broadcast<RankingBroadcast>(new RankingBroadcast
				{
					Payload = BuildNetworkPayload(CurrentEntries)
				}, true, (Channel)0);
			}
		}

		private static void SetupSerializers()
		{
			if (!_serializersReady)
			{
				GenericWriter<RankingBroadcast>.SetWrite((Action<Writer, RankingBroadcast>)delegate(Writer writer, RankingBroadcast value)
				{
					writer.WriteString(value.Payload);
				});
				GenericReader<RankingBroadcast>.SetRead((Func<Reader, RankingBroadcast>)((Reader reader) => new RankingBroadcast
				{
					Payload = reader.ReadStringAllocated()
				}));
				GenericWriter<RankedCatchBroadcast>.SetWrite((Action<Writer, RankedCatchBroadcast>)delegate(Writer writer, RankedCatchBroadcast value)
				{
					writer.WriteInt32(value.ObjectId);
					writer.WriteSingle(value.Size);
					writer.WriteUInt64(value.CatcherId);
					writer.WriteString(value.CatcherName);
				});
				GenericReader<RankedCatchBroadcast>.SetRead((Func<Reader, RankedCatchBroadcast>)((Reader reader) => new RankedCatchBroadcast
				{
					ObjectId = reader.ReadInt32(),
					Size = reader.ReadSingle(),
					CatcherId = reader.ReadUInt64(),
					CatcherName = reader.ReadStringAllocated()
				}));
				_serializersReady = true;
			}
		}

		private static void EnsureNetworkRegistration()
		{
			NetworkManager networkManager = InstanceFinder.NetworkManager;
			if ((Object)(object)networkManager == (Object)(object)_registeredNetworkManager)
			{
				return;
			}
			if ((Object)(object)_registeredNetworkManager != (Object)null)
			{
				try
				{
					_registeredNetworkManager.ClientManager.UnregisterBroadcast<RankingBroadcast>((Action<RankingBroadcast, Channel>)OnRankingBroadcast);
					_registeredNetworkManager.ClientManager.UnregisterBroadcast<RankedCatchBroadcast>((Action<RankedCatchBroadcast, Channel>)OnRankedCatchBroadcast);
				}
				catch
				{
				}
			}
			_registeredNetworkManager = networkManager;
			if ((Object)(object)networkManager != (Object)null)
			{
				networkManager.ClientManager.RegisterBroadcast<RankingBroadcast>((Action<RankingBroadcast, Channel>)OnRankingBroadcast);
				networkManager.ClientManager.RegisterBroadcast<RankedCatchBroadcast>((Action<RankedCatchBroadcast, Channel>)OnRankedCatchBroadcast);
			}
		}

		private static void OnRankingBroadcast(RankingBroadcast message, Channel channel)
		{
			try
			{
				if (!InstanceFinder.IsServerStarted)
				{
					CurrentEntries.Clear();
					ParseNetworkPayload(message.Payload, CurrentEntries);
				}
			}
			catch (Exception exception)
			{
				Plugin.Instance?.LogRankingError("receive", exception);
			}
		}

		private static void OnRankedCatchBroadcast(RankedCatchBroadcast message, Channel channel)
		{
			RankedCatchAnnouncement.Receive(message);
		}

		private static void SelectCurrentWorld()
		{
			string text = ((SaveManager.CurServerSave != null && !string.IsNullOrWhiteSpace(SaveManager.CurServerSave.Name)) ? SaveManager.CurServerSave.Name.Trim() : "Partida actual");
			if (!(text == _currentWorld))
			{
				_currentWorld = text;
				RefreshCurrentEntries();
			}
		}

		private static void RefreshCurrentEntries()
		{
			CurrentEntries.Clear();
			CurrentEntries.AddRange((from e in AllEntries
				where e != null && e.World == _currentWorld
				orderby e.Size descending
				select e).ThenBy<RankingEntry, string>((RankingEntry e) => e.PlayerName, StringComparer.OrdinalIgnoreCase).Take(3));
		}

		private static void LoadSavedData()
		{
			AllEntries.Clear();
			if (_savedData == null || string.IsNullOrWhiteSpace(_savedData.Value))
			{
				return;
			}
			string[] array = _savedData.Value.Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries);
			for (int i = 0; i < array.Length; i++)
			{
				string[] array2 = array[i].Split(',');
				if (array2.Length == 4 && float.TryParse(array2[3], NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
				{
					try
					{
						AllEntries.Add(new RankingEntry
						{
							World = Decode(array2[0]),
							PlayerId = Decode(array2[1]),
							PlayerName = Decode(array2[2]),
							Size = result
						});
					}
					catch (FormatException)
					{
					}
				}
			}
		}

		private static void SaveData()
		{
			if (_savedData != null)
			{
				string value = string.Join(";", from e in AllEntries
					where e != null
					select Encode(e.World) + "," + Encode(e.PlayerId) + "," + Encode(e.PlayerName) + "," + e.Size.ToString("0.00", CultureInfo.InvariantCulture));
				_savedData.Value = value;
			}
		}

		private static string BuildNetworkPayload(IEnumerable<RankingEntry> entries)
		{
			return string.Join(";", from e in entries
				where e != null
				select Encode(e.PlayerName) + "," + e.Size.ToString("0.00", CultureInfo.InvariantCulture));
		}

		private static void ParseNetworkPayload(string payload, List<RankingEntry> destination)
		{
			if (string.IsNullOrWhiteSpace(payload))
			{
				return;
			}
			string[] array = payload.Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries);
			for (int i = 0; i < array.Length; i++)
			{
				string[] array2 = array[i].Split(',');
				if (array2.Length == 2 && float.TryParse(array2[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
				{
					try
					{
						destination.Add(new RankingEntry
						{
							PlayerName = Decode(array2[0]),
							Size = result
						});
					}
					catch (FormatException)
					{
					}
				}
			}
		}

		private static string Encode(string value)
		{
			return Convert.ToBase64String(Encoding.UTF8.GetBytes(value ?? string.Empty));
		}

		private static string Decode(string value)
		{
			return Encoding.UTF8.GetString(Convert.FromBase64String(value));
		}
	}
	internal static class RodSaleBonusRuntime
	{
		[ThreadStatic]
		private static int _bonusPercent;

		public static void Begin(Player seller)
		{
			_bonusPercent = RodUpgradeSystem.GetSaleBonus(seller);
		}

		public static void End()
		{
			_bonusPercent = 0;
		}

		public static int Apply(int original)
		{
			if (_bonusPercent <= 0 || original <= 0)
			{
				return original;
			}
			double value = (double)original * (1.0 + (double)_bonusPercent / 100.0);
			return (int)Math.Min(2147483647.0, Math.Round(value, MidpointRounding.AwayFromZero));
		}
	}
	internal static class RodUpgradeHud
	{
		private static readonly Color Cyan = new Color(0.18f, 0.82f, 0.88f, 1f);

		private static GameObject _canvasRoot;

		private static GameObject _panel;

		private static TextMeshProUGUI _text;

		public static void SetVisible(bool visible, string message)
		{
			if (!visible)
			{
				if ((Object)(object)_canvasRoot != (Object)null)
				{
					_canvasRoot.SetActive(false);
				}
				return;
			}
			TextMeshProUGUI canvasTextPrefab;
			try
			{
				canvasTextPrefab = PlayerUI.CanvasTextPrefab;
			}
			catch
			{
				return;
			}
			if (!((Object)(object)canvasTextPrefab == (Object)null))
			{
				if ((Object)(object)_canvasRoot == (Object)null || (Object)(object)_panel == (Object)null || (Object)(object)_text == (Object)null)
				{
					Destroy();
					Build();
				}
				_canvasRoot.SetActive(true);
				((TMP_Text)_text).text = message;
			}
		}

		public static void Destroy()
		{
			if ((Object)(object)_canvasRoot != (Object)null)
			{
				Object.Destroy((Object)(object)_canvasRoot);
			}
			_canvasRoot = null;
			_panel = null;
			_text = null;
		}

		private static void Build()
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Expected O, but got Unknown
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Expected O, but got Unknown
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: 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_0113: 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_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_024b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0256: Unknown result type (might be due to invalid IL or missing references)
			//IL_0260: Unknown result type (might be due to invalid IL or missing references)
			//IL_0261: Unknown result type (might be due to invalid IL or missing references)
			//IL_0275: Unknown result type (might be due to invalid IL or missing references)
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0285: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0306: Unknown result type (might be due to invalid IL or missing references)
			//IL_033e: Unknown result type (might be due to invalid IL or missing references)
			_canvasRoot = new GameObject("GiantFishUpgradeCanvas", new Type[3]
			{
				typeof(RectTransform),
				typeof(Canvas),
				typeof(CanvasScaler)
			});
			Canvas component = _canvasRoot.GetComponent<Canvas>();
			component.renderMode = (RenderMode)0;
			component.sortingOrder = 5200;
			CanvasScaler component2 = _canvasRoot.GetComponent<CanvasScaler>();
			component2.uiScaleMode = (ScaleMode)1;
			component2.referenceResolution = new Vector2(1920f, 1080f);
			component2.screenMatchMode = (ScreenMatchMode)0;
			component2.matchWidthOrHeight = 0.5f;
			_panel = new GameObject("RodUpgradePanel", new Type[3]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(Outline)
			});
			_panel.transform.SetParent(_canvasRoot.transform, false);
			RectTransform val = (RectTransform)_panel.transform;
			val.anchorMin = new Vector2(0.5f, 0f);
			val.anchorMax = new Vector2(0.5f, 0f);
			val.pivot = new Vector2(0.5f, 0f);
			val.anchoredPosition = new Vector2(0f, 185f);
			val.sizeDelta = new Vector2(800f, 150f);
			Image component3 = _panel.GetComponent<Image>();
			((Graphic)component3).color = new Color(0.018f, 0.065f, 0.08f, 0.97f);
			((Graphic)component3).raycastTarget = false;
			Outline component4 = _panel.GetComponent<Outline>();
			((Shadow)component4).effectColor = new Color(Cyan.r, Cyan.g, Cyan.b, 0.85f);
			((Shadow)component4).effectDistance = new Vector2(3f, -3f);
			GameObject val2 = new GameObject("Accent", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			val2.transform.SetParent(_panel.transform, false);
			RectTransform val3 = (RectTransform)val2.transform;
			val3.anchorMin = new Vector2(0f, 1f);
			val3.anchorMax = new Vector2(1f, 1f);
			val3.pivot = new Vector2(0.5f, 1f);
			val3.anchoredPosition = Vector2.zero;
			val3.sizeDelta = new Vector2(0f, 5f);
			((Graphic)val2.GetComponent<Image>()).color = Cyan;
			((Graphic)val2.GetComponent<Image>()).raycastTarget = false;
			_text = Object.Instantiate<TextMeshProUGUI>(PlayerUI.CanvasTextPrefab, _panel.transform);
			((Object)((Component)_text).gameObject).name = "UpgradeMessage";
			RectTransform rectTransform = ((TMP_Text)_text).rectTransform;
			rectTransform.anchorMin = Vector2.zero;
			rectTransform.anchorMax = Vector2.one;
			rectTransform.offsetMin = new Vector2(18f, 10f);
			rectTransform.offsetMax = new Vector2(-18f, -10f);
			((TMP_Text)_text).fontSize = 19f;
			((TMP_Text)_text).fontStyle = (FontStyles)1;
			((TMP_Text)_text).alignment = (TextAlignmentOptions)514;
			((Graphic)_text).color = Color.white;
			((TMP_Text)_text).textWrappingMode = (TextWrappingModes)1;
			((Graphic)_text).raycastTarget = false;
		}
	}
	internal struct RodUpgradeSync : IBroadcast
	{
		public ulong SteamId;

		public int Level;
	}
	internal struct RodUpgradePurchaseRequest : IBroadcast
	{
		public ulong SteamId;
	}
	internal static class RodUpgradeSystem
	{
		private sealed class TablePlacement
		{
			public Vector3 Position;

			public float Yaw;
		}

		public const int MaxLevel = 25;

		private static readonly int[] Costs = new int[25]
		{
			10, 35, 75, 175, 300, 1000, 2500, 4900, 10000, 17500,
			39000, 85000, 175000, 405000, 900000, 2000000, 4500000, 10000000, 22000000, 50000000,
			110000000, 250000000, 550000000, 1200000000, 2000000000
		};

		private static readonly int[] LuckGain = new int[25]
		{
			1, 1, 2, 2, 2, 3, 3, 3, 3, 4,
			4, 4, 5, 5, 5, 5, 5, 6, 6, 6,
			7, 7, 7, 8, 8
		};

		private static readonly int[] SaleGain = new int[25]
		{
			0, 10, 10, 10, 15, 15, 15, 20, 20, 25,
			25, 25, 30, 30, 35, 35, 40, 40, 45, 45,
			50, 50, 60, 75, 100
		};

		private static readonly Dictionary<ulong, int> Levels = new Dictionary<ulong, int>();

		private static readonly PropertyInfo SyncedCurItemProperty = AccessTools.Property(typeof(PlayerInventory), "SyncedCurItem");

		private static readonly FieldInfo ReelSpeedField = AccessTools.Field(typeof(FishingRod), "_holdReelSpeed");

		private static ConfigEntry<string> _savedLevels;

		private static ConfigEntry<string> _savedPlacements;

		private static readonly Dictionary<string, TablePlacement> Placements = new Dictionary<string, TablePlacement>();

		private static NetworkManager _registeredManager;

		private static int _islandId = int.MinValue;

		private static RodUpgradeTable _table;

		private static float _nextAutomaticPlacementAttempt;

		private static float _nextSync;

		private static float _nextRodApply;

		private static float _interactionReadyTime;

		private static string _currentPlacementKey;

		public static void Initialize(ConfigFile config)
		{
			_savedLevels = config.Bind<string>("RodUpgrades", "PlayerLevels", string.Empty, "Persistent fishing rod upgrade levels by Steam account.");
			_savedPlacements = config.Bind<string>("RodUpgrades", "TablePlacements", string.Empty, "Saved workbench coordinates by saved game and island. Send this value to the mod author to share placements.");
			Load();
			LoadPlacements();
			GenericWriter<RodUpgradeSync>.SetWrite((Action<Writer, RodUpgradeSync>)delegate(Writer writer, RodUpgradeSync value)
			{
				writer.WriteUInt64(value.SteamId);
				writer.WriteInt32(value.Level);
			});
			GenericReader<RodUpgradeSync>.SetRead((Func<Reader, RodUpgradeSync>)((Reader reader) => new RodUpgradeSync
			{
				SteamId = reader.ReadUInt64(),
				Level = reader.ReadInt32()
			}));
			GenericWriter<RodUpgradePurchaseRequest>.SetWrite((Action<Writer, RodUpgradePurchaseRequest>)delegate(Writer writer, RodUpgradePurchaseRequest value)
			{
				writer.WriteUInt64(value.SteamId);
			});
			GenericReader<RodUpgradePurchaseRequest>.SetRead((Func<Reader, RodUpgradePurchaseRequest>)((Reader reader) => new RodUpgradePurchaseRequest
			{
				SteamId = reader.ReadUInt64()
			}));
		}

		public static void Tick()
		{
			EnsureNetworkHandlers();
			EnsureTable();
			HandleLocalInteraction();
			UpdateInteractionHud();
			if (Time.unscaledTime >= _nextSync)
			{
				SyncLocalLevel();
				_nextSync = Time.unscaledTime + 4f;
			}
			if (Time.unscaledTime >= _nextRodApply)
			{
				ApplyReelSpeeds();
				_nextRodApply = Time.unscaledTime + 1f;
			}
		}

		public static void Shutdown()
		{
			if ((Object)(object)_registeredManager != (Object)null)
			{
				try
				{
					_registeredManager.ServerManager.UnregisterBroadcast<RodUpgradeSync>((Action<NetworkConnection, RodUpgradeSync, Channel>)OnServerSync);
				}
				catch
				{
				}
				try
				{
					_registeredManager.ServerManager.UnregisterBroadcast<RodUpgradePurchaseRequest>((Action<NetworkConnection, RodUpgradePurchaseRequest, Channel>)OnServerPurchase);
				}
				catch
				{
				}
				try
				{
					_registeredManager.ClientManager.UnregisterBroadcast<RodUpgradeSync>((Action<RodUpgradeSync, Channel>)OnClientSync);
				}
				catch
				{
				}
			}
			if ((Object)(object)_table != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)_table).gameObject);
			}
			_table = null;
			_registeredManager = null;
			RodUpgradeHud.Destroy();
		}

		public static int GetLevel(Player player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return 0;
			}
			if (!Levels.TryGetValue(player.SteamID, out var value))
			{
				return 0;
			}
			return Mathf.Clamp(value, 0, 25);
		}

		public static int GetLuck(Player player)
		{
			return SumThrough(LuckGain, GetLevel(player));
		}

		public static int GetSaleBonus(Player player)
		{
			return SumThrough(SaleGain, GetLevel(player));
		}

		public static float GetReelMultiplier(Player player)
		{
			return 1f + (float)GetLevel(player) * 0.05f;
		}

		public static Player GetCatcherForCreature(Creature creature)
		{
			FishScaleState fishScaleState = (((Object)(object)creature != (Object)null) ? ((Component)creature).GetComponent<FishScaleState>() : null);
			if ((Object)(object)fishScaleState == (Object)null)
			{
				return null;
			}
			Player val = fishScaleState.Catcher;
			if ((Object)(object)val == (Object)null && (Object)(object)fishScaleState.CatcherRod != (Object)null)
			{
				val = (((Object)(object)((Item)fishScaleState.CatcherRod).SyncedHolder != (Object)null) ? ((Item)fishScaleState.CatcherRod).SyncedHolder : ((Item)fishScaleState.CatcherRod).Holder);
			}
			return val;
		}

		public static int GetLuckForCreature(Creature creature)
		{
			return GetLuck(GetCatcherForCreature(creature));
		}

		public static bool IsHoldingRod(Player player)
		{
			if ((Object)(object)player == (Object)null || (Object)(object)player.Inventory == (Object)null || SyncedCurItemProperty == null)
			{
				return false;
			}
			return SyncedCurItemProperty.GetValue(player.Inventory) is FishingRod;
		}

		public static int GetNextCost(Player player)
		{
			int level = GetLevel(player);
			if (level < 25)
			{
				return Costs[level];
			}
			return 0;
		}

		public static string GetUpgradeDescription(Player player)
		{
			int level = GetLevel(player);
			if (level >= 25)
			{
				return "CAÑA AL NIVEL MÁXIMO\n" + $"ACTUAL  •  Suerte {GetLuck(player)}  •  Recogida +{level * 5}%  •  Venta +{GetSaleBonus(player)}%";
			}
			string arg = (((Object)(object)MoneyManager.Instance != (Object)null && MoneyManager.CanAfford(Costs[level])) ? "Pulsa [E] para mejorar" : $"DINERO INSUFICIENTE  •  Necesitas ${Costs[level]:N0}");
			return $"ACTUAL  •  Nivel {level}  •  Suerte {GetLuck(player)}  •  Recogida +{level * 5}%  •  Venta +{GetSaleBonus(player)}%\n" + $"MEJORA {level + 1}  •  ${Costs[level]:N0}\n" + $"+{LuckGain[level]} suerte   +5% recogida   +{SaleGain[level]}% venta\n{arg}";
		}

		public static void TryPurchase(Player player)
		{
			if (!((Object)(object)player == (Object)null) && IsHoldingRod(player))
			{
				if (InstanceFinder.IsServerStarted)
				{
					PurchaseOnServer(player);
				}
				else if (InstanceFinder.IsClientStarted && (Object)(object)InstanceFinder.ClientManager != (Object)null)
				{
					InstanceFinder.ClientManager.Broadcast<RodUpgradePurchaseRequest>(new RodUpgradePurchaseRequest
					{
						SteamId = player.SteamID
					}, (Channel)0);
				}
			}
		}

		private static void EnsureNetworkHandlers()
		{
			NetworkManager networkManager = InstanceFinder.NetworkManager;
			if ((Object)(object)networkManager == (Object)(object)_registeredManager)
			{
				return;
			}
			if ((Object)(object)_registeredManager != (Object)null)
			{
				try
				{
					_registeredManager.ServerManager.UnregisterBroadcast<RodUpgradeSync>((Action<NetworkConnection, RodUpgradeSync, Channel>)OnServerSync);
				}
				catch
				{
				}
				try
				{
					_registeredManager.ServerManager.UnregisterBroadcast<RodUpgradePurchaseRequest>((Action<NetworkConnection, RodUpgradePurchaseRequest, Channel>)OnServerPurchase);
				}
				catch
				{
				}
				try
				{
					_registeredManager.ClientManager.UnregisterBroadcast<RodUpgradeSync>((Action<RodUpgradeSync, Channel>)OnClientSync);
				}
				catch
				{
				}
			}
			_registeredManager = networkManager;
			if ((Object)(object)networkManager != (Object)null)
			{
				networkManager.ServerManager.RegisterBroadcast<RodUpgradeSync>((Action<NetworkConnection, RodUpgradeSync, Channel>)OnServerSync, true);
				networkManager.ServerManager.RegisterBroadcast<RodUpgradePurchaseRequest>((Action<NetworkConnection, RodUpgradePurchaseRequest, Channel>)OnServerPurchase, true);
				networkManager.ClientManager.RegisterBroadcast<RodUpgradeSync>((Action<RodUpgradeSync, Channel>)OnClientSync);
			}
		}

		private static void OnServerSync(NetworkConnection connection, RodUpgradeSync message, Channel channel)
		{
			if (message.SteamId != 0L)
			{
				int num = Mathf.Clamp(message.Level, 0, 25);
				int value;
				int num2 = (Levels.TryGetValue(message.SteamId, out value) ? value : 0);
				Levels[message.SteamId] = Mathf.Max(num2, num);
			}
		}

		private static void OnServerPurchase(NetworkConnection connection, RodUpgradePurchaseRequest message, Channel channel)
		{
			Player val = ((IEnumerable<Player>)Object.FindObjectsByType<Player>()).FirstOrDefault((Func<Player, bool>)((Player candidate) => (Object)(object)candidate != (Object)null && candidate.SteamID == message.SteamId && ((NetworkBehaviour)candidate).OwnerId == connection.ClientId));
			if ((Object)(object)val != (Object)null)
			{
				PurchaseOnServer(val);
			}
		}

		private static void PurchaseOnServer(Player player)
		{
			if ((Object)(object)player == (Object)null || !IsHoldingRod(player))
			{
				return;
			}
			int level = GetLevel(player);
			if (level >= 25)
			{
				return;
			}
			int num = Costs[level];
			if (!((Object)(object)MoneyManager.Instance == (Object)null) && MoneyManager.CanAfford(num))
			{
				MoneyManager.RemoveMoney(num, player);
				int num2 = level + 1;
				Levels[player.SteamID] = num2;
				Save();
				Plugin.Instance?.LogUpgradePurchase(player, num, num2);
				RodUpgradeSync rodUpgradeSync = new RodUpgradeSync
				{
					SteamId = player.SteamID,
					Level = num2
				};
				if ((Object)(object)InstanceFinder.ServerManager != (Object)null)
				{
					InstanceFinder.ServerManager.Broadcast<RodUpgradeSync>(rodUpgradeSync, true, (Channel)0);
				}
				OnClientSync(rodUpgradeSync, (Channel)0);
			}
		}

		private static void OnClientSync(RodUpgradeSync message, Channel channel)
		{
			if (message.SteamId != 0L)
			{
				Levels[message.SteamId] = Mathf.Clamp(message.Level, 0, 25);
				if ((Object)(object)Player.LocalPlayer != (Object)null && Player.LocalPlayer.SteamID == message.SteamId)
				{
					Save();
				}
			}
		}

		private static void SyncLocalLevel()
		{
			Player localPlayer = Player.LocalPlayer;
			if (!((Object)(object)localPlayer == (Object)null) && localPlayer.SteamID != 0L)
			{
				RodUpgradeSync rodUpgradeSync = new RodUpgradeSync
				{
					SteamId = localPlayer.SteamID,
					Level = GetLevel(localPlayer)
				};
				if (InstanceFinder.IsServerStarted)
				{
					Levels[rodUpgradeSync.SteamId] = rodUpgradeSync.Level;
				}
				else if (InstanceFinder.IsClientStarted && (Object)(object)InstanceFinder.ClientManager != (Object)null)
				{
					InstanceFinder.ClientManager.Broadcast<RodUpgradeSync>(rodUpgradeSync, (Channel)0);
				}
			}
		}

		private static void EnsureTable()
		{
			//IL_0030: 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_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.LocalPlayer;
			Island curIsland = Island.CurIsland;
			if ((Object)(object)localPlayer == (Object)null || (Object)(object)curIsland == (Object)null)
			{
				return;
			}
			int num = ((Object)curIsland).name.GetHashCode() ^ ((object)((Component)curIsland).transform.position/*cast due to .constrained prefix*/).GetHashCode();
			if (num != _islandId)
			{
				if ((Object)(object)_table != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)_table).gameObject);
				}
				_table = null;
				_islandId = num;
				_currentPlacementKey = BuildPlacementKey(curIsland);
				if (Placements.TryGetValue(_currentPlacementKey, out var value))
				{
					_table = RodUpgradeTable.Create(value.Position, value.Yaw);
				}
				else if (TryGetBuiltInPlacement(curIsland, out value))
				{
					_table = RodUpgradeTable.Create(value.Position, value.Yaw);
				}
			}
			if (!((Object)(object)_table != (Object)null) && !(Time.unscaledTime < _nextAutomaticPlacementAttempt))
			{
				_nextAutomaticPlacementAttempt = Time.unscaledTime + 1f;
				if (TryFindAutomaticPlacement(localPlayer, out var placement))
				{
					Placements[_currentPlacementKey] = placement;
					SavePlacements();
					_table = RodUpgradeTable.Create(placement.Position, placement.Yaw);
					_interactionReadyTime = Time.unscaledTime + 0.4f;
				}
			}
		}

		private static void HandleLocalInteraction()
		{
			if (!(Time.unscaledTime < _interactionReadyTime) && TryGetNearbyPlayer(out var player) && Keyboard.current != null && ((ButtonControl)Keyboard.current.eKey).wasPressedThisFrame)
			{
				TryPurchase(player);
			}
		}

		private static void UpdateInteractionHud()
		{
			if (!TryGetNearbyPlayer(out var player))
			{
				RodUpgradeHud.SetVisible(visible: false, string.Empty);
				return;
			}
			string message = (IsHoldingRod(player) ? GetUpgradeDescription(player) : "MESA DE MEJORAS DE CAÑA\nEquipa una caña de pescar o una caña de cangrejos");
			RodUpgradeHud.SetVisible(visible: true, message);
		}

		private static bool TryGetNearbyPlayer(out Player player)
		{
			//IL_0045: 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)
			//IL_007b: 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)
			player = Player.LocalPlayer;
			if ((Object)(object)player == (Object)null)
			{
				return false;
			}
			if ((Object)(object)_table == (Object)null)
			{
				_table = Object.FindObjectsByType<RodUpgradeTable>().FirstOrDefault();
			}
			if ((Object)(object)_table == (Object)null)
			{
				return false;
			}
			float num = Vector3.Distance(((Component)player).transform.position, ((Component)_table).transform.position);
			if ((Object)(object)player.CurCam != (Object)null)
			{
				num = Mathf.Min(num, Vector3.Distance(((Component)player.CurCam).transform.position, ((Component)_table).transform.position));
			}
			return num <= 4.5f;
		}

		private static bool TryFindAutomaticPlacement(Player player, out TablePlacement placement)
		{
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: 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_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due