Decompiled source of ShipwrightTransportation v0.1.3
BepInEx/plugins/ShipwrightAndTransport/ShipwrightAndTransport.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
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