Decompiled source of RavenPost v1.2.1

plugins/RavenPost.dll

Decompiled 16 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[assembly: AssemblyCompany("RavenPost")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.2.1.0")]
[assembly: AssemblyInformationalVersion("1.2.1+8d1a4f08d0304d348a00e83ec809b52a9c363672")]
[assembly: AssemblyProduct("RavenPost")]
[assembly: AssemblyTitle("RavenPost")]
[assembly: AssemblyVersion("1.2.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace RavenPost
{
	internal static class LetterItem
	{
		private class LetterWriter : TextReceiver
		{
			private readonly Player _player;

			private readonly ItemData _item;

			private readonly bool _reopen;

			public LetterWriter(Player player, ItemData item, bool reopen)
			{
				_player = player;
				_item = item;
				_reopen = reopen;
			}

			public string GetText()
			{
				return LetterItem.GetText(_item).Replace("\n", "\\n");
			}

			public void SetText(string text)
			{
				if (Object.op_Implicit((Object)(object)_player) && ((Humanoid)_player).GetInventory().ContainsItem(_item))
				{
					LetterItem.SetText(_item, text, _player.GetPlayerName());
					((Character)_player).Message((MessageType)2, string.IsNullOrEmpty(text) ? "Letter cleared" : "Letter written", 0, (Sprite)null, false);
					if (_reopen && Object.op_Implicit((Object)(object)InventoryGui.instance))
					{
						InventoryGui.instance.Show((Container)null, 1);
					}
				}
			}
		}

		public const string PrefabName = "RavenLetter";

		public const int MaxLength = 500;

		private const string TextKey = "ravenpost_text";

		private const string AuthorKey = "ravenpost_author";

		private const string DayKey = "ravenpost_day";

		private const string FromKey = "ravenpost_from";

		private const string AuthorIdKey = "ravenpost_authorid";

		private const string ReadOnlyId = "locked";

		private static SharedData s_shared;

		private static string LocalPlayerId()
		{
			if (!Object.op_Implicit((Object)(object)Game.instance))
			{
				return "";
			}
			return Game.instance.GetPlayerProfile().GetPlayerID().ToString();
		}

		public static bool CanEdit(ItemData item)
		{
			if (!item.m_customData.TryGetValue("ravenpost_authorid", out var value) || string.IsNullOrEmpty(value))
			{
				return true;
			}
			if (value != "locked")
			{
				return value == LocalPlayerId();
			}
			return false;
		}

		public static void Register()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Expected O, but got Unknown
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Expected O, but got Unknown
			ItemConfig val = new ItemConfig();
			val.Name = "Letter";
			val.Description = "Write on it, keep it as a journal, or send it with a raven.";
			val.CraftingStation = "piece_workbench";
			val.Amount = 2;
			val.Icon = CreateIcon();
			val.Requirements = (RequirementConfig[])(object)new RequirementConfig[2]
			{
				new RequirementConfig("LeatherScraps", 1, 0, true),
				new RequirementConfig("Coal", 1, 0, true)
			};
			ItemConfig val2 = val;
			CustomItem val3 = new CustomItem("RavenLetter", "LeatherScraps", val2);
			SharedData shared = val3.ItemDrop.m_itemData.m_shared;
			shared.m_maxStackSize = 1;
			shared.m_weight = 0.1f;
			shared.m_teleportable = true;
			s_shared = shared;
			ItemManager.Instance.AddItem(val3);
		}

		public static bool IsLetter(ItemData item)
		{
			if (item != null)
			{
				if (!Object.op_Implicit((Object)(object)item.m_dropPrefab) || !(((Object)item.m_dropPrefab).name == "RavenLetter"))
				{
					if (s_shared != null)
					{
						return item.m_shared == s_shared;
					}
					return false;
				}
				return true;
			}
			return false;
		}

		public static string GetText(ItemData item)
		{
			if (!item.m_customData.TryGetValue("ravenpost_text", out var value))
			{
				return "";
			}
			return value;
		}

		public static void SetText(ItemData item, string text, string author)
		{
			text = (text ?? "").Trim();
			if (text.Length > 500)
			{
				text = text.Substring(0, 500);
			}
			item.m_customData["ravenpost_text"] = text;
			item.m_customData["ravenpost_author"] = author ?? "";
			item.m_customData["ravenpost_day"] = RavenMail.Day(PostOffice.Now).ToString();
			item.m_customData["ravenpost_authorid"] = ((text.Length > 0) ? LocalPlayerId() : "");
		}

		public static string Tooltip(ItemData item)
		{
			string text = GetText(item);
			if (string.IsNullOrEmpty(text))
			{
				return "\n\n<color=grey>Blank - use it to write.</color>";
			}
			item.m_customData.TryGetValue("ravenpost_author", out var value);
			item.m_customData.TryGetValue("ravenpost_day", out var value2);
			item.m_customData.TryGetValue("ravenpost_from", out var value3);
			string text2 = (string.IsNullOrEmpty(value) ? "" : ("From " + value));
			if (!string.IsNullOrEmpty(value3))
			{
				text2 = text2 + " @ " + value3;
			}
			string text3 = (string.IsNullOrEmpty(value2) ? "" : ("Day " + value2));
			string text4 = string.Join(", ", new string[2] { text2, text3 }.Where((string s) => s.Length > 0));
			string value4;
			bool flag = item.m_customData.TryGetValue("ravenpost_authorid", out value4) && value4 == "locked";
			string text5 = (CanEdit(item) ? "Use it to edit." : (flag ? "A kept letter can't be changed." : "Only the author can change it."));
			return "\n\n<color=orange>" + text4 + "</color>\n<color=#e8dcc0>" + Escape(text) + "</color>\n\n<color=grey>" + text5 + "</color>";
		}

		private static string Escape(string text)
		{
			return text.Replace("<", "<\u200b");
		}

		public static bool GiveCopy(Player player, Letter letter)
		{
			GameObject val = (Object.op_Implicit((Object)(object)ObjectDB.instance) ? ObjectDB.instance.GetItemPrefab("RavenLetter") : null);
			ItemDrop val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent<ItemDrop>() : null);
			if (!Object.op_Implicit((Object)(object)player) || !Object.op_Implicit((Object)(object)val2))
			{
				return false;
			}
			ItemData val3 = val2.m_itemData.Clone();
			val3.m_stack = 1;
			val3.m_dropPrefab = val;
			val3.m_customData["ravenpost_text"] = letter.Text ?? "";
			val3.m_customData["ravenpost_author"] = letter.FromPlayer ?? "";
			val3.m_customData["ravenpost_from"] = letter.From ?? "";
			val3.m_customData["ravenpost_day"] = RavenMail.Day(letter.SentAt).ToString();
			val3.m_customData["ravenpost_authorid"] = "locked";
			Inventory inventory = ((Humanoid)player).GetInventory();
			if (!inventory.CanAddItem(val3, -1) || !inventory.AddItem(val3))
			{
				((Character)player).Message((MessageType)2, "Your bag is full", 0, (Sprite)null, false);
				return false;
			}
			((Character)player).Message((MessageType)2, "Letter added to your bag", 0, (Sprite)null, false);
			return true;
		}

		public static void OpenWriter(Player player, ItemData item)
		{
			if (!Object.op_Implicit((Object)(object)TextInput.instance))
			{
				return;
			}
			if (!CanEdit(item))
			{
				item.m_customData.TryGetValue("ravenpost_author", out var value);
				string value2;
				bool flag = item.m_customData.TryGetValue("ravenpost_authorid", out value2) && value2 == "locked";
				((Character)player).Message((MessageType)2, (flag || string.IsNullOrEmpty(value)) ? "This letter can't be changed" : ("Only " + value + " can change this letter"), 0, (Sprite)null, false);
				return;
			}
			bool flag2 = InventoryGui.IsVisible();
			if (flag2)
			{
				InventoryGui.instance.Hide();
			}
			TextInput.instance.RequestText((TextReceiver)(object)new LetterWriter(player, item, flag2), "Write your letter  (type \\\u200bn for a new line)", 500);
		}

		private static Sprite CreateIcon()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: 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_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: 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_017f: 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_0181: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false);
			Color val2 = default(Color);
			((Color)(ref val2))..ctor(0f, 0f, 0f, 0f);
			Color val3 = default(Color);
			((Color)(ref val3))..ctor(0.87f, 0.78f, 0.58f);
			Color val4 = default(Color);
			((Color)(ref val4))..ctor(0.62f, 0.5f, 0.32f);
			Color val5 = default(Color);
			((Color)(ref val5))..ctor(0.55f, 0.41f, 0.24f);
			Color val6 = default(Color);
			((Color)(ref val6))..ctor(0.72f, 0.57f, 0.36f);
			Color val7 = default(Color);
			((Color)(ref val7))..ctor(0.25f, 0.17f, 0.1f);
			Color val8 = default(Color);
			((Color)(ref val8))..ctor(0.66f, 0.1f, 0.08f);
			Color val9 = default(Color);
			((Color)(ref val9))..ctor(0.85f, 0.25f, 0.18f);
			for (int i = 0; i < 64; i++)
			{
				for (int j = 0; j < 64; j++)
				{
					Color val10 = val2;
					if (j >= 12 && j <= 51 && i >= 9 && i <= 54)
					{
						val10 = ((j == 12 || j == 51) ? val4 : val3);
						if (j >= 17 && j <= 46 && (i == 42 || i == 36 || i == 30 || i == 24) && (i != 24 || j <= 36))
						{
							val10 = val7;
						}
					}
					if (j >= 8 && j <= 55 && ((i >= 52 && i <= 58) || (i >= 5 && i <= 11)))
					{
						int num = ((i >= 52) ? 55 : 8);
						val10 = ((Mathf.Abs(i - num) <= 1) ? val6 : val5);
					}
					float num2 = j - 44;
					float num3 = i - 17;
					float num4 = Mathf.Sqrt(num2 * num2 + num3 * num3);
					if (num4 <= 6.5f)
					{
						val10 = ((num4 <= 3f) ? val9 : val8);
					}
					val.SetPixel(j, i, val10);
				}
			}
			val.Apply();
			((Texture)val).filterMode = (FilterMode)1;
			return Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f));
		}
	}
	[HarmonyPatch(typeof(Container), "GetHoverText")]
	internal static class ContainerHoverTextPatch
	{
		private static void Postfix(Container __instance, ref string __result)
		{
			RavenPerch component = ((Component)__instance).GetComponent<RavenPerch>();
			if (Object.op_Implicit((Object)(object)component))
			{
				__result += component.GetExtraHoverText();
			}
		}
	}
	[HarmonyPatch(typeof(Game), "Start")]
	internal static class GameStartPatch
	{
		private static void Postfix()
		{
			RavenNet.Register();
		}
	}
	[HarmonyPatch(typeof(Humanoid), "UseItem")]
	internal static class LetterUsePatch
	{
		private static bool Prefix(Humanoid __instance, Inventory inventory, ItemData item)
		{
			if (LetterItem.IsLetter(item))
			{
				Player val = (Player)(object)((__instance is Player) ? __instance : null);
				if (val != null && !((Object)(object)val != (Object)(object)Player.m_localPlayer))
				{
					if (inventory != null && inventory != ((Humanoid)val).GetInventory())
					{
						return true;
					}
					LetterItem.OpenWriter(val, item);
					return false;
				}
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(ItemData), "GetTooltip", new Type[]
	{
		typeof(ItemData),
		typeof(int),
		typeof(bool),
		typeof(float),
		typeof(int),
		typeof(bool)
	})]
	internal static class LetterTooltipPatch
	{
		private static void Postfix(ItemData item, ref string __result)
		{
			if (LetterItem.IsLetter(item))
			{
				__result += LetterItem.Tooltip(item);
			}
		}
	}
	[HarmonyPatch(typeof(Container), "Awake")]
	internal static class ContainerAwakePatch
	{
		private static void Prefix(Container __instance)
		{
			if (Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<RavenPerch>()))
			{
				ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
				ZDO val = (Object.op_Implicit((Object)(object)component) ? component.GetZDO() : null);
				int index = ((val != null) ? val.GetInt("ravenpost_tier", 0) : 0);
				RavenPerch.ApplyTier(__instance, PerchTiers.Get(index));
			}
		}
	}
	[HarmonyPatch(typeof(Container), "UseItem")]
	internal static class ContainerUseItemPatch
	{
		private static bool Prefix(Container __instance, Humanoid user, ItemData item, ref bool __result)
		{
			RavenPerch component = ((Component)__instance).GetComponent<RavenPerch>();
			if (Object.op_Implicit((Object)(object)component))
			{
				Player val = (Player)(object)((user is Player) ? user : null);
				if (val != null)
				{
					__result = component.Feed(val, item);
					return false;
				}
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(Container), "CanBeRemoved")]
	internal static class ContainerCanBeRemovedPatch
	{
		private static void Postfix(Container __instance, ref bool __result)
		{
			if (__result && Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<RavenPerch>()))
			{
				ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
				if (Object.op_Implicit((Object)(object)component) && component.IsValid() && PostOffice.ReadInbox(component.GetZDO()).Count > 0)
				{
					__result = false;
				}
			}
		}
	}
	internal static class PerchModel
	{
		private static readonly string[] s_poleCandidates = new string[3] { "wood_pole2", "wood_pole", "wood_pole_log" };

		private const float PoleHeight = 1.7f;

		private const float PoleThickness = 0.2f;

		private const float BirdScale = 1f;

		public static void Decorate(GameObject perch)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			Bounds chestBounds = LocalBounds(perch, perch.transform);
			Vector3? poleTop = AddPole(perch, chestBounds);
			AddBird(perch, poleTop);
		}

		private static Vector3? AddPole(GameObject perch, Bounds chestBounds)
		{
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: 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_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_021d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_0224: 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_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0249: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_025f: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = null;
			string[] array = s_poleCandidates;
			foreach (string text in array)
			{
				val = PrefabManager.Instance.GetPrefab(text);
				if (Object.op_Implicit((Object)(object)val))
				{
					Plugin.Log.LogInfo((object)("Perch post uses prefab '" + text + "'"));
					break;
				}
			}
			if (!Object.op_Implicit((Object)(object)val))
			{
				Plugin.Log.LogWarning((object)"No wooden pole prefab found; perch keeps the plain chest look.");
				return null;
			}
			WearNTear component = val.GetComponent<WearNTear>();
			GameObject val2 = Object.Instantiate<GameObject>((Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.m_new)) ? component.m_new : val, perch.transform);
			((Object)val2).name = "RavenPost_Pole";
			val2.SetActive(true);
			MonoBehaviour[] componentsInChildren = val2.GetComponentsInChildren<MonoBehaviour>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
			}
			val2.transform.localPosition = Vector3.zero;
			val2.transform.localRotation = Quaternion.identity;
			val2.transform.localScale = Vector3.one;
			Bounds val3 = LocalBounds(val2, perch.transform);
			if (((Bounds)(ref val3)).size.y < 0.01f)
			{
				Object.DestroyImmediate((Object)(object)val2);
				return null;
			}
			float num = Mathf.Max(new float[3]
			{
				((Bounds)(ref val3)).size.x,
				((Bounds)(ref val3)).size.z,
				0.01f
			});
			float num2 = 0.2f / num;
			val2.transform.localScale = new Vector3(num2, 1.7f / ((Bounds)(ref val3)).size.y, num2);
			val3 = LocalBounds(val2, perch.transform);
			Vector3 val4 = default(Vector3);
			((Vector3)(ref val4))..ctor(((Bounds)(ref chestBounds)).max.x + ((Bounds)(ref val3)).extents.x + 0.05f - ((Bounds)(ref val3)).center.x, ((Bounds)(ref chestBounds)).min.y - ((Bounds)(ref val3)).min.y, ((Bounds)(ref chestBounds)).center.z - ((Bounds)(ref val3)).center.z);
			Transform transform = val2.transform;
			transform.localPosition += val4;
			val3 = LocalBounds(val2, perch.transform);
			return new Vector3(((Bounds)(ref val3)).center.x, ((Bounds)(ref val3)).max.y, ((Bounds)(ref val3)).center.z);
		}

		private static void AddBird(GameObject perch, Vector3? poleTop)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: 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_0079: 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_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: 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_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: 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)
			GameObject perchedTemplate = RavenFlight.PerchedTemplate;
			if (Object.op_Implicit((Object)(object)perchedTemplate))
			{
				GameObject obj = Object.Instantiate<GameObject>(perchedTemplate, perch.transform);
				((Object)obj).name = "RavenPost_PerchedRaven";
				obj.SetActive(true);
				obj.transform.localRotation = Quaternion.identity;
				obj.transform.localScale = perchedTemplate.transform.localScale * 1f;
				obj.transform.localPosition = Vector3.zero;
				Bounds val = LocalBounds(obj, perch.transform);
				Vector3 value = default(Vector3);
				if (poleTop.HasValue)
				{
					value = poleTop.Value;
				}
				else
				{
					Bounds val2 = LocalBounds(perch, perch.transform);
					((Vector3)(ref value))..ctor(((Bounds)(ref val2)).center.x, ((Bounds)(ref val2)).max.y, ((Bounds)(ref val2)).center.z);
				}
				obj.transform.localPosition = value - new Vector3(((Bounds)(ref val)).center.x, ((Bounds)(ref val)).min.y, ((Bounds)(ref val)).center.z);
			}
		}

		public static Bounds LocalBounds(GameObject part, Transform space)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			bool any = false;
			Bounds result = default(Bounds);
			Matrix4x4 toSpace = space.worldToLocalMatrix;
			MeshFilter[] componentsInChildren = part.GetComponentsInChildren<MeshFilter>(true);
			foreach (MeshFilter val in componentsInChildren)
			{
				if (Object.op_Implicit((Object)(object)((Component)val).GetComponent<MeshRenderer>()) && IsShown(((Component)val).transform, part.transform))
				{
					Add(val.sharedMesh, ((Component)val).transform);
				}
			}
			SkinnedMeshRenderer[] componentsInChildren2 = part.GetComponentsInChildren<SkinnedMeshRenderer>(true);
			foreach (SkinnedMeshRenderer val2 in componentsInChildren2)
			{
				if (IsShown(((Component)val2).transform, part.transform))
				{
					Add(val2.sharedMesh, ((Component)val2).transform);
				}
			}
			return result;
			void Add(Mesh mesh, Transform t)
			{
				//IL_000a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				//IL_0015: Unknown result type (might be due to invalid IL or missing references)
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0021: Unknown result type (might be due to invalid IL or missing references)
				//IL_0028: Unknown result type (might be due to invalid IL or missing references)
				//IL_002f: 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_0057: Unknown result type (might be due to invalid IL or missing references)
				//IL_005c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0061: 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_0065: 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_0095: Unknown result type (might be due to invalid IL or missing references)
				//IL_0075: Unknown result type (might be due to invalid IL or missing references)
				//IL_0077: Unknown result type (might be due to invalid IL or missing references)
				//IL_007c: 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)
				if (Object.op_Implicit((Object)(object)mesh))
				{
					Matrix4x4 val3 = toSpace * t.localToWorldMatrix;
					Bounds bounds = mesh.bounds;
					for (int j = 0; j < 8; j++)
					{
						Vector3 val4 = ((Bounds)(ref bounds)).center + Vector3.Scale(((Bounds)(ref bounds)).extents, new Vector3((float)(((j & 1) != 0) ? 1 : (-1)), (float)(((j & 2) != 0) ? 1 : (-1)), (float)(((j & 4) != 0) ? 1 : (-1))));
						Vector3 val5 = ((Matrix4x4)(ref val3)).MultiplyPoint3x4(val4);
						if (!any)
						{
							result = new Bounds(val5, Vector3.zero);
							any = true;
						}
						else
						{
							((Bounds)(ref result)).Encapsulate(val5);
						}
					}
				}
			}
		}

		private static bool IsShown(Transform t, Transform root)
		{
			while (Object.op_Implicit((Object)(object)t) && (Object)(object)t != (Object)(object)root)
			{
				if (!((Component)t).gameObject.activeSelf)
				{
					return false;
				}
				t = t.parent;
			}
			return true;
		}
	}
	internal class PerchTier
	{
		public int Index;

		public string Name;

		public string Biome;

		public ConfigEntry<string> Cost;

		public ConfigEntry<int> Width;

		public ConfigEntry<int> Height;

		public ConfigEntry<float> Speed;

		public ConfigEntry<float> MaxWeight;

		public float SpeedMultiplier => Mathf.Max(0.1f, Speed.Value);

		public float CargoWeightLimit
		{
			get
			{
				if (!(MaxWeight.Value > 0f))
				{
					return Mathf.Max(0f, Plugin.MaxCargoWeight.Value);
				}
				return MaxWeight.Value;
			}
		}

		public int CargoWidth => Mathf.Clamp(Width.Value, 1, 8);

		public int CargoHeight => Mathf.Clamp(Height.Value, 1, 10);

		public List<KeyValuePair<string, int>> Requirements()
		{
			List<KeyValuePair<string, int>> list = new List<KeyValuePair<string, int>>();
			string[] array = (Cost.Value ?? "").Split(new char[1] { ',' });
			for (int i = 0; i < array.Length; i++)
			{
				string[] array2 = array[i].Split(new char[1] { ':' });
				if (array2.Length == 2 && int.TryParse(array2[1].Trim(), out var result) && result > 0 && array2[0].Trim().Length > 0)
				{
					list.Add(new KeyValuePair<string, int>(array2[0].Trim(), result));
				}
			}
			return list;
		}

		public List<string> MissingItems()
		{
			return (from r in Requirements()
				select r.Key into name
				where PerchTiers.ItemData(name) == null
				select name).ToList();
		}
	}
	internal static class PerchTiers
	{
		public const string TierKey = "ravenpost_tier";

		private static readonly List<PerchTier> s_tiers = new List<PerchTier>();

		public static IReadOnlyList<PerchTier> All => s_tiers;

		public static int Max => s_tiers.Count - 1;

		public static PerchTier Get(int index)
		{
			return s_tiers[Mathf.Clamp(index, 0, s_tiers.Count - 1)];
		}

		public static void Bind(ConfigFile config)
		{
			Add(config, "Wooden Perch", "Meadows", "", 2, 2, 1f);
			Add(config, "Bronze Perch", "Black Forest", "Bronze:5,BronzeNails:10", 3, 2, 1.2f);
			Add(config, "Iron Perch", "Swamp", "Iron:10,Guck:5", 4, 2, 1.4f);
			Add(config, "Silver Perch", "Mountains", "Silver:10,WolfPelt:4", 5, 3, 1.7f);
			Add(config, "Black Metal Perch", "Plains", "BlackMetal:10,LinenThread:10", 6, 3, 2f);
			Add(config, "Eitr Perch", "Mistlands", "BlackCore:2,Eitr:10,Carapace:10", 7, 4, 2.5f);
			Add(config, "Flametal Perch", "Ashlands", "FlametalNew:10,CelestialFeather:3", 8, 4, 3f);
			Add(config, "Deep North Perch", "Deep North", "FlametalNew:30,MoltenCore:2", 8, 6, 4f);
		}

		private static void Add(ConfigFile config, string name, string biome, string cost, int w, int h, float speed)
		{
			int count = s_tiers.Count;
			string text = $"Tier {count} - {name}";
			s_tiers.Add(new PerchTier
			{
				Index = count,
				Name = name,
				Biome = biome,
				Cost = config.Bind<string>(text, "UpgradeCost", cost, Plugin.Synced((count == 0) ? "Not used: this is the tier you build." : "Items to upgrade to this tier, as PrefabName:Amount, comma-separated.")),
				Width = config.Bind<int>(text, "CargoWidth", w, Plugin.Synced("Cargo slots per row (max 8).")),
				Height = config.Bind<int>(text, "CargoHeight", h, Plugin.Synced("Cargo rows (scrolls when tall).")),
				Speed = config.Bind<float>(text, "Speed", speed, Plugin.Synced("Flight speed multiplier; multiplies with the meal's speed.")),
				MaxWeight = config.Bind<float>(text, "MaxCargoWeight", 0f, Plugin.Synced("Heaviest cargo per flight at this tier, so upgrades can carry more. 0 = use the general Cargo/MaxCargoWeight."))
			});
		}

		public static void ValidateItems()
		{
			foreach (PerchTier item in s_tiers.Skip(1))
			{
				List<string> list = item.MissingItems();
				if (list.Count > 0)
				{
					Plugin.Log.LogWarning((object)(item.Name + ": unknown upgrade item(s) " + string.Join(", ", list) + " - this tier can't be reached until its UpgradeCost is changed in the config."));
				}
			}
		}

		public static ItemData ItemData(string prefabName)
		{
			if (!Object.op_Implicit((Object)(object)ObjectDB.instance))
			{
				return null;
			}
			GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(prefabName);
			ItemDrop val = (Object.op_Implicit((Object)(object)itemPrefab) ? itemPrefab.GetComponent<ItemDrop>() : null);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return null;
			}
			return val.m_itemData;
		}

		public static string DisplayName(string prefabName)
		{
			ItemData val = ItemData(prefabName);
			if (val == null)
			{
				return prefabName;
			}
			return Localization.instance.Localize(val.m_shared.m_name);
		}
	}
	[BepInPlugin("com.ravenpost.valheim", "Raven Post", "1.2.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		internal enum HungryBehaviour
		{
			FlySlowly,
			Refuse
		}

		public const string ModGuid = "com.ravenpost.valheim";

		public const string ModName = "Raven Post";

		public const string ModVersion = "1.2.1";

		public const string PerchPrefabName = "piece_ravenperch";

		internal static ManualLogSource Log;

		internal static ConfigEntry<float> SecondsPer100m;

		internal static ConfigEntry<float> MinFlightSeconds;

		internal static ConfigEntry<float> WeightSlowdown;

		internal static ConfigEntry<bool> AllowNonTeleportable;

		internal static ConfigEntry<float> MaxCargoWeight;

		internal static ConfigEntry<int> MaxFlightsPerPeriod;

		internal static ConfigEntry<int> PeriodDays;

		internal static ConfigEntry<bool> LettersCountAsFlights;

		internal static ConfigEntry<float> MaxFoodSpeed;

		internal static ConfigEntry<bool> UseFood;

		internal static ConfigEntry<HungryBehaviour> Hungry;

		internal static ConfigEntry<float> HungrySpeed;

		internal static ConfigEntry<int> MaxMeals;

		internal static ConfigEntry<float> RawMeatSpeed;

		internal static ConfigEntry<string> RawMeatItems;

		internal static ConfigEntry<KeyCode> NextDestinationKey;

		internal static ConfigEntry<KeyCode> SendKey;

		internal static ConfigEntry<KeyCode> RenameKey;

		private Harmony _harmony;

		internal static ConfigDescription Synced(string description)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			return new ConfigDescription(description, (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} });
		}

		private void Awake()
		{
			//IL_02dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e6: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			SecondsPer100m = ((BaseUnityPlugin)this).Config.Bind<float>("Flight", "SecondsPer100m", 10f, Synced("Real seconds a raven needs to fly 100 metres (in-game time, so sleeping speeds it up)."));
			MinFlightSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Flight", "MinFlightSeconds", 5f, Synced("Shortest possible delivery time, in seconds."));
			WeightSlowdown = ((BaseUnityPlugin)this).Config.Bind<float>("Flight", "WeightSlowdown", 0.5f, Synced("Extra flight time per 100 weight of cargo. 0.5 = +50% per 100 weight."));
			AllowNonTeleportable = ((BaseUnityPlugin)this).Config.Bind<bool>("Cargo", "AllowNonTeleportable", true, Synced("Let ravens carry ore and metals that portals block."));
			MaxCargoWeight = ((BaseUnityPlugin)this).Config.Bind<float>("Cargo", "MaxCargoWeight", 0f, Synced("Heaviest cargo a raven will carry in one flight. 0 = no limit (500 is a good balanced value)."));
			MaxFlightsPerPeriod = ((BaseUnityPlugin)this).Config.Bind<int>("Limits", "MaxFlightsPerPeriod", 0, Synced("How many ravens each perch can send per period. 0 = unlimited."));
			PeriodDays = ((BaseUnityPlugin)this).Config.Bind<int>("Limits", "PeriodDays", 1, Synced("Length of the period in in-game days (1 = per day). Resets when a new period starts; sleeping counts."));
			LettersCountAsFlights = ((BaseUnityPlugin)this).Config.Bind<bool>("Limits", "LettersCountAsFlights", false, Synced("Whether a letter sent without cargo uses up one of the perch's flights."));
			UseFood = ((BaseUnityPlugin)this).Config.Bind<bool>("Food", "UseFood", true, Synced("Ravens eat one stored meal per flight; better food flies faster. Turn off to ignore food entirely."));
			Hungry = ((BaseUnityPlugin)this).Config.Bind<HungryBehaviour>("Food", "HungryRaven", HungryBehaviour.FlySlowly, Synced("What a raven does with no meals stored: FlySlowly (at HungrySpeed) or Refuse to fly."));
			HungrySpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Food", "HungrySpeed", 0.5f, Synced("Speed multiplier for a hungry raven when HungryRaven = FlySlowly. 0.5 = takes twice as long."));
			MaxMeals = ((BaseUnityPlugin)this).Config.Bind<int>("Food", "MaxMeals", 10, Synced("How many meals a perch can store."));
			MaxFoodSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Food", "MaxFoodSpeed", 4f, Synced("Fastest a meal can make a raven. Cooked food gives 1 + health / 50, e.g. 30 hp = x1.6, 75 hp = x2.5."));
			RawMeatSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Food", "RawMeatSpeed", 1.25f, Synced("Speed multiplier for raw meat."));
			RawMeatItems = ((BaseUnityPlugin)this).Config.Bind<string>("Food", "RawMeatItems", "RawMeat,DeerMeat,NeckTail,WolfMeat,LoxMeat,SerpentMeat,BugMeat,HareMeat,ChickenMeat,AsksvinMeat,VoltureMeat,BoneMawSerpentMeat", Synced("Comma-separated item prefab names ravens eat raw."));
			NextDestinationKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Keys", "NextDestination", (KeyCode)106, "While looking at a perch: choose the next destination.");
			SendKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Keys", "Send", (KeyCode)107, "While looking at a perch: send its cargo.");
			RenameKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Keys", "Rename", (KeyCode)110, "While looking at a perch: rename it.");
			PerchTiers.Bind(((BaseUnityPlugin)this).Config);
			PrefabManager.OnVanillaPrefabsAvailable += AddPerchPiece;
			_harmony = new Harmony("com.ravenpost.valheim");
			_harmony.PatchAll(typeof(Plugin).Assembly);
			Log.LogInfo((object)"Raven Post 1.2.1 loaded");
		}

		private void AddPerchPiece()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Expected O, but got Unknown
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected O, but got Unknown
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Expected O, but got Unknown
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Expected O, but got Unknown
			PrefabManager.OnVanillaPrefabsAvailable -= AddPerchPiece;
			PieceConfig val = new PieceConfig();
			val.Name = "Raven Perch";
			val.Description = "Ravens carry cargo from here to your other perches.";
			val.PieceTable = "Hammer";
			val.Category = "Misc";
			val.CraftingStation = "piece_workbench";
			val.Requirements = (RequirementConfig[])(object)new RequirementConfig[3]
			{
				new RequirementConfig("FineWood", 4, 0, true),
				new RequirementConfig("Feathers", 4, 0, true),
				new RequirementConfig("BronzeNails", 5, 0, true)
			};
			PieceConfig val2 = val;
			CustomPiece val3 = new CustomPiece("piece_ravenperch", "piece_chest_wood", val2);
			GameObject piecePrefab = val3.PiecePrefab;
			Container component = piecePrefab.GetComponent<Container>();
			component.m_name = "Raven Perch";
			component.m_width = PerchTiers.Get(0).CargoWidth;
			component.m_height = PerchTiers.Get(0).CargoHeight;
			piecePrefab.AddComponent<RavenPerch>();
			RavenFlight.Prepare();
			try
			{
				PerchModel.Decorate(piecePrefab);
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"Couldn't build the perch model, using the plain chest look: {arg}");
			}
			PieceManager.Instance.AddPiece(val3);
			LetterItem.Register();
		}

		private void Update()
		{
			SendWindow.Tick();
			if (PostOffice.IsActive)
			{
				RavenNet.ServerTick();
				HandleKeys();
			}
		}

		private static void HandleKeys()
		{
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)(object)localPlayer) || InventoryGui.IsVisible() || Menu.IsVisible() || TextInput.IsVisible() || Console.IsVisible() || (Object.op_Implicit((Object)(object)Chat.instance) && Chat.instance.HasFocus()))
			{
				return;
			}
			GameObject hoverObject = ((Humanoid)localPlayer).GetHoverObject();
			RavenPerch ravenPerch = (Object.op_Implicit((Object)(object)hoverObject) ? hoverObject.GetComponentInParent<RavenPerch>() : null);
			if (Object.op_Implicit((Object)(object)ravenPerch))
			{
				if (ZInput.GetKeyDown(NextDestinationKey.Value, false))
				{
					ravenPerch.NextDestination();
				}
				else if (ZInput.GetKeyDown(SendKey.Value, false))
				{
					ravenPerch.Send(localPlayer);
				}
				else if (ZInput.GetKeyDown(RenameKey.Value, false))
				{
					TextInput.instance.RequestText((TextReceiver)(object)ravenPerch, "Name this perch", 24);
				}
			}
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
	internal class Delivery
	{
		public double ArriveAt;

		public string From;

		public bool Notified;

		public byte[] Items;

		public Vector3 FromPos;

		public string Note = "";

		public string FromPlayer = "";

		public double SentAt;

		public bool HasNote => !string.IsNullOrEmpty(Note);

		public bool HasCargo => PostOffice.UnpackItems(Items).NrOfItems() > 0;

		public bool HasArrived(double now)
		{
			return now >= ArriveAt;
		}

		public string Key(ZDOID perch)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			return $"{perch}:{ArriveAt:R}";
		}
	}
	internal class PerchInfo
	{
		public ZDOID Id;

		public string Name;

		public Vector3 Position;
	}
	internal static class PostOffice
	{
		public const string NameKey = "ravenpost_name";

		public const string InboxKey = "ravenpost_inbox";

		private const int InboxVersion = 3;

		private static readonly List<ZDO> s_perches = new List<ZDO>();

		private static float s_perchesRefreshedAt = -999f;

		private static List<PerchInfo> s_clientPerches = new List<PerchInfo>();

		private static float s_clientPerchesRequestedAt = -999f;

		public static bool IsActive
		{
			get
			{
				if (Object.op_Implicit((Object)(object)ZNet.instance) && ZDOMan.instance != null)
				{
					return ZRoutedRpc.instance != null;
				}
				return false;
			}
		}

		public static bool IsServer
		{
			get
			{
				if (Object.op_Implicit((Object)(object)ZNet.instance))
				{
					return ZNet.instance.IsServer();
				}
				return false;
			}
		}

		public static double Now => ZNet.instance.GetTimeSeconds();

		public static List<ZDO> GetAllPerchZdos()
		{
			if (Time.time - s_perchesRefreshedAt > 3f)
			{
				s_perches.Clear();
				int num = 0;
				while (!ZDOMan.instance.GetAllZDOsWithPrefabIterative("piece_ravenperch", s_perches, ref num))
				{
				}
				s_perchesRefreshedAt = Time.time;
			}
			s_perches.RemoveAll((ZDO z) => z == null || !z.IsValid());
			return s_perches;
		}

		public static List<PerchInfo> GetPerches()
		{
			//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_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			if (IsServer)
			{
				List<PerchInfo> list = new List<PerchInfo>();
				foreach (ZDO allPerchZdo in GetAllPerchZdos())
				{
					list.Add(new PerchInfo
					{
						Id = allPerchZdo.m_uid,
						Name = GetName(allPerchZdo),
						Position = allPerchZdo.GetPosition()
					});
				}
				list.Sort((PerchInfo a, PerchInfo b) => string.Compare(a.Name, b.Name, StringComparison.OrdinalIgnoreCase));
				return list;
			}
			if (Time.time - s_clientPerchesRequestedAt > 3f)
			{
				s_clientPerchesRequestedAt = Time.time;
				RavenNet.RequestPerches();
			}
			return s_clientPerches;
		}

		public static void SetClientPerches(List<PerchInfo> perches)
		{
			perches.Sort((PerchInfo a, PerchInfo b) => string.Compare(a.Name, b.Name, StringComparison.OrdinalIgnoreCase));
			s_clientPerches = perches;
		}

		public static void InvalidatePerches()
		{
			s_perchesRefreshedAt = -999f;
			s_clientPerchesRequestedAt = -999f;
		}

		public static void ResetForNewWorld()
		{
			s_perches.Clear();
			s_clientPerches = new List<PerchInfo>();
			InvalidatePerches();
		}

		public static string GetName(ZDO zdo)
		{
			string text = zdo.GetString("ravenpost_name", "");
			if (!string.IsNullOrEmpty(text))
			{
				return text;
			}
			return "Unnamed Perch";
		}

		public static List<Delivery> ReadInbox(ZDO zdo)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			List<Delivery> list = new List<Delivery>();
			byte[] byteArray = zdo.GetByteArray("ravenpost_inbox", (byte[])null);
			if (byteArray == null || byteArray.Length == 0)
			{
				return list;
			}
			ZPackage val = new ZPackage(byteArray);
			int num = val.ReadInt();
			if (num < 1 || num > 3)
			{
				Plugin.Log.LogWarning((object)$"Unknown inbox version {num}; ignoring.");
				return list;
			}
			int num2 = val.ReadInt();
			for (int i = 0; i < num2; i++)
			{
				list.Add(ReadDelivery(val, num));
			}
			return list;
		}

		public static void WriteInbox(ZDO zdo, List<Delivery> inbox)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			ZPackage val = new ZPackage();
			val.Write(3);
			val.Write(inbox.Count);
			foreach (Delivery item in inbox)
			{
				WriteDelivery(val, item);
			}
			zdo.Set("ravenpost_inbox", val.GetArray());
		}

		public static void AppendToInbox(ZDO zdo, Delivery d)
		{
			List<Delivery> list = ReadInbox(zdo);
			list.Add(d);
			WriteInbox(zdo, list);
		}

		private static Delivery ReadDelivery(ZPackage pkg, int version)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			Delivery delivery = new Delivery
			{
				ArriveAt = pkg.ReadDouble(),
				From = pkg.ReadString(),
				Notified = pkg.ReadBool(),
				Items = pkg.ReadByteArray()
			};
			if (version >= 2)
			{
				delivery.FromPos = pkg.ReadVector3();
			}
			if (version >= 3)
			{
				delivery.Note = pkg.ReadString();
				delivery.FromPlayer = pkg.ReadString();
				delivery.SentAt = pkg.ReadDouble();
			}
			return delivery;
		}

		private static void WriteDelivery(ZPackage pkg, Delivery d)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			pkg.Write(d.ArriveAt);
			pkg.Write(d.From ?? "");
			pkg.Write(d.Notified);
			pkg.Write(d.Items ?? new byte[0]);
			pkg.Write(d.FromPos);
			pkg.Write(d.Note ?? "");
			pkg.Write(d.FromPlayer ?? "");
			pkg.Write(d.SentAt);
		}

		public static ZPackage Serialize(Delivery d)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			//IL_0014: Expected O, but got Unknown
			ZPackage val = new ZPackage();
			val.Write(3);
			WriteDelivery(val, d);
			return val;
		}

		public static Delivery Deserialize(ZPackage pkg)
		{
			pkg.SetPos(0);
			int version = pkg.ReadInt();
			return ReadDelivery(pkg, version);
		}

		public static byte[] PackItems(List<ItemData> items)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected O, but got Unknown
			Inventory val = NewCargoInventory();
			foreach (ItemData item in items)
			{
				val.AddItem(item.Clone());
			}
			ZPackage val2 = new ZPackage();
			val.Save(val2);
			return val2.GetArray();
		}

		public static Inventory UnpackItems(byte[] data)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			Inventory val = NewCargoInventory();
			if (data != null && data.Length != 0)
			{
				val.Load(new ZPackage(data));
			}
			return val;
		}

		private static Inventory NewCargoInventory()
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Expected O, but got Unknown
			return new Inventory("RavenCargo", (Sprite)null, 8, 10);
		}

		public static float FlightSeconds(float distance, float weight)
		{
			float num = distance / 100f * Plugin.SecondsPer100m.Value;
			num *= 1f + weight / 100f * Plugin.WeightSlowdown.Value;
			return Mathf.Max(Plugin.MinFlightSeconds.Value, num);
		}

		public static string FormatDuration(double seconds)
		{
			if (seconds < 0.0)
			{
				seconds = 0.0;
			}
			int num = Mathf.CeilToInt((float)seconds);
			if (num < 3600)
			{
				return $"{num / 60}:{num % 60:00}";
			}
			return $"{num / 3600}h {num % 3600 / 60:00}m";
		}

		public static string FormatDistance(float metres)
		{
			if (!(metres >= 1000f))
			{
				return $"{Mathf.RoundToInt(metres)} m";
			}
			return $"{metres / 1000f:0.0} km";
		}

		public static string ArrivalMessage(Delivery d, string at)
		{
			bool hasCargo = d.HasCargo;
			if (d.HasNote && !hasCargo)
			{
				return "Letter from " + d.From + " has landed at " + at;
			}
			if (!d.HasNote)
			{
				return "Raven from " + d.From + " has landed at " + at;
			}
			return "Raven from " + d.From + " has landed at " + at + " with a letter";
		}
	}
	internal class RavenFlight : MonoBehaviour
	{
		private enum Mode
		{
			TakeOff,
			Land
		}

		public const float LandingSeconds = 6f;

		public const float TakeOffSeconds = 12f;

		private const float MinTakeOffSeconds = 3f;

		private const float CruiseSpeed = 5f;

		private const float MaxCruiseSpeed = 30f;

		private const float ClimbSpeed = 1.6f;

		private const float CircleSeconds = 3f;

		private const float FadeSeconds = 1.5f;

		private const float LandingDistance = 30f;

		private const float LandingHeight = 14f;

		private static readonly string[] s_candidatePrefabs = new string[3] { "Crow", "Raven", "Seagal" };

		private static GameObject s_template;

		private static GameObject s_perchedTemplate;

		private static bool s_warned;

		private Mode _mode;

		private Vector3 _origin;

		private Vector3 _target;

		private Vector3 _heading;

		private float _duration;

		private float _circleSeconds = 3f;

		private float _cruiseSpeed = 5f;

		private float _age;

		private Vector3 _baseScale;

		public static GameObject Template
		{
			get
			{
				Prepare();
				return s_template;
			}
		}

		public static GameObject PerchedTemplate
		{
			get
			{
				Prepare();
				return s_perchedTemplate;
			}
		}

		public static void Prepare()
		{
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Expected O, but got Unknown
			if (Object.op_Implicit((Object)(object)s_template))
			{
				return;
			}
			GameObject val = null;
			string[] array = s_candidatePrefabs;
			foreach (string text in array)
			{
				val = PrefabManager.Instance.GetPrefab(text);
				if (Object.op_Implicit((Object)(object)val))
				{
					Plugin.Log.LogInfo((object)("Raven visual uses prefab '" + text + "'"));
					break;
				}
			}
			if (!Object.op_Implicit((Object)(object)val))
			{
				if (!s_warned)
				{
					s_warned = true;
					Plugin.Log.LogWarning((object)"No bird prefab found; ravens will be invisible.");
				}
			}
			else
			{
				GameObject val2 = new GameObject("RavenPost_Templates");
				val2.SetActive(false);
				Object.DontDestroyOnLoad((Object)(object)val2);
				s_template = BuildTemplate(val, val2.transform, landed: false);
				s_perchedTemplate = BuildTemplate(val, val2.transform, landed: true);
			}
		}

		private static GameObject BuildTemplate(GameObject source, Transform holder, bool landed)
		{
			GameObject val = Object.Instantiate<GameObject>(source, holder);
			((Object)val).name = (landed ? "RavenPost_RavenPerched" : "RavenPost_Raven");
			RandomFlyingBird component = val.GetComponent<RandomFlyingBird>();
			if (Object.op_Implicit((Object)(object)component) && !component.m_singleModel && Object.op_Implicit((Object)(object)component.m_flyingModel) && Object.op_Implicit((Object)(object)component.m_landedModel))
			{
				component.m_flyingModel.SetActive(!landed);
				component.m_landedModel.SetActive(landed);
			}
			MonoBehaviour[] componentsInChildren = val.GetComponentsInChildren<MonoBehaviour>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
			}
			Collider[] componentsInChildren2 = val.GetComponentsInChildren<Collider>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren2[i]);
			}
			Rigidbody[] componentsInChildren3 = val.GetComponentsInChildren<Rigidbody>(true);
			for (int i = 0; i < componentsInChildren3.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren3[i]);
			}
			val.AddComponent<BirdPose>().Flying = !landed;
			return val;
		}

		private static RavenFlight Spawn(Vector3 position, Vector3 facing)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)s_template))
			{
				Prepare();
				if (!Object.op_Implicit((Object)(object)s_template))
				{
					return null;
				}
			}
			facing.y = 0f;
			if (((Vector3)(ref facing)).sqrMagnitude < 0.01f)
			{
				facing = Vector3.forward;
			}
			GameObject val = Object.Instantiate<GameObject>(s_template, position, Quaternion.LookRotation(((Vector3)(ref facing)).normalized));
			val.SetActive(true);
			RavenFlight ravenFlight = val.AddComponent<RavenFlight>();
			ravenFlight._baseScale = val.transform.localScale;
			return ravenFlight;
		}

		public static float Launch(Vector3 from, Vector3 to, float flightSeconds, float speedMultiplier)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: 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_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Clamp(flightSeconds * 0.8f, 3f, 12f);
			Vector3 val = to - from;
			val.y = 0f;
			val = ((((Vector3)(ref val)).sqrMagnitude < 0.01f) ? Vector3.forward : ((Vector3)(ref val)).normalized);
			RavenFlight ravenFlight = Spawn(from, val);
			if (!Object.op_Implicit((Object)(object)ravenFlight))
			{
				return 0f;
			}
			ravenFlight._mode = Mode.TakeOff;
			ravenFlight._origin = from;
			ravenFlight._heading = val;
			ravenFlight._duration = num;
			ravenFlight._circleSeconds = Mathf.Min(3f, num * 0.3f);
			ravenFlight._cruiseSpeed = Mathf.Min(30f, 5f * Mathf.Max(1f, speedMultiplier));
			return num;
		}

		public static void Land(Vector3 perch, Vector3 senderPos, float seconds)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//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)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: 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_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: 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_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: 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_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: 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)
			Vector3 val = senderPos - perch;
			val.y = 0f;
			if (senderPos == Vector3.zero || ((Vector3)(ref val)).sqrMagnitude < 0.01f)
			{
				val = Random.insideUnitSphere;
				val.y = 0f;
			}
			val = ((((Vector3)(ref val)).sqrMagnitude < 0.01f) ? Vector3.back : ((Vector3)(ref val)).normalized);
			Vector3 val2 = perch + val * 30f + Vector3.up * 14f;
			RavenFlight ravenFlight = Spawn(val2, -val);
			if (Object.op_Implicit((Object)(object)ravenFlight))
			{
				ravenFlight._mode = Mode.Land;
				ravenFlight._origin = val2;
				ravenFlight._target = perch;
				ravenFlight._heading = -val;
				ravenFlight._duration = Mathf.Max(1f, seconds);
			}
		}

		private void Update()
		{
			_age += Time.deltaTime;
			if (_mode == Mode.TakeOff)
			{
				UpdateTakeOff();
			}
			else
			{
				UpdateLanding();
			}
		}

		private void UpdateTakeOff()
		{
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: 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_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: 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_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: 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_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_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//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_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: 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_017e: 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_018f: Unknown result type (might be due to invalid IL or missing references)
			Vector3 position;
			Vector3 val2;
			if (_age < _circleSeconds)
			{
				float num = _age / _circleSeconds;
				float num2 = num * (float)Math.PI * 2f;
				float num3 = Mathf.Lerp(0.5f, 3f, num);
				Vector3 val = Quaternion.LookRotation(_heading) * new Vector3(Mathf.Sin(num2), 0f, 0f - Mathf.Cos(num2)) * num3;
				position = _origin + val + Vector3.up * (_age * 1.6f * 1.5f);
				val2 = Quaternion.LookRotation(_heading) * new Vector3(Mathf.Cos(num2), 0f, Mathf.Sin(num2));
			}
			else
			{
				float num4 = _age - _circleSeconds;
				position = _origin + Quaternion.LookRotation(_heading) * new Vector3(0f, 0f, -3f) + Vector3.up * (_circleSeconds * 1.6f * 1.5f) + _heading * (num4 * _cruiseSpeed) + Vector3.up * (num4 * 1.6f);
				val2 = _heading;
			}
			((Component)this).transform.position = position;
			((Component)this).transform.rotation = Quaternion.Slerp(((Component)this).transform.rotation, Quaternion.LookRotation(val2), Time.deltaTime * 6f);
			FadeAndExpire(_duration);
		}

		private void UpdateLanding()
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: 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_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			float num = Mathf.Clamp01(_age / _duration);
			float num2 = 1f - (1f - num) * (1f - num);
			Vector3 position = Vector3.Lerp(_origin, _target, num2);
			position.y += Mathf.Sin(num * (float)Math.PI) * 2f;
			((Component)this).transform.position = position;
			((Component)this).transform.rotation = Quaternion.LookRotation(_heading);
			if (_age >= _duration)
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
		}

		private void FadeAndExpire(float lifetime)
		{
			//IL_002c: 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)
			float num = lifetime - _age;
			if (num <= 0f)
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
			else if (num < 1.5f)
			{
				((Component)this).transform.localScale = _baseScale * (num / 1.5f);
			}
		}
	}
	internal class BirdPose : MonoBehaviour
	{
		private static readonly int s_flyingHash = Animator.StringToHash("flying");

		private static readonly int s_flappingHash = Animator.StringToHash("flapping");

		public bool Flying;

		private Animator _animator;

		private bool _hasFlying;

		private bool _hasFlapping;

		private void Start()
		{
			_animator = ((Component)this).GetComponentInChildren<Animator>();
			if (Object.op_Implicit((Object)(object)_animator))
			{
				AnimatorControllerParameter[] parameters = _animator.parameters;
				foreach (AnimatorControllerParameter val in parameters)
				{
					_hasFlying |= val.nameHash == s_flyingHash;
					_hasFlapping |= val.nameHash == s_flappingHash;
				}
				Apply();
			}
		}

		private void Update()
		{
			Apply();
		}

		private void Apply()
		{
			if (Object.op_Implicit((Object)(object)_animator) && ((Behaviour)_animator).isActiveAndEnabled)
			{
				if (_hasFlying)
				{
					_animator.SetBool(s_flyingHash, Flying);
				}
				if (_hasFlapping)
				{
					_animator.SetBool(s_flappingHash, Flying);
				}
			}
		}
	}
	internal static class RavenFood
	{
		public const string MealsKey = "ravenpost_meals";

		private static HashSet<string> s_rawMeats;

		private static string s_rawMeatsSource;

		public static float SpeedFor(ItemData item)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Invalid comparison between Unknown and I4
			if (item == null)
			{
				return 0f;
			}
			SharedData shared = item.m_shared;
			if ((int)shared.m_itemType == 2 && shared.m_food > 0f)
			{
				return Mathf.Min(Plugin.MaxFoodSpeed.Value, 1f + shared.m_food / 50f);
			}
			string item2 = (Object.op_Implicit((Object)(object)item.m_dropPrefab) ? ((Object)item.m_dropPrefab).name : "");
			if (!RawMeats().Contains(item2))
			{
				return 0f;
			}
			return Plugin.RawMeatSpeed.Value;
		}

		private static HashSet<string> RawMeats()
		{
			string text = Plugin.RawMeatItems.Value ?? "";
			if (s_rawMeats == null || text != s_rawMeatsSource)
			{
				s_rawMeatsSource = text;
				s_rawMeats = new HashSet<string>(from x in text.Split(new char[1] { ',' })
					select x.Trim() into x
					where x.Length > 0
					select x);
			}
			return s_rawMeats;
		}

		public static ItemData BestFood(Inventory inventory)
		{
			ItemData result = null;
			float num = 0f;
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				float num2 = SpeedFor(allItem);
				if (num2 > num && !allItem.m_equipped)
				{
					result = allItem;
					num = num2;
				}
			}
			return result;
		}

		public static List<float> ReadMeals(ZDO zdo)
		{
			List<float> list = new List<float>();
			string[] array = zdo.GetString("ravenpost_meals", "").Split(new char[1] { ';' });
			for (int i = 0; i < array.Length; i++)
			{
				if (float.TryParse(array[i], NumberStyles.Float, CultureInfo.InvariantCulture, out var result) && result > 0f)
				{
					list.Add(result);
				}
			}
			list.Sort((float a, float b) => b.CompareTo(a));
			return list;
		}

		public static void WriteMeals(ZDO zdo, List<float> meals)
		{
			meals.Sort((float a, float b) => b.CompareTo(a));
			zdo.Set("ravenpost_meals", string.Join(";", meals.Select((float m) => m.ToString("0.###", CultureInfo.InvariantCulture))));
		}

		public static string FormatSpeed(float speed)
		{
			return $"x{speed:0.##}";
		}
	}
	internal class Letter
	{
		public double SentAt;

		public string From = "";

		public string FromPlayer = "";

		public Vector3 FromPos;

		public string Text = "";

		public bool Read;
	}
	internal static class RavenMail
	{
		public const string MailKey = "ravenpost_mail";

		public const string DraftKey = "ravenpost_draft";

		public const int MaxNoteLength = 200;

		private const int MaxLetters = 50;

		private const int MailVersion = 1;

		public static List<Letter> Read(ZDO zdo)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			List<Letter> list = new List<Letter>();
			byte[] byteArray = zdo.GetByteArray("ravenpost_mail", (byte[])null);
			if (byteArray == null || byteArray.Length == 0)
			{
				return list;
			}
			ZPackage val = new ZPackage(byteArray);
			int num = val.ReadInt();
			if (num != 1)
			{
				Plugin.Log.LogWarning((object)$"Unknown mailbox version {num}; ignoring.");
				return list;
			}
			int num2 = val.ReadInt();
			for (int i = 0; i < num2; i++)
			{
				list.Add(new Letter
				{
					SentAt = val.ReadDouble(),
					From = val.ReadString(),
					FromPlayer = val.ReadString(),
					FromPos = val.ReadVector3(),
					Text = val.ReadString(),
					Read = val.ReadBool()
				});
			}
			return list;
		}

		public static void Write(ZDO zdo, List<Letter> letters)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Expected O, but got Unknown
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			while (letters.Count > 50)
			{
				int num = letters.FindIndex((Letter l) => l.Read);
				letters.RemoveAt((num >= 0) ? num : 0);
			}
			ZPackage val = new ZPackage();
			val.Write(1);
			val.Write(letters.Count);
			foreach (Letter letter in letters)
			{
				val.Write(letter.SentAt);
				val.Write(letter.From ?? "");
				val.Write(letter.FromPlayer ?? "");
				val.Write(letter.FromPos);
				val.Write(letter.Text ?? "");
				val.Write(letter.Read);
			}
			zdo.Set("ravenpost_mail", val.GetArray());
		}

		public static void Deliver(ZDO zdo, Delivery d)
		{
			//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)
			List<Letter> list = Read(zdo);
			list.Add(new Letter
			{
				SentAt = d.SentAt,
				From = d.From,
				FromPlayer = d.FromPlayer,
				FromPos = d.FromPos,
				Text = d.Note,
				Read = false
			});
			Write(zdo, list);
		}

		public static int UnreadCount(ZDO zdo)
		{
			int num = 0;
			foreach (Letter item in Read(zdo))
			{
				if (!item.Read)
				{
					num++;
				}
			}
			return num;
		}

		public static int Day(double time)
		{
			if (!Object.op_Implicit((Object)(object)EnvMan.instance))
			{
				return 0;
			}
			return EnvMan.instance.GetDay(time);
		}

		public static string Preview(string text, int max = 28)
		{
			text = (text ?? "").Replace('\n', ' ');
			if (text.Length > max)
			{
				return text.Substring(0, max - 1) + "…";
			}
			return text;
		}

		public static PerchInfo FindSender(Letter letter)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			PerchInfo result = null;
			float num = float.MaxValue;
			foreach (PerchInfo perch in PostOffice.GetPerches())
			{
				if (!(perch.Name != letter.From))
				{
					float num2 = Vector3.Distance(perch.Position, letter.FromPos);
					if (num2 < num)
					{
						result = perch;
						num = num2;
					}
				}
			}
			return result;
		}
	}
	internal class NoteWriter : TextReceiver
	{
		private readonly RavenPerch _perch;

		private NoteWriter(RavenPerch perch)
		{
			_perch = perch;
		}

		public static void Open(RavenPerch perch, string topic)
		{
			if (Object.op_Implicit((Object)(object)perch) && Object.op_Implicit((Object)(object)TextInput.instance))
			{
				if (Object.op_Implicit((Object)(object)InventoryGui.instance))
				{
					InventoryGui.instance.Hide();
				}
				TextInput.instance.RequestText((TextReceiver)(object)new NoteWriter(perch), topic, MaxNoteLength());
			}
		}

		private static int MaxNoteLength()
		{
			return 200;
		}

		public string GetText()
		{
			if (!Object.op_Implicit((Object)(object)_perch))
			{
				return "";
			}
			return _perch.Draft;
		}

		public void SetText(string text)
		{
			if (Object.op_Implicit((Object)(object)_perch))
			{
				_perch.Draft = text;
				Player localPlayer = Player.m_localPlayer;
				Container component = ((Component)_perch).GetComponent<Container>();
				if (Object.op_Implicit((Object)(object)localPlayer) && Object.op_Implicit((Object)(object)component))
				{
					SendWindow.OpenOnSendTabNext();
					component.Interact((Humanoid)(object)localPlayer, false, false);
				}
			}
		}
	}
	internal static class RavenNet
	{
		private class PendingNotice
		{
			public double At;

			public string Recipient;

			public string Message;
		}

		private const string RpcRequestPerches = "RavenPost_RequestPerches";

		private const string RpcPerches = "RavenPost_Perches";

		private const string RpcDeliver = "RavenPost_Deliver";

		private const string RpcAddToInbox = "RavenPost_AddToInbox";

		private const string RpcServerWrite = "RavenPost_ServerWrite";

		private const string RpcNotify = "RavenPost_Notify";

		private const string RpcTakeOff = "RavenPost_TakeOff";

		private const float TakeOffViewDistance = 150f;

		private static readonly List<PendingNotice> s_pending = new List<PendingNotice>();

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

		private static bool s_scannedWorld;

		private static float s_nextTick;

		public static void Register()
		{
			ZRoutedRpc instance = ZRoutedRpc.instance;
			if (instance != null)
			{
				s_pending.Clear();
				s_scheduled.Clear();
				s_scannedWorld = false;
				PostOffice.ResetForNewWorld();
				instance.Register("RavenPost_RequestPerches", (Action<long>)OnRequestPerches);
				instance.Register<ZPackage>("RavenPost_Perches", (Action<long, ZPackage>)OnPerches);
				instance.Register<ZDOID, ZDOID, ZPackage>("RavenPost_Deliver", (Action<long, ZDOID, ZDOID, ZPackage>)OnDeliver);
				instance.Register<ZDOID, ZPackage>("RavenPost_AddToInbox", (Action<long, ZDOID, ZPackage>)OnAddToInbox);
				instance.Register<ZDOID, ZPackage>("RavenPost_ServerWrite", (Action<long, ZDOID, ZPackage>)OnServerWrite);
				instance.Register<string>("RavenPost_Notify", (Action<long, string>)OnNotify);
				instance.Register<Vector3, Vector3, ZPackage>("RavenPost_TakeOff", (Action<long, Vector3, Vector3, ZPackage>)OnTakeOff);
			}
		}

		public static void RequestPerches()
		{
			ZRoutedRpc instance = ZRoutedRpc.instance;
			if (instance != null)
			{
				instance.InvokeRoutedRPC("RavenPost_RequestPerches", Array.Empty<object>());
			}
		}

		private static void OnRequestPerches(long sender)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Expected O, but got Unknown
			//IL_0033: 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)
			if (!PostOffice.IsServer)
			{
				return;
			}
			List<PerchInfo> perches = PostOffice.GetPerches();
			ZPackage val = new ZPackage();
			val.Write(perches.Count);
			foreach (PerchInfo item in perches)
			{
				val.Write(item.Id);
				val.Write(item.Name);
				val.Write(item.Position);
			}
			ZRoutedRpc.instance.InvokeRoutedRPC(sender, "RavenPost_Perches", new object[1] { val });
		}

		private static void OnPerches(long sender, ZPackage pkg)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			if (!PostOffice.IsServer)
			{
				List<PerchInfo> list = new List<PerchInfo>();
				int num = pkg.ReadInt();
				for (int i = 0; i < num; i++)
				{
					list.Add(new PerchInfo
					{
						Id = pkg.ReadZDOID(),
						Name = pkg.ReadString(),
						Position = pkg.ReadVector3()
					});
				}
				PostOffice.SetClientPerches(list);
			}
		}

		public static void SendDelivery(ZDOID destination, ZDOID source, Delivery d)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			ZRoutedRpc.instance.InvokeRoutedRPC("RavenPost_Deliver", new object[3]
			{
				destination,
				source,
				PostOffice.Serialize(d)
			});
		}

		private static void OnDeliver(long sender, ZDOID destination, ZDOID source, ZPackage pkg)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			if (!PostOffice.IsServer)
			{
				return;
			}
			Delivery delivery = PostOffice.Deserialize(pkg);
			ZDO zDO = ZDOMan.instance.GetZDO(destination);
			string name;
			if (zDO == null || !zDO.IsValid())
			{
				zDO = ZDOMan.instance.GetZDO(source);
				if (zDO == null || !zDO.IsValid())
				{
					Plugin.Log.LogWarning((object)("Delivery from '" + delivery.From + "' has nowhere to go; both perches are gone."));
					return;
				}
				name = PostOffice.GetName(zDO);
				Notify(delivery.FromPlayer, "The perch was gone - your raven flew back to " + name);
			}
			else
			{
				name = PostOffice.GetName(zDO);
			}
			WriteToOwner(zDO, delivery);
			Schedule(zDO.m_uid, name, delivery);
		}

		private static void WriteToOwner(ZDO zdo, Delivery d)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			long owner = zdo.GetOwner();
			long sessionID = ZDOMan.GetSessionID();
			if (owner != 0L && owner != sessionID && ZNet.instance.GetPeer(owner) != null)
			{
				ZRoutedRpc.instance.InvokeRoutedRPC(owner, "RavenPost_AddToInbox", new object[2]
				{
					zdo.m_uid,
					PostOffice.Serialize(d)
				});
			}
			else
			{
				PostOffice.AppendToInbox(zdo, d);
			}
		}

		private static void OnAddToInbox(long sender, ZDOID id, ZPackage pkg)
		{
			//IL_0005: 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)
			ZDO zDO = ZDOMan.instance.GetZDO(id);
			if (zDO != null && zDO.IsOwner())
			{
				PostOffice.AppendToInbox(zDO, PostOffice.Deserialize(pkg));
				return;
			}
			pkg.SetPos(0);
			ZRoutedRpc.instance.InvokeRoutedRPC("RavenPost_ServerWrite", new object[2] { id, pkg });
		}

		private static void OnServerWrite(long sender, ZDOID id, ZPackage pkg)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			if (PostOffice.IsServer)
			{
				ZDO zDO = ZDOMan.instance.GetZDO(id);
				if (zDO != null && zDO.IsValid())
				{
					PostOffice.AppendToInbox(zDO, PostOffice.Deserialize(pkg));
				}
			}
		}

		private static void Schedule(ZDOID perch, string perchName, Delivery d)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			if (s_scheduled.Add(d.Key(perch)))
			{
				string message = PostOffice.ArrivalMessage(d, perchName);
				s_pending.Add(new PendingNotice
				{
					At = d.ArriveAt,
					Recipient = (d.HasNote ? null : d.FromPlayer),
					Message = message
				});
			}
		}

		public static void ServerTick()
		{
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			if (!PostOffice.IsServer || !PostOffice.IsActive || Time.time < s_nextTick)
			{
				return;
			}
			s_nextTick = Time.time + 1f;
			if (!s_scannedWorld)
			{
				s_scannedWorld = true;
				double now = PostOffice.Now;
				foreach (ZDO allPerchZdo in PostOffice.GetAllPerchZdos())
				{
					foreach (Delivery item in PostOffice.ReadInbox(allPerchZdo))
					{
						if (!item.HasArrived(now))
						{
							Schedule(allPerchZdo.m_uid, PostOffice.GetName(allPerchZdo), item);
						}
					}
				}
			}
			double now2 = PostOffice.Now;
			for (int num = s_pending.Count - 1; num >= 0; num--)
			{
				PendingNotice pendingNotice = s_pending[num];
				if (pendingNotice.At <= now2)
				{
					s_pending.RemoveAt(num);
					Notify(pendingNotice.Recipient, pendingNotice.Message);
				}
			}
		}

		private static void Notify(string playerName, string message)
		{
			if (playerName == null)
			{
				ZRoutedRpc.instance.InvokeRoutedRPC(0L, "RavenPost_Notify", new object[1] { message });
				return;
			}
			if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && Player.m_localPlayer.GetPlayerName() == playerName)
			{
				OnNotify(0L, message);
			}
			foreach (ZNetPeer peer in ZNet.instance.GetPeers())
			{
				if (peer.m_playerName == playerName)
				{
					ZRoutedRpc.instance.InvokeRoutedRPC(peer.m_uid, "RavenPost_Notify", new object[1] { message });
				}
			}
		}

		private static void OnNotify(long sender, string message)
		{
			if (Object.op_Implicit((Object)(object)MessageHud.instance))
			{
				MessageHud.instance.ShowMessage((MessageType)1, message, 0, (Sprite)null, false, true);
			}
		}

		public static void BroadcastTakeOff(Vector3 from, Vector3 to, float flightSeconds, float speed)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			ZPackage val = new ZPackage();
			val.Write(flightSeconds);
			val.Write(speed);
			ZRoutedRpc.instance.InvokeRoutedRPC(0L, "RavenPost_TakeOff", new object[3] { from, to, val });
		}

		private static void OnTakeOff(long sender, Vector3 from, Vector3 to, ZPackage pkg)
		{
			//IL_001f: 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_0040: 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_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			if (sender == ZDOMan.GetSessionID() || !Object.op_Implicit((Object)(object)Player.m_localPlayer) || Vector3.Distance(((Component)Player.m_localPlayer).transform.position, from) > 150f)
			{
				return;
			}
			float flightSeconds = pkg.ReadSingle();
			float speedMultiplier = pkg.ReadSingle();
			float num = RavenFlight.Launch(from, to, flightSeconds, speedMultiplier);
			RavenPerch[] array = Object.FindObjectsByType<RavenPerch>((FindObjectsSortMode)0);
			foreach (RavenPerch ravenPerch in array)
			{
				if (Vector3.Distance(ravenPerch.SeatPosition, from) < 0.5f)
				{
					ravenPerch.HideSeatedRaven(num + 1f);
				}
			}
		}
	}
	public class RavenPerch : MonoBehaviour, TextReceiver
	{
		private ZNetView _nview;

		private Container _container;

		private ZDOID _selectedDestination = ZDOID.None;

		private int _appliedTier;

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

		private const float LandingViewDistance = 80f;

		private static bool s_validatedTiers;

		private static readonly FieldInfo s_invWidth = AccessTools.Field(typeof(Inventory), "m_width");

		private static readonly FieldInfo s_invHeight = AccessTools.Field(typeof(Inventory), "m_height");

		private static readonly FieldInfo s_invName = AccessTools.Field(typeof(Inventory), "m_name");

		private const string FlightLogKey = "ravenpost_flights";

		public int TierIndex
		{
			get
			{
				if (Zdo == null)
				{
					return 0;
				}
				return Mathf.Clamp(Zdo.GetInt("ravenpost_tier", 0), 0, PerchTiers.Max);
			}
		}

		internal PerchTier Tier => PerchTiers.Get(TierIndex);

		internal PerchTier NextTier
		{
			get
			{
				if (TierIndex >= PerchTiers.Max)
				{
					return null;
				}
				return PerchTiers.Get(TierIndex + 1);
			}
		}

		private ZDO Zdo
		{
			get
			{
				if (!Object.op_Implicit((Object)(object)_nview) || !_nview.IsValid())
				{
					return null;
				}
				return _nview.GetZDO();
			}
		}

		public string PerchName
		{
			get
			{
				if (Zdo == null)
				{
					return "Raven Perch";
				}
				return PostOffice.GetName(Zdo);
			}
		}

		public float CargoWeight
		{
			get
			{
				Inventory inventory = _container.GetInventory();
				if (inventory == null)
				{
					return 0f;
				}
				return inventory.GetTotalWeight();
			}
		}

		public List<float> Meals
		{
			get
			{
				if (Zdo == null)
				{
					return new List<float>();
				}
				return RavenFood.ReadMeals(Zdo);
			}
		}

		public float NextMealSpeed
		{
			get
			{
				if (!Plugin.UseFood.Value)
				{
					return 1f;
				}
				List<float> meals = Meals;
				if (meals.Count <= 0)
				{
					return Mathf.Max(0.05f, Plugin.HungrySpeed.Value);
				}
				return meals[0];
			}
		}

		public bool IsHungry
		{
			get
			{
				if (Plugin.UseFood.Value)
				{
					return Meals.Count == 0;
				}
				return false;
			}
		}

		public bool RefusesToFly
		{
			get
			{
				if (IsHungry)
				{
					return Plugin.Hungry.Value == Plugin.HungryBehaviour.Refuse;
				}
				return false;
			}
		}

		public string MealsStatus
		{
			get
			{
				if (!Plugin.UseFood.Value)
				{
					return "";
				}
				List<float> meals = Meals;
				if (meals.Count > 0)
				{
					return $"Meals: {meals.Count}/{Mathf.Max(1, Plugin.MaxMeals.Value)} (next {RavenFood.FormatSpeed(meals[0])} speed)";
				}
				if (!RefusesToFly)
				{
					return "<color=#ff9a40>Hungry - flies slowly (" + RavenFood.FormatSpeed(NextMealSpeed) + ")</color>";
				}
				return "<color=#ff6060>Hungry - won't fly until fed</color>";
			}
		}

		public float MaxCargoWeight => Tier.CargoWeightLimit;

		public bool WeightLimited => MaxCargoWeight > 0f;

		public static bool FlightsLimited => Plugin.MaxFlightsPerPeriod.Value > 0;

		private static int PeriodDays => Mathf.Max(1, Plugin.PeriodDays.Value);

		private static int CurrentPeriod => RavenMail.Day(PostOffice.Now) / PeriodDays;

		public int FlightsUsed
		{
			get
			{
				ZDO zdo = Zdo;
				string[] array = (((zdo != null) ? zdo.GetString("ravenpost_flights", "") : null) ?? "").Split(new char[1] { ':' });
				if (array.Length == 2 && int.TryParse(array[0], out var result) && int.TryParse(array[1], out var result2) && result == CurrentPeriod)
				{
					return result2;
				}
				return 0;
			}
		}

		public int FlightsLeft
		{
			get
			{
				if (!FlightsLimited)
				{
					return int.MaxValue;
				}
				return Mathf.Max(0, Plugin.MaxFlightsPerPeriod.Value - FlightsUsed);
			}
		}

		private static string PeriodName
		{
			get
			{
				if (PeriodDays != 1)
				{
					return $"these {PeriodDays} days";
				}
				return "today";
			}
		}

		public string FlightsStatus
		{
			get
			{
				if (!FlightsLimited)
				{
					return "";
				}
				int value = Plugin.MaxFlightsPerPeriod.Value;
				if (FlightsLeft > 0)
				{
					return $"Flights {PeriodName}: {FlightsUsed}/{value}";
				}
				int num = (CurrentPeriod + 1) * PeriodDays;
				return $"<color=#ff6060>Tired ({value}/{value} {PeriodName}) - flies again on day {num}</color>";
			}
		}

		public string Draft
		{
			get
			{
				ZDO zdo = Zdo;
				return ((zdo != null) ? zdo.GetString("ravenpost_draft", "") : null) ?? "";
			}
			set
			{
				if (Zdo != null && EnsureOwner(Player.m_localPlayer))
				{
					string text = (value ?? "").Trim();
					if (text.Length > 200)
					{
						text = text.Substring(0, 200);
					}
					Zdo.Set("ravenpost_draft", text);
				}
			}
		}

		internal List<Letter> Mailbox
		{
			get
			{
				if (Zdo == null)
				{
					return new List<Letter>();
				}
				return RavenMail.Read(Zdo);
			}
		}

		public int UnreadLetters
		{
			get
			{
				if (Zdo == null)
				{
					return 0;
				}
				return RavenMail.UnreadCount(Zdo);
			}
		}

		private Transform SeatedRaven => ((Component)this).transform.Find("RavenPost_PerchedRaven");

		public Vector3 SeatPosition
		{
			get
			{
				//IL_0030: Unknown result type (might be due to invalid IL or missing references)
				//IL_0015: Unknown result type (might be due to invalid IL or missing references)
				//IL_001a: 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_0029: Unknown result type (might be due to invalid IL or missing references)
				Transform seatedRaven = SeatedRaven;
				if (!Object.op_Implicit((Object)(object)seatedRaven))
				{
					return ((Component)this).transform.position + Vector3.up * 1.2f;
				}
				return seatedRaven.position;
			}
		}

		private void Awake()
		{
			_nview = ((Component)this).GetComponent<ZNetView>();
			_container = ((Component)this).GetComponent<Container>();
			if (Object.op_Implicit((Object)(object)_nview) && _nview.GetZDO() != null)
			{
				WearNTear component = ((Component)this).GetComponent<WearNTear>();
				if (Object.op_Implicit((Object)(object)component))
				{
					component.m_onDestroyed = (Action)Delegate.Combine(component.m_onDestroyed, new Action(OnDestroyed));
				}
				if (!s_validatedTiers)
				{
					s_validatedTiers = true;
					PerchTiers.ValidateItems();
				}
				PostOffice.InvalidatePerches();
				_appliedTier = TierIndex;
				((MonoBehaviour)this).InvokeRepeating("CollectArrivals", 1f, 2f);
				((MonoBehaviour)this).InvokeRepeating("CheckLandings", 0.5f, 0.5f);
				((MonoBehaviour)this).InvokeRepeating("SyncTier", 2f, 2f);
			}
		}

		private void SyncTier()
		{
			int tierIndex = TierIndex;
			if (tierIndex != _appliedTier)
			{
				_appliedTier = tierIndex;
				ApplyTier(_container, Tier);
			}
		}

		private void CheckLandings()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: 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_00bb: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if (Zdo == null || !Object.op_Implicit((Object)(object)localPlayer) || Vector3.Distance(((Component)localPlayer).transform.position, ((Component)this).transform.position) > 80f)
			{
				return;
			}
			double now = PostOffice.Now;
			foreach (Delivery item in PostOffice.ReadInbox(Zdo))
			{
				double num = item.ArriveAt - now;
				if (!(num < 0.0) && !(num > (double)LandingLeadFor(item)) && s_landingsShown.Add(item.Key(Zdo.m_uid)))
				{
					float seconds = (float)Math.Max(0.5, num);
					HideSeatedRaven(seconds);
					RavenFlight.Land(SeatPosition, item.FromPos, seconds);
				}
			}
		}

		private static float LandingLeadFor(Delivery d)
		{
			if (d.SentAt <= 0.0)
			{
				return 6f;
			}
			return Mathf.Clamp((float)(d.ArriveAt - d.SentAt) * 0.5f, 1.5f, 6f);
		}

		internal static void ApplyTier(Container container, PerchTier tier)
		{
			container.m_name = tier.Name;
			int num = tier.CargoWidth;
			int num2 = tier.CargoHeight;
			Inventory inventory = container.GetInventory();
			if (inventory == null)
			{
				container.m_width = num;
				container.m_height = num2;
				return;
			}
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				num = Mathf.Max(num, allItem.m_gridPos.x + 1);
				num2 = Mathf.Max(num2, allItem.m_gridPos.y + 1);
			}
			container.m_width = num;
			container.m_height = num2;
			s_invWidth?.SetValue(inventory, num);
			s_invHeight?.SetValue(inventory, num2);
			s_invName?.SetValue(inventory, tier.Name);
		}

		public void Upgrade(Player player)
		{
			PerchTier nextTier = NextTier;
			if (Zdo == null || !Object.op_Implicit((Object)(object)player) || nextTier == null || !EnsureOwner(player))
			{
				return;
			}
			if (nextTier.MissingItems().Count > 0)
			{
				((Character)player).Message((MessageType)2, nextTier.Name + " needs items this game doesn't have yet (see config)", 0, (Sprite)null, false);
				return;
			}
			Inventory inventory = ((Humanoid)player).GetInventory();
			foreach (KeyValuePair<string, int> item in nextTier.Requirements())
			{
				ItemData val = PerchTiers.ItemData(item.Key);
				if (inventory.CountItems(val.m_shared.m_name, -1, true) < item.Value)
				{
					((Character)player).Message((MessageType)2, Localization.instance.Localize($"Not enough {val.m_shared.m_name} ({item.Value} needed)"), 0, (Sprite)null, false);
					return;
				}
			}
			foreach (KeyValuePair<string, int> item2 in nextTier.Requirements())
			{
				inventory.RemoveItem(PerchTiers.ItemData(item2.Key).m_shared.m_name, item2.Value, -1, true);
			}
			Zdo.Set("ravenpost_tier", nextTier.Index);
			ApplyTier(_container, nextTier);
			((Character)player).Message((MessageType)2, $"Upgraded to {nextTier.Name}: {nextTier.CargoWidth}x{nextTier.CargoHeight} cargo, {RavenFood.FormatSpeed(nextTier.SpeedMultiplier)} speed", 0, (Sprite)null, false);
			Plugin.Log.LogInfo((object)("'" + PerchName + "' upgraded to " + nextTier.Name));
		}

		public string GetText()
		{
			ZDO zdo = Zdo;
			return ((zdo != null) ? zdo.GetString("ravenpost_name", "") : null) ?? "";
		}

		public void SetText(string text)
		{
			if (Zdo != null && EnsureOwner(Player.m_localPlayer))
			{
				text = (text ?? "").Trim();
				Zdo.Set("ravenpost_name", text);
				PostOffice.InvalidatePerches();
			}
		}

		internal List<PerchInfo> Destinations()
		{
			if (Zdo != null)
			{
				return (from p in PostOffice.GetPerches()
					where p.Id != Zdo.m_uid
					select p).ToList();
			}
			return new List<PerchInfo>();
		}

		internal PerchInfo SelectedDestination(List<PerchInfo> destinations)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			if (destinations.Count == 0)
			{
				return null;
			}
			PerchInfo perchInfo = destinations.FirstOrDefault((PerchInfo p) => p.Id == _selectedDestination);
			if (perchInfo == null)
			{
				perchInfo = destinations[0];
				_selectedDestination = perchInfo.Id;
			}
			return perchInfo;
		}

		public void Select(ZDOID destination)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			_selectedDestination = destination;
		}

		internal float DistanceTo(PerchInfo destination)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			return Vector3.Distance(((Component)this).transform.position, destination.Position);
		}

		private bool EnsureOwner(Player player)
		{
			if (Zdo == null)
			{
				return false;
			}
			if (_nview.IsOwner())
			{
				return true;
			}
			if (!_container.IsInUse() && Zdo.GetInt(ZDOVars.s_inUse, 0) == 0)
			{
				_nview.ClaimOwnership();
			}
			if (!_nview.IsOwner())
			{
				if (Object.op_Implicit((Object)(object)player))
				{
					((Character)player).Message((MessageType)2, "Someone else is using this perch", 0, (Sprite)null, false);
				}
				return false;
			}
			return true;
		}

		public bool TooHeavy(float weight)
		{
			if (WeightLimited)
			{
				return weight > MaxCargoWeight + 0.001f;
			}
			return false;
		}

		private void RecordFlight()
		{
			if (FlightsLimited && Zdo != null)
			{
				Zdo.Set("ravenpost_flights", $"{CurrentPeriod}:{FlightsUsed + 1}");
			}
		}

		internal float FlightSecondsTo(PerchInfo destination)
		{
			return PostOffice.FlightSeconds(DistanceTo(destination), CargoWeight) / (NextMealSpeed * Tier.SpeedMultiplier);
		}

		internal float LetterSecondsTo(PerchInfo destination)
		{
			return PostOffice.FlightSeconds(DistanceTo(destination), 0f) / Tier.SpeedMultiplier;
		}

		public bool Feed(Player player, ItemData item)
		{
			if (Zdo == null || !Object.op_Implicit((Object)(object)player))
			{
				return false;
			}
			float num = RavenFood.SpeedFor(item);
			if (num <= 0f)
			{
				return false;
			}
			if (!EnsureOwner(player))
			{
				return true;
			}
			List<float> meals = Meals;
			int num2 = Mathf.Max(1, Plugin.MaxMeals.Value);
			if (meals.Count >= num2)
			{
				((Character)player).Message((MessageType)2, "The raven is full", 0, (Sprite)null, false);
				return true;
			}
			if (!((Humanoid)player).GetInventory().RemoveOneItem(item))
			{
				return true;
			}
			meals.Add(num);
			RavenFood.WriteMeals(Zdo, meals);
			((Character)player).Message((MessageType)2, Localization.instance.Localize($"The raven ate {item.m_shared.m_name} ({RavenFood.FormatSpeed(num)} speed) - {meals.Count}/{num2} meals"), 0, (Sprite)null, false);
			return true;
		}

		public void FeedBest(Player player)
		{
			ItemData val = RavenFood.BestFood(((Humanoid)player).GetInventory());
			if (val == null)
			{
				((Character)player).Message((MessageType)2, "You have nothing the raven will eat", 0, (Sprite)null, false);
			}
			else
			{
				Feed(player, val);
			}
		}

		public void NextDestination()
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			if (Zdo == null)
			{
				return;
			}
			List<PerchInfo> list = Destinations();
			if (list.Count != 0)
			{
				int num = list.FindIndex((PerchInfo p) => p.Id == _selectedDestination);
				_selectedDestination = list[(num + 1) % list.Count].Id;
			}
		}

		public void Send(Player player)
		{
			//IL_0202: 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_0236: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a8: 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_02cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d3: Unknown result type (might be due to invalid IL or missing references)
			if (Zdo == null || !PostOffice.IsActive || !EnsureOwner(player))
			{
				return;
			}
			PerchInfo perchInfo = SelectedDestination(Destinations());
			if (perchInfo == null)
			{
				((Character)player).Message((MessageType)2, "Build another Raven Perch to send to", 0, (Sprite)null, false);
				return;
			}
			Inventory inventory = _container.GetInventory();
			List<ItemData> list = inventory.GetAllItems().ToList();
			string draft = Draft;
			bool flag = !string.IsNullOrEmpty(draft);
			if (list.Count == 0 && !flag)
			{
				((Character)player).Message((MessageType)2, "Put some cargo in the perch or write a note first", 0, (Sprite)null, false);
				return;
			}
			bool flag2 = list.Count == 0;
			if (!Plugin.AllowNonTeleportable.Value && !ZoneSystem.instance.GetGlobalKey((GlobalKeys)35))
			{
				ItemData val = ((IEnumerable<ItemData>)list).FirstOrDefault((Func<ItemData, bool>)((ItemData i) => !i.m_shared.m_teleportable));
				if (val != null)
				{
					((Character)player).Message((MessageType)2, Localization.instance.Localize("Ravens refuse to carry " + val.m_shared.m_name), 0, (Sprite)null, false);
					return;
				}
			}
			float totalWeight = inventory.GetTotalWeight();
			if (!flag2 && TooHeavy(totalWeight))
			{
				((Character)player).Message((MessageType)2, $"Too heavy for the raven: {totalWeight:0.#} / {MaxCargoWeight:0.#}", 0, (Sprite)null, false);
				return;
			}
			bool flag3 = !flag2 || Plugin.LettersCountAsFlights.Value;
			if (flag3 && FlightsLimited && FlightsLeft <= 0)
			{
				((Character)player).Message((MessageType)2, "The raven is tired - it rests until the next day", 0, (Sprite)null, false);
				return;
			}
			if (!flag2 && RefusesToFly)
			{
				((Character)player).Message((MessageType)2, "Your raven is hungry - feed it first", 0, (Sprite)null, false);
				return;
			}
			List<float> meals = Meals;
			float num = (flag2 ? 1f : NextMealSpeed);
			float num2 = DistanceTo(perchInfo);
			float num3 = PostOffice.FlightSeconds(num2, totalWeight) / (num * Tier.SpeedMultiplier);
			Delivery d = new Delivery
			{
				ArriveAt = PostOffice.Now + (double)num3,
				From = PerchName,
				Notified = false,
				Items = PostOffi