Decompiled source of FishCraft Link v0.63.0

FishCraftLink.dll

Decompiled 14 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace FishCraftLink
{
	internal sealed class BlockRenderer : IDisposable
	{
		private sealed class Section
		{
			public int Sx;

			public int Sy;

			public int Sz;

			public Mesh Mesh;

			public bool Translucent;

			public GameObject Go;
		}

		private struct Look
		{
			public Shader Shader;

			public bool Cutout;
		}

		private const long BytesPerFrame = 16777216L;

		private readonly Dictionary<long, Section> sections = new Dictionary<long, Section>();

		private readonly GameObject root;

		private Texture2D atlas;

		private bool atlasDirty;

		private float nextAtlasApply;

		private Material solid;

		private Material translucent;

		private string shaderName = "(none yet)";

		private float nextShaderTry;

		private int messages;

		private bool warned;

		private readonly bool useColliders;

		private readonly int startLook;

		private readonly Action<int> onLookChanged;

		private GameObject selGo;

		private Material selMat;

		private Material unlitBlend;

		private readonly SceneRenderer scene;

		private readonly WorldItems items;

		public bool LightenArrowOutline = true;

		private readonly HashSet<long> lightened = new HashSet<long>();

		private bool itemsWarned;

		private float nextAnomaly;

		private static readonly string[] ShaderNames = new string[10] { "Universal Render Pipeline/Lit", "Universal Render Pipeline/Particles/Lit", "Universal Render Pipeline/Unlit", "Universal Render Pipeline/Particles/Unlit", "Universal Render Pipeline/Simple Lit", "Universal Render Pipeline/Particles/Simple Lit", "Particles/Standard Surface", "Particles/Standard Unlit", "Standard", "Unlit/Texture" };

		private readonly List<Look> looks = new List<Look>();

		private int lookIndex = -1;

		public string StatusText = "";

		public float StatusUntil;

		private GameObject testCube;

		private float testCubeUntil;

		private static readonly Vector3[] Normals = (Vector3[])(object)new Vector3[7]
		{
			Vector3.up,
			Vector3.down,
			Vector3.up,
			Vector3.forward,
			Vector3.back,
			Vector3.left,
			Vector3.right
		};

		public int SectionCount => sections.Count;

		public string Summary => "sections=" + sections.Count + " atlas=" + (((Object)(object)atlas != (Object)null) ? (((Texture)atlas).width + "x" + ((Texture)atlas).height) : "none") + " shader='" + shaderName + "' entities=" + scene.Vertices + " items=" + items.Count;

		public Transform RootTransform => root.transform;

		public Material SolidMaterial => solid;

		public Material TranslucentMaterial => translucent;

		public Material UnlitBlendMaterial
		{
			get
			{
				if (!((Object)(object)unlitBlend != (Object)null))
				{
					return translucent;
				}
				return unlitBlend;
			}
		}

		public bool HideEntities
		{
			set
			{
				scene.Suppressed = value;
			}
		}

		public bool HideAvatar
		{
			set
			{
				scene.AvatarHidden = value;
			}
		}

		public Vector3 AvatarOrigin
		{
			set
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				scene.AvatarOrigin = value;
			}
		}

		public List<ArrowSample> ArrowSamples => items.Arrows;

		public List<DroppedItem> DroppedItems => items.Dropped;

		public void PlaceAvatar(Vector3 worldFeet)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			scene.PlaceAvatar(worldFeet);
		}

		public void SetPlayerSkins(string name, Texture2D wide, Texture2D slim)
		{
			scene.SetPlayerSkins(name, wide, slim);
		}

		public void SetVisible(bool visible)
		{
			if ((Object)(object)root != (Object)null && root.activeSelf != visible)
			{
				root.SetActive(visible);
			}
		}

		public BlockRenderer(float unitsPerBlock, bool colliders, int startLook, Action<int> onLookChanged)
		{
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Expected O, but got Unknown
			//IL_0087: 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_00ac: Unknown result type (might be due to invalid IL or missing references)
			useColliders = colliders;
			this.startLook = startLook;
			this.onLookChanged = onLookChanged;
			root = new GameObject("FishCraft_Blocks");
			Object.DontDestroyOnLoad((Object)(object)root);
			root.transform.position = Vector3.zero;
			root.transform.localScale = Vector3.one * Mathf.Max(0.001f, unitsPerBlock);
			scene = new SceneRenderer(this);
			items = new WorldItems(this);
			PickShader();
		}

		private static void SetFloat(Material m, string prop, float v)
		{
			if (m.HasProperty(prop))
			{
				m.SetFloat(prop, v);
			}
		}

		private static void SetColor(Material m, string prop, Color c)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			if (m.HasProperty(prop))
			{
				m.SetColor(prop, c);
			}
		}

		private void PickShader()
		{
			looks.Clear();
			List<Shader> list = new List<Shader>();
			StringBuilder stringBuilder = new StringBuilder("block shader search:");
			string[] shaderNames = ShaderNames;
			foreach (string text in shaderNames)
			{
				Shader val = Shader.Find(text);
				bool flag = (Object)(object)val != (Object)null && val.isSupported;
				stringBuilder.Append(' ').Append(text).Append(flag ? "=YES;" : "=no;");
				if (flag)
				{
					list.Add(val);
				}
			}
			Plugin.Log.LogInfo((object)stringBuilder.ToString());
			if (list.Count == 0)
			{
				Plugin.Log.LogWarning((object)"No usable block shader found yet; blocks will be invisible until one is.");
				return;
			}
			foreach (Shader item in list)
			{
				looks.Add(new Look
				{
					Shader = item,
					Cutout = false
				});
			}
			foreach (Shader item2 in list)
			{
				looks.Add(new Look
				{
					Shader = item2,
					Cutout = true
				});
			}
			ApplyLook(Mathf.Clamp(startLook, 0, looks.Count - 1));
		}

		public void CycleLook()
		{
			if (looks.Count == 0)
			{
				PickShader();
			}
			else
			{
				ApplyLook((lookIndex + 1) % looks.Count);
			}
		}

		private void ApplyLook(int index)
		{
			//IL_006d: 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_008a: Expected O, but got Unknown
			//IL_0113: 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_01c7: 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_01d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Expected O, but got Unknown
			//IL_0297: 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_0314: Unknown result type (might be due to invalid IL or missing references)
			//IL_0319: Unknown result type (might be due to invalid IL or missing references)
			//IL_0324: Unknown result type (might be due to invalid IL or missing references)
			//IL_0331: Expected O, but got Unknown
			//IL_03ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cf: Unknown result type (might be due to invalid IL or missing references)
			lookIndex = index;
			Look look = looks[index];
			if ((Object)(object)solid != (Object)null)
			{
				Object.Destroy((Object)(object)solid);
			}
			if ((Object)(object)translucent != (Object)null)
			{
				Object.Destroy((Object)(object)translucent);
			}
			if ((Object)(object)unlitBlend != (Object)null)
			{
				Object.Destroy((Object)(object)unlitBlend);
			}
			unlitBlend = null;
			solid = new Material(look.Shader)
			{
				name = "FishCraft blocks",
				hideFlags = (HideFlags)32
			};
			SetFloat(solid, "_Surface", 0f);
			SetFloat(solid, "_Cutoff", 0.5f);
			SetFloat(solid, "_Glossiness", 0f);
			SetFloat(solid, "_Smoothness", 0f);
			SetFloat(solid, "_Metallic", 0f);
			SetFloat(solid, "_ColorMode", 0f);
			SetColor(solid, "_BaseColor", Color.white);
			SetColor(solid, "_Color", Color.white);
			if (look.Cutout)
			{
				SetFloat(solid, "_AlphaClip", 1f);
				SetFloat(solid, "_Mode", 1f);
				solid.EnableKeyword("_ALPHATEST_ON");
				solid.SetOverrideTag("RenderType", "TransparentCutout");
				solid.renderQueue = 2450;
			}
			else
			{
				SetFloat(solid, "_AlphaClip", 0f);
				solid.renderQueue = 2000;
			}
			translucent = new Material(look.Shader)
			{
				name = "FishCraft translucent blocks",
				hideFlags = (HideFlags)32
			};
			SetFloat(translucent, "_Surface", 1f);
			SetFloat(translucent, "_Blend", 0f);
			SetFloat(translucent, "_Mode", 2f);
			SetFloat(translucent, "_Glossiness", 0.6f);
			SetFloat(translucent, "_Smoothness", 0.6f);
			SetFloat(translucent, "_SrcBlend", 5f);
			SetFloat(translucent, "_DstBlend", 10f);
			SetFloat(translucent, "_ZWrite", 0f);
			SetColor(translucent, "_BaseColor", Color.white);
			SetColor(translucent, "_Color", Color.white);
			translucent.EnableKeyword("_SURFACE_TYPE_TRANSPARENT");
			translucent.EnableKeyword("_ALPHABLEND_ON");
			translucent.SetOverrideTag("RenderType", "Transparent");
			translucent.renderQueue = 3000;
			Shader val = Shader.Find("Universal Render Pipeline/Particles/Unlit");
			if ((Object)(object)val != (Object)null)
			{
				unlitBlend = new Material(val)
				{
					name = "FishCraft unlit blended",
					hideFlags = (HideFlags)32
				};
				SetFloat(unlitBlend, "_Surface", 1f);
				SetFloat(unlitBlend, "_Blend", 0f);
				SetFloat(unlitBlend, "_SrcBlend", 5f);
				SetFloat(unlitBlend, "_DstBlend", 10f);
				SetFloat(unlitBlend, "_ZWrite", 0f);
				SetFloat(unlitBlend, "_ColorMode", 0f);
				SetColor(unlitBlend, "_BaseColor", Color.white);
				SetColor(unlitBlend, "_Color", Color.white);
				unlitBlend.EnableKeyword("_SURFACE_TYPE_TRANSPARENT");
				unlitBlend.EnableKeyword("_ALPHABLEND_ON");
				unlitBlend.SetOverrideTag("RenderType", "Transparent");
				unlitBlend.renderQueue = 3000;
			}
			shaderName = ((Object)look.Shader).name + (look.Cutout ? " (cutout)" : " (plain)");
			ApplyAtlas();
			foreach (Section value in sections.Values)
			{
				ApplyMaterials(value);
			}
			string text = "Block look " + (index + 1) + "/" + looks.Count + ": " + shaderName;
			Plugin.Log.LogInfo((object)text);
			StatusText = text;
			StatusUntil = Time.unscaledTime + 4f;
			if (onLookChanged != null)
			{
				onLookChanged(index);
			}
		}

		private void ApplyAtlas()
		{
			if ((Object)(object)atlas == (Object)null)
			{
				return;
			}
			Material[] array = (Material[])(object)new Material[3] { solid, translucent, unlitBlend };
			foreach (Material val in array)
			{
				if (!((Object)(object)val == (Object)null))
				{
					val.mainTexture = (Texture)(object)atlas;
					if (val.HasProperty("_BaseMap"))
					{
						val.SetTexture("_BaseMap", (Texture)(object)atlas);
					}
					if (val.HasProperty("_MainTex"))
					{
						val.SetTexture("_MainTex", (Texture)(object)atlas);
					}
				}
			}
		}

		private void ApplyMaterials(Section s)
		{
			if (!((Object)(object)s.Go == (Object)null) && !((Object)(object)solid == (Object)null))
			{
				MeshRenderer component = s.Go.GetComponent<MeshRenderer>();
				if (s.Translucent)
				{
					((Renderer)component).sharedMaterials = (Material[])(object)new Material[2] { solid, translucent };
				}
				else
				{
					((Renderer)component).sharedMaterial = solid;
				}
			}
		}

		public void Diagnose(Camera cam)
		{
			//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_006c: 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_02b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b5: 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_02f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0317: Unknown result type (might be due to invalid IL or missing references)
			//IL_031c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0320: Unknown result type (might be due to invalid IL or missing references)
			//IL_0325: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b8: 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_03c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c8: Unknown result type (might be due to invalid IL or missing references)
			Plugin.Log.LogInfo((object)"=== block diagnostics ===");
			if ((Object)(object)cam != (Object)null)
			{
				Plugin.Log.LogInfo((object)("camera '" + ((Object)cam).name + "' pos=" + ((object)((Component)cam).transform.position/*cast due to .constrained prefix*/).ToString() + " forward=" + ((object)((Component)cam).transform.forward/*cast due to .constrained prefix*/).ToString() + " cullingMask=" + cam.cullingMask + " near=" + cam.nearClipPlane + " far=" + cam.farClipPlane));
			}
			else
			{
				Plugin.Log.LogInfo((object)"no game camera found");
			}
			Plugin.Log.LogInfo((object)("look=" + shaderName + " | " + Summary + " | solid material: " + (((Object)(object)solid != (Object)null) ? ("queue " + solid.renderQueue + ", has _BaseMap " + solid.HasProperty("_BaseMap") + ", texture set " + ((Object)(object)solid.mainTexture != (Object)null)) : "none")));
			int num = 0;
			foreach (Section value in sections.Values)
			{
				if (++num > 6)
				{
					break;
				}
				MeshRenderer val = (((Object)(object)value.Go != (Object)null) ? value.Go.GetComponent<MeshRenderer>() : null);
				ManualLogSource log = Plugin.Log;
				string[] obj = new string[12]
				{
					"section ",
					value.Sx.ToString(),
					",",
					value.Sy.ToString(),
					",",
					value.Sz.ToString(),
					": verts=",
					(((Object)(object)value.Mesh != (Object)null) ? value.Mesh.vertexCount : (-1)).ToString(),
					" worldPos=",
					((Object)(object)value.Go != (Object)null) ? ((object)value.Go.transform.position/*cast due to .constrained prefix*/).ToString() : "none",
					null,
					null
				};
				object obj2;
				Bounds bounds;
				if (!((Object)(object)val != (Object)null))
				{
					obj2 = " (no renderer)";
				}
				else
				{
					string[] obj3 = new string[10] { " boundsCenter=", null, null, null, null, null, null, null, null, null };
					bounds = ((Renderer)val).bounds;
					obj3[1] = ((object)((Bounds)(ref bounds)).center/*cast due to .constrained prefix*/).ToString();
					obj3[2] = " boundsSize=";
					bounds = ((Renderer)val).bounds;
					obj3[3] = ((object)((Bounds)(ref bounds)).size/*cast due to .constrained prefix*/).ToString();
					obj3[4] = " visible=";
					obj3[5] = ((Renderer)val).isVisible.ToString();
					obj3[6] = " enabled=";
					obj3[7] = ((Renderer)val).enabled.ToString();
					obj3[8] = " layer=";
					obj3[9] = value.Go.layer.ToString();
					obj2 = string.Concat(obj3);
				}
				obj[10] = (string)obj2;
				object obj4;
				if (!((Object)(object)cam != (Object)null) || !((Object)(object)val != (Object)null))
				{
					obj4 = "";
				}
				else
				{
					Vector3 position = ((Component)cam).transform.position;
					bounds = ((Renderer)val).bounds;
					obj4 = " distance=" + Vector3.Distance(position, ((Bounds)(ref bounds)).center);
				}
				obj[11] = (string)obj4;
				log.LogInfo((object)string.Concat(obj));
			}
			SpawnTestCube(cam);
			StatusText = "Diagnostics written to the log; a red cube is 5 steps in front of you for 20 s";
			StatusUntil = Time.unscaledTime + 5f;
		}

		private void SpawnTestCube(Camera cam)
		{
			//IL_007f: 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_0094: 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_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Expected O, but got Unknown
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)cam == (Object)null))
			{
				if ((Object)(object)testCube != (Object)null)
				{
					Object.Destroy((Object)(object)testCube);
				}
				Shader val = Shader.Find("Universal Render Pipeline/Unlit");
				if ((Object)(object)val == (Object)null)
				{
					val = Shader.Find("Universal Render Pipeline/Lit");
				}
				testCube = GameObject.CreatePrimitive((PrimitiveType)3);
				Component component = testCube.GetComponent("BoxCollider");
				if ((Object)(object)component != (Object)null)
				{
					Object.Destroy((Object)(object)component);
				}
				testCube.transform.position = ((Component)cam).transform.position + ((Component)cam).transform.forward * 5f;
				testCube.transform.localScale = Vector3.one * 1.5f;
				if ((Object)(object)val != (Object)null)
				{
					Material val2 = new Material(val);
					SetColor(val2, "_BaseColor", Color.red);
					SetColor(val2, "_Color", Color.red);
					((Renderer)testCube.GetComponent<MeshRenderer>()).sharedMaterial = val2;
				}
				testCubeUntil = Time.unscaledTime + 20f;
				Plugin.Log.LogInfo((object)("test cube at " + ((object)testCube.transform.position/*cast due to .constrained prefix*/).ToString() + " using shader " + (((Object)(object)val != (Object)null) ? ((Object)val).name : "default")));
			}
		}

		public void Update(SharedMem mem)
		{
			if ((Object)(object)solid == (Object)null && Time.unscaledTime >= nextShaderTry)
			{
				nextShaderTry = Time.unscaledTime + 3f;
				PickShader();
			}
			if ((Object)(object)testCube != (Object)null && Time.unscaledTime > testCubeUntil)
			{
				Object.Destroy((Object)(object)testCube);
				testCube = null;
			}
			mem.DrainRender(Handle, 16777216L);
			try
			{
				items.Update(mem);
			}
			catch (Exception ex)
			{
				if (!itemsWarned)
				{
					itemsWarned = true;
					Plugin.Log.LogError((object)("Dropped-item renderer error: " + ex));
				}
			}
			if (atlasDirty && (Object)(object)atlas != (Object)null && Time.unscaledTime >= nextAtlasApply)
			{
				atlas.Apply(false);
				atlasDirty = false;
				nextAtlasApply = Time.unscaledTime + 0.1f;
			}
		}

		private void Handle(uint type, IntPtr p, int bytes)
		{
			messages++;
			try
			{
				switch (type)
				{
				case 1u:
					OnAtlas(p, bytes);
					break;
				case 7u:
					OnAtlasRegion(p, bytes);
					break;
				case 2u:
					OnSection(p, bytes);
					break;
				case 3u:
					Clear();
					scene.Clear();
					break;
				case 4u:
					scene.OnTexture(p, bytes);
					break;
				case 6u:
					scene.OnScene(p, bytes);
					break;
				case 5u:
					scene.OnAvatar(p, bytes);
					break;
				}
			}
			catch (Exception ex)
			{
				if (!warned)
				{
					warned = true;
					Plugin.Log.LogError((object)("Render message " + type + " failed: " + ex));
				}
			}
		}

		private unsafe void OnAtlas(IntPtr p, int bytes)
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Expected O, but got Unknown
			byte* ptr = (byte*)p.ToPointer();
			int num = *(int*)ptr;
			int num2 = ((int*)ptr)[1];
			if (num <= 0 || num2 <= 0 || bytes < 8 + (long)num * (long)num2 * 4)
			{
				return;
			}
			if ((Object)(object)atlas == (Object)null || ((Texture)atlas).width != num || ((Texture)atlas).height != num2)
			{
				if ((Object)(object)atlas != (Object)null)
				{
					Object.Destroy((Object)(object)atlas);
				}
				atlas = new Texture2D(num, num2, (TextureFormat)4, false, false);
				((Object)atlas).name = "FishCraft atlas";
				((Object)atlas).hideFlags = (HideFlags)32;
				((Texture)atlas).filterMode = (FilterMode)0;
				((Texture)atlas).wrapMode = (TextureWrapMode)1;
				((Texture)atlas).anisoLevel = 0;
				ApplyAtlas();
			}
			lightened.Clear();
			atlas.LoadRawTextureData(new IntPtr(ptr + 8), num * num2 * 4);
			atlasDirty = true;
			Plugin.Log.LogInfo((object)("Block atlas received: " + num + "x" + num2));
		}

		public bool SpriteFingerprint(float u0, float v0, float u1, float v1, float[] fp)
		{
			if ((Object)(object)atlas == (Object)null || fp == null || fp.Length < 64)
			{
				return false;
			}
			int width = ((Texture)atlas).width;
			int height = ((Texture)atlas).height;
			int num = Mathf.Clamp(Mathf.RoundToInt(u0 * (float)width), 0, width - 1);
			int num2 = Mathf.Clamp(Mathf.RoundToInt(v0 * (float)height), 0, height - 1);
			int num3 = Mathf.Clamp(Mathf.RoundToInt(u1 * (float)width), num + 1, width);
			int num4 = Mathf.Clamp(Mathf.RoundToInt(v1 * (float)height), num2 + 1, height);
			int num5 = num3 - num;
			int num6 = num4 - num2;
			if (num5 < 8 || num6 < 8 || num5 * num6 > 4096)
			{
				return false;
			}
			SpritePrint.Compute(atlas.GetPixels(num, num2, num5, num6), num5, num6, fp);
			return true;
		}

		public void LightenOutline(float u0, float v0, float u1, float v1)
		{
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0301: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0306: Unknown result type (might be due to invalid IL or missing references)
			//IL_0308: Unknown result type (might be due to invalid IL or missing references)
			//IL_030a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0314: Unknown result type (might be due to invalid IL or missing references)
			//IL_0319: Unknown result type (might be due to invalid IL or missing references)
			//IL_0324: Unknown result type (might be due to invalid IL or missing references)
			//IL_0329: Unknown result type (might be due to invalid IL or missing references)
			//IL_032b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0339: Unknown result type (might be due to invalid IL or missing references)
			//IL_0340: Unknown result type (might be due to invalid IL or missing references)
			//IL_0347: Unknown result type (might be due to invalid IL or missing references)
			//IL_0363: Unknown result type (might be due to invalid IL or missing references)
			//IL_036a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0371: Unknown result type (might be due to invalid IL or missing references)
			//IL_0378: Unknown result type (might be due to invalid IL or missing references)
			//IL_037f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0384: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)atlas == (Object)null)
			{
				return;
			}
			int width = ((Texture)atlas).width;
			int height = ((Texture)atlas).height;
			int num = Mathf.Clamp(Mathf.RoundToInt(u0 * (float)width), 0, width - 1);
			int num2 = Mathf.Clamp(Mathf.RoundToInt(v0 * (float)height), 0, height - 1);
			int num3 = Mathf.Clamp(Mathf.RoundToInt(u1 * (float)width), num + 1, width);
			int num4 = Mathf.Clamp(Mathf.RoundToInt(v1 * (float)height), num2 + 1, height);
			long item = ((long)num << 48) | ((long)num2 << 32) | ((long)num3 << 16) | num4;
			if (!lightened.Add(item))
			{
				return;
			}
			int num5 = num3 - num;
			int num6 = num4 - num2;
			if (num5 * num6 > 4096)
			{
				return;
			}
			Color[] pixels = atlas.GetPixels(num, num2, num5, num6);
			Color val = default(Color);
			((Color)(ref val))..ctor(0f, 0f, 0f, 0f);
			int num7 = 0;
			int num8 = 0;
			StringBuilder stringBuilder = new StringBuilder();
			for (int i = 0; i < num6; i++)
			{
				stringBuilder.Length = 0;
				for (int j = 0; j < num5; j++)
				{
					Color val2 = pixels[i * num5 + j];
					float num9 = Mathf.Max(val2.r, Mathf.Max(val2.g, val2.b));
					if (val2.a <= 0.1f)
					{
						stringBuilder.Append('.');
					}
					else if (num9 < 0.2f)
					{
						stringBuilder.Append('#');
					}
					else if (num9 < 0.42f)
					{
						stringBuilder.Append('+');
					}
					else if (num9 < 0.7f)
					{
						stringBuilder.Append('o');
					}
					else
					{
						stringBuilder.Append('O');
					}
					if (val2.a > 0.1f)
					{
						if (num9 < 0.42f)
						{
							num8++;
							continue;
						}
						val += val2;
						num7++;
					}
				}
				if (num5 <= 64 && num6 <= 24)
				{
					Plugin.Log.LogInfo((object)("arrow pixels " + (i + 1).ToString("00") + " " + stringBuilder));
				}
			}
			Plugin.Log.LogInfo((object)("Arrow texture rect " + num + "," + num2 + " " + num5 + "x" + num6 + ": dark pixels " + num8 + ", light pixels " + num7 + (LightenArrowOutline ? ", lightening the dark ones" : ", lightening is off")));
			if (!LightenArrowOutline || num8 == 0)
			{
				return;
			}
			Color val3 = (Color)((num7 > 0) ? (val / (float)num7) : new Color(0.65f, 0.65f, 0.65f, 1f));
			val3 = Color.Lerp(val3, Color.white, 0.2f);
			for (int k = 0; k < pixels.Length; k++)
			{
				Color val4 = pixels[k];
				if (val4.a > 0.1f && Mathf.Max(val4.r, Mathf.Max(val4.g, val4.b)) < 0.42f)
				{
					pixels[k] = new Color(val3.r, val3.g, val3.b, val4.a);
				}
			}
			atlas.SetPixels(num, num2, num5, num6, pixels);
			atlasDirty = true;
		}

		private unsafe void OnAtlasRegion(IntPtr p, int bytes)
		{
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)atlas == (Object)null)
			{
				return;
			}
			byte* ptr = (byte*)p.ToPointer();
			uint* ptr2 = (uint*)ptr;
			int num = (int)(*ptr2);
			int num2 = (int)ptr2[1];
			int num3 = (int)ptr2[2];
			int num4 = (int)ptr2[3];
			if (num3 > 0 && num4 > 0 && num + num3 <= ((Texture)atlas).width && num2 + num4 <= ((Texture)atlas).height && bytes >= 16 + (long)num3 * (long)num4 * 4)
			{
				Color32[] array = (Color32[])(object)new Color32[num3 * num4];
				byte* ptr3 = ptr + 16;
				for (int i = 0; i < num3 * num4; i++)
				{
					byte* ptr4 = ptr3 + i * 4;
					array[i] = new Color32(*ptr4, ptr4[1], ptr4[2], ptr4[3]);
				}
				atlas.SetPixels32(num, num2, num3, num4, array);
				atlasDirty = true;
			}
		}

		private static long Key(int sx, int sy, int sz)
		{
			return ((long)(sx & 0x1FFFFF) << 42) | ((long)(sy & 0x1FFFFF) << 21) | (sz & 0x1FFFFF);
		}

		private unsafe void OnSection(IntPtr p, int bytes)
		{
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: 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_012e: 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_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0225: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Expected O, but got Unknown
			//IL_032f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0336: Expected O, but got Unknown
			//IL_0388: Unknown result type (might be due to invalid IL or missing references)
			byte* ptr = (byte*)p.ToPointer();
			int* ptr2 = (int*)ptr;
			int num = *ptr2;
			int num2 = ptr2[1];
			int num3 = ptr2[2];
			int num4 = ptr2[3];
			long key = Key(num, num2, num3);
			if (num4 <= 0)
			{
				Remove(key);
			}
			else
			{
				if (bytes < 16 + (long)num4 * 32L)
				{
					return;
				}
				Vector3[] array = (Vector3[])(object)new Vector3[num4];
				Vector2[] array2 = (Vector2[])(object)new Vector2[num4];
				Color32[] array3 = (Color32[])(object)new Color32[num4];
				Vector3[] array4 = (Vector3[])(object)new Vector3[num4];
				byte* ptr3 = ptr + 16;
				int num5 = 0;
				while (num5 < num4)
				{
					float* ptr4 = (float*)ptr3;
					array[num5] = new Vector3(*ptr4, ptr4[1], 0f - ptr4[2]);
					array2[num5] = new Vector2(ptr4[3], ptr4[4]);
					byte* ptr5 = ptr3 + 20;
					uint num6 = ((uint*)ptr3)[6];
					int num7 = ((int*)ptr3)[7];
					float num8 = (num6 >> 8) & 0xF;
					float num9 = num6 & 0xF;
					float num10 = Mathf.Lerp(0.25f, 1f, Mathf.Max(num8, num9) / 15f);
					array3[num5] = new Color32((byte)((float)(int)(*ptr5) * num10), (byte)((float)(int)ptr5[1] * num10), (byte)((float)(int)ptr5[2] * num10), ptr5[3]);
					int num11 = (num7 >>> 4) & 7;
					array4[num5] = ((num11 < Normals.Length) ? Normals[num11] : Vector3.up);
					num5++;
					ptr3 += 32;
				}
				List<int> list = new List<int>(num4);
				List<int> list2 = new List<int>();
				byte* ptr6 = ptr + 16 + 28;
				for (int i = 0; i + 2 < num4; i += 3)
				{
					List<int> obj = (((*(uint*)(ptr6 + i * 32) & 2) != 0) ? list2 : list);
					obj.Add(i);
					obj.Add(i + 2);
					obj.Add(i + 1);
				}
				if (!sections.TryGetValue(key, out var value))
				{
					value = new Section
					{
						Sx = num,
						Sy = num2,
						Sz = num3
					};
					sections[key] = value;
				}
				Mesh val = value.Mesh;
				if ((Object)(object)val == (Object)null)
				{
					val = new Mesh();
					((Object)val).name = "FishCraft section " + num + "," + num2 + "," + num3;
					((Object)val).hideFlags = (HideFlags)32;
					val.MarkDynamic();
					value.Mesh = val;
				}
				val.Clear();
				val.indexFormat = (IndexFormat)(num4 > 65535);
				val.vertices = array;
				val.uv = array2;
				val.colors32 = array3;
				val.normals = array4;
				val.subMeshCount = ((list2.Count <= 0) ? 1 : 2);
				val.SetTriangles(list, 0, false);
				if (list2.Count > 0)
				{
					val.SetTriangles(list2, 1, false);
				}
				val.RecalculateBounds();
				value.Translucent = list2.Count > 0;
				if ((Object)(object)value.Go == (Object)null)
				{
					GameObject val2 = new GameObject(((Object)val).name);
					val2.AddComponent<MeshFilter>().sharedMesh = val;
					MeshRenderer obj2 = val2.AddComponent<MeshRenderer>();
					((Renderer)obj2).shadowCastingMode = (ShadowCastingMode)1;
					((Renderer)obj2).receiveShadows = true;
					val2.transform.SetParent(root.transform, false);
					val2.transform.localPosition = new Vector3((float)(num * 16), (float)(num2 * 16), (float)(-(num3 * 16)));
					value.Go = val2;
				}
				ApplyMaterials(value);
				if (useColliders)
				{
					MeshCollider val3 = value.Go.GetComponent<MeshCollider>();
					if ((Object)(object)val3 == (Object)null)
					{
						val3 = value.Go.AddComponent<MeshCollider>();
					}
					val3.sharedMesh = null;
					val3.sharedMesh = val;
				}
			}
		}

		public void UpdateSelection(SharedMem mem, bool show)
		{
			//IL_0045: 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_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: 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_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: 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_01b2: Unknown result type (might be due to invalid IL or missing references)
			if (!show || !mem.ReadSelection(out var min, out var max))
			{
				if ((Object)(object)selGo != (Object)null && selGo.activeSelf)
				{
					selGo.SetActive(false);
				}
				return;
			}
			mem.ReadSelection(out min, out max);
			if ((max.y > 300f || min.y < -300f) && Time.unscaledTime >= nextAnomaly)
			{
				nextAnomaly = Time.unscaledTime + 2f;
				Plugin.Log.LogInfo((object)("Aim anomaly: Minecraft is targeting a block at y " + min.y.ToString("0") + ".." + max.y.ToString("0") + " (x " + min.x.ToString("0") + ", z " + min.z.ToString("0") + ")"));
			}
			if ((Object)(object)selGo == (Object)null)
			{
				CreateSelection();
			}
			if (!((Object)(object)selGo == (Object)null))
			{
				selGo.transform.localPosition = new Vector3(min.x - 0.003f, min.y - 0.003f, 0f - max.z - 0.003f);
				selGo.transform.localScale = new Vector3(max.x - min.x + 0.006f, max.y - min.y + 0.006f, max.z - min.z + 0.006f);
				if (!selGo.activeSelf)
				{
					selGo.SetActive(true);
				}
			}
		}

		private void CreateSelection()
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Expected O, but got Unknown
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: 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_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Expected O, but got Unknown
			Shader val = Shader.Find("Universal Render Pipeline/Unlit");
			if ((Object)(object)val == (Object)null && looks.Count > 0)
			{
				val = looks[0].Shader;
			}
			if (!((Object)(object)val == (Object)null))
			{
				selMat = new Material(val);
				SetColor(selMat, "_BaseColor", Color.black);
				SetColor(selMat, "_Color", Color.black);
				Mesh val2 = new Mesh();
				val2.vertices = (Vector3[])(object)new Vector3[8]
				{
					new Vector3(0f, 0f, 0f),
					new Vector3(1f, 0f, 0f),
					new Vector3(1f, 0f, 1f),
					new Vector3(0f, 0f, 1f),
					new Vector3(0f, 1f, 0f),
					new Vector3(1f, 1f, 0f),
					new Vector3(1f, 1f, 1f),
					new Vector3(0f, 1f, 1f)
				};
				val2.uv = (Vector2[])(object)new Vector2[8];
				val2.SetIndices(new int[24]
				{
					0, 1, 1, 2, 2, 3, 3, 0, 4, 5,
					5, 6, 6, 7, 7, 4, 0, 4, 1, 5,
					2, 6, 3, 7
				}, (MeshTopology)3, 0);
				selGo = new GameObject("FishCraft_Selection");
				selGo.transform.SetParent(root.transform, false);
				selGo.AddComponent<MeshFilter>().sharedMesh = val2;
				MeshRenderer obj = selGo.AddComponent<MeshRenderer>();
				((Renderer)obj).sharedMaterial = selMat;
				((Renderer)obj).shadowCastingMode = (ShadowCastingMode)0;
				((Renderer)obj).receiveShadows = false;
			}
		}

		private void Remove(long key)
		{
			if (sections.TryGetValue(key, out var value))
			{
				sections.Remove(key);
				Destroy(value);
			}
		}

		private static void Destroy(Section s)
		{
			if ((Object)(object)s.Go != (Object)null)
			{
				Object.Destroy((Object)(object)s.Go);
			}
			if ((Object)(object)s.Mesh != (Object)null)
			{
				Object.Destroy((Object)(object)s.Mesh);
			}
		}

		public void Clear()
		{
			foreach (Section value in sections.Values)
			{
				Destroy(value);
			}
			sections.Clear();
		}

		public void Dispose()
		{
			Clear();
			if (scene != null)
			{
				scene.Dispose();
			}
			if (items != null)
			{
				items.Dispose();
			}
			if ((Object)(object)atlas != (Object)null)
			{
				Object.Destroy((Object)(object)atlas);
			}
			if ((Object)(object)solid != (Object)null)
			{
				Object.Destroy((Object)(object)solid);
			}
			if ((Object)(object)translucent != (Object)null)
			{
				Object.Destroy((Object)(object)translucent);
			}
			if ((Object)(object)unlitBlend != (Object)null)
			{
				Object.Destroy((Object)(object)unlitBlend);
			}
			if ((Object)(object)root != (Object)null)
			{
				Object.Destroy((Object)(object)root);
			}
		}
	}
	internal static class CreativeMode
	{
		public static volatile bool Active;

		public static volatile bool Locked;

		public static bool Allow;

		public static bool AllowDamage;

		private static bool installed;

		public static void Install()
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Expected O, but got Unknown
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Expected O, but got Unknown
			if (installed)
			{
				return;
			}
			installed = true;
			try
			{
				Type type = AccessTools.TypeByName("PlayerVitals");
				if (type == null)
				{
					Plugin.Log.LogWarning((object)"creative: the game's vitals were not found; Creative changes nothing in the game");
					return;
				}
				Harmony val = new Harmony("local.fishcraftlink.creative");
				MethodInfo methodInfo = AccessTools.Method(type, "LowerFullness", (Type[])null, (Type[])null);
				MethodInfo methodInfo2 = AccessTools.Method(type, "TakeDamage", (Type[])null, (Type[])null);
				if (methodInfo != null)
				{
					val.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(CreativeMode).GetMethod("SkipHunger", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				if (methodInfo2 != null)
				{
					val.Patch((MethodBase)methodInfo2, new HarmonyMethod(typeof(CreativeMode).GetMethod("SkipDamage", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				Plugin.Log.LogInfo((object)("creative: the player's own hunger and damage can be paused while Minecraft is in Creative (hunger " + (methodInfo != null) + ", damage " + (methodInfo2 != null) + ")"));
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("creative: could not patch the game's hunger and damage calls: " + ex.Message));
			}
		}

		private static bool SkipHunger(object __instance)
		{
			if (!Allow)
			{
				if (Active || Locked)
				{
					return !HfApi.IsLocalVitals(__instance);
				}
				return true;
			}
			return true;
		}

		private static bool SkipDamage(object __instance)
		{
			if (!AllowDamage)
			{
				if (Active)
				{
					return !HfApi.IsLocalVitals(__instance);
				}
				return true;
			}
			return true;
		}
	}
	internal static class CursorGuard
	{
		public static bool ForceFree;

		public static bool ShowCursor;

		public static int Blocked;

		private static bool installed;

		private static int logged;

		public static void Install()
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Expected O, but got Unknown
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Expected O, but got Unknown
			if (installed)
			{
				return;
			}
			try
			{
				Harmony val = new Harmony("local.fishcraftlink.cursor");
				val.Patch((MethodBase)typeof(Cursor).GetProperty("lockState").GetSetMethod(), new HarmonyMethod(typeof(CursorGuard), "LockPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				val.Patch((MethodBase)typeof(Cursor).GetProperty("visible").GetSetMethod(), new HarmonyMethod(typeof(CursorGuard), "VisiblePrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				installed = true;
				Plugin.Log.LogInfo((object)"Cursor guard installed");
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Cursor guard unavailable (" + ex.Message + "); falling back to re-setting the cursor every frame."));
			}
		}

		internal static void LockPrefix(ref CursorLockMode value)
		{
			if (!ForceFree)
			{
				return;
			}
			if ((int)value == 1)
			{
				Blocked++;
				if (logged < 3)
				{
					logged++;
					Plugin.Log.LogInfo((object)("Cursor lock blocked; the game asked from: " + Caller()));
				}
			}
			value = (CursorLockMode)2;
		}

		internal static void VisiblePrefix(ref bool value)
		{
			if (ForceFree)
			{
				value = ShowCursor;
			}
		}

		private static string Caller()
		{
			try
			{
				StackTrace stackTrace = new StackTrace(2, fNeedFileInfo: false);
				StringBuilder stringBuilder = new StringBuilder();
				for (int i = 0; i < stackTrace.FrameCount && i < 4; i++)
				{
					MethodBase method = stackTrace.GetFrame(i).GetMethod();
					if (!(method == null))
					{
						if (stringBuilder.Length > 0)
						{
							stringBuilder.Append(" <- ");
						}
						stringBuilder.Append((method.DeclaringType != null) ? method.DeclaringType.Name : "?").Append('.').Append(method.Name);
					}
				}
				return stringBuilder.ToString();
			}
			catch (Exception)
			{
				return "(unknown)";
			}
		}
	}
	internal sealed class EmeraldHud
	{
		private static readonly string[][] Glyphs = new string[11][]
		{
			new string[7] { ".###.", "#...#", "#..##", "#.#.#", "##..#", "#...#", ".###." },
			new string[7] { "..#..", ".##..", "..#..", "..#..", "..#..", "..#..", ".###." },
			new string[7] { ".###.", "#...#", "....#", "...#.", "..#..", ".#...", "#####" },
			new string[7] { ".###.", "#...#", "....#", "..##.", "....#", "#...#", ".###." },
			new string[7] { "...#.", "..##.", ".#.#.", "#..#.", "#####", "...#.", "...#." },
			new string[7] { "#####", "#....", "####.", "....#", "....#", "#...#", ".###." },
			new string[7] { "..##.", ".#...", "#....", "####.", "#...#", "#...#", ".###." },
			new string[7] { "#####", "....#", "...#.", "..#..", ".#...", ".#...", ".#..." },
			new string[7] { ".###.", "#...#", "#...#", ".###.", "#...#", "#...#", ".###." },
			new string[7] { ".###.", "#...#", "#...#", ".####", "....#", "...#.", ".##.." },
			new string[7] { ".....", "..#..", "..#..", "#####", "..#..", "..#..", "....." }
		};

		private static readonly string[] FallbackEmerald = new string[16]
		{
			"................", "................", ".....KKKKKK.....", "....KLLLMMMK....", "...KLLMMMMMMK...", "..KLMMMMMMMMMK..", "..KMMMMMMMMMDK..", "..KMMMMMMMMDDK..", "...KMMMMMMDDK...", "....KMMMMDDK....",
			".....KMMDDK.....", "......KDDK......", ".......KK.......", "................", "................", "................"
		};

		private Texture2D emerald;

		private readonly Texture2D[] glyph = (Texture2D[])(object)new Texture2D[11];

		private bool built;

		private bool haveMoney;

		private int last = -1;

		private int shown;

		private int gain;

		private float nextRead;

		private float gainUntil;

		private static Texture2D FromTopDown(Color32[] px, int w, int h)
		{
			//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_004b: 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_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Expected O, but got Unknown
			//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)
			Color32[] array = (Color32[])(object)new Color32[w * h];
			for (int i = 0; i < h; i++)
			{
				for (int j = 0; j < w; j++)
				{
					array[(h - 1 - i) * w + j] = px[i * w + j];
				}
			}
			Texture2D val = new Texture2D(w, h, (TextureFormat)4, false)
			{
				filterMode = (FilterMode)0,
				wrapMode = (TextureWrapMode)1
			};
			val.SetPixels32(array);
			val.Apply(false);
			return val;
		}

		private void Build()
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0235: Unknown result type (might be due to invalid IL or missing references)
			//IL_0237: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			if (built)
			{
				return;
			}
			built = true;
			for (int i = 0; i < Glyphs.Length; i++)
			{
				Color32[] array = (Color32[])(object)new Color32[35];
				for (int j = 0; j < 7; j++)
				{
					for (int k = 0; k < 5; k++)
					{
						array[j * 5 + k] = ((Glyphs[i][j][k] == '#') ? new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue) : new Color32((byte)0, (byte)0, (byte)0, (byte)0));
					}
				}
				glyph[i] = FromTopDown(array, 5, 7);
			}
			try
			{
				byte[] array2 = MinecraftAssets.Read("emerald.png", "item/emerald.png");
				if (array2 != null && PngDecoder.TryDecode(array2, out var width, out var height, out var pixels, out var _) && width >= 8 && height >= width)
				{
					Color32[] array3 = (Color32[])(object)new Color32[width * width];
					Array.Copy(pixels, array3, width * width);
					emerald = FromTopDown(array3, width, width);
					Plugin.Log.LogInfo((object)("emerald: Minecraft's own picture loaded (" + width + " x " + width + ")"));
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("emerald picture: " + ex.Message));
			}
			if (!((Object)(object)emerald == (Object)null))
			{
				return;
			}
			Plugin.Log.LogInfo((object)"emerald: Minecraft's picture was not found, so a drawn emerald is used");
			Color32[] array4 = (Color32[])(object)new Color32[256];
			Color32 val = default(Color32);
			for (int l = 0; l < 16; l++)
			{
				for (int m = 0; m < 16; m++)
				{
					switch (FallbackEmerald[l][m])
					{
					case 'K':
						((Color32)(ref val))..ctor((byte)11, (byte)84, (byte)41, byte.MaxValue);
						break;
					case 'L':
						((Color32)(ref val))..ctor((byte)169, byte.MaxValue, (byte)197, byte.MaxValue);
						break;
					case 'M':
						((Color32)(ref val))..ctor((byte)23, (byte)214, (byte)92, byte.MaxValue);
						break;
					case 'D':
						((Color32)(ref val))..ctor((byte)10, (byte)142, (byte)58, byte.MaxValue);
						break;
					default:
						((Color32)(ref val))..ctor((byte)0, (byte)0, (byte)0, (byte)0);
						break;
					}
					array4[l * 16 + m] = val;
				}
			}
			emerald = FromTopDown(array4, 16, 16);
		}

		private void ReadMoney(float now)
		{
			if (HfApi.Money(out var dollars, out var _))
			{
				if (haveMoney && dollars > last)
				{
					gain = ((now < gainUntil) ? gain : 0) + (dollars - last);
					gainUntil = now + 2.5f;
				}
				haveMoney = true;
				last = dollars;
				shown = dollars;
			}
		}

		private void DrawNumber(string text, float x, float y, float ux, float uy, Color color)
		{
			//IL_0037: 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_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < 2; i++)
			{
				float num = ((i == 0) ? ux : 0f);
				float num2 = ((i == 0) ? uy : 0f);
				GUI.color = (Color)((i == 0) ? new Color(0.247f, 0.247f, 0.247f, color.a) : color);
				float num3 = x;
				foreach (char c in text)
				{
					int num4;
					switch (c)
					{
					default:
						num4 = -1;
						break;
					case '0':
					case '1':
					case '2':
					case '3':
					case '4':
					case '5':
					case '6':
					case '7':
					case '8':
					case '9':
						num4 = c - 48;
						break;
					case '+':
						num4 = 10;
						break;
					}
					int num5 = num4;
					if (num5 >= 0)
					{
						GUI.DrawTexture(new Rect(Mathf.Round(num3 + num), Mathf.Round(y + num2), 5f * ux, 7f * uy), (Texture)(object)glyph[num5]);
					}
					num3 += 6f * ux;
				}
			}
		}

		public void Draw(int guiScale, int overlayWidth, int overlayHeight)
		{
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: 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)
			Build();
			if ((Object)(object)emerald == (Object)null)
			{
				return;
			}
			float unscaledTime = Time.unscaledTime;
			if (unscaledTime >= nextRead)
			{
				nextRead = unscaledTime + 0.25f;
				ReadMoney(unscaledTime);
			}
			if (haveMoney)
			{
				int num = ((guiScale >= 1 && guiScale <= 8) ? guiScale : 3);
				float num2 = (float)num * ((overlayWidth > 0) ? ((float)Screen.width / (float)overlayWidth) : 1f);
				float num3 = (float)num * ((overlayHeight > 0) ? ((float)Screen.height / (float)overlayHeight) : 1f);
				float num4 = Mathf.Round(3f * num2);
				float num5 = Mathf.Round((float)Screen.height - 19f * num3);
				Color color = GUI.color;
				GUI.color = Color.white;
				GUI.DrawTexture(new Rect(num4, num5, 16f * num2, 16f * num3), (Texture)(object)emerald);
				DrawNumber(shown.ToString(CultureInfo.InvariantCulture), num4 + 19f * num2, num5 + 4.5f * num3, num2, num3, Color.white);
				if (unscaledTime < gainUntil)
				{
					DrawNumber(color: new Color(0.33f, 1f, 0.33f, Mathf.Clamp01((gainUntil - unscaledTime) / 0.6f)), text: "+" + gain.ToString(CultureInfo.InvariantCulture), x: num4 + 19f * num2, y: num5 - 5.5f * num3, ux: num2, uy: num3);
				}
				GUI.color = color;
			}
		}

		public void Dispose()
		{
			if ((Object)(object)emerald != (Object)null)
			{
				Object.Destroy((Object)(object)emerald);
			}
			for (int i = 0; i < glyph.Length; i++)
			{
				if ((Object)(object)glyph[i] != (Object)null)
				{
					Object.Destroy((Object)(object)glyph[i]);
				}
			}
		}
	}
	internal static class ExplosionFish
	{
		private static bool resolved;

		private static bool ok;

		private static bool warned;

		private static MethodInfo mWaterHeight;

		private static MethodInfo mGetRandomItem;

		private static MethodInfo mKill;

		private static MethodInfo mSpawn;

		private static MethodInfo mStartSim;

		private static MethodInfo mExplosionInfo;

		private static FieldInfo fCreatureMgr;

		private static FieldInfo fExplosionMgr;

		private static FieldInfo fWeights;

		private static PropertyInfo pItemToSpawn;

		private static PropertyInfo pCreature;

		private static PropertyInfo pRigSync;

		private static PropertyInfo pRig;

		private static PropertyInfo pHasUnderwater;

		private static PropertyInfo pFishMinMax;

		private static PropertyInfo pForceRadius;

		private static PropertyInfo pItemForce;

		private static Type tExplosive;

		private static object dynamiteInfo;

		private static float budget = 40f;

		private static float budgetAt;

		private const BindingFlags Any = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;

		private static void Resolve()
		{
			if (resolved)
			{
				return;
			}
			resolved = true;
			try
			{
				Type type = AccessTools.TypeByName("WaterManager");
				Type type2 = AccessTools.TypeByName("CreatureManager");
				Type type3 = AccessTools.TypeByName("ExplosionManager");
				Type type4 = AccessTools.TypeByName("Fishable");
				Type type5 = AccessTools.TypeByName("Item");
				Type type6 = AccessTools.TypeByName("Creature");
				Type type7 = AccessTools.TypeByName("ExplosionInfo");
				Type type8 = AccessTools.TypeByName("RigidbodySync");
				tExplosive = AccessTools.TypeByName("Explosive");
				mWaterHeight = ((type != null) ? type.GetMethod("GetWaterHeight", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(Vector3) }, null) : null);
				fCreatureMgr = ((type2 != null) ? type2.GetField("Instance", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) : null);
				mGetRandomItem = ((type2 != null) ? type2.GetMethod("GetRandomItem", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) : null);
				fExplosionMgr = ((type3 != null) ? type3.GetField("Instance", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) : null);
				fWeights = ((type3 != null) ? type3.GetField("_explodabaleItemWeights", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) : null);
				if (type3 != null)
				{
					MethodInfo[] methods = type3.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
					foreach (MethodInfo methodInfo in methods)
					{
						ParameterInfo[] parameters = methodInfo.GetParameters();
						if (methodInfo.Name == "Spawn" && parameters.Length == 3 && parameters[0].ParameterType == typeof(GameObject))
						{
							mSpawn = methodInfo;
							break;
						}
					}
				}
				pItemToSpawn = ((type4 != null) ? type4.GetProperty("ItemToSpawn", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) : null);
				pCreature = ((type5 != null) ? type5.GetProperty("Creature", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) : null);
				pRigSync = ((type5 != null) ? type5.GetProperty("RigidbodySync", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) : null);
				pRig = ((type5 != null) ? type5.GetProperty("Rig", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) : null);
				mKill = ((type6 != null) ? type6.GetMethod("ServerKillOnSpawn", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) : null);
				mStartSim = ((type8 != null) ? type8.GetMethod("StartSimulateLocal", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[2]
				{
					typeof(Vector3),
					typeof(Quaternion)
				}, null) : null);
				mExplosionInfo = ((tExplosive != null) ? tExplosive.GetMethod("GetExplosionInfo", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null) : null);
				if (type7 != null)
				{
					pHasUnderwater = type7.GetProperty("HasUnderwaterExplosion", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
					pFishMinMax = type7.GetProperty("UnderWaterFishMinMax", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
					pForceRadius = type7.GetProperty("ForceRadius", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
					pItemForce = type7.GetProperty("ItemForce", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				}
				ok = mWaterHeight != null && fCreatureMgr != null && mGetRandomItem != null && fExplosionMgr != null && fWeights != null && mSpawn != null && pItemToSpawn != null && pCreature != null && pRig != null && mExplosionInfo != null && pFishMinMax != null && pForceRadius != null && pItemForce != null;
				Plugin.Log.LogInfo((object)("explosions: " + (ok ? "the game's dynamite fish code was found: Minecraft's explosions in the water make fish burst out" : ("a piece of the game's dynamite fish code was not found, so Minecraft's explosions do not make fish (water " + (mWaterHeight != null) + ", fish table " + (mGetRandomItem != null && fWeights != null) + ", spawn " + (mSpawn != null) + ", dynamite " + (mExplosionInfo != null) + ")"))));
			}
			catch (Exception ex)
			{
				ok = false;
				Plugin.Log.LogWarning((object)("explosions: could not look up the game's dynamite fish code: " + ex.Message));
			}
		}

		private static object DynamiteInfo()
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			if (dynamiteInfo != null)
			{
				return dynamiteInfo;
			}
			Object[] array = Resources.FindObjectsOfTypeAll(tExplosive);
			foreach (Object val in array)
			{
				object obj = mExplosionInfo.Invoke(val, null);
				if (obj != null && (!(pHasUnderwater != null) || (bool)pHasUnderwater.GetValue(obj, null)))
				{
					dynamiteInfo = obj;
					Vector2Int val2 = (Vector2Int)pFishMinMax.GetValue(obj, null);
					Plugin.Log.LogInfo((object)("explosions: using '" + val.name + "': " + ((Vector2Int)(ref val2)).x + " to " + ((Vector2Int)(ref val2)).y + " fish, force radius " + ((float)pForceRadius.GetValue(obj, null)).ToString("0.0") + ", item force " + ((float)pItemForce.GetValue(obj, null)).ToString("0.0")));
					break;
				}
			}
			return dynamiteInfo;
		}

		public static int Burst(Vector3 at, float radiusBlocks, float surfaceMargin)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: 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_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: 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_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: 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_0292: 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_02a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_02af: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0370: Unknown result type (might be due to invalid IL or missing references)
			//IL_032a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0330: Unknown result type (might be due to invalid IL or missing references)
			//IL_033c: 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)
			Resolve();
			if (!ok || !HfApi.IsHost)
			{
				return 0;
			}
			try
			{
				float num = (float)mWaterHeight.Invoke(null, new object[1] { at });
				if (at.y >= num + surfaceMargin)
				{
					return 0;
				}
				object obj = DynamiteInfo();
				if (obj == null)
				{
					if (!warned)
					{
						warned = true;
						Plugin.Log.LogWarning((object)"explosions: the game's dynamite was not found, so no fish");
					}
					return 0;
				}
				object value = fCreatureMgr.GetValue(null);
				object value2 = fExplosionMgr.GetValue(null);
				if (value == null || value2 == null)
				{
					return 0;
				}
				object value3 = fWeights.GetValue(value2);
				Vector2Int val = (Vector2Int)pFishMinMax.GetValue(obj, null);
				float num2 = (float)pForceRadius.GetValue(obj, null);
				float num3 = (float)pItemForce.GetValue(obj, null);
				int num4 = Random.Range(((Vector2Int)(ref val)).x, ((Vector2Int)(ref val)).y);
				num4 = Mathf.Max(1, Mathf.RoundToInt((float)num4 * Mathf.Clamp(radiusBlocks / 3f, 0.5f, 2f)));
				float unscaledTime = Time.unscaledTime;
				budget = Mathf.Min(40f, budget + (unscaledTime - budgetAt) * 40f);
				budgetAt = unscaledTime;
				num4 = Mathf.Min(num4, Mathf.FloorToInt(budget));
				if (num4 <= 0)
				{
					return 0;
				}
				budget -= num4;
				Vector3 val2 = at;
				val2.y = num + 0.1f;
				int num5 = 0;
				for (int i = 0; i < num4; i++)
				{
					object obj2 = mGetRandomItem.Invoke(value, new object[2] { val2, value3 });
					if (obj2 == null)
					{
						continue;
					}
					object? value4 = pItemToSpawn.GetValue(obj2, null);
					Object val3 = (Object)((value4 is Object) ? value4 : null);
					if (val3 == (Object)null)
					{
						continue;
					}
					Vector3 val4 = Random.insideUnitSphere * num2 / 2f;
					val4.y = 0f;
					Vector3 val5 = val2 + val4;
					Object obj3 = Object.Instantiate(val3, val5, Quaternion.Euler(0f, (float)Random.Range(0, 360), 0f));
					Component val6 = (Component)(object)((obj3 is Component) ? obj3 : null);
					if (!((Object)(object)val6 == (Object)null))
					{
						object value5 = pCreature.GetValue(val6, null);
						if (value5 != null && mKill != null)
						{
							mKill.Invoke(value5, null);
						}
						mSpawn.Invoke(value2, new object[3]
						{
							val6.gameObject,
							null,
							(object)default(Scene)
						});
						Vector3 val7 = val5 - val2;
						Vector3 val8 = ((Vector3)(ref val7)).normalized * num3 * 0.15f;
						val8.y = Random.Range(0.8f, 1.2f) * Mathf.Abs(num3);
						object obj4 = ((pRigSync != null) ? pRigSync.GetValue(val6, null) : null);
						if (obj4 != null && mStartSim != null)
						{
							MethodInfo methodInfo = mStartSim;
							object[] array = new object[2];
							val7 = default(Vector3);
							array[0] = val7;
							array[1] = (object)default(Quaternion);
							methodInfo.Invoke(obj4, array);
						}
						object? value6 = pRig.GetValue(val6, null);
						Rigidbody val9 = (Rigidbody)((value6 is Rigidbody) ? value6 : null);
						if ((Object)(object)val9 != (Object)null)
						{
							val9.AddForce(val8);
						}
						num5++;
					}
				}
				return num5;
			}
			catch (Exception ex)
			{
				if (!warned)
				{
					warned = true;
					Plugin.Log.LogWarning((object)("explosions: making fish failed: " + ((ex.InnerException != null) ? ex.InnerException.Message : ex.Message)));
				}
				return 0;
			}
		}
	}
	internal static class FishArt
	{
		public const int Cod = 0;

		public const int Salmon = 1;

		public const int Tropical = 2;

		public const int Puffer = 3;

		public const int Count = 4;

		public const int W = 16;

		public const int H = 10;

		public static readonly string[] Names = new string[4] { "Raw Cod", "Raw Salmon", "Tropical Fish", "Pufferfish" };

		private static readonly string[][] Rows = new string[4][]
		{
			new string[10] { "................", "..F...AAAA......", "..FF.AAAAAAA....", ".FFFAAAAAAAAAA..", "FFFFAAAAAAAAEAA.", "FFFFAAAAAAAAAAAA", ".FFFBBBBBBBBBBA.", "..FF.BBBBBBBB...", "..F...BBBB......", "................" },
			new string[10] { "................", "................", "..F..AAAAAA.....", ".FFFAAAAAAAAAA..", "FFFFAAAAAAAAEAAA", "FFFFBBBBBBBBBBAA", ".FFF.BBBBBBBB.A.", "..F...BBBB......", "................", "................" },
			new string[10] { "................", "..F..AAKWKAA....", ".FFF.AAKWKAAAA..", "FFFFAAAKWKAAAAA.", "FFFFAAAKWKAAAEAA", "FFFFAAAKWKAAAAA.", ".FFF.AAKWKAAAA..", "..F..AAKWKAA....", "................", "................" },
			new string[10] { "................", "....S..S..S.....", "...SAAAAAAAAS...", "..AAAAAAAAAAAA..", ".SAAAAAAAAAEAAAS", ".SAAAAAAAAAAAAAS", "..BBBBBBBBBBBB..", "...SBBBBBBBBS...", "....S..S..S.....", "................" }
		};

		private static Color32 Pixel(int kind, char c)
		{
			//IL_001c: 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_0047: 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_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: 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_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			switch (c)
			{
			case 'E':
				return new Color32((byte)24, (byte)24, (byte)24, byte.MaxValue);
			case 'K':
				return new Color32((byte)40, (byte)30, (byte)30, byte.MaxValue);
			case 'W':
				return new Color32((byte)250, (byte)250, (byte)250, byte.MaxValue);
			default:
				switch (kind)
				{
				case 0:
					switch (c)
					{
					case 'A':
						return new Color32((byte)176, (byte)138, (byte)98, byte.MaxValue);
					case 'B':
						return new Color32((byte)214, (byte)190, (byte)156, byte.MaxValue);
					case 'F':
						return new Color32((byte)112, (byte)84, (byte)58, byte.MaxValue);
					}
					break;
				case 1:
					switch (c)
					{
					case 'A':
						return new Color32((byte)152, (byte)92, (byte)86, byte.MaxValue);
					case 'B':
						return new Color32((byte)226, (byte)150, (byte)128, byte.MaxValue);
					case 'F':
						return new Color32((byte)112, (byte)56, (byte)56, byte.MaxValue);
					}
					break;
				case 2:
					switch (c)
					{
					case 'A':
						return new Color32((byte)243, (byte)136, (byte)32, byte.MaxValue);
					case 'F':
						return new Color32((byte)214, (byte)98, (byte)20, byte.MaxValue);
					}
					break;
				case 3:
					switch (c)
					{
					case 'A':
						return new Color32((byte)232, (byte)204, (byte)64, byte.MaxValue);
					case 'B':
						return new Color32((byte)248, (byte)238, (byte)176, byte.MaxValue);
					case 'S':
						return new Color32((byte)196, (byte)152, (byte)40, byte.MaxValue);
					}
					break;
				}
				return new Color32((byte)0, (byte)0, (byte)0, (byte)0);
			}
		}

		public static Texture2D MakeTexture(int kind)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Expected O, but got Unknown
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			string[] array = Rows[kind];
			Color32[] array2 = (Color32[])(object)new Color32[160];
			for (int i = 0; i < 10; i++)
			{
				for (int j = 0; j < 16; j++)
				{
					array2[(9 - i) * 16 + j] = Pixel(kind, array[i][j]);
				}
			}
			Texture2D val = new Texture2D(16, 10, (TextureFormat)4, false)
			{
				filterMode = (FilterMode)0,
				wrapMode = (TextureWrapMode)1
			};
			val.SetPixels32(array2);
			val.Apply(false);
			return val;
		}
	}
	internal static class FishingEvents
	{
		public static string LastHooked = "";

		public static float HookedAt = -100f;

		private static bool installed;

		public static void Install()
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Expected O, but got Unknown
			if (installed)
			{
				return;
			}
			installed = true;
			try
			{
				Type type = AccessTools.TypeByName("CreatureManager");
				MethodInfo methodInfo = ((type != null) ? AccessTools.Method(type, "HookItem", (Type[])null, (Type[])null) : null);
				if (methodInfo == null)
				{
					Plugin.Log.LogInfo((object)"fishing events: CreatureManager.HookItem not found; catches will not be announced");
					return;
				}
				new Harmony("local.fishcraftlink.fishingevents").Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(FishingEvents).GetMethod("OnHook", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Plugin.Log.LogInfo((object)"fishing events: listening for hooked fish");
			}
			catch (Exception ex)
			{
				Plugin.Log.LogInfo((object)("fishing events could not start: " + ex.GetType().Name + ": " + ex.Message));
			}
		}

		private static void OnHook(object[] __args)
		{
			try
			{
				Object val = (Object)((__args != null && __args.Length != 0) ? /*isinst with value type is only supported in some contexts*/: null);
				LastHooked = ((val != (Object)null) ? val.name : "something").Replace("(Clone)", "").Replace("Prefab", "").Trim();
				HookedAt = Time.unscaledTime;
			}
			catch (Exception)
			{
			}
		}
	}
	internal static class FishingIcon
	{
		public const int Cols = 16;

		public const int Rows = 12;

		public const int Bits = 192;

		private static readonly string[] Vanilla = new string[12]
		{
			"................", ".............#..", "............#...", ".............#..", "............#...", "...........#....", "..........#...#.", ".........#....#.", "........#.....#.", ".......#......#.",
			"......#......#..", ".....###........"
		};

		public static bool[] DefaultMask()
		{
			bool[] array = new bool[192];
			for (int i = 0; i < 12; i++)
			{
				for (int j = 0; j < 16; j++)
				{
					array[i * 16 + j] = Vanilla[i][j] == '#';
				}
			}
			return array;
		}

		public static float Similarity(bool[] a, bool[] b)
		{
			int num = 0;
			int num2 = 0;
			for (int i = 0; i < 192; i++)
			{
				if (a[i] && b[i])
				{
					num++;
				}
				if (a[i] || b[i])
				{
					num2++;
				}
			}
			if (num2 != 0)
			{
				return (float)num / (float)num2;
			}
			return 0f;
		}

		public static string ToHex(bool[] m)
		{
			StringBuilder stringBuilder = new StringBuilder();
			for (int i = 0; i < 24; i++)
			{
				int num = 0;
				for (int j = 0; j < 8; j++)
				{
					if (m[i * 8 + j])
					{
						num |= 1 << j;
					}
				}
				stringBuilder.Append(num.ToString("x2"));
			}
			return stringBuilder.ToString();
		}

		public static bool[] FromHex(string s)
		{
			if (string.IsNullOrEmpty(s) || s.Length != 48)
			{
				return null;
			}
			bool[] array = new bool[192];
			try
			{
				for (int i = 0; i < 24; i++)
				{
					int num = Convert.ToInt32(s.Substring(i * 2, 2), 16);
					for (int j = 0; j < 8; j++)
					{
						array[i * 8 + j] = (num & (1 << j)) != 0;
					}
				}
				return array;
			}
			catch (Exception)
			{
				return null;
			}
		}
	}
	internal static class FishingScout
	{
		private static readonly HashSet<string> Words = new HashSet<string>
		{
			"fish", "fishing", "fisher", "fishes", "rod", "rods", "cast", "casting", "reel", "reeling",
			"bait", "baits", "bobber", "hook", "hooked", "catch", "catching", "caught", "lure", "tackle",
			"bite", "biting", "angler", "line"
		};

		private static readonly string[] SkipAssemblies = new string[20]
		{
			"System", "mscorlib", "netstandard", "Unity", "Mono.", "Microsoft", "BepInEx", "0Harmony", "MonoMod", "Mono",
			"Newtonsoft", "FishCraft", "Cinemachine", "Sirenix", "DOTween", "TextMeshPro", "Il2Cpp", "nunit", "ICSharpCode", "FishNet"
		};

		private const BindingFlags All = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;

		private static bool NameMatches(string name)
		{
			foreach (string item in WaterSystem.Tokens(name))
			{
				if (Words.Contains(item))
				{
					return true;
				}
			}
			return false;
		}

		private static bool Skippable(Assembly a)
		{
			string name = a.GetName().Name;
			string[] skipAssemblies = SkipAssemblies;
			foreach (string value in skipAssemblies)
			{
				if (name.StartsWith(value, StringComparison.Ordinal))
				{
					return true;
				}
			}
			return false;
		}

		private static Type[] SafeTypes(Assembly a)
		{
			try
			{
				return a.GetTypes();
			}
			catch (ReflectionTypeLoadException ex)
			{
				List<Type> list = new List<Type>();
				Type[] types = ex.Types;
				foreach (Type type in types)
				{
					if (type != null)
					{
						list.Add(type);
					}
				}
				return list.ToArray();
			}
			catch (Exception)
			{
				return new Type[0];
			}
		}

		private static string Sig(MethodInfo m)
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append(m.ReturnType.Name).Append(' ').Append(m.Name)
				.Append('(');
			ParameterInfo[] parameters = m.GetParameters();
			for (int i = 0; i < parameters.Length; i++)
			{
				if (i > 0)
				{
					stringBuilder.Append(", ");
				}
				stringBuilder.Append(parameters[i].ParameterType.Name).Append(' ').Append(parameters[i].Name);
			}
			stringBuilder.Append(')');
			if (m.IsStatic)
			{
				stringBuilder.Append(" [static]");
			}
			return stringBuilder.ToString();
		}

		private static bool Simple(Type t)
		{
			if (!t.IsPrimitive && !t.IsEnum && !(t == typeof(string)) && !(t == typeof(Vector3)))
			{
				return t == typeof(Vector2);
			}
			return true;
		}

		public static void Run(bool live)
		{
			//IL_0463: Unknown result type (might be due to invalid IL or missing references)
			//IL_0468: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				int num = 0;
				Plugin.Log.LogInfo((object)("=== fishing scout (" + (live ? "with live values" : "names only") + ") ==="));
				List<Type> list = new List<Type>();
				List<string> list2 = new List<string>();
				Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
				foreach (Assembly a in assemblies)
				{
					if (Skippable(a))
					{
						continue;
					}
					Type[] array = SafeTypes(a);
					foreach (Type type in array)
					{
						if (type == null)
						{
							continue;
						}
						if (NameMatches(type.Name))
						{
							list.Add(type);
						}
						else
						{
							if (!type.IsClass || type.IsGenericTypeDefinition)
							{
								continue;
							}
							MethodInfo[] methods;
							try
							{
								methods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
							}
							catch (Exception)
							{
								continue;
							}
							MethodInfo[] array2 = methods;
							foreach (MethodInfo methodInfo in array2)
							{
								if (NameMatches(methodInfo.Name) && list2.Count < 60)
								{
									list2.Add(type.FullName + "." + Sig(methodInfo));
								}
							}
						}
					}
				}
				List<Type> list3 = new List<Type>();
				foreach (Type item in list)
				{
					Type baseType = item.BaseType;
					while (baseType != null && !Skippable(baseType.Assembly))
					{
						if (!list.Contains(baseType) && !list3.Contains(baseType))
						{
							list3.Add(baseType);
						}
						baseType = baseType.BaseType;
					}
				}
				list.AddRange(list3);
				Plugin.Log.LogInfo((object)("fishing-related classes: " + list.Count));
				for (int l = 0; l < list.Count && l < 45; l++)
				{
					Type type2 = list[l];
					Plugin.Log.LogInfo((object)("class " + type2.FullName + " : " + ((type2.BaseType != null) ? type2.BaseType.Name : "-") + " (" + type2.Assembly.GetName().Name + ")"));
					try
					{
						FieldInfo[] fields = type2.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
						for (int m = 0; m < fields.Length && m < 40; m++)
						{
							Plugin.Log.LogInfo((object)("    field " + fields[m].FieldType.Name + " " + fields[m].Name + (fields[m].IsStatic ? " [static]" : "")));
						}
						MethodInfo[] methods2 = type2.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
						int num2 = 0;
						MethodInfo[] array2 = methods2;
						foreach (MethodInfo methodInfo2 in array2)
						{
							if (!methodInfo2.IsSpecialName)
							{
								if (num2++ >= 60)
								{
									break;
								}
								Plugin.Log.LogInfo((object)("    method " + Sig(methodInfo2)));
							}
						}
					}
					catch (Exception ex2)
					{
						Plugin.Log.LogInfo((object)("    (could not list members: " + ex2.GetType().Name + ")"));
					}
					if (++num > 400)
					{
						break;
					}
				}
				Plugin.Log.LogInfo((object)("methods named like cast/reel/catch/hook elsewhere: " + list2.Count));
				foreach (string item2 in list2)
				{
					Plugin.Log.LogInfo((object)("  " + item2));
				}
				if (live)
				{
					foreach (Type item3 in list)
					{
						if (!typeof(Component).IsAssignableFrom(item3))
						{
							continue;
						}
						Object[] array3;
						try
						{
							array3 = Resources.FindObjectsOfTypeAll(item3);
						}
						catch (Exception)
						{
							continue;
						}
						int num3 = 0;
						Object[] array4 = array3;
						foreach (Object val in array4)
						{
							Component val2 = (Component)(object)((val is Component) ? val : null);
							if ((Object)(object)val2 == (Object)null)
							{
								continue;
							}
							Scene scene = val2.gameObject.scene;
							if (!((Scene)(ref scene)).IsValid())
							{
								continue;
							}
							if (num3++ >= 3)
							{
								break;
							}
							StringBuilder stringBuilder = new StringBuilder();
							stringBuilder.Append("live ").Append(item3.Name).Append(" on '")
								.Append(((Object)val2.gameObject).name)
								.Append("' (active ")
								.Append(val2.gameObject.activeInHierarchy)
								.Append("):");
							int num4 = 0;
							Type type3 = item3;
							while (type3 != null && !Skippable(type3.Assembly))
							{
								FieldInfo[] fields2 = type3.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
								foreach (FieldInfo fieldInfo in fields2)
								{
									if (!fieldInfo.IsStatic && Simple(fieldInfo.FieldType))
									{
										if (num4++ >= 60)
										{
											break;
										}
										object value = null;
										try
										{
											value = fieldInfo.GetValue(val);
										}
										catch (Exception)
										{
										}
										stringBuilder.Append(' ').Append(fieldInfo.Name).Append('=')
											.Append(value);
									}
								}
								type3 = type3.BaseType;
							}
							Plugin.Log.LogInfo((object)stringBuilder.ToString());
							if (!(item3.Name == "Bait") && !(item3.Name == "FishingRod"))
							{
								continue;
							}
							Renderer[] componentsInChildren = val2.GetComponentsInChildren<Renderer>(true);
							for (int n = 0; n < componentsInChildren.Length && n < 10; n++)
							{
								Renderer val3 = componentsInChildren[n];
								string text = "";
								if (((object)val3).GetType().Name == "LineRenderer")
								{
									PropertyInfo property = ((object)val3).GetType().GetProperty("positionCount");
									if (property != null)
									{
										text = " points=" + property.GetValue(val3, null);
									}
								}
								Plugin.Log.LogInfo((object)("    renderer '" + ((Object)val3).name + "' " + ((object)val3).GetType().Name + " enabled=" + val3.enabled + " hiddenByForce=" + val3.forceRenderingOff + " visibleToACamera=" + val3.isVisible + " layer=" + ((Component)val3).gameObject.layer + " shader=" + (((Object)(object)val3.sharedMaterial != (Object)null && (Object)(object)val3.sharedMaterial.shader != (Object)null) ? ((Object)val3.sharedMaterial.shader).name : "-") + text));
							}
						}
					}
				}
				Plugin.Log.LogInfo((object)"=== end of fishing scout ===");
			}
			catch (Exception ex5)
			{
				Plugin.Log.LogInfo((object)("fishing scout failed: " + ex5.GetType().Name + ": " + ex5.Message));
			}
		}
	}
	internal sealed class FishingVisuals : IDisposable
	{
		private Type baitType;

		private Type rodType;

		private readonly List<Component> baits = new List<Component>();

		private readonly List<Component> rods = new List<Component>();

		private readonly List<Renderer> tmpR = new List<Renderer>();

		private float nextRefresh;

		private GameObject bobberRed;

		private GameObject bobberWhite;

		private GameObject ringGo;

		private GameObject lineGo;

		private Mesh lineMesh;

		private Material redMat;

		private Material whiteMat;

		private Material lineMat;

		private Material ringMat;

		private Texture2D ringTex;

		private const int Seg = 10;

		private readonly Vector3[] lineV = (Vector3[])(object)new Vector3[22];

		private readonly Vector2[] lineUv = (Vector2[])(object)new Vector2[22];

		private readonly int[] lineI = new int[120];

		private bool wasUnder;

		private float splashAt = -10f;

		private Vector3 splashPos;

		private bool simActive;

		private Vector3 simBobber;

		private float simDip;

		public float TipU = 0.915f;

		public float TipV = 0.455f;

		private readonly List<Renderer> gameHidden = new List<Renderer>();

		private float nextGameScan;

		public void SetSimulated(bool active, Vector3 bobber, float dip)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			simActive = active;
			simBobber = bobber;
			simDip = dip;
		}

		public void Splash(Vector3 position)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			splashAt = Time.time;
			splashPos = position;
		}

		private static void SetColor(Material m, Color c)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			if (m.HasProperty("_BaseColor"))
			{
				m.SetColor("_BaseColor", c);
			}
			if (m.HasProperty("_Color"))
			{
				m.SetColor("_Color", c);
			}
		}

		private static Material MakeMat(Material template, Texture tex, Color c)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			Material val = new Material(template);
			val.mainTexture = tex;
			if (val.HasProperty("_BaseMap"))
			{
				val.SetTexture("_BaseMap", tex);
			}
			SetColor(val, c);
			return val;
		}

		private static GameObject Primitive(PrimitiveType type, string name, Material mat)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = GameObject.CreatePrimitive(type);
			((Object)obj).name = name;
			Collider component = obj.GetComponent<Collider>();
			if ((Object)(object)component != (Object)null)
			{
				Object.Destroy((Object)(object)component);
			}
			MeshRenderer component2 = obj.GetComponent<MeshRenderer>();
			((Renderer)component2).sharedMaterial = mat;
			((Renderer)component2).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)component2).receiveShadows = false;
			return obj;
		}

		private bool Build(Material template)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: 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_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: 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_0237: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: Expected O, but got Unknown
			//IL_0062: 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_00b8: 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_0282: Unknown result type (might be due to invalid IL or missing references)
			//IL_029a: Unknown result type (might be due to invalid IL or missing references)
			//IL_029f: 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_03c9: Expected O, but got Unknown
			if ((Object)(object)bobberRed != (Object)null)
			{
				return true;
			}
			if ((Object)(object)template == (Object)null)
			{
				return false;
			}
			ringTex = new Texture2D(64, 64, (TextureFormat)4, false);
			((Texture)ringTex).wrapMode = (TextureWrapMode)1;
			for (int i = 0; i < 64; i++)
			{
				for (int j = 0; j < 64; j++)
				{
					float num = Vector2.Distance(new Vector2(((float)j + 0.5f) / 64f, ((float)i + 0.5f) / 64f), new Vector2(0.5f, 0.5f)) / 0.5f;
					float num2 = Mathf.Clamp01(1f - Mathf.Abs(num - 0.8f) / 0.14f);
					ringTex.SetPixel(j, i, new Color(1f, 1f, 1f, num2));
				}
			}
			ringTex.Apply(false);
			redMat = MakeMat(template, (Texture)(object)Texture2D.whiteTexture, new Color(0.95f, 0.1f, 0.1f, 1f));
			whiteMat = MakeMat(template, (Texture)(object)Texture2D.whiteTexture, new Color(1f, 1f, 1f, 1f));
			lineMat = MakeMat(template, (Texture)(object)Texture2D.whiteTexture, new Color(0.07f, 0.07f, 0.07f, 0.95f));
			ringMat = MakeMat(template, (Texture)(object)ringTex, new Color(1f, 1f, 1f, 0.8f));
			bobberRed = Primitive((PrimitiveType)0, "FishCraft bobber", redMat);
			bobberWhite = Primitive((PrimitiveType)0, "FishCraft bobber base", whiteMat);
			bobberRed.transform.localScale = Vector3.one * 0.12f;
			bobberWhite.transform.localScale = Vector3.one * 0.1f;
			ringGo = Primitive((PrimitiveType)5, "FishCraft splash ring", ringMat);
			ringGo.transform.rotation = Quaternion.Euler(90f, 0f, 0f);
			lineMesh = new Mesh();
			((Object)lineMesh).name = "FishCraft fishing line";
			lineMesh.MarkDynamic();
			for (int k = 0; k <= 10; k++)
			{
				float num3 = (float)k / 10f;
				lineUv[k * 2] = new Vector2(0f, num3);
				lineUv[k * 2 + 1] = new Vector2(1f, num3);
			}
			for (int l = 0; l < 10; l++)
			{
				int num4 = l * 2;
				int num5 = l * 12;
				lineI[num5] = num4;
				lineI[num5 + 1] = num4 + 2;
				lineI[num5 + 2] = num4 + 1;
				lineI[num5 + 3] = num4 + 1;
				lineI[num5 + 4] = num4 + 2;
				lineI[num5 + 5] = num4 + 3;
				lineI[num5 + 6] = num4;
				lineI[num5 + 7] = num4 + 1;
				lineI[num5 + 8] = num4 + 2;
				lineI[num5 + 9] = num4 + 1;
				lineI[num5 + 10] = num4 + 3;
				lineI[num5 + 11] = num4 + 2;
			}
			lineMesh.vertices = (Vector3[])(object)new Vector3[22];
			lineMesh.uv = lineUv;
			lineMesh.triangles = lineI;
			lineGo = new GameObject("FishCraft fishing line");
			lineGo.AddComponent<MeshFilter>().sharedMesh = lineMesh;
			MeshRenderer obj = lineGo.AddComponent<MeshRenderer>();
			((Renderer)obj).sharedMaterial = lineMat;
			((Renderer)obj).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)obj).receiveShadows = false;
			HideAll();
			return true;
		}

		private static void Collect(Type t, List<Component> into)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			into.Clear();
			if (t == null)
			{
				return;
			}
			Object[] array = Resources.FindObjectsOfTypeAll(t);
			foreach (Object obj in array)
			{
				Component val = (Component)(object)((obj is Component) ? obj : null);
				if ((Object)(object)val != (Object)null)
				{
					Scene scene = val.gameObject.scene;
					if (((Scene)(ref scene)).IsValid())
					{
						into.Add(val);
					}
				}
			}
		}

		private void RefreshComponents()
		{
			if (!(Time.unscaledTime < nextRefresh))
			{
				nextRefresh = Time.unscaledTime + 1f;
				if (baitType == null)
				{
					baitType = AccessTools.TypeByName("Bait");
				}
				if (rodType == null)
				{
					rodType = AccessTools.TypeByName("FishingRod");
				}
				Collect(baitType, baits);
				Collect(rodType, rods);
			}
		}

		private static Component ActiveOf(List<Component> list)
		{
			for (int i = 0; i < list.Count; i++)
			{
				if ((Object)(object)list[i] != (Object)null && list[i].gameObject.activeInHierarchy)
				{
					return list[i];
				}
			}
			return null;
		}

		public Component ActiveRod()
		{
			RefreshComponents();
			return ActiveOf(rods);
		}

		private Vector3 TipOf(Camera cam)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			return cam.ViewportToWorldPoint(new Vector3(TipU, TipV, 0.6f));
		}

		public void HideGameRod(bool hide)
		{
			if (!hide)
			{
				RestoreGameRod();
				return;
			}
			RefreshComponents();
			if (!(Time.unscaledTime < nextGameScan))
			{
				nextGameScan = Time.unscaledTime + 0.5f;
				HideIn(rods);
				HideIn(baits);
			}
		}

		private void HideIn(List<Component> comps)
		{
			for (int i = 0; i < comps.Count; i++)
			{
				Component val = comps[i];
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				val.GetComponentsInChildren<Renderer>(true, tmpR);
				for (int j = 0; j < tmpR.Count; j++)
				{
					Renderer val2 = tmpR[j];
					if (!((Object)(object)val2 == (Object)null) && !val2.forceRenderingOff && !(((object)val2).GetType().Name == "ParticleSystemRenderer"))
					{
						val2.forceRenderingOff = true;
						gameHidden.Add(val2);
					}
				}
			}
		}

		public void RestoreGameRod()
		{
			for (int i = 0; i < gameHidden.Count; i++)
			{
				if ((Object)(object)gameHidden[i] != (Object)null)
				{
					gameHidden[i].forceRenderingOff = false;
				}
			}
			gameHidden.Clear();
		}

		public void HideAll()
		{
			if ((Object)(object)bobberRed != (Object)null)
			{
				bobberRed.SetActive(false);
			}
			if ((Object)(object)bobberWhite != (Object)null)
			{
				bobberWhite.SetActive(false);
			}
			if ((Object)(object)ringGo != (Object)null)
			{
				ringGo.SetActive(false);
			}
			if ((Object)(object)lineGo != (Object)null)
			{
				lineGo.SetActive(false);
			}
		}

		public void Tick(bool want, Camera cam, WaterSystem water, float units, Material template)
		{
			//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_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: 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_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: 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_0156: 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_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0235: Unknown result type (might be due to invalid IL or missing references)
			//IL_023a: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: 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_024f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0251: Unknown result type (might be due to invalid IL or missing references)
			//IL_0254: 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_0272: Unknown result type (might be due to invalid IL or missing references)
			//IL_0277: 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_027e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0280: Unknown result type (might be due to invalid IL or missing references)
			//IL_0282: Unknown result type (might be due to invalid IL or missing references)
			//IL_0284: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_028e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_029e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ca: Unknown result type (might be due to invali