Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of CompassWaypointsClock v0.1.8
BepInEx/plugins/CompassWaypointsClock/CompassWaypointsClock.dll
Decompiled a week ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Security.Cryptography; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using HarmonyLib; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.UI; [assembly: InternalsVisibleTo("Assembly-CSharp-Editor")] [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: AssemblyMetadata("AI_Assisted_Creation", "Coded with the assistance of ChatGPT 6.0; packaged with OpenAI Codex.")] [assembly: AssemblyMetadata("AI_Model_Vendor", "OpenAI")] [assembly: AssemblyVersion("0.0.0.0")] namespace CompassWaypointsClock; internal sealed class ArrivalSound { private AudioSource source; private AudioClip clip; internal static float[] Samples(int rate) { float[] array = new float[(int)Math.Round((double)rate * 0.24)]; for (int i = 0; i < array.Length; i++) { double num = (double)i / (double)rate; double num2 = Math.Sin(Math.PI * (double)i / (double)(array.Length - 1)); array[i] = (float)(0.24 * num2 * num2 * (Math.Sin(Math.PI * 1760.0 * num) + 0.4 * Math.Sin(Math.PI * 2640.0 * num))); } return array; } internal void Play(GameObject owner, float volume) { if (!(volume <= 0f)) { if (!Object.op_Implicit((Object)(object)source)) { source = owner.AddComponent<AudioSource>(); source.playOnAwake = false; source.spatialBlend = 0f; source.loop = false; } if (!Object.op_Implicit((Object)(object)clip)) { float[] array = Samples(44100); clip = AudioClip.Create("Waypoint arrival", array.Length, 1, 44100, false); typeof(AudioClip).GetMethod("SetData", new Type[2] { typeof(float[]), typeof(int) }).Invoke(clip, new object[2] { array, 0 }); } source.PlayOneShot(clip, Mathf.Clamp01(volume)); } } internal void Dispose() { if (Object.op_Implicit((Object)(object)source)) { Object.Destroy((Object)(object)source); } if (Object.op_Implicit((Object)(object)clip)) { Object.Destroy((Object)(object)clip); } } } internal static class Controls { private static readonly MethodInfo MapPosition = AccessTools.Method(typeof(Minimap), "ScreenToWorldPoint", (Type[])null, (Type[])null); private static readonly PropertyInfo PinRadius = AccessTools.Property(typeof(Minimap), "PinInteractRadius"); private static float nextHint; internal static string BlockReason() { Player localPlayer = Player.m_localPlayer; GameObject val = (Object.op_Implicit((Object)(object)EventSystem.current) ? EventSystem.current.currentSelectedGameObject : null); if (Object.op_Implicit((Object)(object)val) && val.activeInHierarchy && (Object.op_Implicit((Object)(object)val.GetComponentInParent<TMP_InputField>()) || Object.op_Implicit((Object)(object)val.GetComponentInParent<InputField>()))) { return "text field has focus"; } if (!Object.op_Implicit((Object)(object)localPlayer)) { return "no local player"; } if (((Character)localPlayer).IsDead()) { return "player is dead"; } if (((Character)localPlayer).IsTeleporting()) { return "teleport in progress"; } if (((Character)localPlayer).InCutscene()) { return "cutscene or sleep in progress"; } if (TextInput.IsVisible()) { return "text entry is open"; } if (UnifiedPopup.WasVisibleThisFrame()) { return "popup is open"; } if (Console.IsVisible()) { return "console is open"; } if (Menu.IsVisible()) { return "menu is open"; } if (StoreGui.IsVisible()) { return "store is open"; } if (InventoryGui.IsVisible()) { return "inventory is open"; } if (Object.op_Implicit((Object)(object)Chat.instance) && Chat.instance.HasFocus()) { return "chat has focus"; } return null; } internal static bool Blocked() { return BlockReason() != null; } internal static bool MapChord() { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Invalid comparison between Unknown and I4 //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) Plugin instance = Plugin.Instance; Minimap instance2 = Minimap.instance; if (Object.op_Implicit((Object)(object)instance) && instance.Active && instance.EnableWaypoints.Value && !Blocked() && Object.op_Implicit((Object)(object)instance2) && (int)instance2.m_mode == 2 && Object.op_Implicit((Object)(object)instance2.m_mapImageLarge) && RectTransformUtility.RectangleContainsScreenPoint(((Graphic)instance2.m_mapImageLarge).rectTransform, Vector2.op_Implicit(ZInput.pointerPosition), (Camera)null) && (ZInput.GetKey((KeyCode)306, true) || ZInput.GetKey((KeyCode)305, true)) && !ZInput.GetKey((KeyCode)308, true) && !ZInput.GetKey((KeyCode)307, true) && !ZInput.GetKey((KeyCode)304, true)) { return !ZInput.GetKey((KeyCode)303, true); } return false; } internal static bool Dispatch(Plugin plugin, string action, Vector3 position, float radius) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) if (action == "OnMapDblClick") { plugin.Add(position, checkHeight: false, "Waypoint " + (plugin.Engine.Document.Points.Count + 1)); } else if (action == "OnMapLeftClick" && Time.unscaledTime >= nextHint) { nextHint = Time.unscaledTime + 3f; plugin.Notice("Hold Ctrl and double-left-click to add a waypoint"); } else if (action == "RemovePinUnderPointer") { int index = plugin.Engine.FindNearest(position.x, position.z, radius); if (index >= 0) { plugin.Change(() => plugin.Engine.Remove(index, plugin.Now), plugin.Engine.Label(index) + " removed"); } else { plugin.Notice("No waypoint near the cursor"); } } return false; } internal static bool Handle(Minimap map, string action) { //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) try { if (!MapChord()) { Plugin instance = Plugin.Instance; if (Object.op_Implicit((Object)(object)instance) && (ZInput.GetKey((KeyCode)306, true) || ZInput.GetKey((KeyCode)305, true))) { instance.Notice((!instance.EnableWaypoints.Value) ? "Waypoints disabled in config" : ((!instance.Active) ? "Waypoint storage unavailable - check the log" : ("Waypoint input blocked: " + (BlockReason() ?? "use Ctrl only over the large map")))); } return true; } Vector3 position = (Vector3)MapPosition.Invoke(map, new object[1] { ZInput.pointerPosition }); return Dispatch(Plugin.Instance, action, position, (float)PinRadius.GetValue(map, null)); } catch (Exception ex) { Plugin.Instance.Notice("Waypoint action failed: " + ex.Message); return false; } } } [HarmonyPatch] internal static class MapWaypointControls { private static IEnumerable<MethodBase> TargetMethods() { try { string[] array = new string[3] { "OnMapDblClick", "OnMapLeftClick", "RemovePinUnderPointer" }; foreach (string name in array) { yield return AccessTools.Method(typeof(Minimap), name, (Type[])null, (Type[])null); } } finally { } } private static bool Prefix(Minimap __instance, MethodBase __originalMethod) { return Controls.Handle(__instance, __originalMethod.Name); } } internal sealed class Display { private sealed class CompassTarget { internal Vector3 Position; internal Sprite Icon; internal Color Colour; } private readonly Plugin plugin; private GameObject root; private GameObject compass; private GameObject clock; private RectTransform hud; private RectTransform mapUi; private Toggle removeToggle; private GameObject removeCheck; private GameObject filterButton; private GameObject filterPanel; private TextMeshProUGUI mapHint; private Image nextDiamond; private string mapStatus; private float statusUntil; private readonly List<Toggle> filterToggles = new List<Toggle>(); private readonly List<GameObject> filterChecks = new List<GameObject>(); private bool filtersOpen; private TMP_FontAsset font; private TextMeshProUGUI time; private TextMeshProUGUI target; private TextMeshProUGUI heading; private TextMeshProUGUI destination; private readonly List<TextMeshProUGUI> bearings = new List<TextMeshProUGUI>(); private readonly List<Image> mapMarkers = new List<Image>(); private readonly List<CompassTarget> nearby = new List<CompassTarget>(); private static readonly FieldInfo MapPins = AccessTools.Field(typeof(Minimap), "m_pins"); private int previousHeading = -1; private float nextText; private float nextPinScan; private string appliedCompassColour; private string appliedClockColour; private Color compassColour = HudStyle.DefaultColour; internal void SetStatus(string value) { mapStatus = value; statusUntil = Time.unscaledTime + 6f; } internal Display(Plugin owner) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) plugin = owner; } internal void Invalidate() { nextPinScan = 0f; } private static RectTransform Rect(string name, Transform parent, Vector2 anchor, Vector2 position, Vector2 size) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) }); RectTransform component = val.GetComponent<RectTransform>(); ((Transform)component).SetParent(parent, false); Vector2 anchorMin = (component.anchorMax = anchor); component.anchorMin = anchorMin; component.pivot = new Vector2(0.5f, 0.5f); component.anchoredPosition = position; component.sizeDelta = size; return component; } private TextMeshProUGUI Text(string name, Transform parent, Vector2 position, Vector2 size, string value, float fontSize) { //IL_000c: 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_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) RectTransform val = Rect(name, parent, new Vector2(0.5f, 0.5f), position, size); ((Component)val).gameObject.SetActive(false); TextMeshProUGUI val2 = ((Component)val).gameObject.AddComponent<TextMeshProUGUI>(); ((TMP_Text)val2).font = font; ((TMP_Text)val2).fontSize = fontSize; ((TMP_Text)val2).text = value; ((TMP_Text)val2).richText = false; ((Graphic)val2).raycastTarget = false; ((TMP_Text)val2).alignment = (TextAlignmentOptions)514; ((TMP_Text)val2).overflowMode = (TextOverflowModes)1; ((TMP_Text)val2).textWrappingMode = (TextWrappingModes)0; ((Graphic)val2).color = new Color(0.92f, 0.85f, 0.68f); ((Component)val).gameObject.SetActive(true); return val2; } private bool Build() { //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Expected O, but got Unknown //IL_0102: 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_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01be: 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) //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_02b4: Unknown result type (might be due to invalid IL or missing references) //IL_02c3: Unknown result type (might be due to invalid IL or missing references) //IL_02f8: Unknown result type (might be due to invalid IL or missing references) //IL_0307: Unknown result type (might be due to invalid IL or missing references) //IL_033a: Unknown result type (might be due to invalid IL or missing references) //IL_033f: Unknown result type (might be due to invalid IL or missing references) //IL_034e: Unknown result type (might be due to invalid IL or missing references) //IL_03c6: Unknown result type (might be due to invalid IL or missing references) //IL_03cb: Unknown result type (might be due to invalid IL or missing references) //IL_03da: Unknown result type (might be due to invalid IL or missing references) //IL_041a: Unknown result type (might be due to invalid IL or missing references) //IL_0463: Unknown result type (might be due to invalid IL or missing references) //IL_0472: Unknown result type (might be due to invalid IL or missing references) //IL_0481: Unknown result type (might be due to invalid IL or missing references) //IL_04a7: Unknown result type (might be due to invalid IL or missing references) //IL_04b6: Unknown result type (might be due to invalid IL or missing references) //IL_04e0: Unknown result type (might be due to invalid IL or missing references) //IL_04e5: Unknown result type (might be due to invalid IL or missing references) //IL_04ea: Unknown result type (might be due to invalid IL or missing references) //IL_04ff: Unknown result type (might be due to invalid IL or missing references) //IL_0515: Unknown result type (might be due to invalid IL or missing references) //IL_051a: Unknown result type (might be due to invalid IL or missing references) //IL_051b: Unknown result type (might be due to invalid IL or missing references) //IL_0522: Unknown result type (might be due to invalid IL or missing references) //IL_053e: Unknown result type (might be due to invalid IL or missing references) //IL_054d: Unknown result type (might be due to invalid IL or missing references) //IL_055c: Unknown result type (might be due to invalid IL or missing references) //IL_0588: Unknown result type (might be due to invalid IL or missing references) //IL_05ab: Unknown result type (might be due to invalid IL or missing references) //IL_05c1: Unknown result type (might be due to invalid IL or missing references) //IL_05d0: Unknown result type (might be due to invalid IL or missing references) //IL_05df: Unknown result type (might be due to invalid IL or missing references) //IL_060a: Unknown result type (might be due to invalid IL or missing references) //IL_062d: Unknown result type (might be due to invalid IL or missing references) //IL_0632: Unknown result type (might be due to invalid IL or missing references) //IL_0641: Unknown result type (might be due to invalid IL or missing references) //IL_0659: Unknown result type (might be due to invalid IL or missing references) //IL_0697: Unknown result type (might be due to invalid IL or missing references) //IL_06a6: Unknown result type (might be due to invalid IL or missing references) //IL_0727: Unknown result type (might be due to invalid IL or missing references) //IL_0736: Unknown result type (might be due to invalid IL or missing references) //IL_075a: Unknown result type (might be due to invalid IL or missing references) //IL_075f: Unknown result type (might be due to invalid IL or missing references) //IL_0764: Unknown result type (might be due to invalid IL or missing references) //IL_077c: Unknown result type (might be due to invalid IL or missing references) //IL_0792: Unknown result type (might be due to invalid IL or missing references) //IL_07a8: Unknown result type (might be due to invalid IL or missing references) //IL_07be: Unknown result type (might be due to invalid IL or missing references) //IL_07d4: Unknown result type (might be due to invalid IL or missing references) //IL_0802: Unknown result type (might be due to invalid IL or missing references) //IL_0832: Unknown result type (might be due to invalid IL or missing references) //IL_0847: Unknown result type (might be due to invalid IL or missing references) //IL_0866: Unknown result type (might be due to invalid IL or missing references) //IL_0885: Unknown result type (might be due to invalid IL or missing references) font = ((Object.op_Implicit((Object)(object)InventoryGui.instance) && Object.op_Implicit((Object)(object)InventoryGui.instance.m_playerName)) ? InventoryGui.instance.m_playerName.font : TMP_Settings.defaultFontAsset); if (!Object.op_Implicit((Object)(object)font)) { return false; } bearings.Clear(); mapMarkers.Clear(); previousHeading = -1; appliedCompassColour = (appliedClockColour = null); root = new GameObject("Compass Waypoints and Clock", new Type[4] { typeof(RectTransform), typeof(Canvas), typeof(CanvasScaler), typeof(GraphicRaycaster) }); Canvas component = root.GetComponent<Canvas>(); component.renderMode = (RenderMode)0; component.sortingOrder = 75; CanvasScaler component2 = root.GetComponent<CanvasScaler>(); component2.uiScaleMode = (ScaleMode)1; component2.referenceResolution = new Vector2(1920f, 1080f); component2.matchWidthOrHeight = 0.5f; hud = Rect("HUD", root.transform, new Vector2(0.5f, 1f), Vector2.zero, new Vector2(620f, 110f)); compass = ((Component)Rect("Compass", (Transform)(object)hud, new Vector2(0.5f, 0.5f), Vector2.zero, new Vector2(600f, 60f))).gameObject; heading = Text("Heading", compass.transform, new Vector2(0f, 20f), new Vector2(90f, 24f), "", 15f); for (int i = 0; i < 16; i++) { bearings.Add(Text("Bearing" + i, compass.transform, Vector2.zero, new Vector2(52f, 24f), (i % 2 == 0) ? (new string[8] { "N", "NE", "E", "SE", "S", "SW", "W", "NW" })[i / 2] : "·", (i % 2 == 0) ? 18 : 14)); } target = Text("Destination", compass.transform, new Vector2(0f, -29f), new Vector2(590f, 24f), "", 16f); destination = Text("Waypoint bearing", compass.transform, new Vector2(0f, -13f), new Vector2(30f, 20f), "◆", 14f); RectTransform val = Rect("Next waypoint diamond", compass.transform, new Vector2(0.5f, 0.5f), Vector2.zero, new Vector2(20f, 20f)); nextDiamond = ((Component)val).gameObject.AddComponent<Image>(); ((Graphic)nextDiamond).raycastTarget = false; nextDiamond.sprite = MarkerSprites.Get(MarkerKind.Waypoints); ((Component)nextDiamond).gameObject.SetActive(false); for (int j = 0; j < 16; j++) { RectTransform val2 = Rect("Map pin " + j, compass.transform, new Vector2(0.5f, 0.5f), Vector2.zero, new Vector2(18f, 18f)); Image val3 = ((Component)val2).gameObject.AddComponent<Image>(); ((Graphic)val3).raycastTarget = false; val3.preserveAspect = true; ((Graphic)val3).color = new Color(1f, 1f, 1f, 0.65f); ((Component)val3).gameObject.SetActive(false); mapMarkers.Add(val3); } clock = ((Component)Rect("Clock", (Transform)(object)hud, new Vector2(0.5f, 0.5f), new Vector2(0f, -58f), new Vector2(300f, 28f))).gameObject; time = Text("Time", clock.transform, Vector2.zero, new Vector2(300f, 28f), "", 20f); mapUi = Rect("CWC map controls", root.transform, Vector2.zero, Vector2.zero, Vector2.zero); mapUi.anchorMax = Vector2.one; RectTransform obj = mapUi; Vector2 offsetMin = (mapUi.offsetMax = Vector2.zero); obj.offsetMin = offsetMin; RectTransform val4 = Rect("Remove visited waypoints", (Transform)(object)mapUi, new Vector2(0f, 1f), new Vector2(165f, -36f), new Vector2(290f, 36f)); ((Graphic)((Component)val4).gameObject.AddComponent<Image>()).color = new Color(0.055f, 0.07f, 0.065f, 0.9f); removeToggle = ((Component)val4).gameObject.AddComponent<Toggle>(); removeToggle.toggleTransition = (ToggleTransition)0; RectTransform val5 = Rect("Checkbox", (Transform)(object)val4, new Vector2(0.5f, 0.5f), new Vector2(-124f, 0f), new Vector2(20f, 20f)); Image val6 = ((Component)val5).gameObject.AddComponent<Image>(); ((Graphic)val6).color = new Color(0.3f, 0.34f, 0.3f); ((Graphic)val6).raycastTarget = false; Image val7 = ((Component)Rect("Check", (Transform)(object)val5, new Vector2(0.5f, 0.5f), Vector2.zero, new Vector2(10f, 10f))).gameObject.AddComponent<Image>(); ((Graphic)val7).color = HudStyle.DefaultColour; ((Graphic)val7).raycastTarget = false; ((Selectable)removeToggle).targetGraphic = (Graphic)(object)val6; removeCheck = ((Component)val7).gameObject; Text("Label", (Transform)(object)val4, new Vector2(12f, 0f), new Vector2(245f, 30f), "Remove visited waypoints", 17f); removeToggle.SetIsOnWithoutNotify(plugin.AutoRemoveVisited.Value); removeCheck.SetActive(plugin.AutoRemoveVisited.Value); ((UnityEvent<bool>)(object)removeToggle.onValueChanged).AddListener((UnityAction<bool>)delegate(bool value) { removeCheck.SetActive(value); plugin.AutoRemoveVisited.Value = value; plugin.Notice(value ? "Visited waypoints will be removed" : "Visited waypoints will stay on the map"); }); ((Component)val4).gameObject.SetActive(false); mapHint = Text("Waypoint controls", (Transform)(object)mapUi, Vector2.zero, new Vector2(1150f, 64f), "Ctrl + double-left-click: add waypoint | Ctrl + right-click: remove waypoint", 18f); RectTransform val8 = Rect("Waypoint hint panel", (Transform)(object)mapUi, Vector2.zero, Vector2.zero, Vector2.zero); val8.anchorMin = new Vector2(0f, 0f); val8.anchorMax = new Vector2(1f, 0f); val8.pivot = new Vector2(0.5f, 0f); val8.offsetMin = new Vector2(24f, 100f); val8.offsetMax = new Vector2(-180f, 170f); Image val9 = ((Component)val8).gameObject.AddComponent<Image>(); ((Graphic)val9).color = new Color(0.04f, 0.05f, 0.04f, 0.85f); ((Graphic)val9).raycastTarget = false; ((Transform)((TMP_Text)mapHint).rectTransform).SetParent((Transform)(object)val8, false); ((TMP_Text)mapHint).rectTransform.anchorMin = Vector2.zero; ((TMP_Text)mapHint).rectTransform.anchorMax = Vector2.one; ((TMP_Text)mapHint).rectTransform.offsetMin = new Vector2(12f, 6f); ((TMP_Text)mapHint).rectTransform.offsetMax = new Vector2(-12f, -6f); ((TMP_Text)mapHint).enableAutoSizing = true; ((TMP_Text)mapHint).fontSizeMin = 12f; ((TMP_Text)mapHint).fontSizeMax = 18f; ((TMP_Text)mapHint).textWrappingMode = (TextWrappingModes)1; ((Component)mapHint).gameObject.SetActive(false); BuildFilters(); return true; } private void BuildFilters() { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Expected O, but got Unknown //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: 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_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0113: 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_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: 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) //IL_02da: Unknown result type (might be due to invalid IL or missing references) //IL_02ec: Unknown result type (might be due to invalid IL or missing references) //IL_02fb: Unknown result type (might be due to invalid IL or missing references) //IL_0326: Unknown result type (might be due to invalid IL or missing references) //IL_034a: Unknown result type (might be due to invalid IL or missing references) //IL_0362: Unknown result type (might be due to invalid IL or missing references) //IL_0367: Unknown result type (might be due to invalid IL or missing references) //IL_0376: Unknown result type (might be due to invalid IL or missing references) //IL_03a2: Unknown result type (might be due to invalid IL or missing references) filterToggles.Clear(); filterChecks.Clear(); RectTransform val = Rect("Marker filters", (Transform)(object)mapUi, new Vector2(0f, 1f), new Vector2(165f, -79f), new Vector2(290f, 34f)); filterButton = ((Component)val).gameObject; Image val2 = filterButton.AddComponent<Image>(); ((Graphic)val2).color = new Color(0.055f, 0.07f, 0.065f, 0.94f); Button val3 = filterButton.AddComponent<Button>(); ((Selectable)val3).targetGraphic = (Graphic)(object)val2; ((UnityEvent)val3.onClick).AddListener((UnityAction)delegate { filtersOpen = !filtersOpen; }); Text("Label", (Transform)(object)val, Vector2.zero, new Vector2(270f, 30f), "Marker filters", 17f); RectTransform val4 = Rect("Marker filter choices", (Transform)(object)mapUi, new Vector2(0f, 1f), new Vector2(165f, -349f), new Vector2(290f, 496f)); filterPanel = ((Component)val4).gameObject; ((Graphic)filterPanel.AddComponent<Image>()).color = new Color(0.055f, 0.07f, 0.065f, 0.96f); Text("Map heading", (Transform)(object)val4, new Vector2(25f, 225f), new Vector2(65f, 24f), "Map", 15f); Text("Compass heading", (Transform)(object)val4, new Vector2(100f, 225f), new Vector2(85f, 24f), "Compass", 15f); for (int num = 0; num < Enum.GetValues(typeof(MarkerKind)).Length; num++) { MarkerKind kind = (MarkerKind)num; float num2 = 187 - num * 34; Text("Category", (Transform)(object)val4, new Vector2(-66f, num2), new Vector2(126f, 26f), (kind == MarkerKind.SavedPins) ? "Saved pins" : ((kind == MarkerKind.OtherPins) ? "Other icons" : kind.ToString()), 16f); for (int num3 = 0; num3 < 2; num3++) { ConfigEntry<bool> setting = ((num3 == 0) ? plugin.Markers[kind].Map : plugin.Markers[kind].Compass); RectTransform val5 = Rect(string.Concat(kind, " ", (num3 == 0) ? "map" : "compass"), (Transform)(object)val4, new Vector2(0.5f, 0.5f), new Vector2((float)((num3 == 0) ? 25 : 100), num2), new Vector2(26f, 26f)); Image val6 = ((Component)val5).gameObject.AddComponent<Image>(); ((Graphic)val6).color = new Color(0.3f, 0.34f, 0.3f); Toggle val7 = ((Component)val5).gameObject.AddComponent<Toggle>(); ((Selectable)val7).targetGraphic = (Graphic)(object)val6; val7.toggleTransition = (ToggleTransition)0; GameObject check = ((Component)Rect("Checked", (Transform)(object)val5, new Vector2(0.5f, 0.5f), Vector2.zero, new Vector2(14f, 14f))).gameObject; Image val8 = check.AddComponent<Image>(); ((Graphic)val8).raycastTarget = false; ((Graphic)val8).color = HudStyle.DefaultColour; val7.SetIsOnWithoutNotify(setting.Value); check.SetActive(setting.Value); ((UnityEvent<bool>)(object)val7.onValueChanged).AddListener((UnityAction<bool>)delegate(bool value) { setting.Value = value; check.SetActive(value); plugin.Notice(string.Concat(kind, " ", ((ConfigEntryBase)setting).Definition.Key, ": ", value ? "on" : "off")); }); filterToggles.Add(val7); filterChecks.Add(check); } } filterButton.SetActive(false); filterPanel.SetActive(false); } internal void UpdateFilters(bool mapOpen) { //IL_0061: 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_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) Minimap instance = Minimap.instance; if (mapOpen && Object.op_Implicit((Object)(object)instance) && Object.op_Implicit((Object)(object)instance.m_mapImageLarge)) { if ((Object)(object)((Transform)mapUi).parent != (Object)(object)((Component)instance.m_mapImageLarge).transform) { ((Transform)mapUi).SetParent(((Component)instance.m_mapImageLarge).transform, false); } mapUi.anchorMin = Vector2.zero; mapUi.anchorMax = Vector2.one; RectTransform obj = mapUi; Vector2 offsetMin = (mapUi.offsetMax = Vector2.zero); obj.offsetMin = offsetMin; ((Transform)mapUi).SetAsLastSibling(); } else if ((Object)(object)((Transform)mapUi).parent != (Object)(object)root.transform) { ((Transform)mapUi).SetParent(root.transform, false); } ((Component)mapUi).gameObject.SetActive(mapOpen && Object.op_Implicit((Object)(object)instance) && Object.op_Implicit((Object)(object)instance.m_mapImageLarge)); ((Component)mapHint).gameObject.SetActive(mapOpen); ((TMP_Text)mapHint).text = ((!plugin.EnableWaypoints.Value) ? "Waypoints disabled in config" : ((!plugin.Active) ? "Waypoint storage unavailable - check the log" : "Ctrl + double-left-click: add waypoint | Ctrl + right-click: remove waypoint")); if (Time.unscaledTime < statusUntil && !string.IsNullOrEmpty(mapStatus)) { TextMeshProUGUI obj2 = mapHint; ((TMP_Text)obj2).text = ((TMP_Text)obj2).text + "\n" + mapStatus; } filterButton.SetActive(mapOpen); filterPanel.SetActive(mapOpen && filtersOpen); for (int i = 0; i < filterToggles.Count; i++) { MarkerRule markerRule = plugin.Markers[(MarkerKind)(i / 2)]; bool flag = ((i % 2 == 0) ? markerRule.Map.Value : markerRule.Compass.Value); filterToggles[i].SetIsOnWithoutNotify(flag); filterChecks[i].SetActive(flag); } } internal void Tick() { //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Invalid comparison between Unknown and I4 //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Invalid comparison between Unknown and I4 //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Invalid comparison between Unknown and I4 //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Unknown result type (might be due to invalid IL or missing references) //IL_0662: Unknown result type (might be due to invalid IL or missing references) //IL_0667: Unknown result type (might be due to invalid IL or missing references) //IL_03b2: Unknown result type (might be due to invalid IL or missing references) //IL_03c8: Unknown result type (might be due to invalid IL or missing references) //IL_03f0: Unknown result type (might be due to invalid IL or missing references) //IL_040b: Unknown result type (might be due to invalid IL or missing references) //IL_0410: Unknown result type (might be due to invalid IL or missing references) //IL_0450: Unknown result type (might be due to invalid IL or missing references) //IL_046d: Unknown result type (might be due to invalid IL or missing references) //IL_04d7: Unknown result type (might be due to invalid IL or missing references) //IL_034b: Unknown result type (might be due to invalid IL or missing references) //IL_037a: Unknown result type (might be due to invalid IL or missing references) //IL_0548: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)root) && !Build()) { return; } bool flag = Object.op_Implicit((Object)(object)Player.m_localPlayer) && !((Character)Player.m_localPlayer).IsDead() && ((Object.op_Implicit((Object)(object)Minimap.instance) && (int)Minimap.instance.m_mode == 2) || (Object.op_Implicit((Object)(object)Hud.instance) && Hud.instance.IsVisible())); root.SetActive(flag); if (!flag) { if (Object.op_Implicit((Object)(object)mapUi)) { ((Component)mapUi).gameObject.SetActive(false); } return; } hud.anchoredPosition = new Vector2(0f, 0f - plugin.TopOffset.Value - 25f * plugin.HudScale.Value); ((Transform)hud).localScale = Vector3.one * plugin.HudScale.Value; ApplyVisibility(); ApplyColours(); ((Component)removeToggle).gameObject.SetActive(plugin.Active && plugin.EnableWaypoints.Value && Object.op_Implicit((Object)(object)Minimap.instance) && (int)Minimap.instance.m_mode == 2); removeToggle.SetIsOnWithoutNotify(plugin.AutoRemoveVisited.Value); removeCheck.SetActive(plugin.AutoRemoveVisited.Value); UpdateFilters(Object.op_Implicit((Object)(object)Minimap.instance) && (int)Minimap.instance.m_mode == 2); Camera mainCamera = Utils.GetMainCamera(); float num = ((plugin.CameraHeading.Value && Object.op_Implicit((Object)(object)mainCamera)) ? ((Component)mainCamera).transform.eulerAngles.y : ((Component)Player.m_localPlayer).transform.eulerAngles.y); if (plugin.ShowCompass.Value) { for (int i = 0; i < bearings.Count; i++) { float num2 = NavigationMath.Delta((float)i * 22.5f, num); TextMeshProUGUI val = bearings[i]; ((Component)val).gameObject.SetActive(Math.Abs(num2) <= 90f); ((TMP_Text)val).rectTransform.anchoredPosition = new Vector2(num2 * 3f, 0f); ((TMP_Text)val).alpha = compassColour.a * Mathf.Clamp01((94f - Math.Abs(num2)) / 18f); } int num3 = Mathf.RoundToInt(num) % 360; if (previousHeading != num3) { ((TMP_Text)heading).text = num3.ToString("000") + "°"; previousHeading = num3; } List<Waypoint> points = plugin.Engine.Document.Points; int activeIndex = plugin.Engine.ActiveIndex; bool flag2 = plugin.Active && plugin.EnableWaypoints.Value && activeIndex >= 0 && plugin.Markers[MarkerKind.Waypoints].InCompassRange(((Component)Player.m_localPlayer).transform.position, new Vector3(points[activeIndex].X, points[activeIndex].Y, points[activeIndex].Z)); ((Component)destination).gameObject.SetActive(flag2); ((Graphic)destination).color = plugin.Markers[MarkerKind.Waypoints].GetColour(); ((Graphic)target).color = ((Graphic)destination).color; ((Component)nextDiamond).gameObject.SetActive(flag2); ((Graphic)nextDiamond).color = ((Graphic)destination).color; if (flag2) { Vector3 position = ((Component)Player.m_localPlayer).transform.position; float distance = NavigationMath.Distance(points[activeIndex].X - position.x, points[activeIndex].Z - position.z); ((Graphic)nextDiamond).rectTransform.sizeDelta = Vector2.one * (20f * plugin.Markers.IconScale(distance)); float num4 = NavigationMath.Delta(NavigationMath.Bearing(points[activeIndex].X - position.x, points[activeIndex].Z - position.z), num); ((TMP_Text)destination).rectTransform.anchoredPosition = new Vector2(Mathf.Clamp(num4, -90f, 90f) * 3f, -13f); ((TMP_Text)destination).text = ((num4 < -90f) ? "‹" : ((num4 > 90f) ? "›" : "")); ((Component)nextDiamond).gameObject.SetActive(Math.Abs(num4) <= 90f); ((Graphic)nextDiamond).rectTransform.anchoredPosition = ((TMP_Text)destination).rectTransform.anchoredPosition; } UpdateMapMarkers(num); } if (!(Time.unscaledTime >= nextText)) { return; } nextText = Time.unscaledTime + 0.1f; if (plugin.ShowClock.Value) { ((TMP_Text)time).text = ((!Object.op_Implicit((Object)(object)EnvMan.instance)) ? "--" : (plugin.VagueTime.Value ? NavigationMath.VagueClock(EnvMan.instance.GetDayFraction()) : NavigationMath.Clock(EnvMan.instance.GetDayFraction(), plugin.TwelveHour.Value))); } if (plugin.ShowCompass.Value) { RouteDocument document = plugin.Engine.Document; int activeIndex2 = plugin.Engine.ActiveIndex; if (!((Component)destination).gameObject.activeSelf) { ((TMP_Text)target).text = ""; return; } Waypoint waypoint = document.Points[activeIndex2]; Vector3 position2 = ((Component)Player.m_localPlayer).transform.position; float num5 = NavigationMath.Delta(NavigationMath.Bearing(waypoint.X - position2.x, waypoint.Z - position2.z), num); ((TMP_Text)target).text = ((num5 < -8f) ? "‹ " : ((num5 > 8f) ? "› " : "◆ ")) + "Next Waypoint · " + Mathf.RoundToInt(NavigationMath.Distance(waypoint.X - position2.x, waypoint.Z - position2.z)) + " m"; } } internal void ApplyVisibility() { //IL_0070: Unknown result type (might be due to invalid IL or missing references) compass.SetActive(plugin.ShowCompass.Value); clock.SetActive(plugin.ShowClock.Value); clock.GetComponent<RectTransform>().anchoredPosition = new Vector2(0f, plugin.ShowCompass.Value ? (0f - plugin.ClockOffset.Value) : 0f); } internal void ApplyColours() { //IL_011b: 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_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: 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_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) if (appliedCompassColour != plugin.CompassColour.Value) { appliedCompassColour = plugin.CompassColour.Value; if (!HudStyle.TryColour(appliedCompassColour, out compassColour)) { plugin.Notice("Invalid CompassColor; using default warm white"); } foreach (TextMeshProUGUI bearing in bearings) { ((Graphic)bearing).color = compassColour; } TextMeshProUGUI obj = heading; TextMeshProUGUI obj2 = target; Color val = (((Graphic)destination).color = compassColour); Color color = (((Graphic)obj2).color = val); ((Graphic)obj).color = color; } if (appliedClockColour != plugin.ClockColour.Value) { appliedClockColour = plugin.ClockColour.Value; if (!HudStyle.TryColour(appliedClockColour, out var colour)) { plugin.Notice("Invalid ClockColor; using default warm white"); } ((Graphic)time).color = colour; } } private void Consider(Vector3 pos, Vector3 origin, Sprite icon, Color colour) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: 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) Vector2 val = new Vector2(pos.x - origin.x, pos.z - origin.z); float sqrMagnitude = ((Vector2)(ref val)).sqrMagnitude; int i; for (i = 0; i < nearby.Count; i++) { Vector2 val2 = new Vector2(nearby[i].Position.x - origin.x, nearby[i].Position.z - origin.z); if (!(((Vector2)(ref val2)).sqrMagnitude <= sqrMagnitude)) { break; } } if (i < 16) { nearby.Insert(i, new CompassTarget { Position = pos, Icon = icon, Colour = colour }); if (nearby.Count > 16) { nearby.RemoveAt(16); } } } private void UpdateMapMarkers(float direction) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_03b4: Unknown result type (might be due to invalid IL or missing references) //IL_03d2: Unknown result type (might be due to invalid IL or missing references) //IL_0428: Unknown result type (might be due to invalid IL or missing references) //IL_0445: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: 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_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_0287: Unknown result type (might be due to invalid IL or missing references) //IL_028d: Invalid comparison between Unknown and I4 //IL_0291: Unknown result type (might be due to invalid IL or missing references) //IL_0298: Invalid comparison between Unknown and I4 //IL_029c: Unknown result type (might be due to invalid IL or missing references) //IL_029f: Unknown result type (might be due to invalid IL or missing references) //IL_02ae: Unknown result type (might be due to invalid IL or missing references) //IL_02b3: Unknown result type (might be due to invalid IL or missing references) //IL_02bd: Unknown result type (might be due to invalid IL or missing references) Vector3 position = ((Component)Player.m_localPlayer).transform.position; if (Time.unscaledTime >= nextPinScan) { nextPinScan = Time.unscaledTime + 0.25f; nearby.Clear(); foreach (TrackedObject value in plugin.Tracker.Objects.Values) { MarkerKind kind = (MarkerKind)value.Record.Kind; MarkerRule markerRule = plugin.Markers[kind]; if (markerRule.InCompassRange(position, value.Record.Position)) { Color colour = markerRule.GetColour(); if (value.LastSeen) { colour.a *= 0.65f; } Consider(value.Record.Position, position, MarkerSprites.Get(kind), colour); } } if (plugin.Active && plugin.EnableWaypoints.Value) { MarkerRule markerRule2 = plugin.Markers[MarkerKind.Waypoints]; Vector3 val = default(Vector3); foreach (Waypoint point in plugin.Engine.Document.Points) { if (plugin.Engine.ActiveIndex >= 0 && point == plugin.Engine.Document.Points[plugin.Engine.ActiveIndex]) { continue; } ((Vector3)(ref val))..ctor(point.X, point.Y, point.Z); if (markerRule2.InCompassRange(position, val)) { Color colour2 = markerRule2.GetColour(); if (point.Visited) { colour2.a *= 0.5f; } Consider(val, position, MarkerSprites.Get(MarkerKind.Waypoints), colour2); } } } Minimap instance = Minimap.instance; List<PinData> list = ((Object.op_Implicit((Object)(object)instance) && MapPins != null) ? (MapPins.GetValue(instance) as List<PinData>) : null); if (list != null) { foreach (PinData item in list) { MarkerRule markerRule3 = plugin.Markers[MarkerSettings.Category(item)]; if (!item.m_checked && Object.op_Implicit((Object)(object)item.m_icon) && (int)item.m_type != 8 && (int)item.m_type != 13 && markerRule3.InCompassRange(position, item.m_pos)) { Consider(item.m_pos, position, item.m_icon, markerRule3.GetColour()); } } } } for (int i = 0; i < mapMarkers.Count; i++) { Image val2 = mapMarkers[i]; bool flag = i < nearby.Count; float num = (flag ? NavigationMath.Delta(NavigationMath.Bearing(nearby[i].Position.x - position.x, nearby[i].Position.z - position.z), direction) : 0f); ((Component)val2).gameObject.SetActive(flag && Math.Abs(num) <= 90f); if (flag) { val2.sprite = nearby[i].Icon; ((Graphic)val2).color = nearby[i].Colour; ((Graphic)val2).rectTransform.anchoredPosition = new Vector2(num * 3f, -13f); float distance = NavigationMath.Distance(nearby[i].Position.x - position.x, nearby[i].Position.z - position.z); ((Graphic)val2).rectTransform.sizeDelta = Vector2.one * (18f * plugin.Markers.IconScale(distance)); } } if (((TMP_Text)destination).transform.GetSiblingIndex() != compass.transform.childCount - 1) { ((TMP_Text)destination).transform.SetAsLastSibling(); } } internal void Hide() { if (Object.op_Implicit((Object)(object)root)) { root.SetActive(false); } if (Object.op_Implicit((Object)(object)mapUi)) { ((Component)mapUi).gameObject.SetActive(false); } } internal void Reset() { if (Object.op_Implicit((Object)(object)mapUi)) { Object.Destroy((Object)(object)((Component)mapUi).gameObject); } mapUi = null; if (Object.op_Implicit((Object)(object)root)) { Object.Destroy((Object)(object)root); } root = null; bearings.Clear(); mapMarkers.Clear(); nearby.Clear(); filterToggles.Clear(); filterChecks.Clear(); filtersOpen = false; previousHeading = -1; appliedCompassColour = (appliedClockColour = null); } } internal static class HudStyle { internal static readonly Color DefaultColour = new Color(47f / 51f, 0.8509804f, 0.6784314f, 1f); internal static bool TryColour(string value, out Color colour) { //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) string text = (value ?? "").Trim().ToLowerInvariant(); switch (text) { case "gold": text = "#D4AF37"; break; case "amber": text = "#FFBF00"; break; case "ivory": text = "#FFFFF0"; break; case "warmwhite": case "warm white": text = "#EBD9AD"; break; case "gray": text = "grey"; break; case "transparent": text = "#00000000"; break; } if (text.Length == 3 || text.Length == 4 || text.Length == 6 || text.Length == 8) { bool flag = true; string text2 = text; foreach (char character in text2) { if (!Uri.IsHexDigit(character)) { flag = false; break; } } if (flag) { text = "#" + text; } } if (ColorUtility.TryParseHtmlString(text, ref colour)) { return true; } colour = DefaultColour; return false; } } internal enum MarkerKind { Ships, Carts, Portals, Waypoints, SavedPins, Beds, Bosses, Deaths, Players, Events, Pings, Locations, OtherPins } internal sealed class MarkerRule { internal readonly ConfigEntry<bool> Map; internal readonly ConfigEntry<bool> Compass; internal readonly ConfigEntry<string> Colour; internal readonly ConfigEntry<float> Range; private string cached; private Color colour; internal MarkerRule(ConfigFile config, MarkerKind kind, bool map, bool compass, string defaultColour, ConfigEntry<float> range) { string text = "Markers - " + kind; Map = config.Bind<bool>(text, "ShowOnMap", map, "Show this category on the map. This changes visibility, never deletes objects or saved pins."); Compass = config.Bind<bool>(text, "ShowOnCompass", compass, "Show this category on the compass independently of its map filter."); Colour = config.Bind<string>(text, "Color", defaultColour, "Hex RGB/RGBA or a colour name, such as yellow, cyan, gold or red. Applies to map icons, labels and compass markers."); Range = range; } internal Color GetColour() { //IL_0058: Unknown result type (might be due to invalid IL or missing references) if (cached != Colour.Value) { cached = Colour.Value; if (!HudStyle.TryColour(cached, out colour) && Object.op_Implicit((Object)(object)Plugin.Instance)) { Plugin.Instance.Notice("Invalid marker colour; using warm white"); } } return colour; } internal bool InCompassRange(Vector3 origin, Vector3 position) { if (Compass.Value) { return NavigationMath.Distance(position.x - origin.x, position.z - origin.z) <= Range.Value; } return false; } } internal sealed class MarkerSettings { private readonly MarkerRule[] rules; internal readonly ConfigEntry<float> CompassRange; internal readonly ConfigEntry<float> MarkerMinSize; internal readonly ConfigEntry<float> MarkerMaxSize; internal MarkerRule this[MarkerKind kind] => rules[(int)kind]; internal float IconScale(float distance) { float num = Mathf.Min(MarkerMinSize.Value, MarkerMaxSize.Value); float num2 = Mathf.Max(MarkerMinSize.Value, MarkerMaxSize.Value); return Mathf.Lerp(num2, num, Mathf.Clamp01(distance / CompassRange.Value)); } internal MarkerSettings(ConfigFile config, string defaultColour = "#EBD9AD", bool savedCompass = true) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Expected O, but got Unknown CompassRange = config.Bind<float>("Display", "CompassRange", 300f, new ConfigDescription("Shared maximum horizontal distance in metres for all compass marker categories, including waypoints. Does not limit map visibility.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 20000f), new object[0])); MarkerMinSize = config.Bind<float>("Display", "MarkerMinSize", 0.5f, new ConfigDescription("Global compass icon size at the range limit, relative to original size: 0.5 = 50%, 0.1 = 10%. Applies to all categories and waypoint diamonds. If min exceeds max, the two bounds are treated in ascending order.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 5f), new object[0])); MarkerMaxSize = config.Bind<float>("Display", "MarkerMaxSize", 1.2f, new ConfigDescription("Global compass icon size up close, relative to original size: 1.2 = 120%, 2 = 200%. Icons scale smoothly using CompassRange. Equal minimum and maximum give a fixed size.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 5f), new object[0])); rules = new MarkerRule[13] { new MarkerRule(config, MarkerKind.Ships, map: true, compass: true, "yellow", CompassRange), new MarkerRule(config, MarkerKind.Carts, map: true, compass: true, "cyan", CompassRange), new MarkerRule(config, MarkerKind.Portals, map: true, compass: true, "red", CompassRange), new MarkerRule(config, MarkerKind.Waypoints, map: true, compass: true, defaultColour, CompassRange), new MarkerRule(config, MarkerKind.SavedPins, map: true, savedCompass, defaultColour, CompassRange), new MarkerRule(config, MarkerKind.Beds, map: true, compass: true, defaultColour, CompassRange), new MarkerRule(config, MarkerKind.Bosses, map: true, compass: true, defaultColour, CompassRange), new MarkerRule(config, MarkerKind.Deaths, map: true, compass: true, defaultColour, CompassRange), new MarkerRule(config, MarkerKind.Players, map: true, compass: true, defaultColour, CompassRange), new MarkerRule(config, MarkerKind.Events, map: true, compass: true, defaultColour, CompassRange), new MarkerRule(config, MarkerKind.Pings, map: true, compass: true, defaultColour, CompassRange), new MarkerRule(config, MarkerKind.Locations, map: true, compass: true, defaultColour, CompassRange), new MarkerRule(config, MarkerKind.OtherPins, map: true, compass: true, defaultColour, CompassRange) }; } internal static void RemoveObsoleteSettings(ConfigFile config) { string[] array = new string[3] { "RouteManager", "AddAtFeet", "AddAtAim" }; foreach (string text in array) { config.Remove(((ConfigEntryBase)config.Bind<string>("Controls", text, "", (ConfigDescription)null)).Definition); } config.Remove(((ConfigEntryBase)config.Bind<string>("Waypoints", "AutomaticArrival", "", (ConfigDescription)null)).Definition); config.Remove(((ConfigEntryBase)config.Bind<string>("Display", "MarkerScale", "", (ConfigDescription)null)).Definition); foreach (MarkerKind value in Enum.GetValues(typeof(MarkerKind))) { config.Remove(((ConfigEntryBase)config.Bind<string>("Markers - " + value, "CompassRange", "", (ConfigDescription)null)).Definition); } } internal static MarkerKind Category(PinData pin) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected I4, but got Unknown switch ((int)pin.m_type) { case 0: case 1: case 2: case 3: case 6: return MarkerKind.SavedPins; case 4: return MarkerKind.Deaths; case 5: return MarkerKind.Beds; case 9: return MarkerKind.Bosses; case 10: return MarkerKind.Players; case 7: case 12: return MarkerKind.Pings; case 11: case 13: return MarkerKind.Events; case 14: case 15: case 16: case 17: return MarkerKind.Locations; default: return MarkerKind.OtherPins; } } } internal static class MarkerSprites { private static readonly Sprite[] sprites = (Sprite[])(object)new Sprite[4]; internal static Sprite Get(MarkerKind kind) { //IL_0477: Unknown result type (might be due to invalid IL or missing references) //IL_047e: Expected O, but got Unknown //IL_04c8: Unknown result type (might be due to invalid IL or missing references) //IL_04d7: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0264: Unknown result type (might be due to invalid IL or missing references) //IL_0269: Unknown result type (might be due to invalid IL or missing references) //IL_0290: Unknown result type (might be due to invalid IL or missing references) //IL_0295: Unknown result type (might be due to invalid IL or missing references) //IL_044f: Unknown result type (might be due to invalid IL or missing references) //IL_0454: Unknown result type (might be due to invalid IL or missing references) //IL_030e: Unknown result type (might be due to invalid IL or missing references) //IL_0313: Unknown result type (might be due to invalid IL or missing references) //IL_0376: Unknown result type (might be due to invalid IL or missing references) //IL_037b: Unknown result type (might be due to invalid IL or missing references) int num = Math.Min((int)kind, 3); if (Object.op_Implicit((Object)(object)sprites[num])) { return sprites[num]; } Color32[] array = (Color32[])(object)new Color32[4096]; for (int i = 0; i < 64; i++) { for (int j = 0; j < 64; j++) { float num2 = 100f; switch (num) { case 0: { Vector2 val5 = new Vector2((float)(j - 32), (float)(i - 52)); num2 = Math.Abs(((Vector2)(ref val5)).magnitude - 6f); num2 = Math.Min(num2, Line(j, i, 32f, 46f, 32f, 12f)); num2 = Math.Min(num2, Line(j, i, 23f, 37f, 41f, 37f)); num2 = Math.Min(num2, Line(j, i, 12f, 29f, 18f, 18f)); num2 = Math.Min(num2, Line(j, i, 18f, 18f, 32f, 12f)); num2 = Math.Min(num2, Line(j, i, 32f, 12f, 46f, 18f)); num2 = Math.Min(num2, Line(j, i, 46f, 18f, 52f, 29f)); num2 = Math.Min(num2, Line(j, i, 12f, 29f, 12f, 20f)); num2 = Math.Min(num2, Line(j, i, 52f, 29f, 52f, 20f)); break; } case 1: { num2 = Math.Min(Line(j, i, 11f, 44f, 50f, 44f), Line(j, i, 11f, 44f, 16f, 25f)); num2 = Math.Min(num2, Line(j, i, 16f, 25f, 45f, 25f)); num2 = Math.Min(num2, Line(j, i, 45f, 25f, 50f, 44f)); num2 = Math.Min(num2, Line(j, i, 50f, 44f, 59f, 49f)); float val6 = num2; Vector2 val7 = new Vector2((float)(j - 20), (float)(i - 15)); num2 = Math.Min(val6, Math.Abs(((Vector2)(ref val7)).magnitude - 5f)); float val8 = num2; Vector2 val9 = new Vector2((float)(j - 42), (float)(i - 15)); num2 = Math.Min(val8, Math.Abs(((Vector2)(ref val9)).magnitude - 5f)); break; } case 2: num2 = Math.Min(Line(j, i, 14f, 10f, 14f, 36f), Line(j, i, 50f, 10f, 50f, 36f)); if (i >= 36) { float val = num2; Vector2 val2 = new Vector2((float)(j - 32), (float)(i - 36)); num2 = Math.Min(val, Math.Abs(((Vector2)(ref val2)).magnitude - 18f)); } num2 = Math.Min(num2, Line(j, i, 10f, 10f, 54f, 10f)); if (i >= 21 && i <= 39) { float val3 = num2; Vector2 val4 = new Vector2((float)(j - 32) * 1.6f, (float)(i - 30)); num2 = Math.Min(val3, Math.Abs(((Vector2)(ref val4)).magnitude - 10f)); } break; default: num2 = Math.Min(Math.Min(Line(j, i, 32f, 55f, 52f, 32f), Line(j, i, 52f, 32f, 32f, 9f)), Math.Min(Line(j, i, 32f, 9f, 12f, 32f), Line(j, i, 12f, 32f, 32f, 55f))); break; } ref Color32 reference = ref array[i * 64 + j]; reference = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, (byte)(255f * Mathf.Clamp01(3f - num2))); } } Texture2D val10 = new Texture2D(64, 64, (TextureFormat)4, false); ((Object)val10).name = "CWC " + kind; val10.SetPixels32(array); val10.Apply(); ((Texture)val10).wrapMode = (TextureWrapMode)1; sprites[num] = Sprite.Create(val10, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f), 64f); return sprites[num]; } private static float Line(float x, float y, float ax, float ay, float bx, float by) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(x - ax, y - ay); Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(bx - ax, by - ay); Vector2 val3 = val - val2 * Mathf.Clamp01(Vector2.Dot(val, val2) / ((Vector2)(ref val2)).sqrMagnitude); return ((Vector2)(ref val3)).magnitude; } internal static void Release() { for (int i = 0; i < sprites.Length; i++) { if (Object.op_Implicit((Object)(object)sprites[i])) { Object.Destroy((Object)(object)sprites[i].texture); Object.Destroy((Object)(object)sprites[i]); sprites[i] = null; } } } } public static class NavigationApi { public const int ApiVersion = 1; public static bool IsReady { get { if (Object.op_Implicit((Object)(object)Plugin.Instance) && Plugin.Instance.Active) { return Plugin.Instance.EnableWaypoints.Value; } return false; } } public static Waypoint[] GetRoute() { if (!IsReady) { return new Waypoint[0]; } return Plugin.Instance.Engine.Document.Points.ConvertAll((Waypoint p) => p.Copy()).ToArray(); } public static bool TryAppend(string label, Vector3 position, bool checkHeight) { if (!IsReady) { return false; } Plugin instance = Plugin.Instance; Waypoint waypoint = new Waypoint(); waypoint.Name = NavigationMath.Clean(label); waypoint.X = position.x; waypoint.Y = position.y; waypoint.Z = position.z; waypoint.CheckHeight = checkHeight; Waypoint waypoint2 = waypoint; if (string.IsNullOrEmpty(waypoint2.Name) || !instance.Engine.Add(waypoint2, instance.Now)) { return false; } instance.Commit(); if (!instance.Active) { return false; } instance.Notice("Waypoint added: " + waypoint2.Name); return true; } } internal sealed class ObjectMapView { private sealed class Marker { internal RectTransform Root; internal Image Icon; internal TMP_Text Text; internal string Label; internal bool Stale; } private readonly Plugin plugin; private readonly Dictionary<string, Marker> markers = new Dictionary<string, Marker>(); private readonly HashSet<string> shown = new HashSet<string>(); private RectTransform overlay; private RawImage image; private static readonly MarkerKind[] Priority = new MarkerKind[3] { MarkerKind.Ships, MarkerKind.Portals, MarkerKind.Carts }; private int revision = -1; private readonly List<string> waypointLabels = new List<string>(); internal ObjectMapView(Plugin owner) { plugin = owner; } internal static bool Project(Vector3 position, int textureSize, float pixelSize, Rect uv, Rect rect, out Vector2 local) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) local = Vector2.zero; if (textureSize <= 0 || pixelSize <= 0f || ((Rect)(ref uv)).width <= 0f || ((Rect)(ref uv)).height <= 0f) { return false; } Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor((position.x / pixelSize + (float)(textureSize / 2)) / (float)textureSize, (position.z / pixelSize + (float)(textureSize / 2)) / (float)textureSize); if (!((Rect)(ref uv)).Contains(val)) { return false; } local = new Vector2((val.x - ((Rect)(ref uv)).xMin) / ((Rect)(ref uv)).width * ((Rect)(ref rect)).width, (val.y - ((Rect)(ref uv)).yMin) / ((Rect)(ref uv)).height * ((Rect)(ref rect)).height); return true; } internal void Draw() { //IL_001b: 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: Invalid comparison between Unknown and I4 //IL_00da: 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_0100: 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) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_037d: Unknown result type (might be due to invalid IL or missing references) Minimap instance = Minimap.instance; if (!Object.op_Implicit((Object)(object)instance) || !Object.op_Implicit((Object)(object)Player.m_localPlayer) || (int)instance.m_mode == 0) { Hide(); return; } RawImage val = (((int)instance.m_mode == 2) ? instance.m_mapImageLarge : instance.m_mapImageSmall); if (!Object.op_Implicit((Object)(object)val)) { Hide(); return; } if ((Object)(object)image != (Object)(object)val || !Object.op_Implicit((Object)(object)overlay)) { image = val; if (!Object.op_Implicit((Object)(object)overlay)) { overlay = new GameObject("CWC object markers", new Type[2] { typeof(RectTransform), typeof(RectMask2D) }).GetComponent<RectTransform>(); } ((Transform)overlay).SetParent(((Component)image).transform, false); overlay.anchorMin = Vector2.zero; overlay.anchorMax = Vector2.one; RectTransform obj = overlay; Vector2 offsetMin = (overlay.offsetMax = Vector2.zero); obj.offsetMin = offsetMin; } ((Component)overlay).gameObject.SetActive(true); shown.Clear(); TMP_FontAsset val2 = ((Object.op_Implicit((Object)(object)InventoryGui.instance) && Object.op_Implicit((Object)(object)InventoryGui.instance.m_playerName)) ? InventoryGui.instance.m_playerName.font : TMP_Settings.defaultFontAsset); if (!Object.op_Implicit((Object)(object)val2)) { return; } MarkerKind[] priority = Priority; foreach (MarkerKind markerKind in priority) { if (!plugin.Markers[markerKind].Map.Value) { continue; } foreach (KeyValuePair<ZDOID, TrackedObject> @object in plugin.Tracker.Objects) { TrackedObject value = @object.Value; if (value.Record.Kind == (int)markerKind) { DrawOne(value.Key, value.Record.Position, markerKind, value.Record.Name, value.LastSeen, val2, instance); } } } if (plugin.Active && revision != plugin.Engine.Revision) { revision = plugin.Engine.Revision; waypointLabels.Clear(); for (int j = 0; j < plugin.Engine.Document.Points.Count; j++) { waypointLabels.Add(plugin.Engine.Label(j) + (plugin.Engine.Document.Points[j].Visited ? " (visited)" : "")); } } if (plugin.Active && plugin.EnableWaypoints.Value && plugin.Markers[MarkerKind.Waypoints].Map.Value) { for (int k = 0; k < plugin.Engine.Document.Points.Count; k++) { Waypoint waypoint = plugin.Engine.Document.Points[k]; DrawOne(waypoint.Id, new Vector3(waypoint.X, waypoint.Y, waypoint.Z), MarkerKind.Waypoints, waypointLabels[k], stale: false, val2, instance); } } foreach (KeyValuePair<string, Marker> marker in markers) { if (!shown.Contains(marker.Key)) { ((Component)marker.Value.Root).gameObject.SetActive(false); } } } private void DrawOne(string key, Vector3 position, MarkerKind kind, string label, bool stale, TMP_FontAsset font, Minimap map) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: 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_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: 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_0135: 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_0267: Unknown result type (might be due to invalid IL or missing references) //IL_026c: Unknown result type (might be due to invalid IL or missing references) //IL_0291: Unknown result type (might be due to invalid IL or missing references) //IL_0293: Unknown result type (might be due to invalid IL or missing references) //IL_0294: 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) //IL_02af: Unknown result type (might be due to invalid IL or missing references) //IL_02b5: Invalid comparison between Unknown and I4 if (shown.Count < 512 && Project(position, map.m_textureSize, map.m_pixelSize, image.uvRect, ((Graphic)image).rectTransform.rect, out var local)) { shown.Add(key); if (!markers.TryGetValue(key, out var value)) { RectTransform component = new GameObject("CWC " + kind, new Type[1] { typeof(RectTransform) }).GetComponent<RectTransform>(); ((Transform)component).SetParent((Transform)(object)overlay, false); Vector2 anchorMin = (component.anchorMax = Vector2.zero); component.anchorMin = anchorMin; component.sizeDelta = new Vector2(28f, 28f); Image val = ((Component)component).gameObject.AddComponent<Image>(); val.sprite = MarkerSprites.Get(kind); ((Graphic)val).raycastTarget = false; val.preserveAspect = true; RectTransform component2 = new GameObject("Label", new Type[1] { typeof(RectTransform) }).GetComponent<RectTransform>(); ((Transform)component2).SetParent((Transform)(object)component, false); component2.anchoredPosition = new Vector2(0f, -26f); component2.sizeDelta = new Vector2(200f, 24f); ((Component)component2).gameObject.SetActive(false); TextMeshProUGUI val2 = ((Component)component2).gameObject.AddComponent<TextMeshProUGUI>(); ((TMP_Text)val2).font = font; ((TMP_Text)val2).fontSize = 14f; ((TMP_Text)val2).alignment = (TextAlignmentOptions)514; ((TMP_Text)val2).richText = false; ((Graphic)val2).raycastTarget = false; ((TMP_Text)val2).textWrappingMode = (TextWrappingModes)0; ((TMP_Text)val2).overflowMode = (TextOverflowModes)1; ((Component)component2).gameObject.SetActive(true); Marker marker = new Marker(); marker.Root = component; marker.Icon = val; marker.Text = (TMP_Text)(object)val2; value = marker; markers.Add(key, value); } ((Component)value.Root).gameObject.SetActive(true); value.Root.anchoredPosition = local; if (value.Label != label || value.Stale != stale) { value.Label = label; value.Stale = stale; value.Text.text = label + (stale ? " (last seen)" : ""); } Color colour = plugin.Markers[kind].GetColour(); if (stale) { colour.a *= 0.65f; } Image icon = value.Icon; Color color = (((Graphic)value.Text).color = colour); ((Graphic)icon).color = color; ((Component)value.Text).gameObject.SetActive((int)map.m_mode == 2); } } internal void Hide() { if (Object.op_Implicit((Object)(object)overlay)) { ((Component)overlay).gameObject.SetActive(false); } } internal void Reset() { if (Object.op_Implicit((Object)(object)overlay)) { Object.Destroy((Object)(object)((Component)overlay).gameObject); } overlay = null; image = null; markers.Clear(); shown.Clear(); revision = -1; waypointLabels.Clear(); } } internal sealed class TrackedObject { internal TrackedRecord Record; internal Component Live; internal bool LastSeen = true; internal string Key; } internal sealed class ObjectTracker { internal readonly Dictionary<ZDOID, TrackedObject> Objects = new Dictionary<ZDOID, TrackedObject>(); private readonly Plugin plugin; private long world; private long character; private string path; private bool dirty; private bool readOnly; private bool limitWarned; private float nextUpdate; private float nextSave; internal ObjectTracker(Plugin owner) { plugin = owner; } internal void Begin(long w, long c) { //IL_0085: Unknown result type (might be due to invalid IL or missing references) End(); world = w; character = c; if (w == 0 || c == 0) { return; } path = Path.Combine(Paths.ConfigPath, "CompassWaypointsClock", w.ToString("X16") + "-" + c.ToString("X16") + ".objects"); try { bool recovered; TrackedDocument trackedDocument = TrackedStore.Load(path, w, c, out recovered); TrackedRecord[] records = trackedDocument.Records; foreach (TrackedRecord trackedRecord in records) { Objects[trackedRecord.Uid] = new TrackedObject { Record = trackedRecord, Key = trackedRecord.User + ":" + trackedRecord.Id }; } if (recovered) { plugin.Notice("Recovered tracked-object backup; damaged cache preserved"); } } catch (Exception ex) { readOnly = true; plugin.Notice("Tracked-object cache could not be read; keeping its files untouched. Loaded objects still display. " + ex.Message); } Ship[] array = Object.FindObjectsByType<Ship>((FindObjectsSortMode)0); foreach (Ship component in array) { Observe((Component)(object)component); } Vagon[] array2 = Object.FindObjectsByType<Vagon>((FindObjectsSortMode)0); foreach (Vagon component2 in array2) { Observe((Component)(object)component2); } TeleportWorld[] array3 = Object.FindObjectsByType<TeleportWorld>((FindObjectsSortMode)0); foreach (TeleportWorld component3 in array3) { Observe((Component)(object)component3); } } internal void Observe(Component component) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: 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_0075: Unknown result type (might be due to invalid IL or missing references) if (world == 0 || !Object.op_Implicit((Object)(object)component)) { return; } ZNetView component2 = component.GetComponent<ZNetView>(); if (Object.op_Implicit((Object)(object)component2)) { ZDO zDO = component2.GetZDO(); if (zDO != null && !(zDO.m_uid == ZDOID.None)) { MarkerKind kind = ((!(component is Ship)) ? ((component is Vagon) ? MarkerKind.Carts : MarkerKind.Portals) : MarkerKind.Ships); string name = Name(component, kind); Upsert(zDO.m_uid, zDO.GetPrefab(), kind, name, component.transform.position, component); } } } internal void Upsert(ZDOID id, int prefab, MarkerKind kind, string name, Vector3 position, Component live) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) if (!Objects.TryGetValue(id, out var value)) { if (Objects.Count >= 4096) { if (!limitWarned) { plugin.Notice("Tracked-object limit reached; existing markers retained"); limitWarned = true; } return; } TrackedRecord trackedRecord = new TrackedRecord(); trackedRecord.User = ((ZDOID)(ref id)).UserID; trackedRecord.Id = ((ZDOID)(ref id)).ID; trackedRecord.Prefab = prefab; trackedRecord.Kind = (int)kind; trackedRecord.Name = NavigationMath.Clean(name); trackedRecord.Position = position; TrackedRecord trackedRecord2 = trackedRecord; TrackedDocument trackedDocument = new TrackedDocument(); trackedDocument.World = 1L; trackedDocument.Character = 1L; trackedDocument.Records = new TrackedRecord[1] { trackedRecord2 }; TrackedStore.Validate(trackedDocument, 1L, 1L); TrackedObject trackedObject = new TrackedObject(); trackedObject.Record = trackedRecord2; trackedObject.Key = ((ZDOID)(ref id)).UserID + ":" + ((ZDOID)(ref id)).ID; value = trackedObject; Objects.Add(id, value); dirty = true; } else if (value.Record.Prefab != prefab) { Forget(id); Upsert(id, prefab, kind, name, position, live); return; } value.Live = live; value.LastSeen = !Object.op_Implicit((Object)(object)live); } private static string Name(Component component, MarkerKind kind) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) switch (kind) { case MarkerKind.Portals: { string text = ((TeleportWorld)component).GetText(); if (!string.IsNullOrWhiteSpace(text)) { return NavigationMath.Clean(text); } return "Portal"; } case MarkerKind.Carts: return "Cart"; default: { string prefabName = Utils.GetPrefabName(component.gameObject); return prefabName switch { "VikingShip" => "Longship", "Karve" => "Karve", "Raft" => "Raft", "Drakkar" => "Drakkar", _ => NavigationMath.Clean(prefabName), }; } } } internal void Tick() { //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: 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) if (world == 0 || Time.unscaledTime < nextUpdate) { return; } nextUpdate = Time.unscaledTime + 0.25f; foreach (TrackedObject value in Objects.Values) { value.LastSeen = !Object.op_Implicit((Object)(object)value.Live); if (!value.LastSeen) { Vector3 position = value.Live.transform.position; string text = Name(value.Live, (MarkerKind)value.Record.Kind); Vector3 val = position - value.Record.Position; if (((Vector3)(ref val)).sqrMagnitude > 0.01f || value.Record.Name != text) { value.Record.Position = position; value.Record.Name = text; dirty = true; } } } if (Time.unscaledTime >= nextSave) { nextSave = Time.unscaledTime + 15f; Flush(); } } internal void Forget(ZDOID id) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) if (Objects.Remove(id)) { dirty = true; } } private void Flush() { if (!dirty || readOnly || world == 0) { return; } try { List<TrackedRecord> list = new List<TrackedRecord>(); foreach (TrackedObject value in Objects.Values) { list.Add(value.Record); } TrackedStore.Save(path, new TrackedDocument { World = world, Character = character, Records = list.ToArray() }); dirty = false; } catch (Exception ex) { readOnly = true; plugin.Notice("Could not save tracked objects; previous cache preserved. " + ex.Message); } } internal void End() { Flush(); Objects.Clear(); world = (character = 0L); dirty = (readOnly = (limitWarned = false)); nextUpdate = (nextSave = 0f); } } [HarmonyPatch] internal static class DiscoverTrackedObject { private static IEnumerable<MethodBase> TargetMethods() { try { Type[] array = new Type[3] { typeof(Ship), typeof(Vagon), typeof(TeleportWorld) }; foreach (Type type in array) { yield return AccessTools.Method(type, "Awake", (Type[])null, (Type[])null); } } finally { } } private static void Postfix(Component __instance) { Plugin instance = Plugin.Instance; if (Object.op_Implicit((Object)(object)instance) && instance.Tracker != null) { try { instance.Tracker.Observe(__instance); } catch (Exception ex) { instance.Notice("Object discovery failed: " + ex.Message); } } } } [HarmonyPatch(typeof(ZDOMan), "HandleDestroyedZDO")] internal static class RemoveDestroyedTrackedObject { private static void Postfix(ZDOID uid) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) Plugin instance = Plugin.Instance; if (Object.op_Implicit((Object)(object)instance) && instance.Tracker != null) { instance.Tracker.Forget(uid); } } } [BepInPlugin("au.tyvalheim.compasswaypointsclock", "Compass Waypoints and Clock", "0.1.8")] public sealed class Plugin : BaseUnityPlugin { public const string Id = "au.tyvalheim.compasswaypointsclock"; internal static Plugin Instance; internal ConfigEntry<bool> ShowCompass; internal ConfigEntry<bool> ShowClock; internal ConfigEntry<bool> TwelveHour; internal ConfigEntry<bool> CameraHeading; internal ConfigEntry<bool> AutoRemoveVisited; internal ConfigEntry<bool> Diagnostics; internal ConfigEntry<bool> EnableWaypoints; internal ConfigEntry<bool> VagueTime; internal ConfigEntry<bool> ArrivalChime; internal ConfigEntry<float> ArrivalVolume; private readonly ArrivalSound arrivalSound = new ArrivalSound(); internal ConfigEntry<string> CompassColour; internal ConfigEntry<string> ClockColour; internal ConfigEntry<float> Radius; internal ConfigEntry<float> HeightTolerance; internal ConfigEntry<float> HudScale; internal ConfigEntry<float> TopOffset; internal ConfigEntry<float> ClockOffset; internal RouteEngine Engine; internal Display View; internal MarkerSettings Markers; internal ObjectTracker Tracker; internal ObjectMapView ObjectMap; private Harmony harmony; private long world; private long character; private string path; private bool storageFault; private float nextArrival; private Vector3 lastPosition; private bool havePosition; private int savedRevision; private bool displayFault; internal bool Active { get { if (Engine != null) { return !storageFault; } return false; } } internal double Now => Time.unscaledTime; private void Awake() { //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Expected O, but got Unknown //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Expected O, but got Unknown //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Expected O, but got Unknown //IL_026d: Unknown result type (might be due to invalid IL or missing references) //IL_0277: Expected O, but got Unknown //IL_02ac: Unknown result type (might be due to invalid IL or missing references) //IL_02b6: Expected O, but got Unknown //IL_02eb: Unknown result type (might be due to invalid IL or missing references) //IL_02f5: Expected O, but got Unknown //IL_03b2: Unknown result type (might be due to invalid IL or missing references) //IL_03bc: Expected O, but got Unknown Instance = this; ((BaseUnityPlugin)this).Config.SaveOnConfigSet = false; ShowCompass = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "ShowCompass", true, "Display the compass independently of the clock."); ShowClock = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "ShowClock", true, "Display the clock independently of the compass. Clock-only mode is supported."); TwelveHour = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "TwelveHourClock", false, "Use 12-hour time with am/pm."); VagueTime = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "VagueClock", false, "Show descriptions such as Early morning, Midday or Late night instead of exact time. Overrides TwelveHourClock when enabled."); CompassColour = ((BaseUnityPlugin)this).Config.Bind<string>("Display", "CompassColor", "#EBD9AD", "Compass text/marker colour: hex RGB or RGBA (#RGB, #RGBA, #RRGGBB, #RRGGBBAA), or a common name such as white, cyan, gold, amber or ivory. # is optional."); ClockColour = ((BaseUnityPlugin)this).Config.Bind<string>("Display", "ClockColor", "#EBD9AD", "Independent clock colour; accepts the same hex formats and colour names as CompassColor."); CameraHeading = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "CameraHeading", true, "Use camera direction; false uses character direction."); ConfigEntry<bool> val = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "ShowMapPins", true, "Show up to sixteen nearby saved map pins on the compass. Checked pins are omitted."); HudScale = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "Scale", 1f, new ConfigDescription("HUD scale.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 2f), new object[0])); TopOffset = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "TopOffset", 24f, new ConfigDescription("Distance below the top edge, in reference pixels.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 400f), new object[0])); ClockOffset = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "ClockOffset", 50f, new ConfigDescription("Clock distance below the compass in reference pixels. Smaller values move the clock up. Clock-only mode remains at the HUD origin.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(35f, 200f), new object[0])); AutoRemoveVisited = ((BaseUnityPlugin)this).Config.Bind<bool>("Waypoints", "AutoRemoveVisited", true, "Remove reached waypoints and renumber the remainder. False keeps reached markers on the map and guides you to the next unvisited waypoint."); EnableWaypoints = ((BaseUnityPlugin)this).Config.Bind<bool>("Waypoints", "Enabled", true, "Enable route controls and route map markers. Disable for a plain compass/clock. Automatic arrival also pauses while the compass is hidden."); ArrivalChime = ((BaseUnityPlugin)this).Config.Bind<bool>("Waypoints", "ArrivalChime", true, "Play a short chime when reaching the next waypoint."); ArrivalVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Waypoints", "ArrivalVolume", 0.5f, new ConfigDescription("Arrival chime volume.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), new object[0])); Radius = ((BaseUnityPlugin)this).Config.Bind<float>("Waypoints", "ArrivalRadius", 10f, new ConfigDescription("Horizontal arrival distance in metres.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 100f), new object[0])); HeightTolerance = ((BaseUnityPlugin)this).Config.Bind<float>("Waypoints", "HeightTolerance", 15f, new ConfigDescription("Vertical tolerance for terrain/feet placements. Map placements use horizontal distance.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), new object[0])); Diagnostics = ((BaseUnityPlugin)this).Config.Bind<bool>("Diagnostics", "DetailedLogging", true, "Extra diagnostic logging for this test release. User-facing messages always log."); Markers = new MarkerSettings(((BaseUnityPlugin)this).Config, CompassColour.Value, val.Value); ((BaseUnityPlugin)this).Config.Remove(((ConfigEntryBase)val).Definition); MarkerSettings.RemoveObsoleteSettings(((BaseUnityPlugin)this).Config); ((BaseUnityPlugin)this).Config.Save(); ((BaseUnityPlugin)this).Config.SaveOnConfigSet = true; Tracker = new ObjectTracker(this); ObjectMap = new ObjectMapView(this); View = new Display(this); ((BaseUnityPlugin)this).Config.SettingChanged += delegate { SettingsChanged(); }; harmony = new Harmony("au.tyvalheim.compasswaypointsclock"); harmony.PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Compass Waypoints and Clock 0.1.8 ready; diagnostics=" + Diagnostics.Value)); if (Chainloader.PluginInfos.ContainsKey("neobotics.valheim_mod.hudcompass") || Chainloader.PluginInfos.ContainsKey("aedenthorn.ClockMod")) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"HUDCompass or Clock Mod is also loaded. Disable duplicate HUD elements or remove the replaced mod for testing."); } } internal void SettingsChanged() { if (View != null) { View.Invalidate(); } SavedPinStyle.RequestRefresh(Minimap.instance); } private void Update() { //IL_0075: 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_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00df: 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_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Invalid comparison between Unknown and I4 try { Session(); Tracker.Tick(); if (Engine == null || !Object.op_Implicit((Object)(object)Player.m_localPlayer) || displayFault) { View.Hide(); return; } Vector3 position; bool eligible; if (Active && Time.unscaledTime >= nextArrival) { nextArrival = Time.unscaledTime + 0.1f; Player localPlayer = Player.m_localPlayer; position = ((Component)localPlayer).transform.position; eligible = EnableWaypoints.Value && ShowCompass.Value && !((Character)localPlayer).IsDead() && !((Character)localPlayer).IsTeleporting() && !((Character)localPlayer).InCutscene() && (!Object.op_Implicit((Object)(object)Minimap.instance) || (int)Minimap.instance.m_mode != 2); if (havePosition) { Vector3 val = position - lastPosition; if (!(((Vector3)(ref val)).sqrMagnitude > 10000f)) { goto IL_00f6; } } eligible = false; goto IL_00f6; } goto IL_01b7; IL_00f6: havePosition = true; lastPosition = position; Waypoint waypoint = Engine.Arrive(position.x, position.y, position.z, Radius.Value, HeightTolerance.Value, Now, eligible, AutoRemoveVisited.Value); if (waypoint != null) { Commit(); Notice(waypoint.Name + " reached"); if (ArrivalChime.Value) { try { arrivalSound.Play(((Component)this).gameObject, ArrivalVolume.Value); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Arrival chime unavailable: " + ex.Message)); } } } goto IL_01b7; IL_01b7: View.Tick(); } catch (Exception ex2) { ((BaseUnityPlugin)this).Logger.LogError((object)("Update failed; HUD and navigation suspended until next session: " + ex2)); storageFault = true; displayFault = true; View.Hide(); } } private void Session() { Player localPlayer = Player.m_localPlayer; long num = ((Object.op_Implicit((Object)(object)localPlayer) && Object.op_Implicit((Object)(object)ZNet.instance)) ? ZNet.instance.GetWorldUID() : 0); long num2 = (Object.op_Implicit((Object)(object)localPlayer) ? localPlayer.GetPlayerID() : 0); if (num == world && num2 == character) { return; } View.Reset(); ObjectMap.Reset(); Tracker.Begin(num, num2); Engine = null; havePosition = false; storageFault = false; displayFault = false; world = num; character = num2; if (num == 0 || num2 == 0) { return; } path = Path.Combine(Paths.ConfigPath, "CompassWaypointsClock", num.ToString("X16") + "-" + num2.ToString("X16") + ".cwc"); try { string recovery; RouteDocument routeDocument = RouteStore.Load(path, num, num2, out recovery); routeDocument.Paused = false; Engine = new RouteEngine(routeDocument); savedRevision = Engine.Revision; Engine.ResetArrival(Now); if (recovery != null) { Notice(recovery); } if (Diagnostics.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("Session loaded: " + Engine.Document.Points.Count + " waypoints, " + Engine.Document.Plans.Count + " saved routes.")); } } catch (Exception ex) { Engine = new RouteEngine(new RouteDocument { World = num, Character = num2 }); storageFault = true; ((BaseUnityPlugin)this).Logger.LogError((object)ex); Notice("Route storage could not be loaded. Navigation disabled to protect saved routes; compass and clock remain available."); } } internal void Commit() { if (!Active || savedRevision == Engine.Revision) { return; } try { RouteStore.Save(path, Engine.Document); savedRevision = Engine.Revision; View.Invalidate(); if (Diagnostics.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("Route saved: revision " + savedRevision)); } } catch (Exception ex) { storageFault = true; ((BaseUnityPlugin)this).Logger.LogError((object)ex); Notice("Route save failed. Navigation suspended; previous file preserved. Check the log before restarting."); } } internal void Change(Func<bool> action, string message) { if (!Active) { return; } try { if (action()) { Commit(); if (!storageFault) { Notice(message); } } else { Notice("No change: check the selection, name or route limit."); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)ex); Notice("Could not change route. See the log for details."); } } internal void Add(Vector3 pos, bool checkHeight, string name) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) Change(() => Engine.Add(new Waypoint { X = pos.x, Y = pos.y, Z = pos.z, CheckHeight = checkHeight, Name = NavigationMath.Clean(name) }, Now), "Waypoint added: " + name); } internal void Notice(string text) { ((BaseUnityPlugin)this).Logger.LogInfo((object)text); if (View != null) { View.SetStatus(text); } if (Object.op_Implicit((Object)(object)Player.m_localPlayer)) { ((Character)Player.m_localPlayer).Message((MessageType)1, text, 0, (Sprite)null, false); } } private void OnDestroy() { arrivalSound.Dispose(); if (Tracker != null) { Tracker.End(); } if (ObjectMap != null) { ObjectMap.Reset(); } if (View != null) { View.Reset(); } MarkerSprites.Release(); if (harmony != null) { harmony.UnpatchSelf(); } if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } } private void LateUpdate() { if (ObjectMap == null) { return; } try { if (Engine != null && !displayFault) { ObjectMap.Draw(); } else { ObjectMap.Hide(); } } catch (Exception ex) { ObjectMap.Hide(); ((BaseUnityPlugin)this).Logger.LogError((object)("Object map rendering suspended: " + ex)); displayFault = true; } } } public sealed class Waypoint { public string Id = Guid.NewGuid().ToString("N"); public string Name = "Waypoint"; public float X; public float Y; public float Z; public bool CheckHeight = true; public bool Visited; public Waypoint Copy() { return (Waypoint)MemberwiseClone(); } } public sealed class SavedRoute { public string Name; public readonly List<Waypoint> Points = new List<Waypoint>(); } public sealed class RouteDocument { public long World; public long Character; public bool Paused; public readonly List<Waypoint> Points = new List<Waypoint>(); public readonly List<SavedRoute> Plans = new List<SavedRoute>(); } public static class NavigationMath { public static bool Finite(float n) { if (!float.IsNaN(n)) { return !float.IsInfinity(n); } return false; } public static float Bearing(float dx, float dz) { return (float)(Math.Atan2(dx, dz) * 180.0 / Math.PI + 360.0) % 360f; } public static float Delta(float bearing, float heading) { return ((bearing - heading + 540f) % 360f + 360f) % 360f - 180f; } public static float Distance(float dx, float dz) { return (float)Math.Sqrt((double)dx * (double)dx + (double)dz * (double)dz); } public static string Clean(string value) { if (value == null) { return ""; } List<char> list = new List<char>(); string text = value.Trim(); foreach (char c in text) { if (!char.IsControl(c) && c != '<' && c != '>' && !char.IsSurrogate(c) && list.Count < 48) { list.Add(c); } } return new string(list.ToArray()); } public static bool Valid(Waypoint p) { if (p != null && p.Id != null && p.Id.Length == 32 && IsId(p.Id) && p.Name != null && p.Name.Length <= 48 && p.Name == Clean(p.Name) && Finite(p.X) && Finite(p.Y) && Finite(p.Z) && Math.Abs(p.X) <= 50000f && Math.Abs(p.Y) <= 50000f) { return Math.Abs(p.Z) <= 50000f; } return false; } private static bool IsId(string s) { Guid result; return Guid.TryParseExact(s, "N", out result); } public static string Clock(float fraction, bool twelveHour) { if (!Finite(fraction)) { return "--:--"; } int num = ((int)Math.Floor(((double)fraction - Math.Floor(fraction)) * 1440.0) + 1440) % 1440; int num2 = num / 60; if (twelveHour) { return (num2 + 11) % 12 + 1 + ":" + (num % 60).ToString("00") + ((num2 < 12) ? " am" : " pm"); } return num2.ToString("00") + ":" + (num % 60).ToString("00"); } public static string VagueClock(float fraction) { if (!Finite(fraction)) { return "--"; } float num = (float)((double)fraction - Math.Floor(fraction)) * 24f; if (num >= 23f || num < 1f) { return "Midnight"; } if (num < 4f) { return "Late night"; } if (num < 7f) { return "Early morning"; } if (num < 10f) { return "Morning"; } if (num < 12f) { return "Late morning"; } if (num < 14f) { return "Midday"; } if (num < 17f) { return "Afternoon"; } if (num < 20f) { return "Evening"; } if (num < 22f) { return "Late evening"; } return "Night"; } } public sealed class RouteEngine { public const int MaxPoints = 128; public const int MaxPlans = 16; private readonly Stack<RouteDocument> undo = new Stack<RouteDocument>(); private double armedAt; private double insideSince = -1.0; private string tracking; public RouteDocument Document { get; private set; } public int Revision { get; private set; } public int ActiveIndex => Document.Points.FindIndex((Waypoint p) => !p.Visited); public string Label(int index) { return "Waypoint " + (index + 1); } public int FindNearest(float x, float z, float radius) { int result = -1; float num = radius; if (!NavigationMath.Finite(x) || !NavigationMath.Finite(z) || !NavigationMath.Finite(radius) || radius < 0f) { return result; } for (int i = 0; i < Document.Points.Count; i++) { Waypoint waypoint = Document.Points[i]; float num2 = NavigationMath.Distance(waypoint.X - x, waypoint.Z - z); if (num2 <= num) { num = num2; result = i; } } return result; } public RouteEngine(RouteDocument doc) { Validate(doc); Document = Clone(doc); } public static void Validate(RouteDocument doc) { if (doc == null || doc.World == 0 || doc.Character == 0 || doc.Plans.Count > 16) { throw new ArgumentException("Invalid route document"); } ValidatePoints(doc.Points); HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase); foreach (SavedRoute plan in doc.Plans) { if (plan == null || string.IsNullOrEmpty(plan.Name) || plan.Name != NavigationMath.Clean(plan.Name) || !hashSet.Add(plan.Name)) { throw new ArgumentException("Invalid saved route name"); } ValidatePoints(plan.Points); } } private static void ValidatePoints(List<Waypoint> points) { if (points.Count > 128) { throw new ArgumentException("Too many waypoints"); } HashSet<string> hashSet = new HashSet<string>(); foreach (Waypoint point in points) { if (!NavigationMath.Valid(point) || !hashSet.Add(point.Id)) { throw new ArgumentException("Invalid or duplicate waypoint"); } } } public static RouteDocument Clone(RouteDocument d) { RouteDocument routeDocument = new RouteDocument(); routeDocument.World = d.World; routeDocument.Character = d.Character; routeDocument.Paused = d.Paused; RouteDocument routeDocument2 = routeDocument; foreach (Waypoint point in d.Points) { routeDocument2.Points.Add(point.Copy()); } foreach (SavedRoute plan in d.Plans) { SavedRoute savedRoute = new SavedRoute(); savedRoute.Name = plan.Name; SavedRoute savedRoute2 = savedRoute; foreach (Waypoint point2 in plan.Points) { savedRoute2.Points.Add(point2.Copy()); } routeDocument2.Plans.Add(savedRoute2); } return routeDocument2; } private void Before(double now) { if (undo.Count == 20) { RouteDocument[] array = undo.ToArray(); undo.Clear(); for (int num = 18; num >= 0; num--) { undo.Push(array[num]); } } undo.Push(Clone(Document)); Revision++; ResetArrival(now); } public void ResetArrival(double now) { tracking = null; insideSince = -1.0; armedAt = now + 2.0; } public bool Add(Waypoint p, double now) { if (!NavigationMath.Valid(p) || Document.Points.Count >= 128 || Document.Points.Exists((Waypoint q) => q.Id == p.Id)) { return false; } Before(now); Document.Points.Add(p.Copy()); return true; } public bool Remove(int index, double now) { if (index < 0 || index >= Document.Points.Count) { return false; } Before(now); Document.Points.RemoveAt(index); return true; } public bool Move(int from, int to, double now) { if (from < 0 || to < 0 || from >= Document.Points.Count || to >= Do