Decompiled source of ShipwrightTransportation v0.1.3

BepInEx/plugins/ShipwrightAndTransport/ShipwrightAndTransport.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Versioning;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using ShipwrightAndTransport.Compat;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ShipwrightAndTransport
{
	internal sealed class PlateItem : MonoBehaviour
	{
		internal static readonly HashSet<PlateItem> Live = new HashSet<PlateItem>();

		internal PlateRecord Record;

		internal string FaceKey;

		private void Start()
		{
			Live.Add(this);
			SaveablePrefab component = ((Component)this).GetComponent<SaveablePrefab>();
			if (Record == null && Object.op_Implicit((Object)(object)component))
			{
				Record = Plates.RecordOf(component.instanceId);
			}
			if (Record == null)
			{
				Log.Warn("Plates: a name plate (instance " + (Object.op_Implicit((Object)(object)component) ? component.instanceId : 0) + ") has no record; it shows no name.");
				return;
			}
			PlateStyle plateStyle = (Object.op_Implicit((Object)(object)component) ? PlateData.StyleOfPrefab(component.prefabIndex) : null) ?? PlateData.Style(Record.style);
			MeshRenderer component2 = ((Component)this).GetComponent<MeshRenderer>();
			if (Object.op_Implicit((Object)(object)component2))
			{
				Material[] sharedMaterials = ((Renderer)component2).sharedMaterials;
				if (plateStyle.FaceSlot < sharedMaterials.Length)
				{
					((Renderer)component2).sharedMaterials = PlateFaces.Dress(plateStyle, sharedMaterials, Record.font, Record.size, Record.name);
					FaceKey = PlateFaces.Key(plateStyle.Key, Record.font, Record.size, Record.name);
					PlateScaling.Apply(this, PlateData.CleanScale(Record.scale));
				}
			}
		}

		private void OnDestroy()
		{
			Live.Remove(this);
		}
	}
	internal static class PlateScaling
	{
		private static readonly Dictionary<string, Mesh> meshes = new Dictionary<string, Mesh>();

		internal static void Apply(PlateItem plate, float scale)
		{
			//IL_0072: 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_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)plate) || Mathf.Approximately(scale, 1f))
			{
				return;
			}
			try
			{
				MeshFilter component = ((Component)plate).GetComponent<MeshFilter>();
				if (!Object.op_Implicit((Object)(object)component) || !Object.op_Implicit((Object)(object)component.sharedMesh) || !component.sharedMesh.isReadable)
				{
					Log.Warn("Plates: a plate's mesh can't be read, so it stays size 1.");
					return;
				}
				component.sharedMesh = Scaled(component.sharedMesh, scale);
				BoxCollider component2 = ((Component)plate).GetComponent<BoxCollider>();
				if (Object.op_Implicit((Object)(object)component2))
				{
					component2.center *= scale;
					component2.size *= scale;
				}
				ShipItem component3 = ((Component)plate).GetComponent<ShipItem>();
				if (Object.op_Implicit((Object)(object)component3))
				{
					component3.value = Mathf.RoundToInt((float)component3.value * scale);
					component3.inventoryScale /= scale;
					if (scale > 1f)
					{
						((PickupableItem)component3).holdDistance = ((PickupableItem)component3).holdDistance * scale;
					}
				}
			}
			catch (Exception ex)
			{
				Log.Warn("Plates: sizing a plate to " + scale + " failed; it stays size 1: " + ex.Message);
			}
		}

		internal static Mesh Scaled(Mesh source, float scale)
		{
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			string key = ((Object)source).GetInstanceID() + "/" + scale.ToString("R", CultureInfo.InvariantCulture);
			if (meshes.TryGetValue(key, out var value) && Object.op_Implicit((Object)(object)value))
			{
				return value;
			}
			value = Object.Instantiate<Mesh>(source);
			((Object)value).name = ((Object)source).name + " x" + scale;
			Vector3[] vertices = value.vertices;
			for (int i = 0; i < vertices.Length; i++)
			{
				ref Vector3 reference = ref vertices[i];
				reference *= scale;
			}
			value.vertices = vertices;
			value.RecalculateBounds();
			meshes[key] = value;
			return value;
		}
	}
	internal static class Plates
	{
		internal static readonly Vector3 OnDocuments = new Vector3(0f, 0f, 0.05f);

		internal const float StackStep = 0.08f;

		internal static PlateRecord RecordOf(int instanceId)
		{
			if (instanceId != 0)
			{
				return State.Save.plates.Find((PlateRecord p) => p.instanceId == instanceId);
			}
			return null;
		}

		internal static bool Buy(Shipyard yard, ShipyardInfo info, PlateStyle style, string fontAsset, int size, float scale, int shipIndex)
		{
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = PlateBundle.Prefab(style);
			if (!Object.op_Implicit((Object)(object)val))
			{
				Notify.Show("Name plates are\nnot available.");
				return false;
			}
			ShipyardDocuments val2 = Shipyards.Documents(yard);
			if (!Object.op_Implicit((Object)(object)val2))
			{
				return false;
			}
			scale = PlateData.CleanScale(scale);
			int num = Mathf.Clamp(yard.region, 0, Fees.PlatePrice.Length - 1);
			if (!Money.Pay(num, Fees.PlatePriceAt(num, scale)))
			{
				return false;
			}
			PlateRecord plateRecord = new PlateRecord
			{
				style = style.Key,
				name = Ships.NameOf(shipIndex),
				font = fontAsset,
				size = size,
				shipIndex = shipIndex,
				scale = scale
			};
			TableSpot(((Component)val2).transform, BottomOf(val.GetComponent<MeshFilter>().sharedMesh, scale), out var position, out var rotation);
			GameObject val3 = Object.Instantiate<GameObject>(val, position, rotation);
			(val3.GetComponent<PlateItem>() ?? val3.AddComponent<PlateItem>()).Record = plateRecord;
			val3.GetComponent<ShipItem>().sold = true;
			SaveablePrefab component = val3.GetComponent<SaveablePrefab>();
			component.RegisterToSave();
			plateRecord.instanceId = component.instanceId;
			if (Object.op_Implicit((Object)(object)FloatingOriginManager.instance))
			{
				val3.transform.SetParent(((Component)FloatingOriginManager.instance).transform, true);
			}
			State.Save.plates.Add(plateRecord);
			Log.Info("Bought a " + style.Key + " plate \"" + plateRecord.name + "\" (" + fontAsset + ", size " + size + ", plate size " + PlateData.ScaleText(scale) + ", " + Fees.PlatePriceAt(num, scale) + " " + Money.Short[num] + ", instance " + plateRecord.instanceId + ").");
			Notify.Show("Your name plate is ready\non the documents.");
			return true;
		}

		internal static void TableSpot(Transform documents, float plateBottom, out Vector3 position, out Quaternion rotation)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = (Object.op_Implicit((Object)(object)Refs.observerMirror) ? ((Component)Refs.observerMirror).transform.position : (documents.position - documents.up)) - documents.position;
			val.y = 0f;
			val = ((((Vector3)(ref val)).sqrMagnitude > 0.01f) ? ((Vector3)(ref val)).normalized : Vector3.forward);
			rotation = Quaternion.LookRotation(-val, Vector3.up);
			Vector3 val2 = documents.TransformPoint(OnDocuments);
			int num = 0;
			foreach (PlateItem item in PlateItem.Live)
			{
				if (Object.op_Implicit((Object)(object)item))
				{
					Vector3 val3 = ((Component)item).transform.position - val2;
					Vector2 val4 = new Vector2(val3.x, val3.z);
					if (((Vector2)(ref val4)).magnitude < 0.6f && val3.y > -0.05f && val3.y < 6f)
					{
						num++;
					}
				}
			}
			position = val2 + Vector3.up * plateBottom - val * (0.08f * (float)num);
		}

		internal static float BottomOf(Mesh mesh, float scale)
		{
			//IL_0011: 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_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)mesh))
			{
				return 0.25f * scale;
			}
			Bounds bounds = mesh.bounds;
			float y = ((Bounds)(ref bounds)).extents.y;
			bounds = mesh.bounds;
			return (y - ((Bounds)(ref bounds)).center.y) * scale;
		}
	}
	internal static class PlateRegions
	{
		internal const int AllRegions = 7;

		private static readonly string[] Names = new string[3] { "Al'Ankh", "Emerald", "Aestrin" };

		internal static bool UnlockVisited
		{
			get
			{
				if (Plugin.UnlockVisitedPlates != null)
				{
					return Plugin.UnlockVisitedPlates.Value;
				}
				return false;
			}
		}

		internal static bool Visited(int mask, int region)
		{
			if (region >= 0 && region < Names.Length)
			{
				return (mask & (1 << region)) != 0;
			}
			return false;
		}

		internal static int Mark(int mask, int region)
		{
			if (region < 0 || region >= Names.Length)
			{
				return mask;
			}
			return mask | (1 << region);
		}

		internal static List<int> SoldAt(int yardRegion, int visited, bool unlock)
		{
			List<int> list = new List<int>();
			for (int i = 0; i < PlateData.Styles.Length; i++)
			{
				int region = PlateData.Styles[i].Region;
				if (region == yardRegion || (unlock && Visited(visited, region)))
				{
					list.Add(i);
				}
			}
			return list;
		}

		internal static List<int> SoldAt(Shipyard yard)
		{
			return SoldAt(yard.region, State.Save.visitedRegions, UnlockVisited);
		}

		internal static void Visit(Shipyard yard)
		{
			if (Object.op_Implicit((Object)(object)yard) && !State.Off)
			{
				int num = Mark(State.Save.visitedRegions, yard.region);
				if (num != State.Save.visitedRegions)
				{
					State.Save.visitedRegions = num;
					Log.Info("Visited the " + Names[yard.region] + " region (" + (Shipyards.PortOf(yard) ?? ((Object)yard).name) + " shipyard); its name plates are sold at every shipyard " + (UnlockVisited ? "now." : "once [Plates] Unlock visited regions is on."));
				}
			}
		}
	}
	internal sealed class PlateStyle
	{
		internal string Key;

		internal string Title;

		internal int Region;

		internal int PrefabIndex;

		internal int FaceSlot;

		internal int CanvasWidth;

		internal int CanvasHeight;

		internal int BasePixels;

		internal int LettersSlot = -1;

		internal int[] LettersRect;

		internal bool Ornaments;

		internal float Width;

		internal float Height;

		internal float BoxX;

		internal float BoxY;

		internal float BoxWidth;

		internal float BoxHeight;

		internal float EllipseX;

		internal float EllipseY;

		internal float CameraDistance;

		internal float LookY;

		internal bool BrassLetters
		{
			get
			{
				if (LettersSlot >= 0)
				{
					return LettersRect != null;
				}
				return false;
			}
		}
	}
	internal sealed class PlateFont
	{
		internal string Button;

		internal string Asset;

		internal float StrokeWeight;

		internal float LabelScale = 1f;
	}
	internal static class PlateData
	{
		internal const int MinSize = 1;

		internal const int MaxSize = 24;

		internal const int DefaultSize = 10;

		internal static readonly float[] Scales = new float[15]
		{
			0.8f, 0.9f, 1f, 1.1f, 1.2f, 1.3f, 1.4f, 1.5f, 2f, 2.5f,
			3f, 3.5f, 4f, 4.5f, 5f
		};

		internal const int DefaultScaleStep = 2;

		internal static readonly PlateStyle[] Styles = new PlateStyle[6]
		{
			new PlateStyle
			{
				Key = "alankh",
				Region = 0,
				Title = "Al'Ankh Copper Star",
				PrefabIndex = 650,
				FaceSlot = 0,
				Ornaments = true,
				CanvasWidth = 1800,
				CanvasHeight = 420,
				BasePixels = 185,
				BoxX = 185.1f,
				BoxY = 43.3f,
				BoxWidth = 1429.8f,
				BoxHeight = 333.3f,
				Width = 0.8f,
				Height = 0.1867f,
				CameraDistance = 1.28f,
				LookY = 0f
			},
			new PlateStyle
			{
				Key = "alankh_rope",
				Region = 0,
				Title = "Al'Ankh Rope Plaque",
				PrefabIndex = 653,
				FaceSlot = 0,
				Ornaments = true,
				CanvasWidth = 1600,
				CanvasHeight = 800,
				BasePixels = 150,
				BoxX = 179.5f,
				BoxY = 116.7f,
				BoxWidth = 1240.9f,
				BoxHeight = 566.7f,
				EllipseX = 583.2f,
				EllipseY = 255f,
				Width = 0.6343f,
				Height = 0.3343f,
				CameraDistance = 1.03f,
				LookY = 0f
			},
			new PlateStyle
			{
				Key = "aestrin",
				Region = 2,
				Title = "Aestrin Brass Anchor",
				PrefabIndex = 651,
				FaceSlot = 0,
				Ornaments = false,
				CanvasWidth = 1928,
				CanvasHeight = 711,
				BasePixels = 200,
				BoxX = 77.9f,
				BoxY = 260.1f,
				BoxWidth = 1772.3f,
				BoxHeight = 360f,
				LettersSlot = 4,
				LettersRect = new int[4] { 41, 224, 1846, 433 },
				Width = 0.9273f,
				Height = 0.3391f,
				CameraDistance = 1.48f,
				LookY = 0f
			},
			new PlateStyle
			{
				Key = "aestrin_quarter",
				Region = 2,
				Title = "Aestrin Quarter Board",
				PrefabIndex = 654,
				FaceSlot = 0,
				Ornaments = true,
				CanvasWidth = 2200,
				CanvasHeight = 600,
				BasePixels = 150,
				BoxX = 384f,
				BoxY = 160f,
				BoxWidth = 1431.9f,
				BoxHeight = 280f,
				Width = 1.085f,
				Height = 0.226f,
				CameraDistance = 1.64f,
				LookY = 0f
			},
			new PlateStyle
			{
				Key = "emerald",
				Region = 1,
				Title = "Emerald Lacquered Red",
				PrefabIndex = 652,
				FaceSlot = 0,
				Ornaments = true,
				CanvasWidth = 1660,
				CanvasHeight = 388,
				BasePixels = 170,
				BoxX = 233.2f,
				BoxY = 39.9f,
				BoxWidth = 1193.6f,
				BoxHeight = 297.8f,
				LettersSlot = 3,
				LettersRect = new int[4] { 203, 10, 1254, 358 },
				Width = 0.86f,
				Height = 0.2752f,
				CameraDistance = 1.37f,
				LookY = 0f
			},
			new PlateStyle
			{
				Key = "emerald_torii",
				Region = 1,
				Title = "Emerald Torii",
				PrefabIndex = 655,
				FaceSlot = 2,
				Ornaments = false,
				CanvasWidth = 1100,
				CanvasHeight = 440,
				BasePixels = 130,
				BoxX = 43.6f,
				BoxY = 87.2f,
				BoxWidth = 1012.8f,
				BoxHeight = 244.4f,
				Width = 0.9045f,
				Height = 0.4277f,
				CameraDistance = 1.45f,
				LookY = 0.025f
			}
		};

		internal static readonly PlateFont[] Fonts = new PlateFont[6]
		{
			new PlateFont
			{
				Button = "Immortal",
				Asset = "IMMORTAL",
				StrokeWeight = 1f,
				LabelScale = 1f
			},
			new PlateFont
			{
				Button = "Architects Daughter",
				Asset = "ArchitectsDaughter",
				StrokeWeight = 0.55f,
				LabelScale = 0.74f
			},
			new PlateFont
			{
				Button = "Kaushan Script",
				Asset = "KaushanScript-Regular",
				StrokeWeight = 0.8f,
				LabelScale = 0.9f
			},
			new PlateFont
			{
				Button = "Callimundial",
				Asset = "Callimundial",
				StrokeWeight = 0.8f,
				LabelScale = 0.95f
			},
			new PlateFont
			{
				Button = "Polo",
				Asset = "Polo-SemiBold",
				StrokeWeight = 0.85f,
				LabelScale = 1f
			},
			new PlateFont
			{
				Button = "Alex Brush",
				Asset = "AlexBrush-Regular",
				StrokeWeight = 0.4f,
				LabelScale = 1.2f
			}
		};

		internal static int ScaleStep(float scale)
		{
			if (float.IsNaN(scale) || scale <= 0f)
			{
				return 2;
			}
			int num = 2;
			for (int i = 0; i < Scales.Length; i++)
			{
				if (Math.Abs(Scales[i] - scale) < Math.Abs(Scales[num] - scale))
				{
					num = i;
				}
			}
			return num;
		}

		internal static float CleanScale(float scale)
		{
			return Scales[ScaleStep(scale)];
		}

		internal static string ScaleText(float scale)
		{
			return CleanScale(scale).ToString("0.#", CultureInfo.InvariantCulture);
		}

		internal static string SizeText(PlateStyle style, float scale, string times = " × ")
		{
			float num = CleanScale(scale);
			return (style.Width * num).ToString("0.00", CultureInfo.InvariantCulture) + times + (style.Height * num).ToString("0.00", CultureInfo.InvariantCulture) + " m";
		}

		internal static PlateStyle Style(string key)
		{
			PlateStyle[] styles = Styles;
			foreach (PlateStyle plateStyle in styles)
			{
				if (plateStyle.Key == key)
				{
					return plateStyle;
				}
			}
			return Styles[0];
		}

		internal static PlateStyle StyleOfPrefab(int prefabIndex)
		{
			PlateStyle[] styles = Styles;
			foreach (PlateStyle plateStyle in styles)
			{
				if (plateStyle.PrefabIndex == prefabIndex)
				{
					return plateStyle;
				}
			}
			return null;
		}

		internal static PlateFont Font(string asset)
		{
			PlateFont[] fonts = Fonts;
			foreach (PlateFont plateFont in fonts)
			{
				if (plateFont.Asset == asset)
				{
					return plateFont;
				}
			}
			return Fonts[0];
		}
	}
	internal static class PlateBundle
	{
		internal const string FileName = "dogeggz.shipwrighttransport.assets";

		private static AssetBundle bundle;

		private static readonly Dictionary<int, GameObject> prefabs = new Dictionary<int, GameObject>();

		private static readonly Dictionary<string, byte[]> inputs = new Dictionary<string, byte[]>();

		private static readonly HashSet<Shader> bundleShaders = new HashSet<Shader>();

		internal static bool Loaded => prefabs.Count == PlateData.Styles.Length;

		internal static Shader GameStandard { get; private set; }

		internal static void Load(string pluginDirectory)
		{
			string text = Path.Combine(Path.Combine(pluginDirectory, "assets"), "dogeggz.shipwrighttransport.assets");
			if (!File.Exists(text))
			{
				Log.Error("Plates: " + text + " is missing, so there are no name plates.");
				return;
			}
			bundle = AssetBundle.LoadFromFile(text);
			if (!Object.op_Implicit((Object)(object)bundle))
			{
				Log.Error("Plates: " + text + " could not be loaded.");
				return;
			}
			GameObject[] array = bundle.LoadAllAssets<GameObject>();
			foreach (GameObject val in array)
			{
				SaveablePrefab component = val.GetComponent<SaveablePrefab>();
				if (Object.op_Implicit((Object)(object)component) && PlateData.StyleOfPrefab(component.prefabIndex) != null)
				{
					if (!Object.op_Implicit((Object)(object)val.GetComponent<PlateItem>()))
					{
						val.AddComponent<PlateItem>();
					}
					prefabs[component.prefabIndex] = val;
				}
			}
			foreach (Material item in StandardMaterials())
			{
				bundleShaders.Add(item.shader);
			}
			if (Loaded)
			{
				Log.Info("Plates: bundle loaded, prefabs 650-655.");
				return;
			}
			Log.Error("Plates: the bundle has " + prefabs.Count + " of the " + PlateData.Styles.Length + " plate prefabs.");
		}

		internal static GameObject Prefab(PlateStyle style)
		{
			if (!prefabs.TryGetValue(style.PrefabIndex, out var value))
			{
				return null;
			}
			return value;
		}

		internal static void UseGameShader(PrefabsDirectory directory)
		{
			try
			{
				List<Material> list = StandardMaterials();
				if (!Object.op_Implicit((Object)(object)directory) || list.Count == 0)
				{
					return;
				}
				Shader val = null;
				string text = null;
				GameObject[] array = (GameObject[])(((object)directory.directory) ?? ((object)new GameObject[0]));
				for (int i = 0; i < array.Length; i++)
				{
					if (Object.op_Implicit((Object)(object)val))
					{
						break;
					}
					if (!Object.op_Implicit((Object)(object)array[i]) || Object.op_Implicit((Object)(object)array[i].GetComponent<PlateItem>()))
					{
						continue;
					}
					Renderer[] componentsInChildren = array[i].GetComponentsInChildren<Renderer>(true);
					for (int j = 0; j < componentsInChildren.Length; j++)
					{
						Material[] sharedMaterials = componentsInChildren[j].sharedMaterials;
						foreach (Material val2 in sharedMaterials)
						{
							if (Object.op_Implicit((Object)(object)val2) && Object.op_Implicit((Object)(object)val2.shader) && !(((Object)val2.shader).name != "Standard") && !bundleShaders.Contains(val2.shader))
							{
								val = val2.shader;
								text = "prefab " + i + " '" + ((Object)array[i]).name + "', material '" + ((Object)val2).name + "'";
								break;
							}
						}
						if (Object.op_Implicit((Object)(object)val))
						{
							break;
						}
					}
				}
				if (!Object.op_Implicit((Object)(object)val))
				{
					Log.Warn("Plates: no game item has a material on the game's Standard shader, so the plates keep the bundle's, which the fog doesn't cover.");
					return;
				}
				GameStandard = val;
				int num = 0;
				int num2 = 0;
				foreach (Material item in list)
				{
					if ((Object)(object)item.shader != (Object)(object)val)
					{
						string[] shaderKeywords = item.shaderKeywords;
						int renderQueue = item.renderQueue;
						item.shader = val;
						item.shaderKeywords = shaderKeywords;
						if (item.renderQueue != renderQueue)
						{
							item.renderQueue = renderQueue;
						}
						num++;
					}
					if (Object.op_Implicit((Object)(object)item.shader) && ((Object)item.shader).GetInstanceID() == ((Object)val).GetInstanceID())
					{
						num2++;
					}
				}
				if (num2 < list.Count)
				{
					Log.Error("Plates: only " + num2 + " of the " + list.Count + " plate materials use the game's Standard shader (from " + text + ").");
				}
				else if (num > 0)
				{
					Log.Info("Plates: " + num + " of their " + list.Count + " materials now use the game's Standard shader (from " + text + "), so the fog covers them; each checked.");
				}
			}
			catch (Exception ex)
			{
				Log.Error("Plates: switching to the game's Standard shader failed: " + ex);
			}
		}

		private static List<Material> StandardMaterials()
		{
			List<Material> list = new List<Material>();
			foreach (GameObject value in prefabs.Values)
			{
				Renderer[] componentsInChildren = value.GetComponentsInChildren<Renderer>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					Material[] sharedMaterials = componentsInChildren[i].sharedMaterials;
					foreach (Material val in sharedMaterials)
					{
						if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.shader) && ((Object)val.shader).name == "Standard" && !list.Contains(val))
						{
							list.Add(val);
						}
					}
				}
			}
			return list;
		}

		internal static void Register(PrefabsDirectory directory)
		{
			if (!Object.op_Implicit((Object)(object)directory) || prefabs.Count == 0)
			{
				return;
			}
			GameObject[] array = (GameObject[])(((object)directory.directory) ?? ((object)new GameObject[0]));
			int num = 0;
			foreach (int key in prefabs.Keys)
			{
				num = Math.Max(num, key + 1);
			}
			if (array.Length < num)
			{
				GameObject[] array2 = (GameObject[])(object)new GameObject[num];
				Array.Copy(array, array2, array.Length);
				array = array2;
			}
			foreach (KeyValuePair<int, GameObject> prefab in prefabs)
			{
				if (Object.op_Implicit((Object)(object)array[prefab.Key]) && (Object)(object)array[prefab.Key] != (Object)(object)prefab.Value)
				{
					Log.Warn("Plates: prefab index " + prefab.Key + " held '" + ((Object)array[prefab.Key]).name + "'; the name plate takes it.");
				}
				array[prefab.Key] = prefab.Value;
			}
			directory.directory = array;
		}

		internal static byte[] FaceWood(PlateStyle style)
		{
			return Input(style.Key + "-face-wood", style, mask: false);
		}

		internal static byte[] Ornaments(PlateStyle style)
		{
			if (!style.Ornaments)
			{
				return null;
			}
			return Input(style.Key + "-ornaments", style, mask: true);
		}

		private static byte[] Input(string name, PlateStyle style, bool mask)
		{
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			if (inputs.TryGetValue(name, out var value))
			{
				return value;
			}
			byte[] array = null;
			try
			{
				Texture2D val = (Object.op_Implicit((Object)(object)bundle) ? bundle.LoadAsset<Texture2D>(name) : null);
				if (!Object.op_Implicit((Object)(object)val) || ((Texture)val).width != style.CanvasWidth || ((Texture)val).height != style.CanvasHeight)
				{
					Log.Error("Plates: the bundle's " + name + " is missing or not " + style.CanvasWidth + " x " + style.CanvasHeight + ".");
				}
				else
				{
					int width = ((Texture)val).width;
					int height = ((Texture)val).height;
					Color32[] pixels = val.GetPixels32();
					array = new byte[width * height * (mask ? 1 : 4)];
					for (int i = 0; i < height; i++)
					{
						int num = (height - 1 - i) * width;
						for (int j = 0; j < width; j++)
						{
							Color32 val2 = pixels[num + j];
							int num2 = i * width + j;
							if (mask)
							{
								array[num2] = val2.r;
								continue;
							}
							array[num2 * 4] = val2.r;
							array[num2 * 4 + 1] = val2.g;
							array[num2 * 4 + 2] = val2.b;
							array[num2 * 4 + 3] = val2.a;
						}
					}
				}
			}
			catch (Exception ex)
			{
				Log.Error("Plates: reading the bundle's " + name + " failed: " + ex.Message);
				array = null;
			}
			inputs[name] = array;
			return array;
		}
	}
	[HarmonyPatch(typeof(PrefabsDirectory), "Start")]
	internal static class PlateRegistrationPatch
	{
		[HarmonyPriority(0)]
		private static void Prefix(PrefabsDirectory __instance)
		{
			PlateBundle.UseGameShader(__instance);
			PlateBundle.Register(__instance);
		}
	}
	internal static class PlateFaces
	{
		private sealed class Face
		{
			internal Material Material;

			internal Material Letters;

			internal Texture2D Albedo;

			internal Texture2D Normal;

			internal Texture2D LettersTexture;

			internal volatile bool Carved;

			internal volatile bool Failed;

			internal Color32[] AlbedoPixels;

			internal Color32[] NormalPixels;

			internal Color32[] LettersPixels;

			internal int Width;

			internal int Height;

			internal int LettersWidth;

			internal int LettersHeight;

			internal bool Handed;

			internal float LastUse;

			internal readonly List<Action> Then = new List<Action>();
		}

		internal struct Metrics
		{
			internal float Advance;

			internal float InkLeft;

			internal float InkRight;

			internal float InkTop;

			internal float InkBottom;

			internal float InkWidth => InkRight - InkLeft;
		}

		private static readonly Dictionary<string, Face> faces = new Dictionary<string, Face>();

		private static float nextEviction;

		internal static string Key(string style, string font, int size, string name)
		{
			return style + "|" + font + "|" + size + "|" + name;
		}

		internal static Material[] Dress(PlateStyle style, Material[] materials, string fontAsset, int size, string name)
		{
			bool flag = style.BrassLetters && style.LettersSlot < materials.Length;
			Face face = FaceFor(style, materials[style.FaceSlot], flag ? materials[style.LettersSlot] : null, fontAsset, size, name);
			materials[style.FaceSlot] = face.Material;
			if (flag && Object.op_Implicit((Object)(object)face.Letters))
			{
				materials[style.LettersSlot] = face.Letters;
			}
			return materials;
		}

		private static Face FaceFor(PlateStyle style, Material template, Material lettersTemplate, string fontAsset, int size, string name)
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Expected O, but got Unknown
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Expected O, but got Unknown
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			string text = Key(style.Key, fontAsset, size, name);
			if (!faces.TryGetValue(text, out var value) || !Object.op_Implicit((Object)(object)value.Material))
			{
				value = new Face();
				faces[text] = value;
				value.Material = (Object.op_Implicit((Object)(object)template) ? new Material(template) : new Material(Object.op_Implicit((Object)(object)PlateBundle.GameStandard) ? PlateBundle.GameStandard : Shader.Find("Standard")));
				((Object)value.Material).name = "Shipwright plate face " + text;
				if (Object.op_Implicit((Object)(object)lettersTemplate))
				{
					value.Letters = new Material(lettersTemplate)
					{
						name = "Shipwright plate letters " + text
					};
				}
				try
				{
					Start(value, style, fontAsset, size, name);
				}
				catch (Exception ex)
				{
					value.Failed = true;
					value.Carved = true;
					Log.Error("Plates: carving \"" + name + "\" failed: " + ex);
				}
			}
			value.LastUse = Time.unscaledTime;
			return value;
		}

		internal static void WhenDone(PlateStyle style, string fontAsset, int size, string name, Action done)
		{
			if (!faces.TryGetValue(Key(style.Key, fontAsset, size, name), out var value) || value.Handed)
			{
				done();
			}
			else
			{
				value.Then.Add(done);
			}
		}

		internal static bool Done(string key)
		{
			if (faces.TryGetValue(key, out var value))
			{
				return value.Handed;
			}
			return false;
		}

		private static void Start(Face face, PlateStyle style, string fontAsset, int size, string name)
		{
			byte[] woodRgba = PlateBundle.FaceWood(style);
			if (woodRgba == null)
			{
				face.Failed = true;
				face.Carved = true;
				return;
			}
			Font val = Fonts.Find(fontAsset) ?? Fonts.Find("IMMORTAL");
			int w = style.CanvasWidth;
			int h = style.CanvasHeight;
			int px = style.BasePixels;
			Color32[] rendered = (Object.op_Implicit((Object)(object)val) ? NameMask(val, name, style, size, out px) : null);
			byte[] ornaments = PlateBundle.Ornaments(style);
			bool letters = Object.op_Implicit((Object)(object)face.Letters);
			float sigma = Carving.BlurSigma(px, PlateData.Font(fontAsset).StrokeWeight);
			face.Width = w;
			face.Height = h;
			if (letters)
			{
				face.LettersWidth = style.LettersRect[2];
				face.LettersHeight = style.LettersRect[3];
			}
			ThreadPool.QueueUserWorkItem(delegate
			{
				try
				{
					byte[] array = ((rendered != null) ? MaskOf(rendered, w, h) : new byte[w * h]);
					if (letters)
					{
						face.LettersPixels = Pixels(Carving.Letters(array, w, h, style.LettersRect), face.LettersWidth, face.LettersHeight);
					}
					if (ornaments != null)
					{
						for (int i = 0; i < array.Length; i++)
						{
							if (ornaments[i] > array[i])
							{
								array[i] = ornaments[i];
							}
						}
					}
					Carving.Carve(woodRgba, array, w, h, sigma, out var albedo, out var normal);
					face.AlbedoPixels = Pixels(albedo, w, h);
					face.NormalPixels = Pixels(normal, w, h);
				}
				catch (Exception ex)
				{
					face.Failed = true;
					Log.Error("Plates: carving failed: " + ex);
				}
				face.Carved = true;
			});
		}

		internal static void Tick()
		{
			foreach (Face value in faces.Values)
			{
				if (value.Handed || !value.Carved)
				{
					continue;
				}
				value.Handed = true;
				if (!value.Failed && value.AlbedoPixels != null)
				{
					try
					{
						value.Albedo = Upload(value.AlbedoPixels, value.Width, value.Height, linear: false);
						value.Normal = Upload(value.NormalPixels, value.Width, value.Height, linear: true);
						if (Object.op_Implicit((Object)(object)value.Material))
						{
							value.Material.SetTexture("_MainTex", (Texture)(object)value.Albedo);
							value.Material.SetTexture("_BumpMap", (Texture)(object)value.Normal);
							value.Material.EnableKeyword("_NORMALMAP");
							value.Material.SetFloat("_BumpScale", 1f);
						}
						if (value.LettersPixels != null && Object.op_Implicit((Object)(object)value.Letters))
						{
							value.LettersTexture = Upload(value.LettersPixels, value.LettersWidth, value.LettersHeight, linear: false);
							value.Letters.SetTexture("_MainTex", (Texture)(object)value.LettersTexture);
						}
					}
					catch (Exception ex)
					{
						value.Failed = true;
						Log.Error("Plates: uploading a face failed: " + ex);
					}
				}
				value.AlbedoPixels = (value.NormalPixels = (value.LettersPixels = null));
				foreach (Action item in value.Then)
				{
					try
					{
						item();
					}
					catch (Exception ex2)
					{
						Log.Error("Plates: " + ex2);
					}
				}
				value.Then.Clear();
			}
			if (Time.unscaledTime >= nextEviction)
			{
				nextEviction = Time.unscaledTime + 10f;
				Evict();
			}
		}

		internal static Color32[] Pixels(byte[] rgba, int width, int height)
		{
			//IL_0037: 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)
			Color32[] array = (Color32[])(object)new Color32[width * height];
			for (int i = 0; i < height; i++)
			{
				int num = (height - 1 - i) * width * 4;
				int num2 = i * width;
				int num3 = 0;
				while (num3 < width)
				{
					array[num2 + num3] = new Color32(rgba[num], rgba[num + 1], rgba[num + 2], rgba[num + 3]);
					num3++;
					num += 4;
				}
			}
			return array;
		}

		internal static byte[] MaskOf(Color32[] pixels, int width, int height)
		{
			byte[] array = new byte[width * height];
			for (int i = 0; i < height; i++)
			{
				for (int j = 0; j < width; j++)
				{
					array[(height - 1 - i) * width + j] = pixels[i * width + j].r;
				}
			}
			return array;
		}

		private static Texture2D Upload(Color32[] pixels, int width, int height, bool linear)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			Texture2D val = new Texture2D(width, height, (TextureFormat)4, true, linear);
			val.SetPixels32(pixels);
			((Texture)val).wrapMode = (TextureWrapMode)1;
			val.Apply(true, true);
			return val;
		}

		private static void Evict()
		{
			if (faces.Count == 0)
			{
				return;
			}
			HashSet<string> hashSet = new HashSet<string>();
			foreach (PlateItem item in PlateItem.Live)
			{
				if (Object.op_Implicit((Object)(object)item) && item.FaceKey != null)
				{
					hashSet.Add(item.FaceKey);
				}
			}
			if (PlatePreview.ShownKey != null)
			{
				hashSet.Add(PlatePreview.ShownKey);
			}
			List<string> list = new List<string>();
			foreach (KeyValuePair<string, Face> face in faces)
			{
				Face value = face.Value;
				if (!hashSet.Contains(face.Key) && value.Handed && !(Time.unscaledTime - value.LastUse < 10f))
				{
					if (Object.op_Implicit((Object)(object)value.Albedo))
					{
						Object.Destroy((Object)(object)value.Albedo);
					}
					if (Object.op_Implicit((Object)(object)value.Normal))
					{
						Object.Destroy((Object)(object)value.Normal);
					}
					if (Object.op_Implicit((Object)(object)value.LettersTexture))
					{
						Object.Destroy((Object)(object)value.LettersTexture);
					}
					if (Object.op_Implicit((Object)(object)value.Material))
					{
						Object.Destroy((Object)(object)value.Material);
					}
					if (Object.op_Implicit((Object)(object)value.Letters))
					{
						Object.Destroy((Object)(object)value.Letters);
					}
					list.Add(face.Key);
				}
			}
			foreach (string item2 in list)
			{
				faces.Remove(item2);
			}
		}

		internal static Metrics Measure(Font font, string text, int px)
		{
			Metrics result = new Metrics
			{
				InkLeft = float.MaxValue,
				InkRight = float.MinValue,
				InkTop = float.MinValue,
				InkBottom = float.MaxValue
			};
			CharacterInfo val = default(CharacterInfo);
			foreach (char c in text)
			{
				if (font.GetCharacterInfo(c, ref val, px))
				{
					float advance = result.Advance;
					result.Advance += ((CharacterInfo)(ref val)).advance;
					if (((CharacterInfo)(ref val)).maxY != ((CharacterInfo)(ref val)).minY)
					{
						result.InkLeft = Math.Min(result.InkLeft, advance + (float)((CharacterInfo)(ref val)).minX);
						result.InkRight = Math.Max(result.InkRight, advance + (float)((CharacterInfo)(ref val)).maxX);
						result.InkTop = Math.Max(result.InkTop, ((CharacterInfo)(ref val)).maxY);
						result.InkBottom = Math.Min(result.InkBottom, ((CharacterInfo)(ref val)).minY);
					}
				}
			}
			if (result.InkTop < result.InkBottom)
			{
				result.InkTop = (result.InkBottom = 0f);
			}
			if (result.InkRight < result.InkLeft)
			{
				result.InkLeft = (result.InkRight = 0f);
			}
			return result;
		}

		private static float Fit(Metrics m, PlateStyle style)
		{
			return Carving.Fit(m.InkWidth, m.InkTop - m.InkBottom, style.BoxWidth, style.BoxHeight, style.EllipseX, style.EllipseY);
		}

		private static bool Fits(Font font, string name, PlateStyle style, int size)
		{
			int num = Carving.SizePixels(style.BasePixels, size);
			font.RequestCharactersInTexture(name, num);
			return Fit(Measure(font, name, num), style) >= 1f;
		}

		internal static int MaxFittingSize(PlateStyle style, string fontAsset, string name)
		{
			Font val = Fonts.Find(fontAsset);
			if (!Object.op_Implicit((Object)(object)val) || string.IsNullOrEmpty(name))
			{
				return 24;
			}
			int basePixels = style.BasePixels;
			val.RequestCharactersInTexture(name, basePixels);
			Metrics metrics = Measure(val, name, basePixels);
			int num = Carving.MaxFittingSize(style.BasePixels, metrics.InkWidth / (float)basePixels, (metrics.InkTop - metrics.InkBottom) / (float)basePixels, style.BoxWidth, style.BoxHeight, style.EllipseX, style.EllipseY);
			while (num > 1 && !Fits(val, name, style, num))
			{
				num--;
			}
			return num;
		}

		internal static Color32[] NameMask(Font font, string name, PlateStyle style, int size, out int px)
		{
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Expected O, but got Unknown
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			int canvasWidth = style.CanvasWidth;
			int canvasHeight = style.CanvasHeight;
			px = Carving.SizePixels(style.BasePixels, size);
			font.RequestCharactersInTexture(name, px);
			Metrics m = Measure(font, name, px);
			float num = Fit(m, style);
			if (num < 1f)
			{
				px = Math.Max(1, (int)Math.Floor((float)px * num));
				font.RequestCharactersInTexture(name, px);
				m = Measure(font, name, px);
			}
			float num2 = style.BoxX + style.BoxWidth / 2f - (m.InkLeft + m.InkRight) / 2f;
			float num3 = style.BoxY + style.BoxHeight / 2f + (m.InkTop + m.InkBottom) / 2f;
			RenderTexture temporary = RenderTexture.GetTemporary(canvasWidth, canvasHeight, 0, (RenderTextureFormat)0, (RenderTextureReadWrite)1);
			RenderTexture active = RenderTexture.active;
			Texture2D val = new Texture2D(canvasWidth, canvasHeight, (TextureFormat)4, false, true);
			try
			{
				RenderTexture.active = temporary;
				GL.Clear(true, true, Color.black);
				GL.PushMatrix();
				GL.LoadPixelMatrix(0f, (float)canvasWidth, (float)canvasHeight, 0f);
				font.material.SetPass(0);
				GL.Begin(7);
				GL.Color(Color.white);
				CharacterInfo val2 = default(CharacterInfo);
				foreach (char c in name)
				{
					if (font.GetCharacterInfo(c, ref val2, px))
					{
						float num4 = num2 + (float)((CharacterInfo)(ref val2)).minX;
						float num5 = num2 + (float)((CharacterInfo)(ref val2)).maxX;
						float num6 = num3 - (float)((CharacterInfo)(ref val2)).maxY;
						float num7 = num3 - (float)((CharacterInfo)(ref val2)).minY;
						GL.TexCoord(Vector2.op_Implicit(((CharacterInfo)(ref val2)).uvTopLeft));
						GL.Vertex3(num4, num6, 0f);
						GL.TexCoord(Vector2.op_Implicit(((CharacterInfo)(ref val2)).uvTopRight));
						GL.Vertex3(num5, num6, 0f);
						GL.TexCoord(Vector2.op_Implicit(((CharacterInfo)(ref val2)).uvBottomRight));
						GL.Vertex3(num5, num7, 0f);
						GL.TexCoord(Vector2.op_Implicit(((CharacterInfo)(ref val2)).uvBottomLeft));
						GL.Vertex3(num4, num7, 0f);
						num2 += (float)((CharacterInfo)(ref val2)).advance;
					}
				}
				GL.End();
				GL.PopMatrix();
				val.ReadPixels(new Rect(0f, 0f, (float)canvasWidth, (float)canvasHeight), 0, 0);
				val.Apply();
				return val.GetPixels32();
			}
			finally
			{
				RenderTexture.active = active;
				RenderTexture.ReleaseTemporary(temporary);
				Object.Destroy((Object)(object)val);
			}
		}
	}
	internal static class Carving
	{
		internal const float DepthDark = 0.72f;

		internal const float NormalStrength = 8f;

		internal static float Fit(float inkWidth, float inkHeight, float boxWidth, float boxHeight, float ellipseX = 0f, float ellipseY = 0f)
		{
			float num = 1f;
			if (inkWidth > 0f)
			{
				num = Math.Min(num, boxWidth * 0.94f / inkWidth);
			}
			if (inkHeight > 0f)
			{
				num = Math.Min(num, boxHeight * 0.9f / inkHeight);
			}
			if (ellipseX > 0f && ellipseY > 0f && (inkWidth > 0f || inkHeight > 0f))
			{
				float num2 = inkWidth / (2f * ellipseX);
				float num3 = inkHeight / (2f * ellipseY);
				num = Math.Min(num, 1f / (float)Math.Sqrt(num2 * num2 + num3 * num3));
			}
			return num;
		}

		internal static int SizePixels(int basePixels, int size)
		{
			return (int)Math.Floor((double)(basePixels * size) / 10.0);
		}

		internal static int MaxFittingSize(int basePixels, float widthPerPixel, float inkPerPixel, float boxWidth, float boxHeight, float ellipseX = 0f, float ellipseY = 0f)
		{
			for (int num = 24; num > 1; num--)
			{
				int num2 = SizePixels(basePixels, num);
				if (Fit(widthPerPixel * (float)num2, inkPerPixel * (float)num2, boxWidth, boxHeight, ellipseX, ellipseY) >= 1f)
				{
					return num;
				}
			}
			return 1;
		}

		internal static float BlurSigma(int fittedPixels, float strokeWeight)
		{
			return Math.Max(1.2f, (float)fittedPixels * 0.045f * strokeWeight);
		}

		internal static float[] Kernel(float sigma)
		{
			int num = (int)Math.Ceiling(3f * sigma);
			float[] array = new float[2 * num + 1];
			float num2 = 0f;
			for (int i = 0; i < array.Length; i++)
			{
				float num3 = i - num;
				array[i] = (float)Math.Exp((0f - num3) * num3 / (2f * sigma * sigma));
				num2 += array[i];
			}
			for (int j = 0; j < array.Length; j++)
			{
				array[j] /= num2;
			}
			return array;
		}

		internal static float Depth(float mask, float blurred)
		{
			return mask * Math.Min(1f, 1.6f * blurred);
		}

		internal static void Albedo(byte r, byte g, byte b, float depth, out byte outR, out byte outG, out byte outB)
		{
			float num = 1f - 0.72f * (float)Math.Pow(depth, 0.8);
			outR = Clamp((float)(int)r * num + 18f * depth);
			outG = Clamp((float)(int)g * num + 10f * depth);
			outB = Clamp((float)(int)b * num + 4f * depth);
		}

		internal static void Normal(float left, float right, float up, float down, out byte outR, out byte outG, out byte outB)
		{
			float num = (0f - right - (0f - left)) * 0.5f * 8f;
			float num2 = (0f - (0f - down - (0f - up))) * 0.5f * 8f;
			float num3 = 0f - num;
			float num4 = 0f - num2;
			float num5 = 1f;
			float num6 = (float)Math.Sqrt(num3 * num3 + num4 * num4 + num5 * num5);
			outR = Clamp((num3 / num6 * 0.5f + 0.5f) * 255f);
			outG = Clamp((num4 / num6 * 0.5f + 0.5f) * 255f);
			outB = Clamp((num5 / num6 * 0.5f + 0.5f) * 255f);
		}

		private static byte Clamp(float v)
		{
			return (byte)((!(v <= 0f)) ? ((v >= 255f) ? 255u : ((uint)(int)Math.Round(v))) : 0u);
		}

		internal static byte[] Letters(byte[] mask, int width, int height, int[] rect)
		{
			int num = rect[0];
			int num2 = rect[1];
			int num3 = rect[2];
			int num4 = rect[3];
			byte[] array = new byte[num3 * num4 * 4];
			for (int i = 0; i < num4; i++)
			{
				int num5 = num2 + i;
				for (int j = 0; j < num3; j++)
				{
					int num6 = num + j;
					int num7 = (i * num3 + j) * 4;
					int num8 = num7 + 1;
					byte b;
					array[num7 + 2] = (b = byte.MaxValue);
					array[num7] = (array[num8] = b);
					array[num7 + 3] = (byte)((num6 >= 0 && num6 < width && num5 >= 0 && num5 < height) ? mask[num5 * width + num6] : 0);
				}
			}
			return array;
		}

		internal static void Carve(byte[] wood, byte[] mask, int width, int height, float sigma, out byte[] albedo, out byte[] normal)
		{
			int num = width * height;
			albedo = new byte[num * 4];
			normal = new byte[num * 4];
			Buffer.BlockCopy(wood, 0, albedo, 0, Math.Min(wood.Length, albedo.Length));
			for (int i = 0; i < num; i++)
			{
				albedo[i * 4 + 3] = byte.MaxValue;
				normal[i * 4] = 128;
				normal[i * 4 + 1] = 128;
				normal[i * 4 + 2] = byte.MaxValue;
				normal[i * 4 + 3] = byte.MaxValue;
			}
			int num2 = width;
			int num3 = height;
			int num4 = -1;
			int num5 = -1;
			for (int j = 0; j < height; j++)
			{
				for (int k = 0; k < width; k++)
				{
					if (mask[j * width + k] > 0)
					{
						if (k < num2)
						{
							num2 = k;
						}
						if (k > num4)
						{
							num4 = k;
						}
						if (j < num3)
						{
							num3 = j;
						}
						if (j > num5)
						{
							num5 = j;
						}
					}
				}
			}
			if (num4 < 0)
			{
				return;
			}
			float[] array = Kernel(sigma);
			int num6 = array.Length / 2;
			int num7 = Math.Max(0, num2 - num6);
			int num8 = Math.Min(width - 1, num4 + num6);
			int num9 = Math.Max(0, num3 - num6);
			int num10 = Math.Min(height - 1, num5 + num6);
			int num11 = num8 - num7 + 1;
			int num12 = num10 - num9 + 1;
			float[] array2 = new float[num11 * num12];
			for (int l = 0; l < num12; l++)
			{
				int num13 = (num9 + l) * width;
				bool flag = false;
				for (int m = num7; m <= num8; m++)
				{
					if (flag)
					{
						break;
					}
					flag = mask[num13 + m] > 0;
				}
				if (!flag)
				{
					continue;
				}
				for (int n = 0; n < num11; n++)
				{
					float num14 = 0f;
					for (int num15 = -num6; num15 <= num6; num15++)
					{
						int num16 = num7 + n + num15;
						if (num16 >= 0 && num16 < width)
						{
							byte b = mask[num13 + num16];
							if (b != 0)
							{
								num14 += (float)(int)b / 255f * array[num15 + num6];
							}
						}
					}
					array2[l * num11 + n] = num14;
				}
			}
			float[] array3 = new float[num11 * num12];
			for (int num17 = 0; num17 < num12; num17++)
			{
				for (int num18 = 0; num18 < num11; num18++)
				{
					byte b2 = mask[(num9 + num17) * width + num7 + num18];
					if (b2 == 0)
					{
						continue;
					}
					float num19 = 0f;
					for (int num20 = -num6; num20 <= num6; num20++)
					{
						int num21 = num17 + num20;
						if (num21 >= 0 && num21 < num12)
						{
							num19 += array2[num21 * num11 + num18] * array[num20 + num6];
						}
					}
					array3[num17 * num11 + num18] = Depth((float)(int)b2 / 255f, num19);
				}
			}
			for (int num22 = 0; num22 < num12; num22++)
			{
				for (int num23 = 0; num23 < num11; num23++)
				{
					float num24 = array3[num22 * num11 + num23];
					int num25 = ((num9 + num22) * width + num7 + num23) * 4;
					if (num24 > 0f)
					{
						Albedo(wood[num25], wood[num25 + 1], wood[num25 + 2], num24, out albedo[num25], out albedo[num25 + 1], out albedo[num25 + 2]);
					}
					float num26 = array3[num22 * num11 + Math.Max(0, num23 - 1)];
					float num27 = array3[num22 * num11 + Math.Min(num11 - 1, num23 + 1)];
					float num28 = array3[Math.Max(0, num22 - 1) * num11 + num23];
					float num29 = array3[Math.Min(num12 - 1, num22 + 1) * num11 + num23];
					if (num26 != 0f || num27 != 0f || num28 != 0f || num29 != 0f)
					{
						Normal(num26, num27, num28, num29, out normal[num25], out normal[num25 + 1], out normal[num25 + 2]);
					}
				}
			}
		}
	}
	internal static class PlatePreview
	{
		private const int Width = 1024;

		private const int Height = 665;

		private static readonly Quaternion Turn = Quaternion.AngleAxis(-2.86f, Vector3.right) * Quaternion.AngleAxis(8.02f, Vector3.up);

		private static readonly Color Ambient = new Color(0.3f, 0.29f, 0.27f);

		private static GameObject rig;

		private static Camera camera;

		private static MeshFilter subjectMesh;

		private static MeshRenderer subject;

		private static RenderTexture texture;

		private static Material shown;

		private static int layer = -1;

		private static int ticket;

		private static string shownStyle;

		internal static string ShownKey;

		internal static void Show(Renderer picture, PlateStyle style, string fontAsset, int size, string name)
		{
			if (!Object.op_Implicit((Object)(object)picture) || !Prepare())
			{
				return;
			}
			picture.sharedMaterial = shown;
			int mine = ++ticket;
			string key = (ShownKey = PlateFaces.Key(style.Key, fontAsset, size, name));
			GameObject val = PlateBundle.Prefab(style);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return;
			}
			subjectMesh.sharedMesh = val.GetComponent<MeshFilter>().sharedMesh;
			Material[] array = ((Renderer)val.GetComponent<MeshRenderer>()).sharedMaterials;
			if (style.FaceSlot < array.Length)
			{
				array = PlateFaces.Dress(style, array, fontAsset, size, name);
			}
			((Renderer)subject).sharedMaterials = array;
			if (PlateFaces.Done(key))
			{
				Render(style);
				return;
			}
			if (shownStyle != style.Key)
			{
				Render(style);
			}
			PlateFaces.WhenDone(style, fontAsset, size, name, delegate
			{
				if (mine == ticket && Object.op_Implicit((Object)(object)picture))
				{
					Render(style);
				}
			});
		}

		internal static void Release()
		{
			ticket++;
			ShownKey = null;
			shownStyle = null;
			if (Object.op_Implicit((Object)(object)texture))
			{
				texture.Release();
			}
		}

		private static bool Prepare()
		{
			//IL_002b: 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_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Expected O, but got Unknown
			try
			{
				if (!Object.op_Implicit((Object)(object)rig))
				{
					Build();
				}
				if (!Object.op_Implicit((Object)(object)texture))
				{
					texture = new RenderTexture(1024, 665, 24, (RenderTextureFormat)0, (RenderTextureReadWrite)0)
					{
						name = "Shipwright plate picture",
						antiAliasing = 4
					};
				}
				if (!texture.IsCreated())
				{
					texture.Create();
					shownStyle = null;
				}
				camera.targetTexture = texture;
				if (!Object.op_Implicit((Object)(object)shown))
				{
					shown = PictureMaterial();
				}
				shown.mainTexture = (Texture)(object)texture;
				return true;
			}
			catch (Exception ex)
			{
				Log.Error("Plate picture: " + ex);
				return false;
			}
		}

		private static void Build()
		{
			//IL_0017: 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_002c: Expected O, but got Unknown
			//IL_005a: 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_006e: 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_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			if (layer < 0)
			{
				layer = FreeLayer();
			}
			rig = new GameObject("Shipwright plate picture")
			{
				layer = layer
			};
			rig.SetActive(false);
			Object.DontDestroyOnLoad((Object)(object)rig);
			rig.transform.position = new Vector3(0f, -2000f, 0f);
			GameObject val = new GameObject("plate")
			{
				layer = layer
			};
			val.transform.SetParent(rig.transform, false);
			val.transform.localRotation = Turn;
			subjectMesh = val.AddComponent<MeshFilter>();
			subject = val.AddComponent<MeshRenderer>();
			((Renderer)subject).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)subject).receiveShadows = false;
			((Renderer)subject).lightProbeUsage = (LightProbeUsage)0;
			((Renderer)subject).reflectionProbeUsage = (ReflectionProbeUsage)0;
			GameObject val2 = new GameObject("camera")
			{
				layer = layer
			};
			val2.transform.SetParent(rig.transform, false);
			camera = val2.AddComponent<Camera>();
			((Behaviour)camera).enabled = false;
			camera.cullingMask = 1 << layer;
			camera.clearFlags = (CameraClearFlags)2;
			camera.backgroundColor = new Color(0f, 0f, 0f, 0f);
			camera.fieldOfView = 26f;
			camera.nearClipPlane = 0.05f;
			camera.farClipPlane = 10f;
			camera.aspect = 1.5398496f;
			camera.renderingPath = (RenderingPath)1;
			camera.allowHDR = false;
			camera.allowMSAA = true;
			camera.useOcclusionCulling = false;
			AddLight(rig.transform, "key", new Vector3(-4f, 5f, -4f), new Color(1f, 0.957f, 0.878f), 0.75f);
			AddLight(rig.transform, "fill", new Vector3(4f, 1f, -2f), new Color(0.749f, 0.831f, 1f), 0.16f);
		}

		private static void AddLight(Transform parent, string name, Vector3 from, Color colour, float intensity)
		{
			//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_0011: 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_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_004d: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name)
			{
				layer = layer
			};
			val.transform.SetParent(parent, false);
			val.transform.localPosition = from;
			val.transform.localRotation = Quaternion.LookRotation(-from);
			Light obj = val.AddComponent<Light>();
			obj.type = (LightType)1;
			obj.color = colour;
			obj.intensity = intensity;
			obj.shadows = (LightShadows)0;
			obj.cullingMask = 1 << layer;
			obj.renderMode = (LightRenderMode)1;
		}

		private static int FreeLayer()
		{
			for (int num = 31; num >= 8; num--)
			{
				if (string.IsNullOrEmpty(LayerMask.LayerToName(num)))
				{
					return num;
				}
			}
			Log.Warn("Plate picture: no free layer; using 31.");
			return 31;
		}

		private static Material PictureMaterial()
		{
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Expected O, but got Unknown
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Expected O, but got Unknown
			string[] array = new string[3] { "Unlit/Transparent", "Sprites/Default", "UI/Default" };
			foreach (string text in array)
			{
				Shader val = Shader.Find(text);
				if (Object.op_Implicit((Object)(object)val))
				{
					Log.Info("Plate picture shader: " + text + ".");
					return new Material(val)
					{
						name = "Shipwright plate picture"
					};
				}
			}
			Log.Warn("Plate picture: no transparent unlit shader found; using Standard.");
			return new Material(Shader.Find("Standard"))
			{
				name = "Shipwright plate picture"
			};
		}

		private static void Render(PlateStyle style)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			if (!Prepare())
			{
				return;
			}
			Transform transform = ((Component)camera).transform;
			transform.localPosition = new Vector3(0.03f, 0.02f, 0f - style.CameraDistance);
			transform.LookAt(rig.transform.TransformPoint(new Vector3(0f, style.LookY, 0f)));
			Light[] array = Object.FindObjectsOfType<Light>();
			int[] array2 = new int[array.Length];
			AmbientMode ambientMode = RenderSettings.ambientMode;
			Color ambientLight = RenderSettings.ambientLight;
			SphericalHarmonicsL2 ambientProbe = RenderSettings.ambientProbe;
			bool fog = RenderSettings.fog;
			try
			{
				for (int i = 0; i < array.Length; i++)
				{
					array2[i] = array[i].cullingMask;
					Light obj = array[i];
					obj.cullingMask &= ~(1 << layer);
				}
				RenderSettings.ambientMode = (AmbientMode)3;
				RenderSettings.ambientLight = Ambient;
				SphericalHarmonicsL2 ambientProbe2 = default(SphericalHarmonicsL2);
				((SphericalHarmonicsL2)(ref ambientProbe2)).AddAmbientLight(Ambient);
				RenderSettings.ambientProbe = ambientProbe2;
				RenderSettings.fog = false;
				rig.SetActive(true);
				camera.Render();
				shownStyle = style.Key;
			}
			catch (Exception ex)
			{
				Log.Error("Plate picture: rendering failed: " + ex);
			}
			finally
			{
				rig.SetActive(false);
				for (int j = 0; j < array.Length; j++)
				{
					if (Object.op_Implicit((Object)(object)array[j]))
					{
						array[j].cullingMask = array2[j];
					}
				}
				RenderSettings.ambientMode = ambientMode;
				RenderSettings.ambientLight = ambientLight;
				RenderSettings.ambientProbe = ambientProbe;
				RenderSettings.fog = fog;
			}
		}
	}
	internal static class LifeSizePlate
	{
		internal const string Name = "Shipwright plate preview";

		private static GameObject plate;

		internal static bool Showing => Object.op_Implicit((Object)(object)plate);

		internal static bool Show(Transform documents, PlateStyle style, string fontAsset, int size, string name, float scale)
		{
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Expected O, but got Unknown
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			Hide();
			GameObject val = PlateBundle.Prefab(style);
			MeshFilter val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent<MeshFilter>() : null);
			MeshRenderer val3 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent<MeshRenderer>() : null);
			if (!Object.op_Implicit((Object)(object)documents) || !Object.op_Implicit((Object)(object)val2) || !Object.op_Implicit((Object)(object)val2.sharedMesh) || !Object.op_Implicit((Object)(object)val3))
			{
				return false;
			}
			try
			{
				scale = PlateData.CleanScale(scale);
				Mesh sharedMesh = ((Mathf.Approximately(scale, 1f) || !val2.sharedMesh.isReadable) ? val2.sharedMesh : PlateScaling.Scaled(val2.sharedMesh, scale));
				Plates.TableSpot(documents, Plates.BottomOf(val2.sharedMesh, scale), out var position, out var rotation);
				plate = new GameObject("Shipwright plate preview")
				{
					layer = val.layer
				};
				plate.transform.SetPositionAndRotation(position, rotation);
				if (Object.op_Implicit((Object)(object)FloatingOriginManager.instance))
				{
					plate.transform.SetParent(((Component)FloatingOriginManager.instance).transform, true);
				}
				plate.AddComponent<MeshFilter>().sharedMesh = sharedMesh;
				MeshRenderer obj = plate.AddComponent<MeshRenderer>();
				((Renderer)obj).shadowCastingMode = ((Renderer)val3).shadowCastingMode;
				((Renderer)obj).receiveShadows = ((Renderer)val3).receiveShadows;
				Material[] array = ((Renderer)val3).sharedMaterials;
				if (style.FaceSlot < array.Length)
				{
					array = PlateFaces.Dress(style, array, fontAsset, size, name);
				}
				((Renderer)obj).sharedMaterials = array;
				return true;
			}
			catch (Exception ex)
			{
				Log.Error("Plates: the size preview failed: " + ex);
				Hide();
				return false;
			}
		}

		internal static void Hide()
		{
			if (Object.op_Implicit((Object)(object)plate))
			{
				Object.Destroy((Object)(object)plate);
			}
			plate = null;
		}
	}
	internal sealed class Board : MonoBehaviour
	{
		private sealed class PlatePageParts
		{
			internal int Index;

			internal Renderer Picture;

			internal TextMesh Size;

			internal TextMesh Scale;

			internal TextMesh Metres;

			internal TextMesh Price;

			internal readonly List<KeyValuePair<string, MeshRenderer>> FontButtons = new List<KeyValuePair<string, MeshRenderer>>();

			internal readonly List<Material> FontMaterials = new List<Material>();
		}

		[HarmonyPatch(typeof(MissionListUI), "DisablePortMissionUI")]
		internal static class VanillaClosePatch
		{
			private static void Postfix()
			{
				if (IsOpen)
				{
					Close(!GameState.inPortMissionList);
				}
			}
		}

		[HarmonyPatch(typeof(SaveLoadManager), "LoadGame")]
		internal static class LoadClosePatch
		{
			private static void Prefix()
			{
				Close();
				pendingNames.Clear();
			}
		}

		private int plateStyle;

		private string plateFont;

		private int plateSize;

		private int plateScale;

		private PlatePageParts platePage;

		private const float SelectorScale = 0.75f;

		private const float SelectorX = -0.155f;

		private const float ArrowStep = 0.125f;

		internal const string PreviewReminder = "Click the documents\nto go back to the\nname plate page.";

		private bool previewing;

		private float nextReminder;

		private readonly List<GameObject> putAside = new List<GameObject>();

		internal static Board Instance;

		private static BoardParts parts;

		private Shipyard yard;

		private ShipyardInfo info;

		private Transform documents;

		private BoardPage page;

		private BoardList list;

		private readonly List<BoardItem> items = new List<BoardItem>();

		private int picked = -1;

		private int listPage;

		private int rowsShown = 5;

		private Action view;

		private TextMesh title;

		private TextMesh hint;

		private MeshRenderer nameField;

		private Func<string> titleText;

		internal const string HintText = "Click the name to change it, up to 16 characters.";

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

		private bool confirmCancel;

		private const string Separator = "  -  ";

		internal static bool Previewing
		{
			get
			{
				if (IsOpen)
				{
					return Instance.previewing;
				}
				return false;
			}
		}

		internal static bool IsOpen
		{
			get
			{
				if (Object.op_Implicit((Object)(object)Instance))
				{
					return ((Component)Instance).gameObject.activeSelf;
				}
				return false;
			}
		}

		private void ShowStyles(int index)
		{
			if (!PlateBundle.Loaded)
			{
				Notify.Show("Name plates are\nnot available.");
				return;
			}
			plateStyle = Math.Max(0, Array.FindIndex(PlateData.Styles, (PlateStyle s) => s.Region == yard.region));
			plateFont = PlateData.Fonts[0].Asset;
			plateSize = 10;
			plateScale = 2;
			ShowPlate(index);
		}

		private void ShowPlate(int index)
		{
			if (Ships.Find(index) == null)
			{
				ShowShips(-1);
				return;
			}
			PlateList(index);
			PlatePage(index);
		}

		private void PlateList(int index)
		{
			items.Clear();
			List<int> list = PlateRegions.SoldAt(yard);
			if (!list.Contains(plateStyle))
			{
				plateStyle = ((list.Count > 0) ? list[0] : 0);
			}
			foreach (int style in list)
			{
				items.Add(new BoardItem
				{
					Text = PlateData.Styles[style].Title,
					Clicked = delegate
					{
						PickStyle(index, style);
					}
				});
			}
			ShowList(BoardList.Styles, list.IndexOf(plateStyle), paging: false, "back", delegate
			{
				ShowShips(index);
			});
		}

		private void PickStyle(int index, int style)
		{
			if (style != plateStyle)
			{
				plateStyle = style;
				if (Ships.Find(index) == null)
				{
					ShowShips(-1);
					return;
				}
				PlateList(index);
				UpdatePlatePage();
			}
		}

		private void PlatePage(int index)
		{
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			//IL_022f: Unknown result type (might be due to invalid IL or missing references)
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0296: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_031a: Unknown result type (might be due to invalid IL or missing references)
			//IL_032c: Unknown result type (might be due to invalid IL or missing references)
			//IL_033e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0348: Unknown result type (might be due to invalid IL or missing references)
			BeginPage(delegate
			{
				ShowPlate(index);
			});
			PlatePageParts obj = new PlatePageParts
			{
				Index = index
			};
			PlatePageParts platePageParts = obj;
			platePage = obj;
			PlatePageParts platePageParts2 = platePageParts;
			page.Title(Ships.NameOf(index) + " name plate", hint: false);
			for (int num = 0; num < PlateData.Fonts.Length; num++)
			{
				FontButton(num, PlateData.Fonts[num], platePageParts2);
			}
			platePageParts2.Picture = page.Picture(new Vector3(-0.275f, 0.43f, 0.65f), new Vector3(0.95f, 0.6175f, 0.92743f));
			Vector3 scale = BoardPage.PriceLabelScale * 0.75f;
			Vector3 scale2 = new Vector3(0.01248f, 0.01248f, 0.0104f) * 0.75f;
			page.Text(parts.PriceLabel, "Font size", new Vector3(-0.155f, 0.085f, 0.6488f), scale, 4, 1);
			platePageParts2.Size = page.Text(parts.Value, "", new Vector3(-0.155f, 0.02f, 0.648f), scale2, 4, 1);
			page.Arrow(parts.Previous, new Vector3(-0.030000001f, 0.02f, 0.645f), delegate
			{
				StepPlateSize(-1);
			}, 0.75f);
			page.Arrow(parts.Next, new Vector3(-0.28f, 0.02f, 0.645f), delegate
			{
				StepPlateSize(1);
			}, 0.75f);
			page.Text(parts.PriceLabel, "Plate size", new Vector3(-0.155f, -0.05f, 0.6488f), scale, 4, 1);
			platePageParts2.Scale = page.Text(parts.Value, "", new Vector3(-0.155f, -0.115f, 0.648f), scale2, 4, 1);
			page.Arrow(parts.Previous, new Vector3(-0.030000001f, -0.115f, 0.645f), delegate
			{
				StepPlateScale(-1);
			}, 0.75f);
			page.Arrow(parts.Next, new Vector3(-0.28f, -0.115f, 0.645f), delegate
			{
				StepPlateScale(1);
			}, 0.75f);
			Transform val = ((Component)page.Button("Preview size", new Vector3(-0.555f, -0.009f, 0.639f), new Vector3(0.58f, 0.58f, 1f), StartPreview)).transform.parent.Find("text");
			if (Object.op_Implicit((Object)(object)val))
			{
				val.localScale = new Vector3(val.localScale.x * 0.72f, val.localScale.y * 0.72f, val.localScale.z);
			}
			platePageParts2.Metres = page.Small("", -0.36f, -0.115f);
			page.Line(0, "Hang it on any wall.");
			page.Line(1, "A renamed ship");
			page.Line(2, "needs a new plate.");
			platePageParts2.Price = page.Fee("Price:", "", Money.Names[yard.region]);
			page.MainButton("Buy", delegate
			{
				if (!PlateRegions.SoldAt(yard).Contains(plateStyle))
				{
					ShowPlate(index);
				}
				else if (Plates.Buy(yard, info, PlateData.Styles[plateStyle], plateFont, ShownPlateSize(index), PlateData.Scales[plateScale], index))
				{
					ShowShips(index);
				}
			});
			UpdatePlatePage();
		}

		private int ShownPlateSize(int index)
		{
			int fits;
			return ShownPlateSize(index, out fits);
		}

		private int ShownPlateSize(int index, out int fits)
		{
			fits = PlateFaces.MaxFittingSize(PlateData.Styles[plateStyle], plateFont, Ships.NameOf(index));
			return Math.Max(1, Math.Min(plateSize, fits));
		}

		private void UpdatePlatePage()
		{
			PlatePageParts platePageParts = platePage;
			if (platePageParts == null || !Object.op_Implicit((Object)(object)platePageParts.Size) || !Object.op_Implicit((Object)(object)platePageParts.Metres) || !Object.op_Implicit((Object)(object)platePageParts.Picture))
			{
				Refresh();
				return;
			}
			int size = ShownPlateSize(platePageParts.Index);
			platePageParts.Size.text = size.ToString();
			platePageParts.Scale.text = PlateData.ScaleText(PlateData.Scales[plateScale]);
			Font font = platePageParts.Metres.font;
			platePageParts.Metres.text = PlateData.SizeText(PlateData.Styles[plateStyle], PlateData.Scales[plateScale], (Object.op_Implicit((Object)(object)font) && !font.HasCharacter('×')) ? " x " : " × ");
			int currency = Mathf.Clamp(yard.region, 0, Fees.PlatePrice.Length - 1);
			platePageParts.Price.text = Money.Amount(Fees.PlatePriceAt(currency, PlateData.Scales[plateScale]));
			for (int i = 0; i < platePageParts.FontButtons.Count; i++)
			{
				if (Object.op_Implicit((Object)(object)platePageParts.FontButtons[i].Value))
				{
					((Renderer)platePageParts.FontButtons[i].Value).sharedMaterial = ((platePageParts.FontButtons[i].Key == plateFont) ? parts.Medium : platePageParts.FontMaterials[i]);
				}
			}
			PlatePreview.Show(platePageParts.Picture, PlateData.Styles[plateStyle], plateFont, size, Ships.NameOf(platePageParts.Index));
		}

		private void StepPlateSize(int step)
		{
			PlatePageParts platePageParts = platePage;
			if (platePageParts == null)
			{
				return;
			}
			int fits;
			int num = ShownPlateSize(platePageParts.Index, out fits) + step;
			if (num >= 1 && num <= Math.Min(24, fits))
			{
				plateSize = num;
				if (Object.op_Implicit((Object)(object)UISoundPlayer.instance))
				{
					UISoundPlayer.instance.PlayParchmentSound();
				}
				UpdatePlatePage();
			}
		}

		private void StepPlateScale(int step)
		{
			int num = plateScale + step;
			if (num >= 0 && num < PlateData.Scales.Length)
			{
				plateScale = num;
				if (Object.op_Implicit((Object)(object)UISoundPlayer.instance))
				{
					UISoundPlayer.instance.PlayParchmentSound();
				}
				UpdatePlatePage();
			}
		}

		private void StartPreview()
		{
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Expected O, but got Unknown
			PlatePageParts platePageParts = platePage;
			if (previewing || platePageParts == null || !Object.op_Implicit((Object)(object)documents))
			{
				return;
			}
			if (!LifeSizePlate.Show(documents, PlateData.Styles[plateStyle], plateFont, ShownPlateSize(platePageParts.Index), Ships.NameOf(platePageParts.Index), PlateData.Scales[plateScale]))
			{
				Notify.Show("The preview is\nnot available.");
				return;
			}
			previewing = true;
			foreach (Transform item in ((Component)this).transform)
			{
				Transform val = item;
				if (((Component)val).gameObject.activeSelf)
				{
					putAside.Add(((Component)val).gameObject);
					((Component)val).gameObject.SetActive(false);
				}
			}
			MouseLook.ToggleMouseLookAndCursor(true);
			if (Object.op_Implicit((Object)(object)UISoundPlayer.instance))
			{
				UISoundPlayer.instance.PlayCloseSound();
			}
			nextReminder = 0f;
			KeepReminder();
		}

		private void KeepReminder()
		{
			if (previewing && !(Time.unscaledTime < nextReminder))
			{
				nextReminder = Time.unscaledTime + 0.5f;
				Notify.Show("Click the documents\nto go back to the\nname plate page.", 1f);
			}
		}

		private void EndPreview(bool boardStays)
		{
			if (!previewing)
			{
				return;
			}
			previewing = false;
			LifeSizePlate.Hide();
			foreach (GameObject item in putAside)
			{
				if (Object.op_Implicit((Object)(object)item))
				{
					item.SetActive(true);
				}
			}
			putAside.Clear();
			Notify.Show("Click the documents\nto go back to the\nname plate page.", 0.001f);
			if (boardStays)
			{
				MouseLook.ToggleMouseLookAndCursor(false);
			}
		}

		internal static bool ResumeFromPreview(GoPointerButton clicked)
		{
			if (!Previewing || !Object.op_Implicit((Object)(object)clicked) || (Object)(object)((Component)clicked).transform != (Object)(object)Instance.documents)
			{
				return false;
			}
			Instance.EndPreview(boardStays: true);
			if (Object.op_Implicit((Object)(object)UISoundPlayer.instance))
			{
				UISoundPlayer.instance.PlayOpenSound();
			}
			Instance.UpdatePlatePage();
			return true;
		}

		private void FontButton(int i, PlateFont font, PlatePageParts shown)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			BoardButton boardButton = page.Button(font.Button, new Vector3(0.455f, 0.58f - 0.176f * (float)i, 0.639f), new Vector3(0.58f, 0.58f, 1f), delegate
			{
				if (!(plateFont == font.Asset))
				{
					plateFont = font.Asset;
					UpdatePlatePage();
				}
			});
			Transform val = ((Component)boardButton).transform.parent.Find("text");
			TextMesh val2 = (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponent<TextMesh>() : null);
			Font val3 = Fonts.Find(font.Asset);
			if (Object.op_Implicit((Object)(object)val2) && Object.op_Implicit((Object)(object)val3))
			{
				val2.font = val3;
				((Renderer)((Component)val).GetComponent<MeshRenderer>()).sharedMaterial = val3.material;
			}
			if (Object.op_Implicit((Object)(object)val))
			{
				float num = font.LabelScale * 0.72f;
				val.localScale = new Vector3(val.localScale.x * num, val.localScale.y * num, val.localScale.z);
			}
			MeshRenderer component = ((Component)boardButton).GetComponent<MeshRenderer>();
			shown.FontButtons.Add(new KeyValuePair<string, MeshRenderer>(font.Asset, component));
			shown.FontMaterials.Add(Object.op_Implicit((Object)(object)component) ? ((Renderer)component).sharedMaterial : null);
		}

		internal static void Open(ShipyardDocuments documents)
		{
			if (State.Off)
			{
				Notify.Show("Shipwright is off\nfor this save.");
				return;
			}
			Shipyard val = (Object.op_Implicit((Object)(object)documents) ? documents.shipyard : null);
			ShipyardInfo shipyardInfo = Shipyards.InfoOf(val);
			if (shipyardInfo == null || !Shipyards.Present(shipyardInfo) || IsOpen)
			{
				return;
			}
			if (parts == null || !parts.Alive)
			{
				parts = BoardParts.Build();
				if (parts == null)
				{
					return;
				}
				Instance = parts.Root.AddComponent<Board>();
				Instance.page = new BoardPage(parts);
			}
			Instance.Show(documents, val, shipyardInfo);
		}

		private void Show(ShipyardDocuments documents, Shipyard yard, ShipyardInfo info)
		{
			this.documents = ((Component)documents).transform;
			this.yard = yard;
			this.info = info;
			PlateRegions.Visit(yard);
			confirmCancel = false;
			GameState.inPortMissionList = true;
			MouseLook.ToggleMouseLookAndCursor(false);
			((Component)this).gameObject.SetActive(true);
			if (Object.op_Implicit((Object)(object)UISoundPlayer.instance))
			{
				UISoundPlayer.instance.PlayOpenSound();
			}
			ShowShips(-1);
		}

		internal static void Close(bool vanillaClosed = false)
		{
			if (!IsOpen)
			{
				return;
			}
			NameEditor.Commit();
			Instance.EndPreview(boardStays: false);
			((Component)Instance).gameObject.SetActive(false);
			Instance.page.Clear();
			Instance.view = null;
			PlatePreview.Release();
			if (!vanillaClosed)
			{
				GameState.inPortMissionList = false;
				if (GameState.inCursorMenu)
				{
					MouseLook.ToggleMouseLookAndCursor(true);
				}
				if (Object.op_Implicit((Object)(object)UISoundPlayer.instance))
				{
					UISoundPlayer.instance.PlayCloseSound();
				}
			}
			GameAccess.ForgetMissionUI();
		}

		private void Update()
		{
			//IL_002d: 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)
			if (!Object.op_Implicit((Object)(object)documents) || !Object.op_Implicit((Object)(object)Refs.observerMirror) || GameState.sleeping || GameState.currentlyLoading || Vector3.Distance(documents.position, ((Component)Refs.observerMirror).transform.position) > 4f)
			{
				Close();
				return;
			}
			KeepReminder();
			NameEditor.Update();
		}

		internal void Refresh()
		{
			view?.Invoke();
		}

		private void SetTabs(BoardTab active)
		{
			//IL_0043: 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)
			bool active2 = info.Builds.Length != 0;
			parts.OrderTab.Root.SetActive(active2);
			SetTab(parts.OrderTab, "order", new Vector3(0f, 0.022f, 0.004f), active == BoardTab.Order, delegate
			{
				confirmCancel = false;
				ShowOrders(-1);
			});
			SetTab(parts.ShipsTab, "ship list", new Vector3(0.008f, 0.026f, 0.004f), active == BoardTab.Ships, delegate
			{
				ShowShips(-1);
			});
		}

		private static void SetTab(BoardRow row, string text, Vector3 position, bool active, Action clicked)
		{
			//IL_0017: 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)
			row.Text.text = text;
			((Component)row.Text).transform.localPosition = position;
			((Component)row.Text).transform.localScale = new Vector3(0.008736f, 0.009672f, 0.0124f);
			((Renderer)row.Plate).sharedMaterial = (active ? parts.Lit : parts.Dark);
			row.Button.Clicked = clicked;
		}

		private void ShowList(BoardList kind, int selected, bool paging, string back, Action backClicked)
		{
			list = kind;
			picked = selected;
			rowsShown = ((kind == BoardList.Styles && !paging) ? parts.Rows.Length : 5);
			int pages = Math.Max(1, (items.Count + 5 - 1) / 5);
			if (!paging)
			{
				listPage = 0;
			}
			else if (selected >= 0)
			{
				listPage = selected / 5;
			}
			listPage = Mathf.Clamp(listPage, 0, pages - 1);
			DrawRows();
			parts.Next.Root.SetActive(paging);
			parts.Previous.Root.SetActive(paging);
			((Component)parts.PageCount).gameObject.SetActive(paging);
			if (paging)
			{
				parts.PageCount.text = listPage + 1 + " / " + pages;
				parts.Next.Button.Clicked = delegate
				{
					TurnPage(1, pages);
				};
				parts.Previous.Button.Clicked = delegate
				{
					TurnPage(-1, pages);
				};
			}
			parts.Back.Text.text = back;
			parts.Back.Button.Clicked = backClicked;
		}

		private void DrawRows()
		{
			for (int i = 0; i < parts.Rows.Length; i++)
			{
				BoardRow boardRow = parts.Rows[i];
				int num = listPage * rowsShown + i;
				if (i >= rowsShown || num >= items.Count)
				{
					boardRow.Root.SetActive(false);
					continue;
				}
				BoardItem boardItem = items[num];
				boardRow.Root.SetActive(true);
				TextFit.Fit(boardRow, boardItem.Text);
				((Renderer)boardRow.Plate).sharedMaterial = ((num == picked) ? parts.Medium : (boardItem.Plate ?? parts.Lit));
				boardRow.Button.Clicked = boardItem.Clicked;
			}
		}

		private void TurnPage(int step, int pages)
		{
			int num = Mathf.Clamp(listPage + step, 0, pages - 1);
			if (num != listPage)
			{
				listPage = num;
				parts.PageCount.text = listPage + 1 + " / " + pages;
				if (Object.op_Implicit((Object)(object)UISoundPlayer.instance))
				{
					UISoundPlayer.instance.PlayParchmentSound();
				}
				DrawRows();
			}
		}

		private void BeginPage(Action redraw)
		{
			EndPreview(boardStays: true);
			NameEditor.Cancel();
			page.Clear();
			title = null;
			hint = null;
			nameField = null;
			titleText = null;
			view = redraw;
		}

		private void NameTitle(Func<string> shown, Func<string> typed, Action<string> save)
		{
			titleText = shown;
			nameField = page.NameField(delegate
			{
				if (!NameEditor.Typing)
				{
					NameEditor.Begin(typed(), delegate(string name)
					{
						save(name);
						Refresh();
					}, RedrawTitle);
				}
			});
			((Renderer)nameField).enabled = false;
			title = page.Title(shown(), hint: true);
			hint = page.Hint("Click the name to change it, up to 16 characters.");
		}

		private void RedrawTitle()
		{
			if (Object.op_Implicit((Object)(object)title))
			{
				bool typing = NameEditor.Typing;
				title.text = (typing ? NameEditor.Shown : titleText());
				if (Object.op_Implicit((Object)(object)nameField))
				{
					((Renderer)nameField).enabled = typing;
				}
				if (Object.op_Implicit((Object)(object)hint))
				{
					hint.text = (typing ? "Enter saves, Esc cancels" : "Click the name to change it, up to 16 characters.");
				}
			}
		}

		internal void ShowOrders(int hull)
		{
			if (info.Builds.Length == 0)
			{
				ShowShips(-1);
				return;
			}
			OrderRecord orderRecord = Orders.OrderAt(info.Name);
			if (hull < 0)
			{
				hull = orderRecord?.hull ?? info.Builds[0];
			}
			items.Clear();
			int[] builds = info.Builds;
			foreach (int num in builds)
			{
				int each = num;
				string text = ShipTypes.Name(num, null);
				items.Add(new BoardItem
				{
					Text = ((orderRecord != null && orderRecord.hull == num) ? (text + "  -  ordered") : text),
					Clicked = delegate
					{
						confirmCancel = false;
						ShowOrders(each);
					}
				});
			}
			SetTabs(BoardTab.Order);
			ShowList(BoardList.Hulls, Array.IndexOf(info.Builds, hull), paging: false, "close", delegate
			{
				Close();
			});
			if (orderRecord != null && orderRecord.hull == hull)
			{
				OrderStatusPage(orderRecord);
			}
			else
			{
				OrderPage(hull, orderRecord);
			}
		}

		private static string BuildTime(int hours)
		{
			double num = (double)hours / 24.0;
			if (num != Math.Floor(num))
			{
				return num.ToString("0.#", CultureInfo.InvariantCulture) + " days";
			}
			return Days((int)num);
		}

		private void OrderPage(int hull, OrderRecord existing)
		{
			string type = ShipTypes.Name(hull, null);
			string key = info.Name + "/" + hull;
			BeginPage(delegate
			{
				ShowOrders(hull);
			});
			NameTitle(() => (!pendingNames.TryGetValue(key, out var value) || value.Length <= 0) ? ShipNames.Default(type, ShipNames.PeekNumber(State.Save, type)) : value, () => (!pendingNames.TryGetValue(key, out value)) ? "" : value, delegate(string name)
			{
				pendingNames[key] = name;
			});
			Orders.Bill bill = Orders.BillFor(hull);
			if (Orders.Instant)
			{
				page.Block(0.676f, 0.64f, "Build time:", "at once", "no materials needed");
				page.Block(0.676f, 0.36f, "When it is built:", "stored here", "see the ship list");
			}
			else
			{
				page.Block(0.676f, 0.64f, "Build time:", BuildTime(bill.Hours), "after all materials delivered");
				page.Block(0.676f, 0.36f, "Bring the goods to:", "SHIPWRIGHT sign", "on the dock");
				page.Block(0.676f, 0.08f, "When it is built:", "stored here", "see the ship list");
				Table("Materials:", bill, null);
			}
			int region = yard.region;
			int amount = Fees.BuildingFee(Orders.Price(hull), Money.Rate(region));
			page.Fee("Building fee:", Money.Amount(amount), Money.Names[region] + ", paid now");
			if (Orders.Instant)
			{
				page.Small("Instant ships is on:", 0.676f, -0.33f);
				page.Small("no goods, no waiting.", 0.676f, -0.405f);
			}
			else
			{
				page.Small("One order at a time.", 0.676f, -0.33f);
				page.Small("A cancelled order refunds", 0.676f, -0.405f);
				page.Small("neither coins nor goods.", 0.676f, -0.48f);
			}
			page.MainButton("Order", delegate
			{
				pendingNames.TryGetValue(key, out value);
				if (Orders.Place(yard, info, hull, value, out var built))
				{
					pendingNames.Remove(key);
					if (built > 0)
					{
						ShowShips(built);
					}
					else
					{
						ShowOrders(hull);
					}
				}
			}, ((existing != null) ? 1 : 0) + " / 1");
		}

		private void OrderStatusPage(OrderRecord order)
		{
			string type = ShipTypes.Name(order.hull, null);
			BeginPage(delegate
			{
				ShowOrders(order.hull);
			});
			NameTitle(() => (order.typed.Length <= 0) ? ShipNames.Default(type, ShipNames.PeekNumber(State.Save, type)) : order.typed, () => order.typed, delegate(string name)
			{
				order.typed = name;
			});
			Orders.Bill bill = Orders.BillFor(order.hull);
			bool num = Orders.Building(order);
			page.Block(0.676f, 0.64f, "Ordered:", "day " + order.orderedDay, Money.Amount(order.feePaid) + " " + Money.Names[order.currency] + " paid");
			if (num)
			{
				page.Block(0.676f, 0.36f, "Status:", "building", "all materials delivered");
				page.Block(0.676f, 0.08f, "When it is built:", "stored here", "see the ship list");
			}
			else
			{
				int num2 = Orders.Missing(order);
				page.Block(0.676f, 0.36f, "Status:", "waiting for goods", num2 + ((num2 == 1) ? " good" : " goods") + " still to bring");
				page.Block(0.676f, 0.08f, "Bring the goods to:", "SHIPWRIGHT sign", "on the dock");
			}
			Table("Delivered:", bill, order.delivered);
			if (num)
			{
				page.Fee("Remaining time:", Fees.Remaining(order.readyHour - GameClock.Hours), "ready on day " + GameClock.DayOf(order.readyHour));
			}
			else
			{
				page.Fee("Remaining time:", BuildTime(bill.Hours), null);
			}
			page.Small("Cancelling refunds", 0.676f, -0.33f);
			page.Small("neither coins nor goods.", 0.676f, -0.405f);
			int hull = order.hull;
			BoardButton cancel = null;
			cancel = page.MainButton(confirmCancel ? "Confirm" : "Cancel order", delegate
			{
				if (!confirmCancel)
				{
					confirmCancel = true;
					BoardPage.Relabel(cancel, "Confirm");
				}
				else
				{
					confirmCancel = false;
					Orders.Cancel(info);
					ShowOrders(hull);
				}
			}, "1 / 1");
		}

		private void Table(string heading, Orders.Bill bill, int[] delivered)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: 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_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			page.Text(parts.Label, heading, new Vector3(-0.08f, 0.64f, 0.648f), BoardPage.LabelScale, 3, 0);
			int num = 0;
			for (int i = 0; i < Orders.Goods.Length; i++)
			{
				if (bill.Amounts[i] != 0)
				{
					float num2 = 0.54f - 0.087f * (float)num++;
					page.Text(parts.Label, Orders.Goods[i], new Vector3(-0.08f, num2, 0.648f), BoardPage.LabelScale, 3, 0);
					string text = ((delivered == null) ? bill.Amounts[i].ToString() : (delivered[i] + " / " + bill.Amounts[i]));
					page.Text(parts.Value, text, new Vector3(-0.62f, num2, 0.648f), BoardPage.ValueScale, 5, 2);
				}
			}
		}

		private static string Days(int days)
		{
			return days + ((days == 1) ? " day" : " days");
		}

		internal void ShowShips(int index)
		{
			List<KeyValuePair<OwnedShip, ShipFacts>> list = Ships.ListFor(info.Name, yard);
			items.Clear();
			int num = -1;
			for (int i = 0; i < list.Count; i++)
			{
				OwnedShip key = list[i].Key;
				ShipFacts value = list[i].Value;
				Where obj = Whereabouts.Decide(value, info.Name);
				string text = Whereabouts.Note(obj, value);
				int shipIndex = key.Index;
				items.Add(new BoardItem
				{
					Text = ((text.Length == 0) ? key.Name : (key.Name + "  -  " + text)),
					Plate = ((obj == Where.ArrivingHere) ? parts.Dark : null),
					Clicked = delegate
					{
						ShowShips(shipIndex);
					}
				});
				if (shipIndex == index)
				{
					num = i;
				}
			}
			if (num < 0 && list.Count > 0)
			{
				num = 0;
			}
			SetTabs(BoardTab.Ships);
			ShowList(BoardList.Ships, num, paging: true, "close", delegate
			{
				Close();
			});
			if (num < 0)
			{
				BeginPage(delegate
				{
					ShowShips(-1);
				});
				page.Title("Ship list", hint: false);
				page.Block(0.676f, 0.7f, "Your ships:", "none yet");
			}
			else
			{
				ShipPage(list[num].Key, list[num].Value);
			}
		}

		private void ShipPage(OwnedShip ship, ShipFacts facts)
		{
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: 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)
			//IL_022f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			int index = ship.Index;
			BeginPage(delegate
			{
				ShowShips(index);
			});
			NameTitle(() => Ships.NameOf(index), () => ShipNames.Typed(State.Save, index), delegate(string name)
			{
				ShipNames.SetTyped(State.Save, index, name);
			});
			Where obj = Whereabouts.Decide(facts, info.Name);
			StoredShip record = Storage.RecordOf(index);
			TransportRecord transportRecord = Transport.RecordOf(index);
			if (transportRecord != null && transportRecord.tow)
			{
				TowTripPage(transportRecord);
				page.MainButton("Name plate", delegate
				{
					ShowStyles(index);
				});
				return;
			}
			switch (obj)
			{
			case Where.StoredHere:
				StoragePage(ship, record);
				return;
			case Where.LeavingHere:
				TripPage(transportRecord, arriving: false);
				return;
			case Where.ArrivingHere:
				TripPage(transportRecord, arriving: true);
				return;
			case Where.StoredElsewhere:
			{
				if (transportRecord != null)
				{
					TripPage(transportRecord, arriving: false);
					return;
				}
				page.Block(0.676f, 0.64f, Whereabouts.Label(obj, facts), Whereabouts.Value(obj, facts));
				Vector3 scale = default(Vector3);
				((Vector3)(ref scale))..ctor(0.7f, 0.7f, 1f);
				page.Button("Transport", new Vector3(0.49f, -0.602f, 0.639f), scale, delegate
				{
					ShowDestinations(index, null, confirm: false);
				});
				page.Button("Name plate", new Vector3(0f, -0.602f, 0.639f), scale, delegate
				{
					ShowStyles(index);
				});
				return;
			}
			}
			page.Block(0.676f, 0.64f, Whereabouts.Label(obj, facts), Whereabouts.Value(obj, facts));
			Vector3 scale2 = default(Vector3);
			((Vector3)(ref scale2))..ctor(0.7f, 0.7f, 1f);
			if (Object.op_Implicit((Object)(object)ship.Boat) && transportRecord == null)
			{
				page.Button("Transport", new Vector3(0.49f, -0.602f, 0.639f), scale2, delegate
				{
					ShowTowDestinations(index, null, confirm: false);
				});
			}
			page.Button("Name plate", new Vector3(0f, -0.602f, 0.639f), scale2, delegate
			{
				ShowStyles(index);
			});
		}

		private void StoragePage(OwnedShip ship, StoredShip record)
		{
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0296: Unknown result type (might be due to invalid IL or missing references)
			//IL_029b: Unknown result type (might be due to invalid IL or missing references)
			int region = yard.region;
			int num = Storage.DailyFee(record, region);
			int amount = Storage.FeeDue(record, region);
			page.Block(0.676f, 0.64f, "Stored since:", "day " + record.dayStored);
			page.Block(0.676f, 0.41f, "Storage days:", Days(Storage.Days(record)));
			page.Block(0.676f, 0.18f, "Storage fee:", num + " " + Money.Short[region] + " a day", "paid when taken out");
			page.Block(-0.08f, 0.64f, "To take it out:", "empty shipyard", "no other ship in it");
			page.Text(parts.PriceLabel, "Fee due:", new Vector3(-0.08f, 0.36f, 0.6488f), new Vector3(0.010695f, 0.01196f, 0.0104f), 3, 0);
			page.Text(parts.Price, Money.Amount(amount), new Vector3(-0.08f, 0.225f, 0.651f), new Vector3(0.016875f, 0.016875f, 0.0125f), 3, 0);
			page.Text(parts.Label, Money.Names[region], new Vector3(-0.08f, 0.117f, 0.648f), new Vector3(0.00782f, 0.009775f, 0.0085f), 3, 0);
			int index = ship.Index;
			Vector3 scale = default(Vector3);
			((Vector3)(ref scale))..ctor(0.7f, 0.7f, 1f);
			page.Button("Transport", new Vector3(0.49f, -0.602f, 0.639f), scale, delegate
			{
				ShowDestinations(index, null, confirm: false);
			});
			page.Button("Name plate", new Vector3(0f, -0.602f, 0.639f), scale, delegate
			{
				ShowStyles(index);
			});
			page.Button("Take out", new Vector3(-0.49f, -0.602f, 0.639f), scale, delegate
			{
				TakeOut(index);
			});
			if (CopyEngine.RecordOfIndex(index) != null)
			{
				page.Button("Sell", new Vector3(-0.49f, -0.36f, 0.639f