Decompiled source of Mailbox v1.0.0

plugins/Mailbox.dll

Decompiled 3 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using System.Threading;
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 Splatform;
using UnityEngine;
using UnityEngine.Networking;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Mailbox")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Mailbox")]
[assembly: AssemblyTitle("Mailbox")]
[assembly: AssemblyVersion("1.0.0.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 Mailbox
{
	internal sealed class ConfigurationManagerAttributes
	{
		public int? Order;

		public bool? HideDefaultButton;

		public Action<ConfigEntryBase> CustomDrawer;
	}
	internal static class FilePicker
	{
		[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
		private class OpenFileName
		{
			public int lStructSize;

			public IntPtr hwndOwner;

			public IntPtr hInstance;

			public string lpstrFilter;

			public string lpstrCustomFilter;

			public int nMaxCustFilter;

			public int nFilterIndex;

			public string lpstrFile;

			public int nMaxFile;

			public string lpstrFileTitle;

			public int nMaxFileTitle;

			public string lpstrInitialDir;

			public string lpstrTitle;

			public int Flags;

			public short nFileOffset;

			public short nFileExtension;

			public string lpstrDefExt;

			public IntPtr lCustData;

			public IntPtr lpfnHook;

			public string lpTemplateName;

			public IntPtr pvReserved;

			public int dwReserved;

			public int FlagsEx;
		}

		private const int OFN_NOCHANGEDIR = 8;

		private const int OFN_PATHMUSTEXIST = 2048;

		private const int OFN_FILEMUSTEXIST = 4096;

		private const int OFN_EXPLORER = 524288;

		private static volatile bool _isOpen;

		private static volatile string _result;

		public static bool IsSupported
		{
			get
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0006: Invalid comparison between Unknown and I4
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				//IL_000e: Invalid comparison between Unknown and I4
				if ((int)Application.platform != 2)
				{
					return (int)Application.platform == 7;
				}
				return true;
			}
		}

		public static bool IsOpen => _isOpen;

		public static void Open()
		{
			if (!_isOpen && IsSupported)
			{
				_isOpen = true;
				IntPtr owner = GetActiveWindow();
				Thread thread = new Thread((ThreadStart)delegate
				{
					Run(owner);
				});
				thread.IsBackground = true;
				thread.Name = "Mailbox file picker";
				thread.SetApartmentState(ApartmentState.STA);
				thread.Start();
			}
		}

		public static bool TryTakeResult(out string path)
		{
			path = _result;
			if (path == null)
			{
				return false;
			}
			_result = null;
			return true;
		}

		private static void Run(IntPtr owner)
		{
			try
			{
				OpenFileName openFileName = new OpenFileName
				{
					hwndOwner = owner,
					lpstrFilter = "Audio files (*.wav, *.ogg, *.mp3)\0*.wav;*.ogg;*.mp3\0All files (*.*)\0*.*\0\0",
					lpstrFile = new string('\0', 1024),
					lpstrTitle = "Mailbox - choose a sound",
					Flags = 530440
				};
				openFileName.nMaxFile = openFileName.lpstrFile.Length;
				openFileName.lStructSize = Marshal.SizeOf(openFileName);
				if (GetOpenFileNameW(openFileName))
				{
					string text = openFileName.lpstrFile?.TrimEnd('\0');
					if (!string.IsNullOrEmpty(text))
					{
						_result = text;
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Could not open the file dialog: " + ex.Message));
			}
			finally
			{
				_isOpen = false;
			}
		}

		[DllImport("user32.dll")]
		private static extern IntPtr GetActiveWindow();

		[DllImport("comdlg32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
		private static extern bool GetOpenFileNameW([In][Out] OpenFileName ofn);
	}
	internal class Letter
	{
		public long Id;

		public string Sender;

		public string Text;

		public long SentTicks;

		public bool Read;
	}
	internal static class LetterStore
	{
		public const int MaxLetters = 20;

		public const int MaxLength = 300;

		public const string ZdoKey = "batera_mailbox_letters";

		private const int FormatVersion = 1;

		private const string ZeroWidthSpace = "\u200b";

		public static List<Letter> Load(ZDO zdo)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			List<Letter> list = new List<Letter>();
			string text = ((zdo != null) ? zdo.GetString("batera_mailbox_letters", "") : null);
			if (string.IsNullOrEmpty(text))
			{
				return list;
			}
			try
			{
				ZPackage val = new ZPackage(text);
				if (val.ReadInt() != 1)
				{
					return list;
				}
				int num = val.ReadInt();
				for (int i = 0; i < num; i++)
				{
					list.Add(new Letter
					{
						Id = val.ReadLong(),
						Sender = val.ReadString(),
						Text = val.ReadString(),
						SentTicks = val.ReadLong(),
						Read = val.ReadBool()
					});
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Could not read mailbox letters: " + ex.Message));
			}
			return list;
		}

		public static void Save(ZDO zdo, List<Letter> letters)
		{
			//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(1);
			val.Write(letters.Count);
			foreach (Letter letter in letters)
			{
				val.Write(letter.Id);
				val.Write(letter.Sender ?? "");
				val.Write(letter.Text ?? "");
				val.Write(letter.SentTicks);
				val.Write(letter.Read);
			}
			zdo.Set("batera_mailbox_letters", val.GetBase64());
		}

		public static string Sanitize(string text)
		{
			if (text == null)
			{
				return "";
			}
			text = text.Replace('<', ' ').Replace('>', ' ').Replace("$", "$\u200b")
				.Trim();
			if (text.Length <= 300)
			{
				return text;
			}
			return text.Substring(0, 300);
		}

		public static string ForRuneFont(string text)
		{
			if (string.IsNullOrEmpty(text))
			{
				return "";
			}
			StringBuilder stringBuilder = new StringBuilder(text.Length);
			string text2 = text.Replace("\u200b", "").Normalize(NormalizationForm.FormD);
			foreach (char c in text2)
			{
				if (CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark)
				{
					stringBuilder.Append(c);
				}
			}
			return stringBuilder.ToString().Normalize(NormalizationForm.FormC);
		}
	}
	internal class MailboxComponent : MonoBehaviour, Hoverable, Interactable, TextReceiver
	{
		private const string RpcAdd = "Batera_Mailbox_Add";

		private const string RpcMarkRead = "Batera_Mailbox_MarkRead";

		private const string RpcDelete = "Batera_Mailbox_Delete";

		private const string OwnerNameKey = "batera_mailbox_owner";

		private const float WriteCooldown = 10f;

		private const float AnnounceDistance = 15f;

		private static float s_lastWriteTime = -999f;

		private ZNetView _nview;

		private Piece _piece;

		private Transform _flag;

		private float _flagAngle = 90f;

		private long _lastReadId;

		private bool _writeAnonymous;

		private bool _announced;

		private string _cachedData;

		private List<Letter> _cachedLetters = new List<Letter>();

		private void Awake()
		{
			_nview = ((Component)this).GetComponent<ZNetView>();
			_piece = ((Component)this).GetComponent<Piece>();
			_flag = ((Component)this).transform.Find("mailbox_model/flag_pivot");
			if (!((Object)(object)_nview == (Object)null) && _nview.GetZDO() != null)
			{
				_nview.Register<string, string, long>("Batera_Mailbox_Add", (Action<long, string, string, long>)RPC_Add);
				_nview.Register<long>("Batera_Mailbox_MarkRead", (Action<long, long>)RPC_MarkRead);
				_nview.Register<long>("Batera_Mailbox_Delete", (Action<long, long>)RPC_Delete);
			}
		}

		private void Start()
		{
			if (IsValid() && _nview.IsOwner() && IsMine())
			{
				ZDO zDO = _nview.GetZDO();
				if (string.IsNullOrEmpty(zDO.GetString("batera_mailbox_owner", "")) && (Object)(object)Player.m_localPlayer != (Object)null)
				{
					zDO.Set("batera_mailbox_owner", Player.m_localPlayer.GetPlayerName());
				}
			}
		}

		private void Update()
		{
			//IL_0067: 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_00ae: Unknown result type (might be due to invalid IL or missing references)
			if (IsValid())
			{
				int num = CountUnread(Letters());
				float num2 = ((num > 0) ? 0f : 90f);
				_flagAngle = Mathf.MoveTowards(_flagAngle, num2, 180f * Time.deltaTime);
				if ((Object)(object)_flag != (Object)null)
				{
					_flag.localRotation = Quaternion.Euler(_flagAngle, 0f, 0f);
				}
				if (num == 0)
				{
					_announced = false;
				}
				else if (!_announced && IsMine() && (Object)(object)Player.m_localPlayer != (Object)null && Vector3.Distance(((Component)Player.m_localPlayer).transform.position, ((Component)this).transform.position) < 15f)
				{
					_announced = true;
					Message((MessageType)2, Translations.Format("$batera_mailbox_you_have_mail", num));
				}
			}
		}

		public string GetHoverName()
		{
			return Translations.Get("$piece_batera_mailbox");
		}

		public float GetHoverOffset()
		{
			return 0f;
		}

		public string GetHoverText()
		{
			if (!IsValid())
			{
				return "";
			}
			string text = _nview.GetZDO().GetString("batera_mailbox_owner", "");
			string text2 = (string.IsNullOrEmpty(text) ? Translations.Get("$piece_batera_mailbox") : Translations.Format("$batera_mailbox_owned_by", text));
			List<Letter> list = Letters();
			if (IsMine())
			{
				if (list.Count == 0)
				{
					return text2 + "\n" + Translations.Get("$batera_mailbox_empty");
				}
				text2 = text2 + "\n" + Translations.Format("$batera_mailbox_counts", CountUnread(list), list.Count);
				text2 = text2 + "\n" + Translations.Get("[<color=yellow><b>$KEY_Use</b></color>] $batera_mailbox_read");
				if (_lastReadId != 0L)
				{
					text2 = text2 + "\n" + Translations.Get("[<color=yellow><b>" + AltKey() + " + $KEY_Use</b></color>] $batera_mailbox_delete");
				}
				return text2;
			}
			if (list.Count >= 20)
			{
				return text2 + "\n" + Translations.Get("$batera_mailbox_full");
			}
			return text2 + "\n" + Translations.Get("[<color=yellow><b>$KEY_Use</b></color>] $batera_mailbox_write") + "\n" + Translations.Get("[<color=yellow><b>" + AltKey() + " + $KEY_Use</b></color>] $batera_mailbox_write_anonymous");
		}

		private static string AltKey()
		{
			if (!ZInput.IsNonClassicFunctionality() || !ZInput.IsGamepadActive())
			{
				return "$KEY_AltPlace";
			}
			return "$KEY_AltKeys";
		}

		public bool Interact(Humanoid user, bool hold, bool alt)
		{
			if (hold || !IsValid())
			{
				return false;
			}
			if (IsMine())
			{
				if (alt)
				{
					DeleteLastRead();
				}
				else
				{
					ReadNext();
				}
				return true;
			}
			if (Letters().Count >= 20)
			{
				Message((MessageType)2, Translations.Get("$batera_mailbox_full"));
				return true;
			}
			if (Time.time - s_lastWriteTime < 10f || (Object)(object)TextInput.instance == (Object)null)
			{
				return true;
			}
			_writeAnonymous = alt;
			string text = _nview.GetZDO().GetString("batera_mailbox_owner", "");
			string text2 = Translations.Format(alt ? "$batera_mailbox_write_topic_anonymous" : "$batera_mailbox_write_topic", text);
			TextInput.instance.RequestText((TextReceiver)(object)this, text2, 300);
			return true;
		}

		public bool UseItem(Humanoid user, ItemData item)
		{
			return false;
		}

		public string GetText()
		{
			return "";
		}

		public void SetText(string text)
		{
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			text = LetterStore.Sanitize(text);
			if (!string.IsNullOrEmpty(text) && IsValid())
			{
				s_lastWriteTime = Time.time;
				string text2 = (_writeAnonymous ? "" : (((Object)(object)Player.m_localPlayer != (Object)null) ? Player.m_localPlayer.GetPlayerName() : "?"));
				long num = DateTime.UtcNow.Ticks + Random.Range(0, 10000);
				_nview.InvokeRPC("Batera_Mailbox_Add", new object[3] { text2, text, num });
				if ((Object)(object)_piece != (Object)null)
				{
					OwnerNotify.Send(_piece.GetCreator(), text2, ((Component)this).transform.position);
				}
				string text3 = _nview.GetZDO().GetString("batera_mailbox_owner", "");
				Message((MessageType)2, Translations.Format("$batera_mailbox_sent", text3));
			}
		}

		private void ReadNext()
		{
			List<Letter> list = Letters();
			if (list.Count == 0)
			{
				Message((MessageType)2, Translations.Get("$batera_mailbox_empty"));
				return;
			}
			Letter letter = list.Find((Letter l) => !l.Read);
			if (letter == null)
			{
				int num = list.FindIndex((Letter l) => l.Id == _lastReadId);
				letter = list[(num + 1) % list.Count];
			}
			string text = new DateTime(letter.SentTicks, DateTimeKind.Utc).ToLocalTime().ToString("dd/MM/yyyy HH:mm");
			string text2 = (string.IsNullOrEmpty(letter.Sender) ? Translations.Get("$batera_mailbox_anonymous_letter") : Translations.Format("$batera_mailbox_letter_from", LetterStore.Sanitize(letter.Sender)));
			TextViewer instance = TextViewer.instance;
			if ((Object)(object)instance != (Object)null)
			{
				instance.ShowText((Style)0, text2, letter.Text + "\n\n" + text, true);
				if ((Object)(object)instance.m_runeText != (Object)null)
				{
					instance.m_runeText.text = LetterStore.ForRuneFont(letter.Text);
				}
			}
			_lastReadId = letter.Id;
			if (!letter.Read)
			{
				_nview.InvokeRPC("Batera_Mailbox_MarkRead", new object[1] { letter.Id });
			}
		}

		private void DeleteLastRead()
		{
			if (_lastReadId != 0L)
			{
				_nview.InvokeRPC("Batera_Mailbox_Delete", new object[1] { _lastReadId });
				_lastReadId = 0L;
				TextViewer instance = TextViewer.instance;
				if (instance != null)
				{
					instance.Hide();
				}
				Message((MessageType)2, Translations.Get("$batera_mailbox_deleted"));
			}
		}

		private void RPC_Add(long sender, string from, string text, long id)
		{
			if (_nview.IsOwner())
			{
				List<Letter> list = LetterStore.Load(_nview.GetZDO());
				if (list.Count < 20 && !list.Exists((Letter l) => l.Id == id))
				{
					list.Add(new Letter
					{
						Id = id,
						Sender = from,
						Text = LetterStore.Sanitize(text),
						SentTicks = DateTime.UtcNow.Ticks
					});
					LetterStore.Save(_nview.GetZDO(), list);
				}
			}
		}

		private void RPC_MarkRead(long sender, long id)
		{
			if (_nview.IsOwner())
			{
				List<Letter> list = LetterStore.Load(_nview.GetZDO());
				Letter letter = list.Find((Letter l) => l.Id == id);
				if (letter != null && !letter.Read)
				{
					letter.Read = true;
					LetterStore.Save(_nview.GetZDO(), list);
				}
			}
		}

		private void RPC_Delete(long sender, long id)
		{
			if (_nview.IsOwner())
			{
				List<Letter> list = LetterStore.Load(_nview.GetZDO());
				if (list.RemoveAll((Letter l) => l.Id == id) > 0)
				{
					LetterStore.Save(_nview.GetZDO(), list);
				}
			}
		}

		private bool IsValid()
		{
			if ((Object)(object)_nview != (Object)null)
			{
				return _nview.IsValid();
			}
			return false;
		}

		public bool HasLetters()
		{
			if (IsValid())
			{
				return Letters().Count > 0;
			}
			return false;
		}

		public bool IsMine()
		{
			if ((Object)(object)_piece != (Object)null)
			{
				return _piece.IsCreator();
			}
			return false;
		}

		private List<Letter> Letters()
		{
			string text = _nview.GetZDO().GetString("batera_mailbox_letters", "");
			if ((object)text != _cachedData && text != _cachedData)
			{
				_cachedData = text;
				_cachedLetters = LetterStore.Load(_nview.GetZDO());
			}
			return _cachedLetters;
		}

		private static int CountUnread(List<Letter> letters)
		{
			int num = 0;
			foreach (Letter letter in letters)
			{
				if (!letter.Read)
				{
					num++;
				}
			}
			return num;
		}

		private static void Message(MessageType type, string text)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)MessageHud.instance != (Object)null)
			{
				MessageHud.instance.ShowMessage(type, text, 0, (Sprite)null, false, true);
			}
		}
	}
	internal static class MailboxModel
	{
		public const string FlagPath = "mailbox_model/flag_pivot";

		private static readonly Color IronFallback = new Color(0.35f, 0.35f, 0.38f);

		private static readonly Color DoorColor = new Color(0.62f, 0.5f, 0.4f);

		private static readonly Color FlagColor = new Color(0.75f, 0.12f, 0.08f);

		public static void Apply(GameObject prefab)
		{
			//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_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Expected O, but got Unknown
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: 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_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0296: Unknown result type (might be due to invalid IL or missing references)
			//IL_02aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0306: Unknown result type (might be due to invalid IL or missing references)
			//IL_030b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0318: Unknown result type (might be due to invalid IL or missing references)
			//IL_0326: Unknown result type (might be due to invalid IL or missing references)
			//IL_033b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0345: Unknown result type (might be due to invalid IL or missing references)
			//IL_035a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0364: Unknown result type (might be due to invalid IL or missing references)
			//IL_0381: Unknown result type (might be due to invalid IL or missing references)
			//IL_0395: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03da: Unknown result type (might be due to invalid IL or missing references)
			//IL_0406: Unknown result type (might be due to invalid IL or missing references)
			//IL_041f: Unknown result type (might be due to invalid IL or missing references)
			Material val = FirstMaterial(prefab);
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogError((object)"Mailbox: base prefab has no material to reuse.");
				return;
			}
			Material material = ItemMaterial("Iron") ?? Tinted(val, IronFallback);
			Material material2 = Tinted(val, DoorColor);
			Material material3 = Tinted(val, FlagColor);
			RemoveBaseVisuals(prefab);
			GameObject val2 = new GameObject("mailbox_model");
			val2.transform.SetParent(prefab.transform, false);
			val2.layer = LayerMask.NameToLayer("piece");
			Mesh mesh = PrimitiveMesh((PrimitiveType)3);
			Mesh mesh2 = PrimitiveMesh((PrimitiveType)2);
			Transform transform = val2.transform;
			Part(transform, "foot", mesh, val, new Vector3(0f, 0.02f, 0f), new Vector3(0.26f, 0.04f, 0.26f));
			Part(transform, "post", mesh, val, new Vector3(0f, 0.5f, 0f), new Vector3(0.09f, 1f, 0.09f));
			Part(transform, "box", mesh, val, new Vector3(0f, 1.11f, 0f), new Vector3(0.28f, 0.22f, 0.46f));
			Part(transform, "roof", mesh2, val, new Vector3(0f, 1.22f, 0f), new Vector3(0.28f, 0.23f, 0.28f), Quaternion.Euler(90f, 0f, 0f));
			float[] array = new float[2] { -0.15f, 0.15f };
			foreach (float num in array)
			{
				Part(transform, "band", mesh, material, new Vector3(0f, 1.11f, num), new Vector3(0.295f, 0.225f, 0.025f));
				Part(transform, "band_roof", mesh2, material, new Vector3(0f, 1.22f, num), new Vector3(0.295f, 0.0125f, 0.295f), Quaternion.Euler(90f, 0f, 0f));
			}
			Part(transform, "door", mesh, material2, new Vector3(0f, 1.13f, 0.233f), new Vector3(0.22f, 0.24f, 0.012f));
			Part(transform, "handle", mesh, material, new Vector3(0f, 1.2f, 0.245f), new Vector3(0.06f, 0.015f, 0.02f));
			GameObject val3 = new GameObject("flag_pivot")
			{
				layer = val2.layer
			};
			val3.transform.SetParent(transform, false);
			val3.transform.localPosition = new Vector3(0.15f, 1.08f, -0.08f);
			val3.transform.localRotation = Quaternion.Euler(90f, 0f, 0f);
			Part(val3.transform, "flag_pole", mesh, material, new Vector3(0.01f, 0.12f, 0f), new Vector3(0.015f, 0.24f, 0.015f));
			Part(val3.transform, "flag", mesh, material3, new Vector3(0.01f, 0.2f, 0.06f), new Vector3(0.012f, 0.08f, 0.11f));
			BoxCollider obj = val2.AddComponent<BoxCollider>();
			obj.center = new Vector3(0f, 0.68f, 0f);
			obj.size = new Vector3(0.34f, 1.36f, 0.5f);
			WearNTear component = prefab.GetComponent<WearNTear>();
			if ((Object)(object)component != (Object)null)
			{
				component.m_new = val2;
				component.m_worn = val2;
				component.m_broken = val2;
				component.m_wet = null;
				component.m_fragmentRoots = null;
			}
		}

		private static void RemoveBaseVisuals(GameObject prefab)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			List<GameObject> list = new List<GameObject>();
			foreach (Transform item in prefab.transform)
			{
				Transform val = item;
				list.Add(((Component)val).gameObject);
			}
			foreach (GameObject item2 in list)
			{
				Object.DestroyImmediate((Object)(object)item2);
			}
			LODGroup[] components = prefab.GetComponents<LODGroup>();
			for (int i = 0; i < components.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)components[i]);
			}
			Renderer[] components2 = prefab.GetComponents<Renderer>();
			for (int i = 0; i < components2.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)components2[i]);
			}
			MeshFilter[] components3 = prefab.GetComponents<MeshFilter>();
			for (int i = 0; i < components3.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)components3[i]);
			}
			Collider[] components4 = prefab.GetComponents<Collider>();
			for (int i = 0; i < components4.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)components4[i]);
			}
		}

		private static GameObject Part(Transform parent, string name, Mesh mesh, Material material, Vector3 position, Vector3 scale, Quaternion? rotation = null)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: 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_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Expected O, but got Unknown
			GameObject val = new GameObject(name)
			{
				layer = ((Component)parent).gameObject.layer
			};
			val.transform.SetParent(parent, false);
			val.transform.localPosition = position;
			val.transform.localRotation = (Quaternion)(((??)rotation) ?? Quaternion.identity);
			val.transform.localScale = scale;
			val.AddComponent<MeshFilter>().sharedMesh = mesh;
			((Renderer)val.AddComponent<MeshRenderer>()).sharedMaterial = material;
			return val;
		}

		private static Mesh PrimitiveMesh(PrimitiveType type)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = GameObject.CreatePrimitive(type);
			Mesh sharedMesh = obj.GetComponent<MeshFilter>().sharedMesh;
			Object.DestroyImmediate((Object)(object)obj);
			return sharedMesh;
		}

		private static Material FirstMaterial(GameObject go)
		{
			MeshRenderer[] componentsInChildren = go.GetComponentsInChildren<MeshRenderer>(true);
			foreach (MeshRenderer val in componentsInChildren)
			{
				if ((Object)(object)((Renderer)val).sharedMaterial != (Object)null)
				{
					return ((Renderer)val).sharedMaterial;
				}
			}
			return null;
		}

		private static Material ItemMaterial(string itemPrefab)
		{
			GameObject prefab = Cache.GetPrefab<GameObject>(itemPrefab);
			if (!((Object)(object)prefab != (Object)null))
			{
				return null;
			}
			return FirstMaterial(prefab);
		}

		private static Material Tinted(Material source, Color color)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			Material val = new Material(source)
			{
				name = ((Object)source).name + "_mailbox"
			};
			if (val.HasProperty("_Color"))
			{
				val.color = color;
			}
			return val;
		}
	}
	internal static class MailboxPiece
	{
		public const string PrefabName = "piece_batera_mailbox";

		private const string BasePrefab = "itemstand";

		public static void Register()
		{
			PrefabManager.OnVanillaPrefabsAvailable += AddPiece;
		}

		private static void AddPiece()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Expected O, but got Unknown
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Expected O, but got Unknown
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Expected O, but got Unknown
			PrefabManager.OnVanillaPrefabsAvailable -= AddPiece;
			PieceConfig val = new PieceConfig();
			val.Name = "$piece_batera_mailbox";
			val.Description = "$piece_batera_mailbox_desc";
			val.PieceTable = PieceTables.Hammer;
			val.Category = PieceCategories.Furniture;
			val.CraftingStation = CraftingStations.Workbench;
			val.Requirements = (RequirementConfig[])(object)new RequirementConfig[2]
			{
				new RequirementConfig("Wood", 4, 0, true),
				new RequirementConfig("Copper", 1, 0, true)
			};
			PieceConfig val2 = val;
			CustomPiece val3 = new CustomPiece("piece_batera_mailbox", "itemstand", val2);
			if (!val3.IsValid())
			{
				Plugin.Log.LogError((object)"Could not create the mailbox piece from 'itemstand'.");
				return;
			}
			ReplaceBehaviour(val3.PiecePrefab);
			MailboxModel.Apply(val3.PiecePrefab);
			val3.PiecePrefab.AddComponent<MailboxComponent>();
			SetIcon(val3);
			PieceManager.Instance.AddPiece(val3);
		}

		private static void SetIcon(CustomPiece piece)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			Sprite val = RenderManager.Instance.Render(piece.PiecePrefab, Quaternion.Euler(12f, 35f, 0f));
			if ((Object)(object)val != (Object)null)
			{
				piece.Piece.m_icon = val;
			}
			else
			{
				Plugin.Log.LogWarning((object)"Could not render the mailbox icon; using the base piece icon.");
			}
		}

		private static void ReplaceBehaviour(GameObject prefab)
		{
			MonoBehaviour[] componentsInChildren = prefab.GetComponentsInChildren<MonoBehaviour>(true);
			foreach (MonoBehaviour val in componentsInChildren)
			{
				if (val is Interactable || val is Hoverable || val is TextReceiver)
				{
					Object.DestroyImmediate((Object)(object)val);
				}
			}
		}
	}
	internal static class MapPing
	{
		public static void Show(Vector3 position, string label, float seconds)
		{
			//IL_0028: 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_0038: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)Minimap.instance == (Object)null) && !(seconds <= 0f) && !((Object)(object)SoundPlayer.Instance == (Object)null))
			{
				PinData pin = Minimap.instance.AddPin(position, (PinType)12, label, false, false, 0L, default(PlatformUserID));
				((MonoBehaviour)SoundPlayer.Instance).StartCoroutine(RemoveLater(pin, seconds));
			}
		}

		private static IEnumerator RemoveLater(PinData pin, float seconds)
		{
			yield return (object)new WaitForSeconds(seconds);
			if ((Object)(object)Minimap.instance != (Object)null)
			{
				Minimap.instance.RemovePin(pin);
			}
		}
	}
	internal static class OwnerNotify
	{
		[HarmonyPatch(typeof(Game), "Start")]
		private static class GameStartPatch
		{
			private static void Postfix()
			{
				ZRoutedRpc instance = ZRoutedRpc.instance;
				if (instance != null)
				{
					instance.Register<long, string, Vector3>("Batera_Mailbox_NotifyOwner", (Action<long, long, string, Vector3>)RPC_NotifyOwner);
				}
			}
		}

		private const string RpcNotify = "Batera_Mailbox_NotifyOwner";

		public static void Send(long ownerId, string sender, Vector3 position)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			if (ownerId != 0L && ZRoutedRpc.instance != null)
			{
				ZRoutedRpc.instance.InvokeRoutedRPC(0L, "Batera_Mailbox_NotifyOwner", new object[3] { ownerId, sender, position });
			}
		}

		private static void RPC_NotifyOwner(long peer, long ownerId, string sender, Vector3 position)
		{
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || localPlayer.GetPlayerID() != ownerId || !Plugin.NotifyNewLetter.Value)
			{
				return;
			}
			SoundPlayer.Instance?.Play2D();
			if (string.IsNullOrEmpty(sender))
			{
				sender = Translations.Get("$batera_mailbox_anonymous");
			}
			if ((Object)(object)MessageHud.instance != (Object)null)
			{
				string text = Plugin.NotifyMessage.Value;
				if (string.IsNullOrWhiteSpace(text))
				{
					text = "Nova carta de {player}!";
				}
				MessageHud.instance.ShowMessage((MessageType)2, text.Replace("{player}", sender), 0, (Sprite)null, false, true);
			}
			MapPing.Show(position, Translations.Format("$batera_mailbox_new_letter_pin", sender), Plugin.MapPingSeconds.Value);
		}
	}
	[BepInPlugin("batera.Mailbox", "Mailbox", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "batera.Mailbox";

		public const string PluginName = "Mailbox";

		public const string PluginVersion = "1.0.0";

		internal static Plugin Instance;

		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> NotifyNewLetter;

		internal static ConfigEntry<string> NotifyMessage;

		internal static ConfigEntry<float> MapPingSeconds;

		internal static ConfigEntry<SoundPreset> SoundPresetSetting;

		internal static ConfigEntry<string> SoundFile;

		internal static ConfigEntry<float> Volume;

		private Harmony _harmony;

		private void Awake()
		{
			//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_0027: Expected O, but got Unknown
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			BindConfig();
			GameObject val = new GameObject("Mailbox");
			Object.DontDestroyOnLoad((Object)val);
			val.AddComponent<SoundPlayer>();
			Translations.Register();
			MailboxPiece.Register();
			_harmony = new Harmony("batera.Mailbox");
			_harmony.PatchAll(typeof(Plugin).Assembly);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Mailbox 1.0.0 loaded");
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		private void BindConfig()
		{
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Expected O, but got Unknown
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Expected O, but got Unknown
			NotifyNewLetter = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - New letters", "Notify", true, Desc("When someone writes to your mailbox, play a sound and show a message wherever you are.", 3));
			NotifyMessage = ((BaseUnityPlugin)this).Config.Bind<string>("1 - New letters", "MessageText", "Nova carta de {player}!", Desc("Message shown when you get a letter. {player} = who wrote it.", 2));
			MapPingSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("1 - New letters", "MapPingSeconds", 30f, Desc("How long (seconds) your mailbox stays marked on your map after a new letter. Only you see it. 0 = off.", 1, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 300f)));
			SoundPresetSetting = ((BaseUnityPlugin)this).Config.Bind<SoundPreset>("2 - Sound", "SoundPreset", SoundPreset.MagicBells, Desc("Sound for new letters. DingDong is built into the mod; MagicBells, Knock and Forge are game sounds; Custom uses SoundFile.", 5));
			Volume = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Sound", "Volume", 0.7f, Desc("Sound volume.", 4, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f)));
			SoundFile = ((BaseUnityPlugin)this).Config.Bind<string>("2 - Sound", "SoundFile", "", new ConfigDescription("Custom sound file (.wav, .ogg or .mp3), used when SoundPreset = Custom. Click Browse to pick a file, or Reset to clear it.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 3,
					CustomDrawer = DrawSoundFile
				}
			}));
			((BaseUnityPlugin)this).Config.Bind<string>("2 - Sound", "TestSound", "", new ConfigDescription("Plays the new letter sound with the current settings.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 2,
					HideDefaultButton = true,
					CustomDrawer = DrawTestButton
				}
			}));
		}

		private static ConfigDescription Desc(string text, int order, AcceptableValueBase range = null)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			return new ConfigDescription(text, range, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = order
				}
			});
		}

		private static void DrawSoundFile(ConfigEntryBase entry)
		{
			string value = SoundFile.Value;
			GUILayout.Label(string.IsNullOrEmpty(value) ? "(none)" : Path.GetFileName(value), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
			if (FilePicker.IsSupported)
			{
				bool enabled = GUI.enabled;
				GUI.enabled = enabled && !FilePicker.IsOpen;
				if (GUILayout.Button(FilePicker.IsOpen ? "Choosing..." : "Browse...", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(90f) }))
				{
					FilePicker.Open();
				}
				GUI.enabled = enabled;
			}
		}

		private static void DrawTestButton(ConfigEntryBase entry)
		{
			if (GUILayout.Button("Test sound", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }))
			{
				SoundPlayer.Instance?.Play2D();
			}
		}
	}
	[HarmonyPatch(typeof(Piece), "CanBeRemoved")]
	internal static class RemovalGuard
	{
		private static float s_lastHint = -999f;

		private static void Postfix(Piece __instance, ref bool __result)
		{
			if (!__result)
			{
				return;
			}
			MailboxComponent component = ((Component)__instance).GetComponent<MailboxComponent>();
			if (!((Object)(object)component == (Object)null) && component.HasLetters())
			{
				__result = false;
				if (Time.time - s_lastHint > 3f && (Object)(object)MessageHud.instance != (Object)null)
				{
					s_lastHint = Time.time;
					MessageHud.instance.ShowMessage((MessageType)1, Translations.Get("$batera_mailbox_remove_hint"), 0, (Sprite)null, false, true);
				}
			}
		}
	}
	internal class SoundPlayer : MonoBehaviour
	{
		private static readonly Dictionary<SoundPreset, string> GameSounds = new Dictionary<SoundPreset, string>
		{
			{
				SoundPreset.MagicBells,
				"sfx_secretfound"
			},
			{
				SoundPreset.Knock,
				"sfx_gui_craftitem_workbench"
			},
			{
				SoundPreset.Forge,
				"sfx_gui_craftitem_forge_end"
			}
		};

		private readonly Dictionary<SoundPreset, AudioClip> _gameClips = new Dictionary<SoundPreset, AudioClip>();

		private AudioSource _source2D;

		private AudioClip _dingDong;

		private AudioClip _customClip;

		public static SoundPlayer Instance { get; private set; }

		private void Awake()
		{
			Instance = this;
			_source2D = ((Component)this).gameObject.AddComponent<AudioSource>();
			_source2D.playOnAwake = false;
			_source2D.spatialBlend = 0f;
			_source2D.ignoreListenerPause = true;
			_dingDong = CreateDingDong();
			LoadCustomClip();
			Plugin.SoundFile.SettingChanged += delegate
			{
				if (!string.IsNullOrWhiteSpace(Plugin.SoundFile.Value))
				{
					Plugin.SoundPresetSetting.Value = SoundPreset.Custom;
				}
				LoadCustomClip();
			};
		}

		private void Update()
		{
			if (FilePicker.TryTakeResult(out var path))
			{
				Plugin.SoundFile.Value = path;
			}
		}

		public void Play2D()
		{
			_source2D.Stop();
			_source2D.PlayOneShot(GetClip(), Plugin.Volume.Value);
		}

		private AudioClip GetClip()
		{
			SoundPreset value = Plugin.SoundPresetSetting.Value;
			if (value == SoundPreset.Custom)
			{
				if (!((Object)(object)_customClip != (Object)null))
				{
					return _dingDong;
				}
				return _customClip;
			}
			if (GameSounds.TryGetValue(value, out var value2))
			{
				if (!_gameClips.TryGetValue(value, out var value3) || (Object)(object)value3 == (Object)null)
				{
					value3 = FindGameClip(value2);
					if ((Object)(object)value3 != (Object)null)
					{
						_gameClips[value] = value3;
					}
				}
				if ((Object)(object)value3 != (Object)null)
				{
					return value3;
				}
			}
			return _dingDong;
		}

		private static AudioClip FindGameClip(string prefabName)
		{
			if ((Object)(object)ZNetScene.instance == (Object)null)
			{
				return null;
			}
			GameObject prefab = ZNetScene.instance.GetPrefab(prefabName);
			ZSFX val = (((Object)(object)prefab != (Object)null) ? prefab.GetComponentInChildren<ZSFX>(true) : null);
			if ((Object)(object)val == (Object)null || val.m_audioClips == null || val.m_audioClips.Length == 0)
			{
				Plugin.Log.LogWarning((object)("Game sound '" + prefabName + "' not found. Using the built-in ding-dong."));
				return null;
			}
			return val.m_audioClips[0];
		}

		private void LoadCustomClip()
		{
			//IL_008a: 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_008f: 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)
			_customClip = null;
			string text = Plugin.SoundFile.Value?.Trim().Trim('"');
			if (string.IsNullOrEmpty(text))
			{
				return;
			}
			string text2 = ResolveSoundPath(text);
			if (text2 == null)
			{
				Plugin.Log.LogWarning((object)("Sound file not found: '" + text + "'. Using the built-in ding-dong."));
				return;
			}
			AudioType type;
			switch (Path.GetExtension(text2).ToLowerInvariant())
			{
			case ".wav":
				type = (AudioType)20;
				break;
			case ".ogg":
				type = (AudioType)14;
				break;
			case ".mp3":
				type = (AudioType)13;
				break;
			default:
				Plugin.Log.LogWarning((object)("Unsupported sound format '" + text2 + "'. Use .wav, .ogg or .mp3."));
				return;
			}
			((MonoBehaviour)this).StartCoroutine(LoadClip(text2, type));
		}

		private static string ResolveSoundPath(string setting)
		{
			if (Path.IsPathRooted(setting))
			{
				if (!File.Exists(setting))
				{
					return null;
				}
				return setting;
			}
			string directoryName = Path.GetDirectoryName(((BaseUnityPlugin)Plugin.Instance).Info.Location);
			string[] array = new string[3]
			{
				Paths.ConfigPath,
				directoryName,
				Paths.PluginPath
			};
			foreach (string text in array)
			{
				if (!string.IsNullOrEmpty(text))
				{
					string text2 = Path.Combine(text, setting);
					if (File.Exists(text2))
					{
						return text2;
					}
				}
			}
			return null;
		}

		private IEnumerator LoadClip(string path, AudioType type)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			UnityWebRequest request = UnityWebRequestMultimedia.GetAudioClip(new Uri(path).AbsoluteUri, type);
			try
			{
				yield return request.SendWebRequest();
				if ((int)request.result != 1)
				{
					Plugin.Log.LogWarning((object)("Failed to load sound '" + path + "': " + request.error));
					yield break;
				}
				AudioClip content = DownloadHandlerAudioClip.GetContent(request);
				if ((Object)(object)content == (Object)null || content.length <= 0f)
				{
					Plugin.Log.LogWarning((object)("Sound '" + path + "' is empty or invalid."));
					yield break;
				}
				((Object)content).name = Path.GetFileNameWithoutExtension(path);
				_customClip = content;
				Plugin.Log.LogInfo((object)("Loaded custom mailbox sound: " + path));
			}
			finally
			{
				((IDisposable)request)?.Dispose();
			}
		}

		private static AudioClip CreateDingDong()
		{
			float[] array = new float[2] { 659.25f, 523.25f };
			int num = 85995;
			float[] array2 = new float[num];
			for (int i = 0; i < array.Length; i++)
			{
				float num2 = array[i];
				int num3 = (int)(24255f * (float)i);
				int num4 = 61740;
				for (int j = 0; j < num4 && num3 + j < num; j++)
				{
					float num5 = (float)j / 44100f;
					float num6 = Mathf.Clamp01(num5 / 0.004f);
					float num7 = Mathf.Exp((0f - num5) * 3.2f);
					float num8 = Mathf.Sin(MathF.PI * 2f * num2 * num5) + 0.5f * Mathf.Sin(MathF.PI * 2f * num2 * 2f * num5) * Mathf.Exp((0f - num5) * 5f) + 0.25f * Mathf.Sin(MathF.PI * 2f * num2 * 3.01f * num5) * Mathf.Exp((0f - num5) * 9f);
					array2[num3 + j] += num8 * num6 * num7 * 0.35f;
				}
			}
			AudioClip obj = AudioClip.Create("MailboxDingDong", array2.Length, 1, 44100, false);
			obj.SetData(array2, 0);
			return obj;
		}
	}
	public enum SoundPreset
	{
		MagicBells,
		DingDong,
		Knock,
		Forge,
		Custom
	}
	internal static class Translations
	{
		public const string PieceName = "$piece_batera_mailbox";

		public const string PieceDescription = "$piece_batera_mailbox_desc";

		public const string OwnedBy = "$batera_mailbox_owned_by";

		public const string Write = "$batera_mailbox_write";

		public const string WriteTopic = "$batera_mailbox_write_topic";

		public const string WriteAnonymous = "$batera_mailbox_write_anonymous";

		public const string WriteTopicAnonymous = "$batera_mailbox_write_topic_anonymous";

		public const string AnonymousLetter = "$batera_mailbox_anonymous_letter";

		public const string Anonymous = "$batera_mailbox_anonymous";

		public const string Full = "$batera_mailbox_full";

		public const string Read = "$batera_mailbox_read";

		public const string Delete = "$batera_mailbox_delete";

		public const string Counts = "$batera_mailbox_counts";

		public const string Empty = "$batera_mailbox_empty";

		public const string LetterFrom = "$batera_mailbox_letter_from";

		public const string Sent = "$batera_mailbox_sent";

		public const string Deleted = "$batera_mailbox_deleted";

		public const string YouHaveMail = "$batera_mailbox_you_have_mail";

		public const string NewLetterPin = "$batera_mailbox_new_letter_pin";

		public const string RemoveHint = "$batera_mailbox_remove_hint";

		public static void Register()
		{
			CustomLocalization localization = LocalizationManager.Instance.GetLocalization();
			string text = "English";
			localization.AddTranslation(ref text, new Dictionary<string, string>
			{
				{
					Key("$piece_batera_mailbox"),
					"Mailbox"
				},
				{
					Key("$piece_batera_mailbox_desc"),
					"Other players can leave you letters, even inside your ward. Only you can read them."
				},
				{
					Key("$batera_mailbox_owned_by"),
					"{0}'s mailbox"
				},
				{
					Key("$batera_mailbox_write"),
					"Write a letter"
				},
				{
					Key("$batera_mailbox_write_topic"),
					"Letter to {0} (type \\n for a new line)"
				},
				{
					Key("$batera_mailbox_write_anonymous"),
					"Write an anonymous letter"
				},
				{
					Key("$batera_mailbox_write_topic_anonymous"),
					"Anonymous letter to {0} (type \\n for a new line)"
				},
				{
					Key("$batera_mailbox_anonymous_letter"),
					"Anonymous letter"
				},
				{
					Key("$batera_mailbox_anonymous"),
					"anonymous"
				},
				{
					Key("$batera_mailbox_full"),
					"Mailbox full"
				},
				{
					Key("$batera_mailbox_read"),
					"Read letter"
				},
				{
					Key("$batera_mailbox_delete"),
					"Delete the letter you just read"
				},
				{
					Key("$batera_mailbox_counts"),
					"{0} new, {1} total"
				},
				{
					Key("$batera_mailbox_empty"),
					"No letters"
				},
				{
					Key("$batera_mailbox_letter_from"),
					"Letter from {0}"
				},
				{
					Key("$batera_mailbox_sent"),
					"Letter delivered to {0}'s mailbox"
				},
				{
					Key("$batera_mailbox_deleted"),
					"Letter deleted"
				},
				{
					Key("$batera_mailbox_you_have_mail"),
					"You have {0} new letter(s)!"
				},
				{
					Key("$batera_mailbox_new_letter_pin"),
					"Letter from {0}"
				},
				{
					Key("$batera_mailbox_remove_hint"),
					"Delete all letters before removing the mailbox"
				}
			});
			text = "Portuguese_Brazilian";
			localization.AddTranslation(ref text, new Dictionary<string, string>
			{
				{
					Key("$piece_batera_mailbox"),
					"Caixa de correio"
				},
				{
					Key("$piece_batera_mailbox_desc"),
					"Outros jogadores podem te deixar cartas, mesmo dentro do seu ward. Só você pode ler."
				},
				{
					Key("$batera_mailbox_owned_by"),
					"Caixa de correio de {0}"
				},
				{
					Key("$batera_mailbox_write"),
					"Escrever carta"
				},
				{
					Key("$batera_mailbox_write_topic"),
					"Carta para {0} (digite \\n para pular linha)"
				},
				{
					Key("$batera_mailbox_write_anonymous"),
					"Escrever carta anônima"
				},
				{
					Key("$batera_mailbox_write_topic_anonymous"),
					"Carta anônima para {0} (digite \\n para pular linha)"
				},
				{
					Key("$batera_mailbox_anonymous_letter"),
					"Carta anônima"
				},
				{
					Key("$batera_mailbox_anonymous"),
					"anônimo"
				},
				{
					Key("$batera_mailbox_full"),
					"Caixa de correio cheia"
				},
				{
					Key("$batera_mailbox_read"),
					"Ler carta"
				},
				{
					Key("$batera_mailbox_delete"),
					"Apagar a carta que você leu"
				},
				{
					Key("$batera_mailbox_counts"),
					"{0} nova(s), {1} no total"
				},
				{
					Key("$batera_mailbox_empty"),
					"Nenhuma carta"
				},
				{
					Key("$batera_mailbox_letter_from"),
					"Carta de {0}"
				},
				{
					Key("$batera_mailbox_sent"),
					"Carta entregue na caixa de correio de {0}"
				},
				{
					Key("$batera_mailbox_deleted"),
					"Carta apagada"
				},
				{
					Key("$batera_mailbox_you_have_mail"),
					"Você tem {0} carta(s) nova(s)!"
				},
				{
					Key("$batera_mailbox_new_letter_pin"),
					"Carta de {0}"
				},
				{
					Key("$batera_mailbox_remove_hint"),
					"Apague todas as cartas antes de remover a caixa de correio"
				}
			});
		}

		public static string Get(string token)
		{
			if (Localization.instance == null)
			{
				return token;
			}
			return Localization.instance.Localize(token);
		}

		public static string Format(string token, params object[] args)
		{
			return string.Format(Get(token), args);
		}

		private static string Key(string token)
		{
			return token.TrimStart('$');
		}
	}
}