Decompiled source of PostalExpansion v1.1.2

BepInEx/plugins/PostalExpansion/PostalExpansion.dll

Decompiled 24 minutes ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")]
[assembly: AssemblyCompany("PostalExpansion")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.1.0")]
[assembly: AssemblyInformationalVersion("1.1.1")]
[assembly: AssemblyProduct("PostalExpansion")]
[assembly: AssemblyTitle("PostalExpansion")]
[assembly: AssemblyVersion("1.1.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class IsReadOnlyAttribute : Attribute
	{
	}
	[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 PostalExpansion
{
	internal sealed class AestraAbbeyGraveRobberTableMission : RegisteredLetterMissionDefinition
	{
		internal static readonly AestraAbbeyGraveRobberTableMission Instance = new AestraAbbeyGraveRobberTableMission();

		private AestraAbbeyGraveRobberTableMission()
			: base("aestra_abbey_grave_robber_table", "Aestra Abbey", 26, new Vector3(232.158f, -0.924f, 194.327f), new Vector3(0f, 136.291f, 0f), new Vector3(2f, 2f, 2f), LetterDeliveryWindow.Day, new int[2] { 18, 6 }, "Table of grave robber")
		{
		}//IL_001c: 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_0044: Unknown result type (might be due to invalid IL or missing references)


		internal override string GetDeliveryDialogue(Mission mission)
		{
			int originPortIndex = LetterMissionDefinition.GetOriginPortIndex(mission);
			if (originPortIndex == 6 || originPortIndex == 18)
			{
				return "(You put the letter under the table)";
			}
			return UnexpectedOrigin(mission);
		}
	}
	internal sealed class AestraAbbeyMainAbbeyMission : RegisteredLetterMissionDefinition
	{
		internal static readonly AestraAbbeyMainAbbeyMission Instance = new AestraAbbeyMainAbbeyMission();

		private AestraAbbeyMainAbbeyMission()
			: base("aestra_abbey_main_abbey", "Aestra Abbey", 26, new Vector3(-117.4f, 56.962f, -81.718f), new Vector3(0f, 220.653f, 0f), new Vector3(1.5f, 1.5f, 1.5f), LetterDeliveryWindow.Day, new int[3] { 28, 21, 10 }, "Abbey")
		{
		}//IL_001c: 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_0044: Unknown result type (might be due to invalid IL or missing references)


		internal override string GetDeliveryDialogue(Mission mission)
		{
			return LetterMissionDefinition.GetOriginPortIndex(mission) switch
			{
				28 => "Castigo corpus meum.", 
				21 => "A solis ortus cardine.", 
				10 => "Pacem in terries.", 
				_ => UnexpectedOrigin(mission), 
			};
		}
	}
	internal sealed class AestraAbbeyOracleBenchMission : AnonymousLetterMissionDefinition
	{
		internal static readonly AestraAbbeyOracleBenchMission Instance = new AestraAbbeyOracleBenchMission();

		private AestraAbbeyOracleBenchMission()
			: base("aestra_abbey_oracle_bench", "Aestra Abbey", 26, new Vector3(-129.328f, -1.928f, 1355.791f), new Vector3(0f, 257.793f, 0f), new Vector3(2.5f, 2.5f, 2.5f), 1362.3f, new LetterDeliveryWindow(19f, 7f, "19-07"), new int[3] { 24, 29, 27 }, "Oracle bench")
		{
		}//IL_001c: 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_0044: Unknown result type (might be due to invalid IL or missing references)


		internal override string GetDeliveryDialogue(Mission mission)
		{
			return LetterMissionDefinition.GetOriginPortIndex(mission) switch
			{
				24 => "(Letter open by itself once you approach one of the shrooms, showing totemic pattern before flying away. Closest shroom is gone)", 
				29 => "(The letter tries to let out the light but it got put out by shrooms quickly.)", 
				27 => "(You place the letter on bench. You heard a pleasent chime.)", 
				_ => UnexpectedOrigin(mission), 
			};
		}
	}
	internal sealed class AlAnkhAcademyKeyKeeperMission : RegisteredLetterMissionDefinition
	{
		internal static readonly AlAnkhAcademyKeyKeeperMission Instance = new AlAnkhAcademyKeyKeeperMission();

		private AlAnkhAcademyKeyKeeperMission()
			: base("al_ankh_academy_key_keeper", "Al'Ankh Academy", 5, new Vector3(-0.173f, 0.833f, 1.175f), new Vector3(0f, 170.709f, 0f), new Vector3(2f, 2f, 2f), LetterDeliveryWindow.Day, new int[11]
			{
				0, 6, 32, 16, 9, 10, 25, 22, 23, 15,
				21
			}, "Key Keeper")
		{
		}//IL_001b: 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_0043: Unknown result type (might be due to invalid IL or missing references)


		internal override string GetDeliveryDialogue(Mission mission)
		{
			switch (LetterMissionDefinition.GetOriginPortIndex(mission))
			{
			case 0:
			case 6:
			case 9:
			case 15:
			case 22:
			case 23:
				return "Endless applications... I need a day off.";
			case 32:
				return "Oh! Ibn Doraid will be interested in this!";
			case 16:
				return "These glasses cost a big fortune for sure.";
			case 10:
			case 25:
				return "These ideas are... interesting.";
			case 21:
				return "(Whistles) Your journey must have been eventful.";
			default:
				return UnexpectedOrigin(mission);
			}
		}
	}
	internal sealed class AlbacoreTownCreepyGuyMission : RegisteredLetterMissionDefinition
	{
		internal static readonly AlbacoreTownCreepyGuyMission Instance = new AlbacoreTownCreepyGuyMission();

		private AlbacoreTownCreepyGuyMission()
			: base("albacore_town_creepy_guy", "Albacore Town", 3, new Vector3(40.721f, 3.318f, -50.81f), new Vector3(0f, 55.492f, 0f), new Vector3(1.5f, 1.5f, 1.5f), LetterDeliveryWindow.Night, new int[3] { 15, 12, 25 }, "Creepy guy")
		{
		}//IL_001b: 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_0043: Unknown result type (might be due to invalid IL or missing references)


		internal override string GetDeliveryDialogue(Mission mission)
		{
			switch (LetterMissionDefinition.GetOriginPortIndex(mission))
			{
			case 12:
			case 15:
				return "Were you seen? You'd better not.";
			case 25:
				return "This makes me homesick... but I need to know where the fishing ground is.";
			default:
				return UnexpectedOrigin(mission);
			}
		}
	}
	internal sealed class AlchemistsIslandApprenticeMission : RegisteredLetterMissionDefinition
	{
		internal static readonly AlchemistsIslandApprenticeMission Instance = new AlchemistsIslandApprenticeMission();

		private AlchemistsIslandApprenticeMission()
			: base("alchemists_island_apprentice", "Alchemist's Island", 4, new Vector3(-0.235f, 0.336f, 14.538f), new Vector3(0f, 35.018f, 0f), new Vector3(3f, 3f, 3f), LetterDeliveryWindow.Day, new int[12]
			{
				0, 6, 32, 5, 20, 9, 10, 25, 22, 19,
				28, 21
			}, "Alchemist's apprentice")
		{
		}//IL_001b: 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_0043: Unknown result type (might be due to invalid IL or missing references)


		internal override string GetDeliveryDialogue(Mission mission)
		{
			switch (LetterMissionDefinition.GetOriginPortIndex(mission))
			{
			case 0:
			case 6:
			case 9:
			case 20:
			case 22:
			case 32:
				return "I will inform my mentor about this. Thank you.";
			case 5:
				return "This again... When will they stop trying?";
			case 10:
			case 25:
				return "That's... a brilliant idea! I need to tell my mentor now!";
			case 19:
			case 28:
				return "Your God cannot help the exhausted miners? Heh.";
			case 21:
				return "...Really?";
			default:
				return UnexpectedOrigin(mission);
			}
		}
	}
	internal sealed class AlNilemLionsFangObeliskMission : AnonymousLetterMissionDefinition
	{
		internal static readonly AlNilemLionsFangObeliskMission Instance = new AlNilemLionsFangObeliskMission();

		private AlNilemLionsFangObeliskMission()
			: base("al_nilem_lions_fang_obelisk", "Al'Nilem", 1, new Vector3(807.097f, 4.672f, 1451.161f), new Vector3(0f, 318.985f, 0f), new Vector3(5f, 5f, 5f), 1659.3f, new LetterDeliveryWindow(11f, 13f, "11-13"), new int[6] { 2, 31, 32, 29, 24, 28 }, "Isle of Clear Mind Obelisk")
		{
		}//IL_001b: 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_0043: Unknown result type (might be due to invalid IL or missing references)


		internal override string GetDeliveryDialogue(Mission mission)
		{
			switch (LetterMissionDefinition.GetOriginPortIndex(mission))
			{
			case 2:
			case 31:
			case 32:
				return "(Letter burns away after you place it on ground, you feel hotter)";
			case 29:
				return "(Letter open by itself once you approach the obelisk, showing totemic pattern before flying away)";
			case 24:
			case 28:
				return "(Letter got eject away before you can approach, falls into the seas)";
			default:
				return UnexpectedOrigin(mission);
			}
		}
	}
	[HarmonyPatch(typeof(ShipItem), "UpdateLookText")]
	internal static class AnonymousLetterItemLookTextPatch
	{
		private static bool Prefix(ShipItem __instance)
		{
			if ((Object)(object)__instance == (Object)null || !PostalMail.IsRegisteredLetter(((Component)__instance).GetComponent<SaveablePrefab>()))
			{
				return true;
			}
			Good component = ((Component)__instance).GetComponent<Good>();
			int num = (((Object)(object)component != (Object)null) ? component.GetMissionIndex() : (-1));
			if (num < 0 || PlayerMissions.missions == null || num >= PlayerMissions.missions.Length)
			{
				return true;
			}
			Mission val = PlayerMissions.missions[num];
			if (!AnonymousLetterMissions.TryGetDefinition(val, out var _))
			{
				return true;
			}
			((GoPointerButton)__instance).lookText = "due: " + val.GetDueText();
			return false;
		}
	}
	internal abstract class AnonymousLetterMissionDefinition : LetterMissionDefinition
	{
		internal sealed override float DistanceToOffice { get; }

		internal sealed override bool UsePersistentWorldAnchor => true;

		internal sealed override bool UseDeliveryLocationForRoute => true;

		internal sealed override bool ShowDeliveryCoordinates => true;

		internal sealed override bool HideDestination => true;

		protected AnonymousLetterMissionDefinition(string id, string destinationPortName, int destinationPortIndex, Vector3 localPosition, Vector3 localEulerAngles, Vector3 triggerSize, float distanceToOffice, LetterDeliveryWindow deliveryWindow, int[] spawnPortIndices, string locationDescription)
			: base(id, destinationPortName, destinationPortIndex, localPosition, localEulerAngles, triggerSize, deliveryWindow, spawnPortIndices, locationDescription)
		{
			//IL_0004: 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_0008: Unknown result type (might be due to invalid IL or missing references)
			DistanceToOffice = distanceToOffice;
		}
	}
	internal static class AnonymousLetterMissionRegistry
	{
		private static readonly LetterMissionRegistry<AnonymousLetterMissionDefinition> Registry = new LetterMissionRegistry<AnonymousLetterMissionDefinition>("Anonymous Letter", OasisPirateHideoutMission.Instance, HappyBayUnnamedGraveMission.Instance, EastwindLighthouseMission.Instance, SaffronIslandTraderMission.Instance, AlNilemLionsFangObeliskMission.Instance, OldAnkhTownClearMindMission.Instance, AestraAbbeyOracleBenchMission.Instance, TurtleIslandPonderingPeakMission.Instance, DeadCoveNamelessRockMission.Instance);

		internal static IReadOnlyList<AnonymousLetterMissionDefinition> All => Registry.All;
	}
	internal static class AnonymousLetterMissions
	{
		internal const int RequiredReputation = 8;

		internal const float DueDayBaseSpeed = 3f;

		internal const float ReputationMultiplier = 10f;

		internal const int FixedGoldReward = 5;

		internal const int OneDayLateGoldReward = 1;

		internal const int SeverelyLatePenalty = -8000;

		private static readonly LetterMissionSaveKeys SaveKeys = new LetterMissionSaveKeys("PostalExpansion.AnonymousLetter.Active.v1", "PostalExpansion.AnonymousLetter.Claimed.v1");

		private static readonly LetterMissionSaveKeys LegacyPirateHideoutSaveKeys = new LetterMissionSaveKeys("PostalExpansion.RegisteredLetter.Active.v1", "PostalExpansion.RegisteredLetter.Claimed.v1");

		private static readonly LetterMissionSet<AnonymousLetterMissionDefinition> Missions = new LetterMissionSet<AnonymousLetterMissionDefinition>("Anonymous Letter", AnonymousLetterMissionRegistry.All, SaveKeys, 8, 3f, 5, (Port destination) => "Anonymous letter");

		internal static void AddMissions(Port origin, List<Mission> missions)
		{
			Missions.AddMissions(origin, missions);
		}

		internal static int GetGoldReward(int daysLate)
		{
			if (daysLate <= 0)
			{
				return 5;
			}
			return (daysLate == 1) ? 1 : 0;
		}

		internal static List<string> GetDebugStatusLines()
		{
			return Missions.GetDebugStatusLines();
		}

		internal static bool TryGetDefinition(Mission mission, out AnonymousLetterMissionDefinition definition)
		{
			return Missions.TryGetDefinition(mission, out definition);
		}

		internal static void MissionAccepted(Mission mission)
		{
			Missions.MissionAccepted(mission);
		}

		internal static void MissionDelivered(Mission mission)
		{
			Missions.MissionDelivered(mission);
		}

		internal static void SavePersistentState()
		{
			Missions.SavePersistentState();
		}

		internal static void LoadPersistentState()
		{
			Missions.LoadPersistentState(LegacyPirateHideoutSaveKeys);
		}

		internal static void ResetRuntimeState()
		{
			Missions.ResetRuntimeState();
		}
	}
	internal sealed class ChronosChurchHouseMission : RegisteredLetterMissionDefinition
	{
		internal static readonly ChronosChurchHouseMission Instance = new ChronosChurchHouseMission();

		private ChronosChurchHouseMission()
			: base("chronos_church_house", "Chronos", 21, new Vector3(-19.175f, 31.109f, -62.909f), new Vector3(0f, 17.783f, 0f), new Vector3(1.5f, 1.5f, 1.5f), LetterDeliveryWindow.Day, new int[5] { 26, 28, 5, 0, 9 }, "Church house")
		{
		}//IL_001c: 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_0044: Unknown result type (might be due to invalid IL or missing references)


		internal override string GetDeliveryDialogue(Mission mission)
		{
			switch (LetterMissionDefinition.GetOriginPortIndex(mission))
			{
			case 26:
			case 28:
				return "There is little common ground after the schism.";
			case 5:
				return "We appreciate the knowledge seeking.";
			case 0:
			case 9:
				return "The Church is under maintenance thus not open for visiting.";
			default:
				return UnexpectedOrigin(mission);
			}
		}
	}
	internal sealed class ConfigurationManagerAttributes
	{
		public Action<ConfigEntryBase> CustomDrawer;

		public object DefaultValue;
	}
	internal sealed class CrabBeachHouseMission : RegisteredLetterMissionDefinition
	{
		internal static readonly CrabBeachHouseMission Instance = new CrabBeachHouseMission();

		private CrabBeachHouseMission()
			: base("crab_beach_house", "Crab Beach", 11, new Vector3(-100.447f, 4.35f, 30.655f), new Vector3(0f, 188.793f, 0f), new Vector3(1.5f, 1.5f, 1.5f), LetterDeliveryWindow.Day, new int[5] { 9, 0, 15, 22, 21 }, "House at beach")
		{
		}//IL_001c: 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_0044: Unknown result type (might be due to invalid IL or missing references)


		internal override string GetDeliveryDialogue(Mission mission)
		{
			switch (LetterMissionDefinition.GetOriginPortIndex(mission))
			{
			case 0:
			case 9:
			case 15:
			case 22:
				return "I SAID I DON'T BUILD SHIPS ANYMORE! GO AWAY!";
			case 21:
				return "...Where?";
			default:
				return UnexpectedOrigin(mission);
			}
		}
	}
	internal sealed class DailySpecialMissionState
	{
		private sealed class Marker
		{
		}

		private readonly string activeMissionDataKey;

		private readonly string claimedOfferDataKey;

		private readonly Func<int, Mission, string> serializeActiveMission;

		private readonly Func<Mission, string[], bool> matchesSavedMission;

		private readonly Action<Mission> onMissionRestored;

		private ConditionalWeakTable<Mission, Marker> markedMissions = new ConditionalWeakTable<Mission, Marker>();

		private readonly HashSet<string> claimedOffers = new HashSet<string>(StringComparer.Ordinal);

		internal DailySpecialMissionState(string activeMissionDataKey, string claimedOfferDataKey, Func<int, Mission, string> serializeActiveMission, Func<Mission, string[], bool> matchesSavedMission, Action<Mission> onMissionRestored)
		{
			this.activeMissionDataKey = activeMissionDataKey;
			this.claimedOfferDataKey = claimedOfferDataKey;
			this.serializeActiveMission = serializeActiveMission;
			this.matchesSavedMission = matchesSavedMission;
			this.onMissionRestored = onMissionRestored;
		}

		internal bool IsMarked(Mission mission)
		{
			Marker value;
			if (mission != null)
			{
				return markedMissions.TryGetValue(mission, out value);
			}
			return false;
		}

		internal void Mark(Mission mission)
		{
			if (mission != null)
			{
				markedMissions.GetValue(mission, (Mission _) => new Marker());
			}
		}

		internal bool CanOfferAt(Port origin)
		{
			if ((Object)(object)origin == (Object)null)
			{
				return false;
			}
			PruneClaimsForCurrentDay();
			return !claimedOffers.Contains(GetClaimKey(GameState.day, origin.portIndex));
		}

		internal void MissionAccepted(Mission mission)
		{
			if (IsMarked(mission) && !((Object)(object)mission.originPort == (Object)null) && mission.missionIndex >= 0 && PlayerMissions.missions != null && mission.missionIndex < PlayerMissions.missions.Length && PlayerMissions.missions[mission.missionIndex] == mission)
			{
				PruneClaimsForCurrentDay();
				claimedOffers.Add(GetClaimKey(GameState.day, mission.originPort.portIndex));
			}
		}

		internal void SavePersistentState()
		{
			if (GameState.modData == null)
			{
				GameState.modData = new Dictionary<string, string>();
			}
			List<string> list = new List<string>();
			if (PlayerMissions.missions != null)
			{
				for (int i = 0; i < PlayerMissions.missions.Length; i++)
				{
					Mission val = PlayerMissions.missions[i];
					if (IsMarked(val) && !((Object)(object)val.originPort == (Object)null) && !((Object)(object)val.destinationPort == (Object)null))
					{
						string text = serializeActiveMission(i, val);
						if (!string.IsNullOrEmpty(text))
						{
							list.Add(text);
						}
					}
				}
			}
			GameState.modData[activeMissionDataKey] = string.Join(";", list);
			PruneClaimsForCurrentDay();
			List<string> list2 = new List<string>(claimedOffers);
			list2.Sort(StringComparer.Ordinal);
			GameState.modData[claimedOfferDataKey] = string.Join(";", list2);
		}

		internal void LoadPersistentState()
		{
			ResetRuntimeState();
			if (GameState.modData != null)
			{
				LoadClaims();
				LoadActiveMissions();
			}
		}

		internal void ResetRuntimeState()
		{
			markedMissions = new ConditionalWeakTable<Mission, Marker>();
			claimedOffers.Clear();
		}

		private void LoadClaims()
		{
			if (!GameState.modData.TryGetValue(claimedOfferDataKey, out var value))
			{
				return;
			}
			string value2 = GameState.day + ",";
			string[] array = value.Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries);
			foreach (string text in array)
			{
				if (text.StartsWith(value2, StringComparison.Ordinal))
				{
					claimedOffers.Add(text);
				}
			}
		}

		private void LoadActiveMissions()
		{
			if (PlayerMissions.missions == null || !GameState.modData.TryGetValue(activeMissionDataKey, out var value))
			{
				return;
			}
			string[] array = value.Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries);
			for (int i = 0; i < array.Length; i++)
			{
				string[] array2 = array[i].Split(new char[1] { ',' });
				if (array2.Length != 0 && int.TryParse(array2[0], out var result) && result >= 0 && result < PlayerMissions.missions.Length)
				{
					Mission val = PlayerMissions.missions[result];
					if (val != null && val.missionIndex == result && (Object)(object)val.originPort != (Object)null && (Object)(object)val.destinationPort != (Object)null && matchesSavedMission(val, array2))
					{
						Mark(val);
						onMissionRestored?.Invoke(val);
					}
				}
			}
		}

		private static string GetClaimKey(int day, int originPortIndex)
		{
			return day + "," + originPortIndex;
		}

		private void PruneClaimsForCurrentDay()
		{
			string currentDayPrefix = GameState.day + ",";
			claimedOffers.RemoveWhere((string claim) => !claim.StartsWith(currentDayPrefix, StringComparison.Ordinal));
		}
	}
	internal sealed class DeadCoveNamelessRockMission : AnonymousLetterMissionDefinition
	{
		internal static readonly DeadCoveNamelessRockMission Instance = new DeadCoveNamelessRockMission();

		private DeadCoveNamelessRockMission()
			: base("dead_cove_nameless_rock", "Dead Cove", 30, new Vector3(-852.584f, 2.539f, -826.316f), new Vector3(0f, 26.327f, 0f), new Vector3(8f, 8f, 8f), 1195.2f, LetterDeliveryWindow.Night, new int[3] { 1, 19, 11 }, "Nameless rock southren tip")
		{
		}//IL_001c: 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_0044: Unknown result type (might be due to invalid IL or missing references)


		internal override string GetDeliveryDialogue(Mission mission)
		{
			int originPortIndex = LetterMissionDefinition.GetOriginPortIndex(mission);
			if (originPortIndex == 1 || originPortIndex == 11 || originPortIndex == 19)
			{
				return "(There is no remarkable landmark so you just throw the letter on the rock randomly. You have no idea what you are doing.)";
			}
			return UnexpectedOrigin(mission);
		}
	}
	internal sealed class DragonCliffsBrownTobaccoVendorMission : RegisteredLetterMissionDefinition
	{
		internal static readonly DragonCliffsBrownTobaccoVendorMission Instance = new DragonCliffsBrownTobaccoVendorMission();

		private DragonCliffsBrownTobaccoVendorMission()
			: base("dragon_cliffs_brown_tobacco_vendor", "Dragon Cliffs", 9, new Vector3(47.025f, 1.993f, -11.703f), new Vector3(0f, 106.371f, 0f), new Vector3(3f, 3f, 3f), LetterDeliveryWindow.Day, new int[5] { 0, 15, 12, 20, 28 }, "Brown Tobacco Vendor")
		{
		}//IL_001c: 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_0044: Unknown result type (might be due to invalid IL or missing references)


		internal override string GetDeliveryDialogue(Mission mission)
		{
			switch (LetterMissionDefinition.GetOriginPortIndex(mission))
			{
			case 12:
			case 15:
			case 20:
			case 28:
				return "(Sigh) How much longer do I need to stay here...?";
			case 0:
				return "Hmm...";
			default:
				return UnexpectedOrigin(mission);
			}
		}
	}
	internal sealed class DragonCliffsChimesHutMission : RegisteredLetterMissionDefinition
	{
		internal static readonly DragonCliffsChimesHutMission Instance = new DragonCliffsChimesHutMission();

		private DragonCliffsChimesHutMission()
			: base("dragon_cliffs_small_hut_beside_chimes", "Dragon Cliffs", 9, new Vector3(-45.037f, 0.07f, -119.983f), new Vector3(0f, 148.902f, 0f), new Vector3(1.5f, 1.5f, 1.5f), LetterDeliveryWindow.Day, new int[10] { 13, 29, 24, 16, 1, 25, 22, 28, 10, 21 }, "Small hut beside chimes")
		{
		}//IL_001c: 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_0044: Unknown result type (might be due to invalid IL or missing references)


		internal override string GetDeliveryDialogue(Mission mission)
		{
			switch (LetterMissionDefinition.GetOriginPortIndex(mission))
			{
			case 1:
			case 10:
			case 13:
			case 16:
			case 22:
			case 24:
			case 25:
			case 28:
			case 29:
				return "(Gasp) It finally arrived! Thanks!";
			case 21:
				return "What took you so long?";
			default:
				return UnexpectedOrigin(mission);
			}
		}
	}
	internal sealed class DragonCliffsTeaMerchantHouseMission : RegisteredLetterMissionDefinition
	{
		internal static readonly DragonCliffsTeaMerchantHouseMission Instance = new DragonCliffsTeaMerchantHouseMission();

		private DragonCliffsTeaMerchantHouseMission()
			: base("dragon_cliffs_house_behind_tea_merchant", "Dragon Cliffs", 9, new Vector3(-6.196f, 2.711f, -52.022f), new Vector3(0f, 101.025f, 0f), new Vector3(1.5f, 1.5f, 1.5f), LetterDeliveryWindow.Night, new int[5] { 6, 20, 22, 18, 0 }, "House behind tea merchant")
		{
		}//IL_001c: 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_0044: Unknown result type (might be due to invalid IL or missing references)


		internal override string GetDeliveryDialogue(Mission mission)
		{
			switch (LetterMissionDefinition.GetOriginPortIndex(mission))
			{
			case 6:
				if (!VanillaQuestState.IsHideoutQuestComplete())
				{
					return "Thank you.";
				}
				return "New order, matey?";
			case 0:
			case 18:
			case 20:
			case 22:
				if (!VanillaQuestState.IsHideoutQuestComplete())
				{
					return "...You can leave now.";
				}
				return "Which scurvy dog brings ye 'ere?";
			default:
				return UnexpectedOrigin(mission);
			}
		}
	}
	internal sealed class EastwindLighthouseMission : AnonymousLetterMissionDefinition
	{
		internal static readonly EastwindLighthouseMission Instance = new EastwindLighthouseMission();

		private EastwindLighthouseMission()
			: base("eastwind_lighthouse", "Eastwind", 19, new Vector3(3070.795f, 8.574f, -4694.155f), new Vector3(0f, 266.217f, 0f), new Vector3(1.5f, 1.5f, 1.5f), 5610.9f, new LetterDeliveryWindow(22f, 2f, "22-02"), new int[6] { 2, 10, 26, 21, 23, 6 }, "Light house")
		{
		}//IL_001c: 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_0044: Unknown result type (might be due to invalid IL or missing references)


		internal override string GetDeliveryDialogue(Mission mission)
		{
			switch (LetterMissionDefinition.GetOriginPortIndex(mission))
			{
			case 6:
				return "Aye matey, Me belong 'ere now.";
			case 2:
			case 10:
			case 21:
			case 23:
			case 26:
				return "YER GODS 'AVE NO POWER 'ERE LANDLUBBER!";
			default:
				return UnexpectedOrigin(mission);
			}
		}
	}
	internal sealed class FeyValleyWaterfallManorVendorMission : RegisteredLetterMissionDefinition
	{
		internal static readonly FeyValleyWaterfallManorVendorMission Instance = new FeyValleyWaterfallManorVendorMission();

		private FeyValleyWaterfallManorVendorMission()
			: base("fey_valley_waterfall_manor_vendor", "Fey Valley", 27, new Vector3(-126.239f, 51.409f, 42.779f), new Vector3(0f, 300.007f, 0f), new Vector3(1.5f, 1.5f, 1.5f), LetterDeliveryWindow.Day, new int[6] { 15, 0, 9, 20, 12, 26 }, "Waterfall manor vendor")
		{
		}//IL_001c: 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_0044: Unknown result type (might be due to invalid IL or missing references)


		internal override string GetDeliveryDialogue(Mission mission)
		{
			switch (LetterMissionDefinition.GetOriginPortIndex(mission))
			{
			case 26:
				return "Gods be praised! This year should be a good harvest year!";
			case 12:
			case 20:
				return "We're supposed to bring their fruit back, not the other way around!";
			case 0:
			case 9:
			case 15:
				return "I will let the Abbot know about the orders.";
			default:
				return UnexpectedOrigin(mission);
			}
		}
	}
	internal sealed class FireFishTownPainterMission : RegisteredLetterMissionDefinition
	{
		internal static readonly FireFishTownPainterMission Instance = new FireFishTownPainterMission();

		private FireFishTownPainterMission()
			: base("fire_fish_town_painter", "Fire Fish Town", 23, new Vector3(7.186f, 3.075f, 216.135f), new Vector3(0f, 190.815f, 0f), new Vector3(3f, 3f, 3f), LetterDeliveryWindow.Day, new int[5] { 15, 0, 9, 21, 20 }, "Painter")
		{
		}//IL_001c: 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_0044: Unknown result type (might be due to invalid IL or missing references)


		internal override string GetDeliveryDialogue(Mission mission)
		{
			switch (LetterMissionDefinition.GetOriginPortIndex(mission))
			{
			case 0:
			case 15:
				return "Always happy to hear from fellow painters!";
			case 9:
				return "Ugh! I escape there for a reason!";
			case 20:
				return "Daddy...";
			case 21:
				return "I would like to visit there one day!";
			default:
				return UnexpectedOrigin(mission);
			}
		}
	}
	internal sealed class FireFishTownTempleHouseMission : RegisteredLetterMissionDefinition
	{
		internal static readonly FireFishTownTempleHouseMission Instance = new FireFishTownTempleHouseMission();

		private FireFishTownTempleHouseMission()
			: base("fire_fish_town_temple_house", "Fire Fish Town", 23, new Vector3(-5.519f, 7.688f, 82.87f), new Vector3(0f, 35.728f, 0f), new Vector3(1.5f, 1.5f, 1.5f), LetterDeliveryWindow.Day, new int[1] { 10 }, "Temple house")
		{
		}//IL_001c: 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_0044: Unknown result type (might be due to invalid IL or missing references)


		internal override string GetDeliveryDialogue(Mission mission)
		{
			if (LetterMissionDefinition.GetOriginPortIndex(mission) != 10)
			{
				return UnexpectedOrigin(mission);
			}
			return "All is well.";
		}
	}
	internal sealed class FireflyGrottoChurchMission : RegisteredLetterMissionDefinition
	{
		internal static readonly FireflyGrottoChurchMission Instance = new FireflyGrottoChurchMission();

		private FireflyGrottoChurchMission()
			: base("firefly_grotto_church", "Firefly Grotto", 28, new Vector3(128.273f, 5.458f, 37.452f), new Vector3(0f, 107.82f, 0f), new Vector3(2.5f, 2.5f, 2.5f), LetterDeliveryWindow.Day, new int[4] { 26, 12, 20, 9 }, "Chruch")
		{
		}//IL_001c: 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_0044: Unknown result type (might be due to invalid IL or missing references)


		internal override string GetDeliveryDialogue(Mission mission)
		{
			switch (LetterMissionDefinition.GetOriginPortIndex(mission))
			{
			case 26:
				return "Ora et Labora.";
			case 9:
			case 12:
			case 20:
				return "We must continued our missionary work.";
			default:
				return UnexpectedOrigin(mission);
			}
		}
	}
	internal sealed class FortAestrinUpperTownGateMission : RegisteredLetterMissionDefinition
	{
		internal static readonly FortAestrinUpperTownGateMission Instance = new FortAestrinUpperTownGateMission();

		private FortAestrinUpperTownGateMission()
			: base("fort_aestrin_upper_town_gate", "Fort Aestrin", 15, new Vector3(112.355f, 35.876f, -61.713f), new Vector3(359.526f, 116.915f, 359.692f), new Vector3(3f, 3f, 3f), LetterDeliveryWindow.Day, new int[10] { 0, 6, 22, 9, 12, 20, 26, 28, 19, 21 }, "Upper Town Gate")
		{
		}//IL_001c: 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_0044: Unknown result type (might be due to invalid IL or missing references)


		internal override string GetDeliveryDialogue(Mission mission)
		{
			switch (LetterMissionDefinition.GetOriginPortIndex(mission))
			{
			case 0:
			case 6:
			case 9:
			case 19:
			case 22:
				return "Your job here is done, courier. Now move along.";
			case 12:
			case 20:
				return "I wonder when we'll get the next shipment of that colorful tobacco.";
			case 26:
			case 28:
				return "God be praised!";
			case 21:
				return "You've come a long way, my friend!";
			default:
				return UnexpectedOrigin(mission);
			}
		}
	}
	internal sealed class FortAestrinWesternmostPierHouseMission : RegisteredLetterMissionDefinition
	{
		internal static readonly FortAestrinWesternmostPierHouseMission Instance = new FortAestrinWesternmostPierHouseMission();

		private FortAestrinWesternmostPierHouseMission()
			: base("fort_aestrin_westernmost_house_at_pier", "Fort Aestrin", 15, new Vector3(-144.465f, -1.242f, -99.124f), new Vector3(359.794f, 152.539f, 359.474f), new Vector3(1.5f, 1.5f, 1.5f), LetterDeliveryWindow.Night, new int[4] { 0, 2, 32, 31 }, "Westernmost house on the pier")
		{
		}//IL_001c: 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_0044: Unknown result type (might be due to invalid IL or missing references)


		internal override string GetDeliveryDialogue(Mission mission)
		{
			int originPortIndex = LetterMissionDefinition.GetOriginPortIndex(mission);
			if (originPortIndex == 0 || originPortIndex == 2 || (uint)(originPortIndex - 31) <= 1u)
			{
				return "Sabbih Ash-shams!";
			}
			return UnexpectedOrigin(mission);
		}
	}
	internal static class GoldenDeliveryMissions
	{
		private readonly struct DestinationCandidate
		{
			internal Port Destination { get; }

			internal float Distance { get; }

			internal DestinationCandidate(Port destination, float distance)
			{
				Destination = destination;
				Distance = distance;
			}
		}

		internal const string DisplayName = "Golden Delivery";

		internal const int RequiredReputation = 9;

		internal const float MoneyMultiplier = 10f;

		internal const float ReputationMultiplier = 15f;

		internal const int SeverelyLatePenalty = -50000;

		private const float SpawnChance = 0.5f;

		private const float MinimumDistance = 288f;

		private const float DueDayBaseSpeed = 4f;

		private const float ComparableRegularMailPackageMultiplier = 2f;

		private const string ActiveMissionDataKey = "PostalExpansion.GoldenDelivery.Active.v1";

		private const string ClaimedOfferDataKey = "PostalExpansion.GoldenDelivery.Claimed.v1";

		private static readonly DailySpecialMissionState State = new DailySpecialMissionState("PostalExpansion.GoldenDelivery.Active.v1", "PostalExpansion.GoldenDelivery.Claimed.v1", SerializeActiveMission, MatchesSavedMission, ApplyMissionName);

		internal static bool IsGolden(Mission mission)
		{
			return State.IsMarked(mission);
		}

		internal static void AddMission(Port origin, List<Mission> missions)
		{
			if (!CanOfferAt(origin) || missions == null || !PostalExpressMail.EnsureRegistered(PrefabsDirectory.instance))
			{
				return;
			}
			Random random = new Random(GetDailySeed(origin));
			if (!(random.NextDouble() >= 0.5))
			{
				List<DestinationCandidate> candidates = GetCandidates(origin);
				if (candidates.Count != 0)
				{
					DestinationCandidate candidate = candidates[random.Next(candidates.Count)];
					Mission val = GenerateMission(origin, candidate);
					MarkRuntime(val);
					missions.Add(val);
				}
			}
		}

		internal static void MissionAccepted(Mission mission)
		{
			State.MissionAccepted(mission);
		}

		internal static void SavePersistentState()
		{
			State.SavePersistentState();
		}

		internal static void LoadPersistentState()
		{
			State.LoadPersistentState();
		}

		internal static void ResetRuntimeState()
		{
			State.ResetRuntimeState();
		}

		private static bool CanOfferAt(Port origin)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)origin == (Object)null || origin.portIndex == 33 || origin.portIndex == 7 || PlayerReputation.GetRepLevel(origin.region) < 9)
			{
				return false;
			}
			return State.CanOfferAt(origin);
		}

		private static List<DestinationCandidate> GetCandidates(Port origin)
		{
			List<DestinationCandidate> list = new List<DestinationCandidate>();
			if (Port.ports == null)
			{
				return list;
			}
			Port[] ports = Port.ports;
			foreach (Port val in ports)
			{
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)origin) && val.portIndex != 7 && !PlayerAlreadyHasGoldenMission(origin, val))
				{
					float distance = Mission.GetDistance(origin, val);
					if (distance > 288f)
					{
						list.Add(new DestinationCandidate(val, distance));
					}
				}
			}
			return list;
		}

		private static Mission GenerateMission(Port origin, DestinationCandidate candidate)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Expected O, but got Unknown
			Good component = PostalExpressMail.Prefab.GetComponent<Good>();
			int num = Mathf.RoundToInt(candidate.Distance * DebugMarketTracker.instance.missionDistanceFee * 2f * Plugin.RegularMailRewardMultiplier.Value * 10f);
			num = CurrencyMarket.instance.GetSellPriceInCurrency((Currency)candidate.Destination.region, (float)num, false);
			int num2 = MailDueDateCalculator.Calculate(origin, candidate.Destination, component, 4f);
			Mission val = new Mission(origin, candidate.Destination, PostalExpressMail.Prefab, 1, num, 1f, 0, num2);
			val.pricePerKm = (float)val.totalPrice / val.distance;
			return val;
		}

		private static void MarkRuntime(Mission mission)
		{
			State.Mark(mission);
			ApplyMissionName(mission);
		}

		private static void ApplyMissionName(Mission mission)
		{
			mission.missionName = "Golden Delivery to " + mission.destinationPort.GetPortName();
		}

		private static bool IsExpressMission(Mission mission)
		{
			if (mission == null || (Object)(object)mission.goodPrefab == (Object)null)
			{
				return false;
			}
			return PostalMail.IsExpressMail(mission.goodPrefab.GetComponent<SaveablePrefab>());
		}

		private static bool PlayerAlreadyHasGoldenMission(Port origin, Port destination)
		{
			if (PlayerMissions.missions == null)
			{
				return false;
			}
			Mission[] missions = PlayerMissions.missions;
			foreach (Mission val in missions)
			{
				if (IsGolden(val) && (Object)(object)val.originPort == (Object)(object)origin && (Object)(object)val.destinationPort == (Object)(object)destination)
				{
					return true;
				}
			}
			return false;
		}

		private static int GetDailySeed(Port origin)
		{
			return ((1907 + GameState.day) * 31 + origin.portIndex) * 31 + 9;
		}

		private static string SerializeActiveMission(int slot, Mission mission)
		{
			return string.Join(",", slot, mission.originPort.portIndex, mission.destinationPort.portIndex, mission.dueDay, mission.totalPrice);
		}

		private static bool MatchesSavedMission(Mission mission, string[] fields)
		{
			if (fields.Length == 5 && int.TryParse(fields[1], out var result) && int.TryParse(fields[2], out var result2) && int.TryParse(fields[3], out var result3) && int.TryParse(fields[4], out var result4) && IsExpressMission(mission) && mission.goodCount == 1 && mission.originPort.portIndex == result && mission.destinationPort.portIndex == result2 && mission.dueDay == result3)
			{
				return mission.totalPrice == result4;
			}
			return false;
		}
	}
	internal sealed class GoldRockCityPalaceFishVendorMission : RegisteredLetterMissionDefinition
	{
		internal static readonly GoldRockCityPalaceFishVendorMission Instance = new GoldRockCityPalaceFishVendorMission();

		private GoldRockCityPalaceFishVendorMission()
			: base("gold_rock_city_palace_fish_vendor", "Gold Rock City", 0, new Vector3(-130.644f, 2.269f, 70.875f), new Vector3(0f, 226.858f, 0f), new Vector3(2f, 2f, 2f), LetterDeliveryWindow.Day, new int[7] { 15, 3, 23, 22, 9, 20, 6 }, "Fish vendor at palace")
		{
		}//IL_001b: 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_0043: Unknown result type (might be due to invalid IL or missing references)


		internal override string GetDeliveryDialogue(Mission mission)
		{
			switch (LetterMissionDefinition.GetOriginPortIndex(mission))
			{
			case 3:
			case 15:
			case 22:
			case 23:
				return "People love exotic fish!";
			case 9:
			case 20:
				return "Eels... not sure about that.";
			case 6:
				if (!VanillaQuestState.IsHideoutQuestComplete())
				{
					return "I will need a fast boat for this delivery.";
				}
				return "Our mutual friend has come up with some new stuff, eh?";
			default:
				return UnexpectedOrigin(mission);
			}
		}
	}
	internal sealed class GoldRockCityPalaceGateMission : RegisteredLetterMissionDefinition
	{
		internal static readonly GoldRockCityPalaceGateMission Instance = new GoldRockCityPalaceGateMission();

		private GoldRockCityPalaceGateMission()
			: base("gold_rock_city_palace_gate", "Gold Rock City", 0, new Vector3(-94.099f, 7.512f, -36.68f), new Vector3(0f, 261.509f, 0f), new Vector3(1.5f, 1.5f, 1.5f), LetterDeliveryWindow.Day, new int[8] { 15, 5, 6, 32, 9, 22, 20, 21 }, "Palace Gate")
		{
		}//IL_001b: 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_0043: Unknown result type (might be due to invalid IL or missing references)


		internal override string GetDeliveryDialogue(Mission mission)
		{
			return "Letter Received. Leave.";
		}
	}
	internal sealed class HappyBayLocalPrinceMission : RegisteredLetterMissionDefinition
	{
		internal static readonly HappyBayLocalPrinceMission Instance = new HappyBayLocalPrinceMission();

		private HappyBayLocalPrinceMission()
			: base("happy_bay_local_prince", "Happy Bay", 20, new Vector3(102.092f, 17.839f, -23.281f), new Vector3(0f, 81.201f, 0f), new Vector3(3f, 3f, 3f), LetterDeliveryWindow.Day, new int[10] { 0, 12, 15, 9, 22, 26, 28, 21, 2, 6 }, "Local Prince")
		{
		}//IL_001c: 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_0044: Unknown result type (might be due to invalid IL or missing references)


		internal override string GetDeliveryDialogue(Mission mission)
		{
			switch (LetterMissionDefinition.GetOriginPortIndex(mission))
			{
			case 12:
			case 15:
				return "More demands...";
			case 2:
			case 26:
			case 28:
				return "Take your god or whatever somewhere else.";
			case 9:
			case 22:
				return "These merchants only care about gold.";
			case 0:
				return "A surprise, but a welcome one.";
			case 21:
				return "At least they stay away from this.";
			case 6:
				if (!VanillaQuestState.IsHideoutQuestComplete())
				{
					return "You're going to have a hard time on the return trip.";
				}
				return "Nice doing business with you.";
			default:
				return UnexpectedOrigin(mission);
			}
		}
	}
	internal sealed class HappyBayUnnamedGraveMission : AnonymousLetterMissionDefinition
	{
		internal static readonly HappyBayUnnamedGraveMission Instance = new HappyBayUnnamedGraveMission();

		private HappyBayUnnamedGraveMission()
			: base("happy_bay_unnamed_grave", "Happy Bay", 20, new Vector3(-6791.194f, 55.928f, -5663.258f), new Vector3(0f, 355.344f, 0f), new Vector3(2.5f, 2.5f, 2.5f), 8844.2f, new LetterDeliveryWindow(5f, 7f, "05-07"), new int[1] { 2 }, "Unnamed grave")
		{
		}//IL_001c: 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_0044: Unknown result type (might be due to invalid IL or missing references)


		internal override string GetDeliveryDialogue(Mission mission)
		{
			if (LetterMissionDefinition.GetOriginPortIndex(mission) != 2)
			{
				return UnexpectedOrigin(mission);
			}
			return "(You place the letter on the grave. It fades into light when sun raise up)";
		}
	}
	internal sealed class KiciaBayWesternmostHouseMission : RegisteredLetterMissionDefinition
	{
		internal static readonly KiciaBayWesternmostHouseMission Instance = new KiciaBayWesternmostHouseMission();

		private KiciaBayWesternmostHouseMission()
			: base("kicia_bay_westernmost_house", "Kicia Bay", 22, new Vector3(204.082f, 3.362f, -107.532f), new Vector3(0f, 74.864f, 0f), new Vector3(1.5f, 1.5f, 1.5f), LetterDeliveryWindow.Night, new int[5] { 6, 9, 0, 18, 20 }, "Western most house")
		{
		}//IL_001c: 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_0044: Unknown result type (might be due to invalid IL or missing references)


		internal override string GetDeliveryDialogue(Mission mission)
		{
			int originPortIndex = LetterMissionDefinition.GetOriginPortIndex(mission);
			if (!VanillaQuestState.IsHideoutQuestComplete())
			{
				switch (originPortIndex)
				{
				case 0:
				case 6:
					return "I wish for a dryer air...";
				case 9:
				case 18:
				case 20:
					return "Oranges...Always oranges...";
				default:
					return UnexpectedOrigin(mission);
				}
			}
			switch (originPortIndex)
			{
			case 6:
				return "Aye...more work! Ye should be shipwreck in the fog!";
			case 0:
			case 9:
			case 18:
			case 20:
				return "They just want me blue tobacco, feck off!";
			default:
				return UnexpectedOrigin(mission);
			}
		}
	}
	internal static class Letter
	{
		internal const int LetterGoodIndex = 68;

		private const int QuestLetterItemIndex = 330;

		private const string LetterName = "Registered Letter";

		private const string InheritedLabelObjectName = "label";

		private const string LetterSealTextureFile = "registered_letter_seal.png";

		private const string LetterSealObjectName = "postal_expansion_registered_letter_seal";

		private const float LetterSealSize = 0.11f;

		private const float LetterSealSurfaceOffset = 0.002f;

		private static GameObject letterPrefab;

		private static readonly PostalSealVisual LetterSeal = new PostalSealVisual("postal_expansion_registered_letter_seal", "registered_letter_seal.png", "registered_letter_seal", 0.11f);

		internal static GameObject Prefab => letterPrefab;

		internal static bool EnsureRegistered(PrefabsDirectory directory)
		{
			if ((Object)(object)directory == (Object)null || directory.directory == null)
			{
				return false;
			}
			if (PostalPrefabRegistration.IsRegistered(directory, 238, letterPrefab))
			{
				return true;
			}
			if (!HasPrefab(directory, 221))
			{
				Debug.LogWarning((object)"Postal Expansion: regular mail prefab 221 was not found.");
				return false;
			}
			if (!HasPrefab(directory, 330))
			{
				Debug.LogWarning((object)"Postal Expansion: vanilla quest letter prefab 330 was not found.");
				return false;
			}
			if (PostalPrefabRegistration.IsSlotOccupiedByAnotherPrefab(directory, 238, letterPrefab))
			{
				Debug.LogError((object)"Postal Expansion: prefab index 238 is already occupied.");
				return false;
			}
			GameObject val = directory.directory[221];
			GameObject questLetterPrefab = directory.directory[330];
			if (!HasRequiredComponents(val, questLetterPrefab) || !PostalPrefabRegistration.EnsureCapacity(directory, 238))
			{
				Debug.LogError((object)"Postal Expansion: Registered Letter prefab components could not be prepared.");
				return false;
			}
			if ((Object)(object)letterPrefab == (Object)null)
			{
				letterPrefab = Object.Instantiate<GameObject>(val);
				((Object)letterPrefab).name = string.Format("{0} ({1}) {2}", 238, 68, "Registered Letter");
				Object.DontDestroyOnLoad((Object)(object)letterPrefab);
			}
			ConfigurePrefab(letterPrefab, questLetterPrefab);
			if (!PostalPrefabRegistration.RegisterShipItem(directory, 238, letterPrefab))
			{
				Debug.LogError((object)"Postal Expansion: Registered Letter prefab could not be registered as a ship item.");
				return false;
			}
			directory.directory[238] = letterPrefab;
			return true;
		}

		private static bool HasPrefab(PrefabsDirectory directory, int prefabIndex)
		{
			if (directory.directory.Length > prefabIndex)
			{
				return (Object)(object)directory.directory[prefabIndex] != (Object)null;
			}
			return false;
		}

		private static bool HasRequiredComponents(GameObject regularMailPrefab, GameObject questLetterPrefab)
		{
			if ((Object)(object)regularMailPrefab.GetComponent<SaveablePrefab>() != (Object)null && (Object)(object)regularMailPrefab.GetComponent<ShipItem>() != (Object)null && (Object)(object)regularMailPrefab.GetComponent<Good>() != (Object)null && (Object)(object)regularMailPrefab.GetComponent<MeshFilter>() != (Object)null && (Object)(object)regularMailPrefab.GetComponent<MeshRenderer>() != (Object)null && (Object)(object)regularMailPrefab.GetComponent<BoxCollider>() != (Object)null && (Object)(object)questLetterPrefab.GetComponent<ShipItem>() != (Object)null && (Object)(object)questLetterPrefab.GetComponent<MeshFilter>() != (Object)null && (Object)(object)questLetterPrefab.GetComponent<MeshRenderer>() != (Object)null)
			{
				return (Object)(object)questLetterPrefab.GetComponent<BoxCollider>() != (Object)null;
			}
			return false;
		}

		private static void ConfigurePrefab(GameObject prefab, GameObject questLetterPrefab)
		{
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: 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_0161: 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_0181: Unknown result type (might be due to invalid IL or missing references)
			prefab.SetActive(true);
			((Object)prefab).name = string.Format("{0} ({1}) {2}", 238, 68, "Registered Letter");
			prefab.GetComponent<SaveablePrefab>().prefabIndex = 238;
			ShipItem component = prefab.GetComponent<ShipItem>();
			ShipItem component2 = questLetterPrefab.GetComponent<ShipItem>();
			component.name = "Registered Letter";
			component.mass = 1f;
			((PickupableItem)component).big = ((PickupableItem)component2).big;
			((PickupableItem)component).holdDistance = ((PickupableItem)component2).holdDistance;
			((PickupableItem)component).holdHeight = ((PickupableItem)component2).holdHeight;
			((PickupableItem)component).heldRotationOffset = ((PickupableItem)component2).heldRotationOffset;
			component.inventoryScale = component2.inventoryScale;
			component.inventoryRotation = component2.inventoryRotation;
			component.inventoryRotationX = component2.inventoryRotationX;
			prefab.GetComponent<Good>().requiredRepLevel = 7;
			MeshFilter component3 = questLetterPrefab.GetComponent<MeshFilter>();
			MeshRenderer component4 = questLetterPrefab.GetComponent<MeshRenderer>();
			BoxCollider component5 = questLetterPrefab.GetComponent<BoxCollider>();
			prefab.GetComponent<MeshFilter>().sharedMesh = component3.sharedMesh;
			((Renderer)prefab.GetComponent<MeshRenderer>()).sharedMaterials = ((Renderer)component4).sharedMaterials;
			BoxCollider component6 = prefab.GetComponent<BoxCollider>();
			component6.center = component5.center;
			component6.size = component5.size;
			Transform val = prefab.transform.Find("label");
			if ((Object)(object)val != (Object)null)
			{
				((Component)val).gameObject.SetActive(false);
				Object.Destroy((Object)(object)((Component)val).gameObject);
			}
			Vector3 center = component6.center;
			center.z += component6.size.z / 2f + 0.002f;
			LetterSeal.Ensure(prefab, center, Quaternion.identity);
		}
	}
	internal sealed class LetterDeliveryArea : MonoBehaviour
	{
		private Port port;

		private LetterMissionDefinition definition;

		private LetterDialoguePresenceArea dialogueArea;

		private Good waitingLetter;

		private bool closedNoticeShown;

		internal void Initialize(Port destinationPort, LetterMissionDefinition missionDefinition, LetterDialoguePresenceArea presenceArea)
		{
			port = destinationPort;
			definition = missionDefinition;
			dialogueArea = presenceArea;
		}

		private void OnTriggerEnter(Collider other)
		{
			Good componentInParent = ((Component)other).GetComponentInParent<Good>();
			if (IsLetter(componentInParent))
			{
				if (!TryGetMatchingMission(componentInParent, out var _))
				{
					ShowNotification("Wrong Letter!");
					return;
				}
				waitingLetter = componentInParent;
				closedNoticeShown = false;
				TryDeliver();
			}
		}

		private void OnTriggerExit(Collider other)
		{
			if ((Object)(object)((Component)other).GetComponentInParent<Good>() == (Object)(object)waitingLetter)
			{
				waitingLetter = null;
				closedNoticeShown = false;
			}
		}

		private void Update()
		{
			if ((Object)(object)waitingLetter != (Object)null && LetterDeliveryHours.IsOpen(definition.DeliveryWindow))
			{
				TryDeliver();
			}
		}

		private void TryDeliver()
		{
			if ((Object)(object)waitingLetter == (Object)null || !TryGetMatchingMission(waitingLetter, out var mission))
			{
				waitingLetter = null;
			}
			else if (!LetterDeliveryHours.IsOpen(definition.DeliveryWindow))
			{
				if (!closedNoticeShown)
				{
					closedNoticeShown = true;
					ShowNotification("Wrong Time!");
				}
			}
			else
			{
				Good obj = waitingLetter;
				waitingLetter = null;
				closedNoticeShown = false;
				string deliveryDialogue = definition.GetDeliveryDialogue(mission);
				LetterMissions.MissionDelivered(mission);
				obj.Deliver();
				dialogueArea?.ShowForDelivery(deliveryDialogue);
			}
		}

		private bool TryGetMatchingMission(Good letter, out Mission mission)
		{
			mission = null;
			if ((Object)(object)letter == (Object)null || PlayerMissions.missions == null)
			{
				return false;
			}
			int missionIndex = letter.GetMissionIndex();
			if (missionIndex < 0 || missionIndex >= PlayerMissions.missions.Length)
			{
				return false;
			}
			mission = PlayerMissions.missions[missionIndex];
			if (mission != null && mission.missionIndex == missionIndex && (Object)(object)mission.destinationPort == (Object)(object)port && LetterMissions.TryGetDefinition(mission, out var letterMissionDefinition))
			{
				return string.Equals(letterMissionDefinition.Id, definition.Id, StringComparison.Ordinal);
			}
			return false;
		}

		private static bool IsLetter(Good good)
		{
			return PostalMail.IsRegisteredLetter(((Object)(object)good != (Object)null) ? ((Component)good).GetComponent<SaveablePrefab>() : null);
		}

		private static void ShowNotification(string message)
		{
			if ((Object)(object)NotificationUi.instance != (Object)null)
			{
				NotificationUi.instance.ShowNotification(message);
			}
		}
	}
	[HarmonyPatch(typeof(PortDude), "Awake")]
	internal static class LetterDeliveryAreaCreationPatch
	{
		private const string AreaRootPrefix = "postal_expansion_letter_";

		private static void Postfix(PortDude __instance)
		{
			if ((Object)(object)__instance == (Object)null || (Object)(object)__instance.GetPort() == (Object)null)
			{
				return;
			}
			foreach (LetterMissionDefinition item in LetterMissionDefinitions.All)
			{
				if (item.DestinationPortIndex == __instance.GetPort().portIndex)
				{
					EnsureArea(__instance, item);
				}
			}
		}

		private static void EnsureArea(PortDude portDude, LetterMissionDefinition definition)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			//IL_00a6: 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)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: 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_0069: 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_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_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			string text = "postal_expansion_letter_" + definition.Id;
			Transform areaParent = GetAreaParent(portDude, definition);
			if (!((Object)(object)areaParent == (Object)null) && !((Object)(object)areaParent.Find(text) != (Object)null))
			{
				GameObject val = new GameObject(text);
				if (definition.UsePersistentWorldAnchor)
				{
					val.transform.position = ((Component)portDude).transform.TransformPoint(definition.LocalPosition);
					val.transform.rotation = ((Component)portDude).transform.rotation * Quaternion.Euler(definition.LocalEulerAngles);
					val.transform.SetParent(areaParent, true);
				}
				else
				{
					val.transform.SetParent(areaParent, false);
					val.transform.localPosition = definition.LocalPosition;
					val.transform.localRotation = Quaternion.Euler(definition.LocalEulerAngles);
				}
				LetterDialoguePresenceArea dialogueArea = CreateDialogueArea(val, definition);
				CreateDeliveryArea(val, portDude.GetPort(), definition, dialogueArea);
				if (definition.UsePersistentWorldAnchor)
				{
					val.AddComponent<PersistentLetterDeliveryAnchor>().Initialize(((Component)portDude).transform, definition.LocalPosition, definition.LocalEulerAngles);
				}
			}
		}

		private static Transform GetAreaParent(PortDude portDude, LetterMissionDefinition definition)
		{
			if (!definition.UsePersistentWorldAnchor)
			{
				return ((Component)portDude).transform;
			}
			if ((Object)(object)Refs.shiftingWorld != (Object)null)
			{
				return Refs.shiftingWorld;
			}
			FloatingOriginManager val = Object.FindObjectOfType<FloatingOriginManager>();
			if ((Object)(object)val != (Object)null)
			{
				return ((Component)val).transform;
			}
			Debug.LogWarning((object)("Postal Expansion: Cannot create persistent delivery area " + definition.Id + "; shifting world is unavailable."));
			return null;
		}

		internal static bool TryGetAreaTransform(LetterMissionDefinition definition, out Transform areaTransform)
		{
			areaTransform = null;
			if (definition == null)
			{
				return false;
			}
			Transform val = null;
			if (definition.UsePersistentWorldAnchor)
			{
				val = Refs.shiftingWorld;
			}
			else if (Port.ports != null && definition.DestinationPortIndex >= 0 && definition.DestinationPortIndex < Port.ports.Length)
			{
				Port val2 = Port.ports[definition.DestinationPortIndex];
				PortDude val3 = (((Object)(object)val2 != (Object)null) ? val2.GetDude() : null);
				val = (((Object)(object)val3 != (Object)null) ? ((Component)val3).transform : null);
			}
			areaTransform = (((Object)(object)val != (Object)null) ? val.Find("postal_expansion_letter_" + definition.Id) : null);
			return (Object)(object)areaTransform != (Object)null;
		}

		private static LetterDialoguePresenceArea CreateDialogueArea(GameObject root, LetterMissionDefinition definition)
		{
			//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_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			GameObject val = new GameObject("postal_expansion_letter_dialogue_" + definition.Id)
			{
				layer = 2
			};
			val.transform.SetParent(root.transform, false);
			BoxCollider obj = val.AddComponent<BoxCollider>();
			((Collider)obj).isTrigger = true;
			obj.size = definition.TriggerSize * 5f;
			AddTriggerRigidbody(val);
			LetterDialoguePresenceArea letterDialoguePresenceArea = val.AddComponent<LetterDialoguePresenceArea>();
			letterDialoguePresenceArea.Initialize(definition);
			return letterDialoguePresenceArea;
		}

		private static void CreateDeliveryArea(GameObject root, Port port, LetterMissionDefinition definition, LetterDialoguePresenceArea dialogueArea)
		{
			//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_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Expected O, but got Unknown
			GameObject val = new GameObject("postal_expansion_letter_delivery_" + definition.Id)
			{
				layer = 2
			};
			val.transform.SetParent(root.transform, false);
			BoxCollider obj = val.AddComponent<BoxCollider>();
			((Collider)obj).isTrigger = true;
			obj.size = definition.TriggerSize;
			AddTriggerRigidbody(val);
			val.AddComponent<LetterDeliveryArea>().Initialize(port, definition, dialogueArea);
		}

		private static void AddTriggerRigidbody(GameObject areaObject)
		{
			Rigidbody obj = areaObject.AddComponent<Rigidbody>();
			obj.isKinematic = true;
			obj.useGravity = false;
		}
	}
	internal sealed class LetterDeliveryDialogue
	{
		private const string BubbleGraphicsName = "gfx";

		private const string BubbleReferenceText = "Share a drink with a fellow sailor?";

		private const int DialogueWrapCharacterLimit = 40;

		private const float ObserverOffset = 0.75f;

		private const float HeadHeightOffset = 0.5f;

		private const float MinimumBubbleWidthMultiplier = 0.35f;

		private const float MaximumBubbleWidthMultiplier = 1.8f;

		private static bool missingBubbleGraphicsWarningLogged;

		private readonly Transform anchor;

		private readonly int portIndex;

		private bool missingTemplateWarningLogged;

		private GameObject panel;

		private TextMesh text;

		private Transform bubbleGraphics;

		private Vector3 baseBubbleScale;

		private float baseTextWidth;

		internal LetterDeliveryDialogue(Transform dialogueAnchor, int destinationPortIndex)
		{
			anchor = dialogueAnchor;
			portIndex = destinationPortIndex;
		}

		internal bool Show(string dialogueText)
		{
			if (!EnsureCreated())
			{
				return false;
			}
			string dialogueText2 = Wrap(dialogueText, 40);
			text.text = dialogueText2;
			ResizeBubble(dialogueText2);
			PositionTowardObserver();
			panel.SetActive(true);
			FaceObserver();
			return true;
		}

		internal void Hide()
		{
			if ((Object)(object)panel != (Object)null)
			{
				panel.SetActive(false);
			}
		}

		internal void FaceObserver()
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)panel == (Object)null) && panel.activeInHierarchy && !((Object)(object)Refs.observerMirror == (Object)null))
			{
				PositionTowardObserver();
				panel.transform.rotation = ((Component)Refs.observerMirror).transform.rotation;
			}
		}

		private void PositionTowardObserver()
		{
			//IL_0026: 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_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_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_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: 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_008b: 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_00b8: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)panel == (Object)null) && !((Object)(object)Refs.observerMirror == (Object)null))
			{
				Vector3 val = ((Component)Refs.observerMirror).transform.position - anchor.position;
				val.y = 0f;
				if (((Vector3)(ref val)).sqrMagnitude < 0.001f)
				{
					val = -anchor.forward;
				}
				else
				{
					((Vector3)(ref val)).Normalize();
				}
				Vector3 position = anchor.position + val * 0.75f;
				position.y = ((Component)Refs.observerMirror).transform.position.y + 0.5f;
				panel.transform.position = position;
			}
		}

		private bool EnsureCreated()
		{
			if ((Object)(object)panel != (Object)null && (Object)(object)text != (Object)null)
			{
				return true;
			}
			panel = LetterDialogueTemplate.Create(anchor, out text);
			if ((Object)(object)panel == (Object)null || (Object)(object)text == (Object)null)
			{
				if (!missingTemplateWarningLogged)
				{
					missingTemplateWarningLogged = true;
					int num = portIndex;
					Debug.LogWarning((object)("Postal Expansion: the letter dialogue template is unavailable at port " + num + "."));
				}
				return false;
			}
			InitializeBubbleLayout();
			panel.SetActive(false);
			return true;
		}

		private void InitializeBubbleLayout()
		{
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			Transform val = (((Object)(object)text != (Object)null) ? ((Component)text).transform.parent : null);
			bubbleGraphics = (((Object)(object)val != (Object)null) ? val.Find("gfx") : null);
			if ((Object)(object)bubbleGraphics == (Object)null || (Object)(object)text == (Object)null || (Object)(object)text.font == (Object)null)
			{
				if (!missingBubbleGraphicsWarningLogged)
				{
					missingBubbleGraphicsWarningLogged = true;
					Debug.LogWarning((object)"Postal Expansion: letter dialogue bubble graphics could not be found; dynamic sizing is disabled.");
				}
			}
			else
			{
				baseBubbleScale = bubbleGraphics.localScale;
				baseTextWidth = MeasureMaximumLineWidth("Share a drink with a fellow sailor?");
			}
		}

		private void ResizeBubble(string dialogueText)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)bubbleGraphics == (Object)null) && !((Object)(object)text == (Object)null) && !((Object)(object)text.font == (Object)null) && !(baseTextWidth <= 0f))
			{
				bubbleGraphics.localScale = baseBubbleScale;
				float num = MeasureMaximumLineWidth(dialogueText);
				if (!(num <= 0f))
				{
					float num2 = Mathf.Clamp(num / baseTextWidth, 0.35f, 1.8f);
					Vector3 localScale = baseBubbleScale;
					localScale.x *= num2;
					bubbleGraphics.localScale = localScale;
				}
			}
		}

		private float MeasureMaximumLineWidth(string value)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			text.font.RequestCharactersInTexture(value, text.fontSize, text.fontStyle);
			float num = 0f;
			float num2 = 0f;
			CharacterInfo val = default(CharacterInfo);
			foreach (char c in value)
			{
				if (c == '\n')
				{
					num2 = Mathf.Max(num2, num);
					num = 0f;
				}
				else if (text.font.GetCharacterInfo(c, ref val, text.fontSize, text.fontStyle))
				{
					num += (float)((CharacterInfo)(ref val)).advance;
				}
			}
			return Mathf.Max(num2, num);
		}

		private static string Wrap(string value, int size)
		{
			value = value.TrimStart(Array.Empty<char>());
			if (value.Length <= size)
			{
				return value;
			}
			int num = value.LastIndexOf(' ', size);
			if (num == -1)
			{
				num = Mathf.Min(value.Length, size);
			}
			return value.Substring(0, num) + ((num >= value.Length) ? string.Empty : ("\n" + Wrap(value.Substring(num), size)));
		}
	}
	internal readonly struct LetterDeliveryWindow
	{
		internal static readonly LetterDeliveryWindow Day = new LetterDeliveryWindow(7f, 18f, "07-18");

		internal static readonly LetterDeliveryWindow Night = new LetterDeliveryWindow(19f, 5f, "19 - 05");

		internal float StartHour { get; }

		internal float EndHour { get; }

		internal string DisplayHours { get; }

		internal LetterDeliveryWindow(float startHour, float endHour, string displayHours)
		{
			StartHour = startHour;
			EndHour = endHour;
			DisplayHours = displayHours;
		}
	}
	internal static class LetterDeliveryHours
	{
		internal static bool IsOpen(LetterDeliveryWindow window)
		{
			if ((Object)(object)Sun.sun == (Object)null)
			{
				return false;
			}
			float localTime = Sun.sun.localTime;
			if (!(window.StartHour <= window.EndHour))
			{
				if (!(localTime >= window.StartHour))
				{
					return localTime <= window.EndHour;
				}
				return true;
			}
			if (localTime >= window.StartHour)
			{
				return localTime <= window.EndHour;
			}
			return false;
		}

		internal static string GetDisplayHours(LetterDeliveryWindow window)
		{
			return window.DisplayHours;
		}
	}
	internal sealed class LetterDialoguePresenceArea : MonoBehaviour
	{
		private const float DialogueRetryInterval = 0.5f;

		private readonly HashSet<Collider> playerColliders = new HashSet<Collider>();

		private LetterDeliveryDialogue dialogue;

		private string pendingText;

		private bool shown;

		private bool consumed;

		private float nextDialogueRetryTime;

		internal void Initialize(LetterMissionDefinition missionDefinition)
		{
			dialogue = new LetterDeliveryDialogue(((Component)this).transform, missionDefinition.DestinationPortIndex);
		}

		internal void ShowForDelivery(string text)
		{
			if (!string.IsNullOrEmpty(text) && !shown && pendingText == null)
			{
				consumed = false;
				pendingText = text;
				nextDialogueRetryTime = 0f;
				TryShow();
			}
		}

		private void OnTriggerEnter(Collider other)
		{
			if (((Component)other).CompareTag("Player"))
			{
				playerColliders.Add(other);
				TryShow();
			}
		}

		private void OnTriggerExit(Collider other)
		{
			if (!((Component)other).CompareTag("Player"))
			{
				return;
			}
			playerColliders.Remove(other);
			if (playerColliders.Count == 0)
			{
				if (shown)
				{
					dialogue.Hide();
				}
				shown = false;
				consumed = true;
				pendingText = null;
				nextDialogueRetryTime = 0f;
			}
		}

		private void Update()
		{
			if (shown)
			{
				dialogue.FaceObserver();
			}
			else if (pendingText != null && playerColliders.Count > 0 && Time.time >= nextDialogueRetryTime)
			{
				nextDialogueRetryTime = Time.time + 0.5f;
				TryShow();
			}
		}

		private void TryShow()
		{
			if (!shown && !consumed && pendingText != null && playerColliders.Count != 0)
			{
				shown = dialogue.Show(pendingText);
			}
		}
	}
	internal static class LetterDialogueTemplate
	{
		private const string TemplateObjectName = "postal_expansion_letter_dialogue_template";

		private static GameObject template;

		private static string textRelativePath;

		internal static bool TryCapture(TavernRumorsDude source)
		{
			if ((Object)(object)template != (Object)null)
			{
				return true;
			}
			if ((Object)(object)source == (Object)null || (Object)(object)source.speechUI == (Object)null || (Object)(object)source.text == (Object)null)
			{
				return false;
			}
			string relativePath = GetRelativePath(source.speechUI.transform, ((Component)source.text).transform);
			if (relativePath == null)
			{
				return false;
			}
			GameObject val = Object.Instantiate<GameObject>(source.speechUI);
			((Object)val).name = "postal_expansion_letter_dialogue_template";
			val.transform.SetParent((Transform)null, true);
			if ((Object)(object)source.drinkButton != (Object)null)
			{
				string relativePath2 = GetRelativePath(source.speechUI.transform, source.drinkButton.transform);
				Transform val2 = FindRelativeTransform(val.transform, relativePath2);
				if ((Object)(object)val2 != (Object)null)
				{
					((Component)val2).gameObject.SetActive(false);
					Object.Destroy((Object)(object)((Component)val2).gameObject);
				}
			}
			val.SetActive(false);
			Object.DontDestroyOnLoad((Object)(object)val);
			template = val;
			textRelativePath = relativePath;
			return true;
		}

		internal static GameObject Create(Transform parent, out TextMesh dialogueText)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			dialogueText = null;
			if ((Object)(object)parent == (Object)null || (!EnsureCaptured() && (Object)(object)template == (Object)null))
			{
				return null;
			}
			GameObject val = Object.Instantiate<GameObject>(template);
			((Object)val).name = "postal_expansion_letter_dialogue";
			val.transform.SetParent(parent, false);
			val.transform.localPosition = Vector3.zero;
			val.transform.localRotation = Quaternion.identity;
			Transform val2 = FindRelativeTransform(val.transform, textRelativePath);
			dialogueText = (((Object)(object)val2 != (Object)null) ? ((Component)val2).GetComponent<TextMesh>() : null);
			val.SetActive(false);
			if ((Object)(object)dialogueText != (Object)null)
			{
				return val;
			}
			Object.Destroy((Object)(object)val);
			return null;
		}

		internal static void Dispose()
		{
			if ((Object)(object)template != (Object)null)
			{
				Object.Destroy((Object)(object)template);
			}
			template = null;
			textRelativePath = null;
		}

		private static bool EnsureCaptured()
		{
			if ((Object)(object)template != (Object)null)
			{
				return true;
			}
			TavernRumorsDude[] array = Object.FindObjectsOfType<TavernRumorsDude>();
			for (int i = 0; i < array.Length; i++)
			{
				if (TryCapture(array[i]))
				{
					return true;
				}
			}
			array = Resources.FindObjectsOfTypeAll<TavernRumorsDude>();
			for (int i = 0; i < array.Length; i++)
			{
				if (TryCapture(array[i]))
				{
					return true;
				}
			}
			return false;
		}

		private static Transform FindRelativeTransform(Transform root, string relativePath)
		{
			if ((Object)(object)root == (Object)null || relativePath == null)
			{
				return null;
			}
			if (relativePath.Length != 0)
			{
				return root.Find(relativePath);
			}
			return root;
		}

		private static string GetRelativePath(Transform root, Transform child)
		{
			if ((Object)(object)root == (Object)null || (Object)(object)child == (Object)null)
			{
				return null;
			}
			List<string> list = new List<string>();
			Transform val = child;
			while ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)root)
			{
				list.Add(((Object)val).name);
				val = val.parent;
			}
			if ((Object)(object)val != (Object)(object)root)
			{
				return null;
			}
			list.Reverse();
			return string.Join("/", list.ToArray());
		}
	}
	[HarmonyPatch(typeof(TavernRumorsDude), "Awake")]
	internal static class LetterDialogueTemplateCapturePatch
	{
		private static void Postfix(TavernRumorsDude __instance)
		{
			LetterDialogueTemplate.TryCapture(__instance);
		}
	}
	internal static class LetterMissionDebug
	{
		private const int EntriesPerPage = 5;

		private static int page;

		internal static void ShowSpawnLocations()
		{
			List<string> list = new List<string>();
			list.AddRange(RegisteredLetterMissions.GetDebugStatusLines());
			list.AddRange(AnonymousLetterMissions.GetDebugStatusLines());
			int num = Mathf.Max(1, Mathf.CeilToInt((float)list.Count / 5f));
			page = Mathf.Clamp(page, 0, num - 1);
			int num2 = page * 5;
			int num3 = Mathf.Min(5, list.Count - num2);
			List<string> list2 = new List<string>();
			list2.Add("Letter mission spawns (" + (page + 1) + "/" + num + "):");
			List<string> list3 = list2;
			for (int i = 0; i < num3; i++)
			{
				list3.Add(list[num2 + i]);
			}
			Debug.Log((object)("Postal Expansion: letter mission spawns: | " + string.Join(" | ", list)));
			if ((Object)(object)NotificationUi.instance != (Object)null)
			{
				NotificationUi.instance.ShowNotification(string.Join("\n", list3));
			}
			page = (page + 1) % num;
		}

		internal static void Reset()
		{
			page = 0;
		}
	}
	internal abstract class LetterMissionDefinition
	{
		internal string Id { get; }

		internal string DestinationPortName { get; }

		internal int DestinationPortIndex { get; }

		internal Vector3 LocalPosition { get; }

		internal Vector3 LocalEulerAngles { get; }

		internal Vector3 TriggerSize { get; }

		internal LetterDeliveryWindow DeliveryWindow { get; }

		internal int[] SpawnPortIndices { get; }

		internal string LocationDescription { get; }

		internal virtual float DistanceToOffice
		{
			get
			{
				//IL_0001: 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_0016: 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)
				Vector2 val = new Vector2(LocalPosition.x, LocalPosition.z);
				return ((Vector2)(ref val)).magnitude;
			}
		}

		internal virtual bool UsePersistentWorldAnchor => false;

		internal virtual bool UseDeliveryLocationForRoute => false;

		internal virtual bool ShowDeliveryCoordinates => false;

		internal virtual bool HideDestination => false;

		protected LetterMissionDefinition(string id, string destinationPortName, int destinationPortIndex, Vector3 localPosition, Vector3 localEulerAngles, Vector3 triggerSize, LetterDeliveryWindow deliveryWindow, int[] spawnPortIndices, string locationDescription)
		{
			//IL_001c: 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_0024: 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_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			Id = id;
			DestinationPortName = destinationPortName;
			DestinationPortIndex = destinationPortIndex;
			LocalPosition = localPosition;
			LocalEulerAngles = localEulerAngles;
			TriggerSize = triggerSize;
			DeliveryWindow = deliveryWindow;
			SpawnPortIndices = spawnPortIndices;
			LocationDescription = locationDescription;
		}

		internal abstract string GetDeliveryDialogue(Mission mission);

		protected static int GetOriginPortIndex(Mission mission)
		{
			return mission?.originPort?.portIndex ?? (-1);
		}

		protected string UnexpectedOrigin(Mission mission)
		{
			Port val = mission?.originPort;
			string text = (((Object)(object)val != (Object)null) ? (val.GetPortName() + " (" + val.portIndex + ")") : "missing origin");
			Debug.LogWarning((object)("Postal Expansion: letter mission " + Id + " received unexpected origin " + text + "."));
			return string.Empty;
		}
	}
	[HarmonyPatch(typeof(MissionDetailsUI), "InsertMissionData")]
	internal static class LetterMissionDetailsPatch
	{
		private const float LocationLabelPosition = 0.45f;

		private const float LocationValuePosition = 0.8f;

		private const float DeliveryHoursValueOffset = 0.5f;

		private const string LocationLabelObjectName = "postal_expansion_letter_location_label";

		private const string LocationValueObjectName = "postal_expansion_letter_location_value";

		private const string DeliveryHoursLabelObjectName = "postal_expansion_letter_delivery_hours_label";

		private const string DeliveryHoursValueObjectName = "postal_expansion_letter_delivery_hours_value";

		private static readonly FieldInfo LocationTextField = AccessTools.Field(typeof(MissionDetailsUI), "locationText");

		private static readonly FieldInfo DestinationTextField = AccessTools.Field(typeof(MissionDetailsUI), "destination");

		private static readonly FieldInfo DueTextField = AccessTools.Field(typeof(MissionDetailsUI), "due");

		private static readonly FieldInfo DistanceTextField = AccessTools.Field(typeof(MissionDetailsUI), "distance");

		private static readonly FieldInfo TotalGoldTextField = AccessTools.Field(typeof(MissionDetailsUI), "totalGold");

		private static readonly FieldInfo MapRendererField = AccessTools.Field(typeof(MissionDetailsUI), "mapRenderer");

		private static void Postfix(MissionDetailsUI __instance, Mission mission)
		{
			//IL_0215: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0309: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance == (Object)null || LocationTextField == null || DestinationTextField == null || DueTextField == null || DistanceTextField == null || TotalGoldTextField == null)
			{
				return;
			}
			object? value = DestinationTextField.GetValue(__instance);
			TextMesh val = (TextMesh)((value is TextMesh) ? value : null);
			object? value2 = DueTextField.GetValue(__instance);
			TextMesh val2 = (TextMesh)((value2 is TextMesh) ? value2 : null);
			object? value3 = DistanceTextField.GetValue(__instance);
			TextMesh val3 = (TextMesh)((value3 is TextMesh) ? value3 : null);
			object? value4 = TotalGoldTextField.GetValue(__instance);
			TextMesh val4 = (TextMesh)((value4 is TextMesh) ? value4 : null);
			if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null || (Object)(object)val3 == (Object)null || (Object)(object)val4 == (Object)null)
			{
				return;
			}
			Transform parent = ((Component)val).transform.parent;
			Transform parent2 = ((Component)val3).transform.parent;
			TextMesh val5 = FindText(parent, "postal_expansion_letter_location_label");
			TextMesh val6 = FindText(parent, "postal_expansion_letter_location_value");
			TextMesh val7 = FindText(parent2, "postal_expansion_letter_delivery_hours_label");
			TextMesh val8 = FindText(parent2, "postal_expansion_letter_delivery_hours_value");
			TextMesh val9 = FindTextByContent(parent, "Destination:");
			TextMesh val10 = FindTextStartingWith(parent, "Cargo:");
			if (!LetterMissions.TryGetDefinition(mission, out var definition))
			{
				SetActive(val9, active: true);
				SetActive(val, active: true);
				SetActive(val5, active: false);
				SetActive(val6, active: false);
				SetActive(val7, active: false);
				SetActive(val8, active: false);
				return;
			}
			val4.text = LetterMissions.GetFixedGoldReward(mission) + " " + PlayerGold.GetCurrencyName(3);
			if ((Object)(object)val9 == (Object)null || (Object)(object)val10 == (Object)null)
			{
				Debug.LogWarning((object)"Postal Expansion: mission detail labels were not found.");
				return;
			}
			val5 = val5 ?? CloneText(val9, "postal_expansion_letter_location_label");
			val6 = val6 ?? CloneText(val, "postal_expansion_letter_location_value");
			if ((Object)(object)val5 == (Object)null || (Object)(object)val6 == (Object)null)
			{
				return;
			}
			if (definition.HideDestination)
			{
				((Component)val5).transform.localPosition = ((Component)val9).transform.localPosition;
				((Component)val6).transform.localPosition = ((Component)val).transform.localPosition;
			}
			else
			{
				float y = ((Component)val).transform.localPosition.y;
				float y2 = ((Component)val10).transform.localPosition.y;
				SetLocalY(((Component)val5).transform, Mathf.Lerp(y, y2, 0.45f));
				SetLocalY(((Component)val6).transform, Mathf.Lerp(y, y2, 0.8f));
			}
			val5.text = "Location:";
			val6.text = definition.LocationDescription;
			SetActive(val9, !definition.HideDestination);
			SetActive(val, !definition.HideDestination);
			SetActive(val5, active: true);
			SetActive(val6, active: true);
			val7 = val7 ?? CloneText(val3, "postal_expansion_letter_delivery_hours_label");
			val8 = val8 ?? CloneText(val2, "postal_expansion_letter_delivery_hours_value");
			if ((Object)(object)val7 != (Object)null && (Object)(object)val8 != (Object)null)
			{
				float y3 = Mathf.Lerp(((Component)val2).transform.localPosition.y, ((Component)val3).transform.localPosition.y, 0.5f);
				SetLocalY(((Component)val7).transform, y3);
				SetLocalY(((Component)val8).transform, y3);
				val7.text = "Delivery hours:";
				val8.text = LetterDeliveryHours.GetDisplayHours(definition.DeliveryWindow);
				SetActive(val7, active: true);
				SetActive(val8, active: true);
				PositionDeliveryHoursValue(val7, val8);
			}
			object? value5 = LocationTextField.GetValue(__instance);
			TextMesh val11 = (TextMesh)((value5 is TextMesh) ? value5 : null);
			object? obj = MapRendererField?.GetValue(__instance);
			Renderer val12 = (Renderer)((obj is Renderer) ? obj : null);
			if (definition.ShowDeliveryCoordinates)
			{
				if ((Object)(object)val12 != (Object)null)
				{
					((Component)val12).gameObject.SetActive(false);
				}
				if ((Object)(object)val11 != (Object)null)
				{
					val11.text = (((Object)(object)FloatingOriginManager.instance != (Object)null && LetterDeliveryAreaCreationPatch.TryGetAreaTransform(definition, out var areaTransform)) ? GetVanillaLocationText(areaTransform) : "approximate location:\nunavailable");
				}
			}
			else if ((Object)(object)val11 != (Object)null)
			{
				val11.text = string.Empty;
			}
		}

		private static string GetVanillaLocationText(Transform deliveryArea)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			Vector3 globeCoords = FloatingOriginManager.instance.GetGlobeCoords(deliveryArea);
			int num = Mathf.RoundToInt(globeCoords.x);
			int num2 = Mathf.RoundToInt(globeCoords.z);
			string text = ((num < 0) ? "W" : "E");
			string text2 = ((num2 < 0) ? "S" : "N");
			return "approximate location:\n" + num2 + " " + text2 + ", " + num + " " + text;
		}

		private static TextMesh CloneText(TextMesh source, string objectName)
		{
			if ((Object)(object)source == (Object)null || (Object)(object)((Component)source).transform.parent == (Object)null)
			{
				return null;
			}
			GameObject obj = Object.Instantiate<GameObject>(((Component)source).gameObject, ((Component)source).transform.parent);
			((Object)obj).name = objectName;
			return obj.GetComponent<TextMesh>();
		}

		private static TextMesh FindText(Transform root, string objectName)
		{
			Transform val = (((Object)(object)root != (Object)null) ? root.Find(objectName) : null);
			if (!((Object)(object)val != (Object)null))
			{
				return null;
			}
			return ((Component)val).GetComponent<TextMesh>();
		}

		private static TextMesh FindTextByContent(Transform root, string content)
		{
			return FindText(root, (string text) => string.Equals(text.Trim(), content, StringComparison.Ordinal));
		}

		private static TextMesh FindTextStartingWith(Transform root, string content)
		{
			return FindText(root, (string text) => text.TrimStart(Array.Empty<char>()).StartsWith(content, StringComparison.Ordinal));
		}

		private static TextMesh FindText(Transform root, Func<string, bool> predicate)
		{
			if ((Object)(object)root == (Object)null)
			{
				return null;
			}
			TextMesh[] componentsInChildren = ((Component)root).GetComponentsInChildren<TextMesh>(true);
			foreach (TextMesh val in componentsInChildren)
			{
				if ((Object)(object)val != (Object)null && predicate(val.text ?? string.Empty))
				{
					return val;
				}
			}
			return null;
		}

		private static void SetLocalY(Transform target, float y)
		{
			//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_0010: Unknown result type (might be due to invalid IL or missing references)
			Vector3 localPosition = target.localPosition;
			localPosition.y = y;
			target.localPosition = localPosition;
		}

		private static void PositionDeliveryHoursValue(TextMesh label, TextMesh value)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: 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_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: 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_0057: 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)
			Vector3 val = ((Component)label).transform.localRotation * Vector3.right;
			Vector3 localPosition = ((Component)label).transform.localPosition + ((Vector3)(ref val)).normalized * 0.5f;
			localPosition.y = ((Component)value).transform.localPosition.y;
			localPosition.z = ((Component)value).transform.localPosition.z;
			((Component)value).transform.localPosition = localPosition;
		}

		private static void SetActive(TextMesh text, bool active)
		{
			if ((Object)(object)text != (Object)null)
			{
				((Component)text).gameObject.SetActive(active);
			}
		}
	}
	internal sealed class LetterMissionRegistry<TDefinition> where TDefinition : LetterMissionDefinition
	{
		private readonly List<TDefinition> definitions = new List<TDefinition>();

		internal IReadOnlyList<TDefinition> All => definitions;

		internal LetterMissionRegistry(string categoryName, params TDefinition[] candidates)
		{
			HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal);
			foreach (TDefinition val in candidates)
			{
				if (val == null || string.IsNullOrEmpty(val.Id))
				{
					Debug.LogError((object)("Postal Expansion: ignored a " + categoryName + " mission without an ID."));
				}
				else if (!hashSet.Add(val.Id))
				{
					Debug.LogError((object)("Postal Expansion: ignored duplicate " + categoryName + " mission ID " + val.Id + "."));
				}
				else
				{
					definitions.Add(val);
				}
			}
		}
	}
	internal static class LetterMissionDefinitions
	{
		private static readonly IReadOnlyList<LetterMissionDefinition> Definitions = BuildDefinitions();

		internal static IReadOnlyList<LetterMissionDefinition> All => Definitions;

		private static IReadOnlyList<LetterMissionDefinition> BuildDefinitions()
		{
			List<LetterMissionDefinition> list = new List<LetterMissionDefinition>();
			foreach (RegisteredLetterMissionDefinition item in RegisteredLetterMissionRegistry.All)
			{
				list.Add(item);
			}
			foreach (AnonymousLetterMissionDefinition item2 in AnonymousLetterMissionRegistry.All)
			{
				list.Add(item2);
			}
			return list.AsReadOnly();
		}
	}
	internal static class LetterMissionRoute
	{
		internal static float GetMissionDistance(Port origin, Port destination, LetterMissionDefinition definition)
		{
			float distance = Mission.GetDistance(origin, destination);
			if (!definition.UseDeliveryLocationForRoute || (Object)(object)destination == (Object)null || destination.portIndex != definition.DestinationPortIndex)
			{
				return distance;
			}
			return distance + definition.DistanceToOffice / 100f;
		}
	}
	internal static class LetterMissions
	{
		internal static bool TryGetDefinition(Mission mission, out LetterMissionDefinition definition)
		{
			if (AnonymousLetterMissions.TryGetDefinition(mission, out var definition2))
			{
				definition = definition2;
				return true;
			}
			if (RegisteredLetterMissions.TryGetDefinition(mission, out var definition3))
			{
				definition = definition3;
				return true;
			}
			definition = null;
			return false;
		}

		internal static void MissionDelivered(Mission mission)
		{
			AnonymousLetterMissions.MissionDelivered(mission);
			RegisteredLetterMissions.MissionDelivered(mission);
		}

		internal static int GetFixedGoldReward(Mission mission)
		{
			if (!AnonymousLetterMissions.TryGetDefinition(mission, out var _))
			{
				return 1;
			}
			return 5;
		}

		internal static float GetReputationMultiplier(Mission mission)
		{
			if (!AnonymousLetterMissions.TryGetDefinition(mission, out var _))
			{
				return 8f;
			}
			return 10f;
		}

		internal static int GetSeverelyLatePenalty(Mission mission)
		{
			if (!AnonymousLetterMissions.TryGetDefinition(mission, out var _))
			{
				return -5000;
			}
			return -8000;
		}
	}
	internal readonly struct LetterMissionSaveKeys
	{
		internal string ActiveMissions { get; }

		internal string ClaimedOffers { get; }

		internal LetterMissionSaveKeys(string activeMissions, string claimedOffers)
		{
			ActiveMissions = activeMissions;
			ClaimedOffers = claimedOffers;
		}
	}
	internal sealed class LetterMissionSet<TDefinition> where TDefinition : LetterMissionDefinition
	{
		private sealed class MissionData
		{
			internal TDefinition Definition { get; }

			internal MissionData(TDefinition definition)
			{
				Definition = definition;
			}
		}

		private readonly string categoryName;

		private readonly IReadOnlyList<TDefinition> definitions;

		private readonly Dictionary<string, TDefinition> definitionsById;

		private readonly LetterMissionSaveKeys saveKeys;

		private readonly int requiredReputation;

		private readonly float dueDayBaseSpeed;

		private readonly int fixedGoldReward;

		private readonly Func<Port, string> getMissionName;

		private ConditionalWeakTable<Mission, MissionData> missionData = new ConditionalWeakTable<Mission, MissionData>();

		private readonly Dictionary<string, Mission> dailyOffers = new Dictionary<string, Mission>(StringComparer.Ordinal);

		private readonly HashSet<string> claimedOffers = new HashSet<string>(StringComparer.Ordinal);

		private int dailyOfferDay = int.MinValue;

		internal LetterMissionSet(string categoryName, IReadOnlyList<TDefinition> definitions, LetterMissionSaveKeys saveKeys, int requiredReputation, float dueDayBaseSpeed, int fixedGoldReward, Func<Port, string> getMissionName)
		{
			this.categoryName = categoryName;
			this.definitions = definitions;
			this.saveKeys = saveKeys;
			this.requiredReputation = requiredReputation;
			this.dueDayBaseSpeed = dueDayBaseSpeed;
			this.fixedGoldReward = fixedGoldReward;
			this.getMissionName = getMissionName;
			definitionsById = new Dictionary<string, TDefinition>(StringComparer.Ordinal);
			foreach (TDefinition definition in definitions)
			{
				definitionsById.Add(definition.Id, definition);
			}
		}

		internal void AddMissions(Port origin, List<Mission> missions)
		{
			if ((Object)(object)origin == (Object)null || missions == null)
			{
				return;
			}
			EnsureDailyOffers();
			foreach (TDefinition definition in definitions)
			{
				if (dailyOffers.TryGetValue(definition.Id, out var value) && value != null && !((Object)(object)value.originPort != (Object)(object)origin) && CanOfferFrom(origin, value.destinationPort) && value.missionIndex == -1 && !IsClaimed(definition.Id) && !HasActiveMission(definition.Id))
				{
					missions.Add(value);
				}
			}
		}

		internal List<string> GetDebugStatusLines()
		{
			EnsureDailyOffers();
			List<string> list = new List<string>();
			foreach (TDefinition definition in definitions)
			{
				Mission activeMission;
				Mission value;
				string text = ((!TryGetActiveMission(definition.Id, out activeMission)) ? ((!IsClaimed(definition.Id)) ? ((!dailyOffers.TryGetValue(definition.Id, out value) || value == null || value.missionIndex != -1 || !CanOfferFrom(value.originPort, value.destinationPort)) ? "not available today" : GetPortName(value.originPort)) : "already claimed today") : ("active from " + GetPortName(activeMission.originPort)));
				list.Add(categoryName + " | " + definition.LocationDescription + ": " + text);
			}
			return list;
		}

		internal bool TryGetDefinition(Mission mission, out TDefinition definition)
		{
			if (mission != null && missionData.TryGetValue(mission, out var value))
			{
				definition = value.Definition;
				return true;
			}
			definition = null;
			return false;
		}

		internal void MissionAccepted(Mission mission)
		{
			if (TryGetDefinition(mission, out var definition) && mission.missionIndex >= 0 && PlayerMissions.missions != null && mission.missionIndex < PlayerMissions.missions.Length && PlayerMissions.missions[mission.missionIndex] == mission)
			{
				claimedOffers.Add(GetClaimKey(GameState.day, definition.Id));
			}
		}

		internal void MissionDelivered(Mission mission)
		{
			if (TryGetDefinition(mission, out var definition))
			{
				claimedOffers.Add(GetClaimKey(GameState.day, definition.Id));
			}
		}

		internal void SavePersistentState()
		{
			if (GameState.modData == null)
			{
				GameState.modData = new Dictionary<string, string>();
			}
			List<string> list = new List<string>();
			if (PlayerMissions.missions != null)
			{
				for (int i = 0; i < PlayerMissions.missions.Length; i++)
				{
					Mission val = PlayerMissions.missions[i];
					if (TryGetDefinition(val, out var definition) && !((Object)(object)val.originPort == (Object)null) && !((Object)(object)val.destinationPort == (Object)null))
					{
						list.Add(string.Join(",", i, val.originPort.portIndex, val.destinationPort.portIndex, definition.Id));
					}
				}
			}
			GameState.modData[saveKeys.ActiveMissions] = string.Join(";", list);
			PruneClaimsForCurrentDay();
			List<string> list2 = new List<string>(claimedOffers);
			list2.Sort(StringComparer.Ordinal);
			GameState.modData[saveKeys.ClaimedOffers] = string.Join(";", list2);
		}

		internal void LoadPersistentState(params LetterMissionSaveKeys[] legacySaveKeys)
		{
			ResetRuntimeState();
			if (GameState.modData != null)
			{
				LoadClaims(saveKeys);
				LoadActiveMissions(saveKeys);
				foreach (LetterMissionSaveKeys sourceKeys in legacySaveKeys)
				{
					LoadClaims(sourceKeys);
					LoadActiveMissions(sourceKeys);
				}
			}
		}

		internal void ResetRuntimeState()
		{
			missionData = new ConditionalWeakTable<Mission, MissionData>();
			dailyOffers.Clear();
			claimedOffers.Clear();
			dailyOfferDay = int.MinValue;
		}

		private void LoadClaims(LetterMissionSaveKeys sourceKeys)
		{
			if (!GameState.modData.TryGetValue(sourceKeys.ClaimedOffers, out var value))
			{
				return;
			}
			string text = GameState.day + ",";
			string[] array = value.Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries);
			foreach (string text2 in array)
			{
				if (text2.StartsWith(text, StringComparison.Ordinal))
				{
					string key = text2.Substring(text.Length);
					if (definitionsById.ContainsKey(key))
					{
						claimedOffers.Add(text2);
					}
				}
			}
		}

		private void LoadActiveMissions(LetterMissionSaveKeys sourceKeys)
		{
			if (PlayerMissions.missions == null || !GameState.modData.TryGetValue(sourceKeys.ActiveMissions, out var value))
			{
				return;
			}
			string[] array = value.Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries);
			for (int i = 0; i < array.Length; i++)
			{
				string[] array2 = array[i].Split(new char[1] { ',' });
				if (array2.Length == 4 && int.TryParse(array2[0], out var result) && int.TryParse(array2[1], out var result2) && int.TryParse(array2[2], out var result3) && result >= 0 && result < PlayerMissions.missions.Length && definitionsByI