Decompiled source of Hiking GPS v1.1.0
plugins\HikingGPS.dll
Decompiled 2 weeks ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security.Cryptography; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using PEAKLib.Core; using PEAKLib.Items; using PeakMapInteractive.Automation; using PeakMapInteractive.Capture; using PeakMapInteractive.Collect; using PeakMapInteractive.Export; using PeakMapInteractive.Minimap; using PeakMapInteractive.Pipeline; using PeakMapInteractive.Tracker; using Photon.Pun; using TMPro; using Unity.Collections; using Unity.Jobs; using UnityEngine; using UnityEngine.Rendering; using UnityEngine.Rendering.Universal; using UnityEngine.SceneManagement; using UnityEngine.UI; using Zorro.Core; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("HikingGPS")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.1.0.0")] [assembly: AssemblyInformationalVersion("1.1.0+6f245a30bbced66f5f3bf20cdca66255b36f5a0c")] [assembly: AssemblyProduct("HikingGPS")] [assembly: AssemblyTitle("HikingGPS")] [assembly: AssemblyVersion("1.1.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace PeakMapInteractive { [BepInPlugin("com.abra9987.hikinggps", "Hiking GPS", "1.1.0")] [BepInProcess("PEAK.exe")] public sealed class Plugin : BaseUnityPlugin { public const string Guid = "com.abra9987.hikinggps"; public const string Name = "Hiking GPS"; public const string Version = "1.1.0"; private Harmony _harmony; private float _nextHeldLog; private const string PeakLibItems = "com.github.PEAKModding.PEAKLib.Items"; private bool _itemTried; private bool _itemInDatabase; internal static Plugin Instance { get; private set; } internal static ManualLogSource Logger { get; private set; } internal static PluginConfig Settings { get; private set; } internal static string OutputDir { get; private set; } internal static bool HasPeakLib => Chainloader.PluginInfos.ContainsKey("com.github.PEAKModding.PEAKLib.Items"); private void Awake() { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Expected O, but got Unknown //IL_015a: Unknown result type (might be due to invalid IL or missing references) Instance = this; Logger = ((BaseUnityPlugin)this).Logger; Settings = new PluginConfig(((BaseUnityPlugin)this).Config); OutputDir = ResolveOutputDir(Settings.OutputDirectory.Value); Directory.CreateDirectory(OutputDir); if (Settings.AutoRun.Value) { _harmony = new Harmony("com.abra9987.hikinggps"); _harmony.PatchAll(typeof(Plugin).Assembly); Logger.LogWarning((object)"AutoRun is on: the game will be driven automatically."); } if (Settings.AutoRun.Value && Settings.QuietCapture.Value) { Application.runInBackground = true; AudioListener.volume = 0f; AudioListener.pause = true; Logger.LogInfo((object)"Quiet capture: audio muted, running in background."); } if (Settings.AutoRun.Value && Settings.MinimapEnabled.Value) { Logger.LogWarning((object)"AutoRun is on, so the minimap stays off: automation interrupts the character's spawn and is not safe to play under. Icons are still photographed if AutoBakeIcons is set — that needs the loaded level, not a working character."); } if (Settings.MinimapEnabled.Value && !Settings.AutoRun.Value && !Settings.TrackerAsItem.Value) { ((Component)this).gameObject.AddComponent<MinimapController>(); Logger.LogInfo((object)$"Minimap enabled (toggle: {Settings.MinimapToggleKey.Value})."); } Logger.LogInfo((object)"Hiking GPS 1.1.0 loaded."); Logger.LogInfo((object)("Output directory: " + OutputDir)); Logger.LogInfo((object)$"Automation: autoRun={Settings.AutoRun.Value}, quitWhenDone={Settings.QuitWhenDone.Value}"); } private void LogHeldItem() { //IL_00eb: 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_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014a: 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_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Unknown result type (might be due to invalid IL or missing references) //IL_0251: Unknown result type (might be due to invalid IL or missing references) //IL_0256: Unknown result type (might be due to invalid IL or missing references) //IL_0277: Unknown result type (might be due to invalid IL or missing references) //IL_027c: Unknown result type (might be due to invalid IL or missing references) //IL_029e: Unknown result type (might be due to invalid IL or missing references) //IL_02a3: Unknown result type (might be due to invalid IL or missing references) //IL_02c5: Unknown result type (might be due to invalid IL or missing references) //IL_02ca: 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_02f1: 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_0318: Unknown result type (might be due to invalid IL or missing references) //IL_031c: Unknown result type (might be due to invalid IL or missing references) //IL_0321: Unknown result type (might be due to invalid IL or missing references) //IL_0343: Unknown result type (might be due to invalid IL or missing references) //IL_0348: Unknown result type (might be due to invalid IL or missing references) //IL_036a: Unknown result type (might be due to invalid IL or missing references) //IL_036f: Unknown result type (might be due to invalid IL or missing references) //IL_0373: Unknown result type (might be due to invalid IL or missing references) //IL_0378: Unknown result type (might be due to invalid IL or missing references) if (Time.unscaledTime < _nextHeldLog) { return; } _nextHeldLog = Time.unscaledTime + 2f; Character localCharacter = Character.localCharacter; Item val = (((Object)(object)localCharacter == (Object)null || (Object)(object)localCharacter.data == (Object)null) ? null : localCharacter.data.currentItem); if (!((Object)(object)val == (Object)null)) { Transform val2 = val.transform.Find("Hand_L"); Transform val3 = val.transform.Find("Hand_R"); Rigidbody component = ((Component)val).GetComponent<Rigidbody>(); CharacterRefs refs = localCharacter.refs; ManualLogSource logger = Logger; string[] array = new string[32]; array[0] = $"Held: '{((Object)val).name}' mass {val.mass} rigMass {(((Object)(object)component == (Object)null) ? (-1f) : component.mass)} "; array[1] = "inertia "; Vector3 val4 = (((Object)(object)component == (Object)null) ? Vector3.zero : component.inertiaTensor); array[2] = ((Vector3)(ref val4)).ToString("F4"); array[3] = " com "; val4 = (((Object)(object)component == (Object)null) ? Vector3.zero : component.centerOfMass); array[4] = ((Vector3)(ref val4)).ToString("F3"); array[5] = " "; val4 = val.transform.lossyScale; array[6] = string.Format("scale {0} forceScale {1} ", ((Vector3)(ref val4)).ToString("F2"), val.forceScale); array[7] = "defaultPos "; array[8] = ((Vector3)(ref val.defaultPos)).ToString("F3"); array[9] = " defaultForward "; array[10] = ((Vector3)(ref val.defaultForward)).ToString("F2"); array[11] = " | Hand_L "; object obj; if (!((Object)(object)val2 == (Object)null)) { val4 = val2.localPosition; string text = ((Vector3)(ref val4)).ToString("F3"); val4 = val2.localEulerAngles; obj = text + " euler " + ((Vector3)(ref val4)).ToString("F1"); } else { obj = "missing"; } array[12] = (string)obj; array[13] = " | Hand_R "; object obj2; if (!((Object)(object)val3 == (Object)null)) { val4 = val3.localPosition; string text2 = ((Vector3)(ref val4)).ToString("F3"); val4 = val3.localEulerAngles; obj2 = text2 + " euler " + ((Vector3)(ref val4)).ToString("F1"); } else { obj2 = "missing"; } array[14] = (string)obj2; array[15] = " | item at "; val4 = val.transform.position; array[16] = ((Vector3)(ref val4)).ToString("F2"); array[17] = " fwd "; val4 = val.transform.forward; array[18] = ((Vector3)(ref val4)).ToString("F2"); array[19] = " anim item at "; val4 = refs.animationItemTransform.position; array[20] = ((Vector3)(ref val4)).ToString("F2"); array[21] = " fwd "; val4 = refs.animationItemTransform.forward; array[22] = ((Vector3)(ref val4)).ToString("F2"); array[23] = " | IK L "; val4 = refs.IKHandTargetLeft.position; array[24] = ((Vector3)(ref val4)).ToString("F2"); array[25] = " / "; Quaternion rotation = refs.IKHandTargetLeft.rotation; val4 = ((Quaternion)(ref rotation)).eulerAngles; array[26] = ((Vector3)(ref val4)).ToString("F0"); array[27] = " | IK R "; val4 = refs.IKHandTargetRight.position; array[28] = ((Vector3)(ref val4)).ToString("F2"); array[29] = " / "; rotation = refs.IKHandTargetRight.rotation; val4 = ((Quaternion)(ref rotation)).eulerAngles; array[30] = ((Vector3)(ref val4)).ToString("F0"); array[31] = " "; logger.LogInfo((object)string.Concat(array)); } } private void SpawnDeviceInHand() { //IL_0070: 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) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) Character localCharacter = Character.localCharacter; if ((Object)(object)localCharacter == (Object)null) { Logger.LogWarning((object)"Spawn: there is no local character yet."); return; } string text = Settings.SpawnItemName.Value?.Trim(); GameObject val; if (string.IsNullOrEmpty(text)) { if (!TrackerItem.Registered) { Logger.LogWarning((object)"Spawn: the item is not registered; is PEAKLib installed?"); return; } val = HandShot.Spawn(localCharacter); } else { try { val = PhotonNetwork.Instantiate("0_Items/" + text, localCharacter.Center + Vector3.up * 0.5f, Quaternion.identity, (byte)0, (object[])null); } catch (Exception ex) { Logger.LogWarning((object)("Spawn: could not spawn '" + text + "': " + ex.Message)); return; } } Item val2 = (((Object)(object)val == (Object)null) ? null : val.GetComponent<Item>()); if (!((Object)(object)val2 == (Object)null)) { val2.Interact(localCharacter); Logger.LogInfo((object)("Spawn: '" + ((Object)val2).name + "' handed over.")); } } private void Update() { //IL_006d: 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_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) if (Settings.AutoRun.Value && Settings.QuietCapture.Value && AudioListener.volume != 0f) { AudioListener.volume = 0f; } if (CaptureRunner.IsRunning) { return; } if (Settings.ExportMeshes.Value && !CaptureRunner.HasCompleted) { MeshPrimer.Tick(); } TryRegisterItem(); if (Input.GetKeyDown(Settings.ScreenshotKey.Value)) { Snapshot(); } if (Input.GetKeyDown(Settings.ReloadConfigKey.Value)) { ((BaseUnityPlugin)this).Config.Reload(); Logger.LogInfo((object)"Config reloaded from disk."); } if (Input.GetKeyDown(Settings.SpawnDeviceKey.Value)) { SpawnDeviceInHand(); } if ((int)Settings.SpawnDeviceKey.Value != 0) { LogHeldItem(); } if (Input.GetKeyDown(Settings.CaptureHotkey.Value)) { Logger.LogInfo((object)"Capture hotkey pressed."); Run(CaptureRunner.Run()); } else { if (!Settings.AutoRun.Value || !IsMapReady()) { return; } if (Settings.TrackerPreview.Value) { if (!TrackerRun.HasCompleted) { Logger.LogInfo((object)"AutoRun: map is ready, photographing the device."); Run(TrackerRun.Run()); } } else if (Settings.MinimapAutoBakeIcons.Value) { if (!IconRun.HasCompleted) { Logger.LogInfo((object)"AutoRun: map is ready, photographing icons."); Run(IconRun.Run()); } } else if (!CaptureRunner.HasCompleted) { Logger.LogInfo((object)"AutoRun: map is ready, starting capture."); Run(CaptureRunner.Run()); } } } private void TryRegisterItem() { if (!Settings.TrackerAsItem.Value) { return; } if (_itemTried && !_itemInDatabase && HasPeakLib) { try { _itemInDatabase = TrackerRegistration.EnsureInDatabase(); } catch (Exception arg) { _itemInDatabase = true; Logger.LogError((object)$"The navigator could not be added to the item database: {arg}"); } } if (_itemTried || (Object)(object)Shader.Find("W/Peak_Standard") == (Object)null) { return; } _itemTried = true; if (!HasPeakLib) { Logger.LogInfo((object)"PEAKLib is not installed, so the navigator stays a map in the corner rather than an item you can pick up. Nothing else is affected."); BuildMap(onDevice: false); return; } bool flag = false; try { flag = TrackerRegistration.Register(); if (!flag) { Logger.LogWarning((object)"The navigator could not be registered as an item."); } } catch (Exception arg2) { Logger.LogError((object)$"The navigator could not be registered as an item: {arg2}"); } BuildMap(flag); } private void BuildMap(bool onDevice) { //IL_006d: Unknown result type (might be due to invalid IL or missing references) if (Settings.MinimapEnabled.Value && !Settings.AutoRun.Value && !((Object)(object)((Component)this).gameObject.GetComponent<MinimapController>() != (Object)null)) { MinimapController.OnDevice = onDevice; ((Component)this).gameObject.AddComponent<MinimapController>(); if (onDevice) { TrackerObject.ShowMap(MinimapController.DeviceScreen); } Logger.LogInfo((object)(onDevice ? "The map is on the navigator's screen; find one in the luggage on the beach." : $"Minimap enabled (toggle: {Settings.MinimapToggleKey.Value}).")); } } private static bool IsMapReady() { if (LoadingScreenHandler.loading) { return false; } Character localCharacter = Character.localCharacter; if ((Object)(object)localCharacter == (Object)null) { return false; } if ((Object)(object)localCharacter.data == (Object)null) { return false; } if (localCharacter.data.passedOut || localCharacter.data.fullyPassedOut) { return false; } if (localCharacter.data.passedOutOnTheBeach > 0f) { return false; } MapHandler instance = Singleton<MapHandler>.Instance; if (instance?.segments != null && instance.segments.Length != 0) { MapSegment obj = instance.segments[0]; return (Object)(object)((obj != null) ? obj.segmentParent : null) != (Object)null; } return false; } private static void Snapshot() { try { string text = Path.Combine(OutputDir, "shots"); Directory.CreateDirectory(text); string text2 = Path.Combine(text, $"peak-{DateTime.Now:yyyyMMdd-HHmmss}.png"); ScreenCapture.CaptureScreenshot(text2); Logger.LogInfo((object)("Screenshot: " + text2)); } catch (Exception ex) { Logger.LogWarning((object)("Screenshot failed: " + ex.Message)); } } private void OnDestroy() { try { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } catch { } } private static string ResolveOutputDir(string configured) { if (!string.IsNullOrWhiteSpace(configured) && Path.IsPathRooted(configured)) { return configured; } string? directoryName = Path.GetDirectoryName(Application.dataPath); string path = (string.IsNullOrWhiteSpace(configured) ? "capture-output" : configured); return Path.GetFullPath(Path.Combine(directoryName, path)); } internal static Coroutine Run(IEnumerator routine) { return ((MonoBehaviour)Instance).StartCoroutine(routine); } } internal enum ScreenCorner { TopRight, TopLeft, BottomRight, BottomLeft } internal sealed class PluginConfig { public readonly ConfigEntry<string> OutputDirectory; public readonly ConfigEntry<bool> AutoRun; public readonly ConfigEntry<bool> QuitWhenDone; public readonly ConfigEntry<bool> QuietCapture; public readonly ConfigEntry<int> HeightResolution; public readonly ConfigEntry<int> AlbedoResolution; public readonly ConfigEntry<float> BoundsPadding; public readonly ConfigEntry<bool> WriteDiagnostics; public readonly ConfigEntry<bool> ExportMeshes; public readonly ConfigEntry<float> MeshMinSize; public readonly ConfigEntry<int> MeshTriangleBudget; public readonly ConfigEntry<int> MeshLodLevel; public readonly ConfigEntry<int> MeshOnlySegment; public readonly ConfigEntry<bool> MeshIncludeFoliage; public readonly ConfigEntry<KeyCode> CaptureHotkey; public readonly ConfigEntry<bool> MinimapEnabled; public readonly ConfigEntry<float> MinimapSize; public readonly ConfigEntry<ScreenCorner> MinimapCorner; public readonly ConfigEntry<float> MinimapMarginX; public readonly ConfigEntry<float> MinimapMarginY; public readonly ConfigEntry<string> MinimapPlayerColour; public readonly ConfigEntry<int> MinimapStartZoom; public readonly ConfigEntry<KeyCode> MinimapToggleKey; public readonly ConfigEntry<KeyCode> MinimapZoomInKey; public readonly ConfigEntry<KeyCode> MinimapZoomOutKey; public readonly ConfigEntry<KeyCode> MinimapAngleKey; public readonly ConfigEntry<float> MinimapCompassNeedleOffset; public readonly ConfigEntry<bool> MinimapIcons; public readonly ConfigEntry<float> MinimapMarkerSize; public readonly ConfigEntry<bool> MinimapDumpIcons; public readonly ConfigEntry<bool> MinimapAutoBakeIcons; public readonly ConfigEntry<KeyCode> MinimapBakeAllKey; public readonly ConfigEntry<KeyCode> ScreenshotKey; public readonly ConfigEntry<float> MinimapStartDelay; public readonly ConfigEntry<int> MinimapIconResolution; public readonly ConfigEntry<bool> TrackerPreview; public readonly ConfigEntry<float> SoundVolume; public readonly ConfigEntry<bool> TrackerAsItem; public readonly ConfigEntry<Rarity> TrackerRarity; public readonly ConfigEntry<SpawnPool> TrackerSpawnPools; public readonly ConfigEntry<float> TrackerScale; public readonly ConfigEntry<float> TrackerReadoutScale; public readonly ConfigEntry<float> TrackerArrowScale; public readonly ConfigEntry<float> TrackerMarkerScale; public readonly ConfigEntry<float> TrackerHoldX; public readonly ConfigEntry<float> TrackerHoldY; public readonly ConfigEntry<float> TrackerHoldZ; public readonly ConfigEntry<float> TrackerTilt; public readonly ConfigEntry<float> TrackerLuggageLift; public readonly ConfigEntry<float> TrackerLuggageTurn; public readonly ConfigEntry<float> TrackerLuggageAcross; public readonly ConfigEntry<float> TrackerLuggageAlong; public readonly ConfigEntry<float> TrackerOffsetUp; public readonly ConfigEntry<float> TrackerOffsetAway; public readonly ConfigEntry<float> TrackerGripAcross; public readonly ConfigEntry<float> TrackerGripBehind; public readonly ConfigEntry<float> TrackerGripHeight; public readonly ConfigEntry<float> TrackerGripAngleX; public readonly ConfigEntry<float> TrackerGripAngleY; public readonly ConfigEntry<float> TrackerGripAngleZ; public readonly ConfigEntry<KeyCode> ReloadConfigKey; public readonly ConfigEntry<KeyCode> SpawnDeviceKey; public readonly ConfigEntry<string> SpawnItemName; public PluginConfig(ConfigFile cfg) { //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Expected O, but got Unknown //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Expected O, but got Unknown //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Expected O, but got Unknown //IL_0273: Unknown result type (might be due to invalid IL or missing references) //IL_027d: 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_02fa: Unknown result type (might be due to invalid IL or missing references) //IL_0304: Expected O, but got Unknown //IL_03a7: Unknown result type (might be due to invalid IL or missing references) //IL_03b1: Expected O, but got Unknown //IL_03fc: Unknown result type (might be due to invalid IL or missing references) //IL_0406: Expected O, but got Unknown //IL_0435: Unknown result type (might be due to invalid IL or missing references) //IL_043f: Expected O, but got Unknown //IL_046b: Unknown result type (might be due to invalid IL or missing references) //IL_0475: Expected O, but got Unknown //IL_05e4: Unknown result type (might be due to invalid IL or missing references) //IL_05ee: Expected O, but got Unknown //IL_061d: Unknown result type (might be due to invalid IL or missing references) //IL_0627: Expected O, but got Unknown //IL_0656: Unknown result type (might be due to invalid IL or missing references) //IL_0660: Expected O, but got Unknown //IL_068f: Unknown result type (might be due to invalid IL or missing references) //IL_0699: Expected O, but got Unknown //IL_06c8: Unknown result type (might be due to invalid IL or missing references) //IL_06d2: Expected O, but got Unknown //IL_0701: Unknown result type (might be due to invalid IL or missing references) //IL_070b: Expected O, but got Unknown //IL_073a: Unknown result type (might be due to invalid IL or missing references) //IL_0744: Expected O, but got Unknown //IL_0773: Unknown result type (might be due to invalid IL or missing references) //IL_077d: Expected O, but got Unknown //IL_07ac: Unknown result type (might be due to invalid IL or missing references) //IL_07b6: Expected O, but got Unknown //IL_07e5: Unknown result type (might be due to invalid IL or missing references) //IL_07ef: Expected O, but got Unknown //IL_081e: Unknown result type (might be due to invalid IL or missing references) //IL_0828: Expected O, but got Unknown //IL_0857: Unknown result type (might be due to invalid IL or missing references) //IL_0861: Expected O, but got Unknown //IL_0890: Unknown result type (might be due to invalid IL or missing references) //IL_089a: Expected O, but got Unknown //IL_08c9: Unknown result type (might be due to invalid IL or missing references) //IL_08d3: Expected O, but got Unknown //IL_0902: Unknown result type (might be due to invalid IL or missing references) //IL_090c: Expected O, but got Unknown //IL_093b: Unknown result type (might be due to invalid IL or missing references) //IL_0945: Expected O, but got Unknown //IL_0974: Unknown result type (might be due to invalid IL or missing references) //IL_097e: Expected O, but got Unknown //IL_09ad: Unknown result type (might be due to invalid IL or missing references) //IL_09b7: Expected O, but got Unknown //IL_09e6: Unknown result type (might be due to invalid IL or missing references) //IL_09f0: Expected O, but got Unknown //IL_0a1f: Unknown result type (might be due to invalid IL or missing references) //IL_0a29: Expected O, but got Unknown CaptureHotkey = cfg.Bind<KeyCode>("Automation", "CaptureHotkey", (KeyCode)0, "Exports the whole mountain to disk when pressed. Unbound by default: it borrows the camera, hides scenery and writes hundreds of megabytes, none of which anybody wants from a stray keypress mid-climb. Bind it to F9 to use it."); OutputDirectory = cfg.Bind<string>("Output", "Directory", "capture-output", "Where snapshots are written. Relative paths resolve against the PEAK install folder."); AutoRun = cfg.Bind<bool>("Automation", "AutoRun", false, "Take the game over: go offline, start a solo run on its own, and capture or photograph without anybody at the keyboard. Off by default and it must stay that way — somebody who installs this mod to get a map is not expecting it to seize their session and quit the game. For developing the mod, not for playing it."); QuitWhenDone = cfg.Bind<bool>("Automation", "QuitWhenDone", false, "Quit the game once the automated work is finished. Only ever does anything under AutoRun, and off by default for the same reason AutoRun is."); QuietCapture = cfg.Bind<bool>("Automation", "QuietCapture", true, "During an automatic capture, mute the game and keep it running while unfocused, so a scheduled run does not interrupt whatever you are doing."); HeightResolution = cfg.Bind<int>("Capture", "HeightResolution", 1024, new ConfigDescription("Heightfield samples per axis. 1024 gives roughly one sample per metre on a typical segment and costs ~2 MB per segment.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(128, 4096), Array.Empty<object>())); AlbedoResolution = cfg.Bind<int>("Capture", "AlbedoResolution", 4096, new ConfigDescription("Orthophoto resolution per axis.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(512, 8192), Array.Empty<object>())); BoundsPadding = cfg.Bind<float>("Capture", "BoundsPadding", 25f, "Extra world units added around a segment's computed bounds, so geometry at the very edge is not clipped."); ExportMeshes = cfg.Bind<bool>("Mesh", "ExportMeshes", false, "Export the segment's real geometry, so caves and overhangs survive. A heightfield cannot represent them at all."); MeshMinSize = cfg.Bind<float>("Mesh", "MinSize", 10f, "Smallest world-space extent a loose mesh must have to be exported. Drops thousands of pebbles and keeps terrain and landmarks."); MeshTriangleBudget = cfg.Bind<int>("Mesh", "TriangleBudget", 2000000, "Triangles per segment. Largest objects are exported first, so a tight budget still yields the landmarks."); MeshLodLevel = cfg.Bind<int>("Mesh", "LodLevel", 0, "Which LOD to export: 0 is the detail the player sees up close. The coarsest level is what a game draws at a distance and looks like cheap low-poly when a map lets you zoom in on it."); MeshOnlySegment = cfg.Bind<int>("Mesh", "OnlySegment", -1, "Export geometry for this segment only (-1 for all). Set it while dialling one biome in: a full capture is six times the wait per iteration."); MeshIncludeFoliage = cfg.Bind<bool>("Mesh", "IncludeFoliage", false, "Include grass, vines and leaves. They are most of the triangle count and little of the map, but a faithful reproduction needs them."); MinimapEnabled = cfg.Bind<bool>("Minimap", "Enabled", true, "Show a live top-down view of the mountain in a corner of the screen, for seeing where you are and planning where to climb next."); MinimapSize = cfg.Bind<float>("Minimap", "SizePixels", 320f, new ConfigDescription("On-screen size of the map window.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(120f, 900f), Array.Empty<object>())); MinimapCorner = cfg.Bind<ScreenCorner>("Minimap", "Corner", ScreenCorner.TopRight, "Which corner of the screen the GPS hangs in. Dragging it with the mouse is not offered on purpose: during a run the cursor belongs to the game, and prising it away to move a window is a worse trade than picking a corner once. Both top corners are clear of PEAK's own HUD. The bottom two are not — at the default margin the GPS sits on the stamina bar on the left and on the item slots on the right — so raise MarginYPixels to about 95 or 115 to lift it off."); MinimapMarginX = cfg.Bind<float>("Minimap", "MarginXPixels", 14f, new ConfigDescription("How far in from the side of the screen.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 600f), Array.Empty<object>())); MinimapMarginY = cfg.Bind<float>("Minimap", "MarginYPixels", 14f, new ConfigDescription("How far in from the top or bottom of the screen. This is the one to raise if a bottom corner puts the GPS over the stamina bar or the item slots.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 600f), Array.Empty<object>())); MinimapPlayerColour = cfg.Bind<string>("Minimap", "PlayerMarkerColour", "#FF8C33", "The colour of the arrow that is you, as a hex value. Anything the game can read works: #RRGGBB, or #RRGGBBAA to make it see-through."); MinimapStartZoom = cfg.Bind<int>("Minimap", "StartZoomStep", 3, new ConfigDescription("Which zoom step the map opens on, counting the tightest as 1. The steps run 20, 29, 41, 58, 83, 119, 170, 243, 347, 496, 708, 1012, 1446 and 2000 metres across, and the zoom keys move one step at a time.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 14), Array.Empty<object>())); MinimapToggleKey = cfg.Bind<KeyCode>("Minimap", "ToggleKey", (KeyCode)109, "Shows or hides the map."); MinimapZoomInKey = cfg.Bind<KeyCode>("Minimap", "ZoomInKey", (KeyCode)61, "Zooms in."); MinimapZoomOutKey = cfg.Bind<KeyCode>("Minimap", "ZoomOutKey", (KeyCode)45, "Zooms out."); MinimapAngleKey = cfg.Bind<KeyCode>("Minimap", "AngleKey", (KeyCode)110, "Cycles the viewing angle: straight down, 75 degrees, 45 degrees. A tilted view shows how much climbing lies between you and somewhere, which looking straight down flattens away."); MinimapCompassNeedleOffset = cfg.Bind<float>("Minimap", "CompassNeedleOffset", 45f, new ConfigDescription("Which way the needle already points in the compass artwork, in degrees clockwise from up. The whole icon is rotated to aim that needle, so this is what stops it pointing off by a fixed amount.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-180f, 180f), Array.Empty<object>())); MinimapIcons = cfg.Bind<bool>("Minimap", "Icons", true, "Draw markers as pictures of the thing rather than as coloured dots. The picture is photographed from the model already loaded in the game, once per kind of thing, so nothing of PEAK's is copied and nothing is shipped. Turn off to go back to plain markers."); MinimapMarkerSize = cfg.Bind<float>("Minimap", "MarkerSizePixels", 26f, new ConfigDescription("How large a marker is drawn. Markers still grow and shrink around this figure with how far above or below you the thing sits. Large enough that the picture inside is recognisable is the whole constraint.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(8f, 48f), Array.Empty<object>())); MinimapStartDelay = cfg.Bind<float>("Minimap", "StartDelaySeconds", 10f, new ConfigDescription("How long after the mountain finishes loading before the map opens and icons are photographed. The run begins with the character lying on the beach with their eyes shut while the world is still being assembled, and an icon is baked once and kept, so one taken too early stays wrong for the rest of the run.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 120f), Array.Empty<object>())); MinimapIconResolution = cfg.Bind<int>("Minimap", "IconResolutionPixels", 384, new ConfigDescription("How many pixels across each marker icon is photographed at, before it is trimmed to the object. The marker itself is drawn far smaller, so this buys detail in the mipmaps rather than on screen — which is what stops a suitcase turning to mush at map size.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(64, 1024), Array.Empty<object>())); ScreenshotKey = cfg.Bind<KeyCode>("Debug", "ScreenshotKey", (KeyCode)0, "Saves a full-resolution screenshot to a 'shots' folder in the output directory. Unbound, because it exists to photograph the map while working on the mod, and a player already has Steam, the graphics driver and Windows itself for screenshots — three keys that do it better than a fourth would. Set a key here if you are working on the mod."); ReloadConfigKey = cfg.Bind<KeyCode>("Debug", "ReloadConfigKey", (KeyCode)0, "Re-reads this file while the game is running, so a setting can be tried without restarting. Unbound: it exists for tuning the mod, not for playing it. Only the settings that act on their own change take effect at once — the grip points do; keys and sizes are read every frame anyway."); SpawnDeviceKey = cfg.Bind<KeyCode>("Debug", "SpawnDeviceKey", (KeyCode)0, "Puts a navigator straight into your hands, wherever you are — the airport included, where the mirror shows how it is held. Unbound: it is for working on the grip, and a player is meant to find the thing in a suitcase. Needs PEAKLib, like the item itself."); SpawnItemName = cfg.Bind<string>("Debug", "SpawnItemName", "", "What SpawnDeviceKey hands over. Empty for the navigator; otherwise the name of one of the game's own items, such as Compass or Passport, so the two can be held one after the other in front of the airport mirror and compared."); MinimapBakeAllKey = cfg.Bind<KeyCode>("Minimap", "BakeAllKey", (KeyCode)0, "Photographs every kind of thing anywhere on the loaded mountain at once, rather than waiting to walk past one of each. Unbound: it is meant for working on the icons, where the nearest statue can be five minutes of climbing away, and it is a lot of work to set off by leaning on a key mid-climb. Playing needs none of it — an icon is photographed the first time you see that kind of thing anyway."); MinimapAutoBakeIcons = cfg.Bind<bool>("Minimap", "AutoBakeIcons", false, "With AutoRun on, walk the game into a solo run, photograph every marker icon on the mountain and quit, with nobody at the keyboard. Replaces the map capture for that run. For working on the icons: judging one only needs the PNG, and making one only needs a loaded level."); MinimapDumpIcons = cfg.Bind<bool>("Debug", "DumpIcons", false, "Write every baked marker icon to an 'icons' folder in the output directory, as a PNG. The only way to judge whether an icon reads as what it is without squinting at it twenty pixels across in the corner of the screen."); SoundVolume = cfg.Bind<float>("Sound", "Volume", 0.7f, "How loud the device is: the chirp as it wakes, the click of its buttons, and the dull knock when the zoom will go no further. Set to 0 for a silent map. The clicks are deliberately quieter than the chirps, because a climb involves a great many more of them."); TrackerAsItem = cfg.Bind<bool>("Tracker", "AsItem", true, "Put the navigator in the world as a real item: found in luggage, carried in both hands, droppable and shareable. Needs PEAKLib installed; with it absent this does nothing and the map still works from the corner of the screen, which is why the dependency is a soft one."); TrackerRarity = cfg.Bind<Rarity>("Tracker", "Rarity", (Rarity)2, "How often the navigator turns up in the luggage it can appear in. The game's own scale, from Common to RidiculouslyRare. Rare by default: a map should be a find rather than a fixture, and a party only needs one."); TrackerSpawnPools = cfg.Bind<SpawnPool>("Tracker", "SpawnPools", (SpawnPool)1024, "Which luggage it can be found in, from the game's own list — several can be combined with commas. The beach by default, because a map is worth most before the climb rather than after it: a navigator found in the Citadel is a souvenir."); TrackerScale = cfg.Bind<float>("Tracker", "Scale", 4f, new ConfigDescription("How large the navigator is, as a multiple of its real size. It is drawn at 90 by 120 millimetres, which is what a handheld unit measures and is also small in a pair of hands — a map on it is legible, a line of numbers under the map less so. Raising this trades the honest scale for a screen you can read at a glance. The case, its collision and the grip points all scale together, so the hands keep hold of it. Held in the game it reads as far smaller than its measurements suggest, because PEAK's characters have enormous hands and every prop is drawn to match them rather than to scale. Four was settled by holding it.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 6f), Array.Empty<object>())); TrackerReadoutScale = cfg.Bind<float>("Tracker", "ReadoutScale", 1f, new ConfigDescription("How large the line of numbers under the map is, as a multiple. The strip and the lettering in it grow together, and both take the space from the map. Separate from Scale because they are different trades: one makes the whole device bigger in the world, this one gives the numbers more of a device that is already the size it should be.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 3f), Array.Empty<object>())); TrackerArrowScale = cfg.Bind<float>("Tracker", "ArrowScale", 3f, new ConfigDescription("How large the arrow showing where you are is on the device's screen, as a multiple. It was drawn for a map pinned to a corner of the screen at full resolution; on a device the same picture arrives much smaller, and the one marker anybody looks for first vanished into the terrain.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 8f), Array.Empty<object>())); TrackerHoldX = cfg.Bind<float>("Tracker", "HoldX", 0f, new ConfigDescription("Where the device is held, to the right of the head, in metres.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-1f, 1f), Array.Empty<object>())); TrackerHoldY = cfg.Bind<float>("Tracker", "HoldY", -0.25f, new ConfigDescription("Where the device is held, above the head, in metres. Negative is below.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-1.5f, 1f), Array.Empty<object>())); TrackerHoldZ = cfg.Bind<float>("Tracker", "HoldZ", 0.85f, new ConfigDescription("Where the device is held, in front of the head, in metres. Zero is inside the head, which is what an item gets when nobody says otherwise.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1.5f), Array.Empty<object>())); TrackerLuggageLift = cfg.Bind<float>("Tracker", "LuggageLift", 0.06f, new ConfigDescription("How far above the suitcase's spawn spots the device is laid, in metres, so it rests on the floor of the case rather than through it.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-0.2f, 0.4f), Array.Empty<object>())); TrackerLuggageTurn = cfg.Bind<float>("Tracker", "LuggageTurn", 0f, new ConfigDescription("Which way the antenna points when the device is laid in a suitcase, in degrees about the vertical. 0 and 180 lie across the case, 90 and -90 along it.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-180f, 180f), Array.Empty<object>())); TrackerLuggageAcross = cfg.Bind<float>("Tracker", "LuggageAcross", 0f, new ConfigDescription("How far across the suitcase, from the middle of its spawn spots, the device is laid, in metres. Positive is towards the case's own +Z.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-0.5f, 0.5f), Array.Empty<object>())); TrackerLuggageAlong = cfg.Bind<float>("Tracker", "LuggageAlong", 0f, new ConfigDescription("How far along the suitcase, from the middle of its spawn spots, the device is laid, in metres.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-0.5f, 0.5f), Array.Empty<object>())); TrackerTilt = cfg.Bind<float>("Tracker", "TiltDegrees", 10f, new ConfigDescription("How far the top of the device leans back towards the face, in degrees. Zero holds it square to the line of sight; a phone in real hands is tipped ten or fifteen degrees so the screen faces the eyes.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-45f, 45f), Array.Empty<object>())); TrackerOffsetUp = cfg.Bind<float>("Tracker", "OffsetUp", 0f, new ConfigDescription("How far above the held position the device sits, in metres at Scale 1. The game's compass rides 0.15 above its own. Negative is below.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-0.3f, 0.3f), Array.Empty<object>())); TrackerOffsetAway = cfg.Bind<float>("Tracker", "OffsetAway", 0f, new ConfigDescription("How far from the face the device sits, in metres at Scale 1, beyond where the game holds it. Positive pushes it away, negative pulls it in.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-0.3f, 0.3f), Array.Empty<object>())); TrackerGripAcross = cfg.Bind<float>("Tracker", "GripAcross", 0.05f, new ConfigDescription("How far each hand sits from the centre of the device, sideways, in metres at Scale 1. The case is 0.045 wide from the centre to its edge, so 0.045 puts the palms on its sides and more than that holds it from outside. Multiplied by Scale along with the case, so at Scale 3 a centimetre here moves a hand three.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.2f), Array.Empty<object>())); TrackerGripBehind = cfg.Bind<float>("Tracker", "GripBehind", -0.033f, new ConfigDescription("How far behind the middle of the case the hands sit, in metres at Scale 1. Positive is towards the back cover, negative towards the glass. Too far back and the hands meet behind the device holding nothing.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-0.1f, 0.1f), Array.Empty<object>())); TrackerGripHeight = cfg.Bind<float>("Tracker", "GripHeight", -0.012f, new ConfigDescription("How far up the device the hands sit, in metres at Scale 1, from the model's origin. The case is 0.12 tall; low is how a handheld is held, with the thumbs near the buttons.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-0.15f, 0.15f), Array.Empty<object>())); TrackerGripAngleX = cfg.Bind<float>("Tracker", "GripAngleX", 270f, new ConfigDescription("Left hand rotation about the item's sideways axis, in degrees. 270 is what every two-handed item in the game uses. The right hand mirrors it.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 360f), Array.Empty<object>())); TrackerGripAngleY = cfg.Bind<float>("Tracker", "GripAngleY", 202f, new ConfigDescription("Left hand rotation about the vertical, in degrees. 180 is two parallel hands; above it the fingers turn in towards each other. The passport uses 202, bottles 195. The right hand takes the opposite angle.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 360f), Array.Empty<object>())); TrackerGripAngleZ = cfg.Bind<float>("Tracker", "GripAngleZ", 0f, new ConfigDescription("Left hand rotation about the item's forward axis, in degrees: the roll of the wrist. Zero for the passport and the bottles, 45 for the compass. The right hand takes the opposite angle.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 360f), Array.Empty<object>())); TrackerMarkerScale = cfg.Bind<float>("Tracker", "MarkerScale", 2f, new ConfigDescription("How large the chest and creature markers are on the device's screen, as a multiple of Minimap/MarkerSizePixels. The same reason as ArrowScale: the markers were sized for a map in a corner at full resolution, and on a screen seen at a fraction of that the round plates shrank to dots.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 5f), Array.Empty<object>())); TrackerPreview = cfg.Bind<bool>("Tracker", "PreviewModel", false, "With AutoRun on, stand the 3D device in front of the camera, photograph it from four sides into a 'tracker' folder, and quit. Replaces the other automated work for that run. For building the device: every way the model can arrive wrong — inside out, wrongly coloured, facing backwards — is invisible in the code and obvious in a photograph."); WriteDiagnostics = cfg.Bind<bool>("Debug", "WriteDiagnostics", false, "Write an extra diagnostics.json listing every component type seen while collecting markers. Useful when the game adds content the registry does not know."); } } public static class MyPluginInfo { public const string PLUGIN_GUID = "HikingGPS"; public const string PLUGIN_NAME = "HikingGPS"; public const string PLUGIN_VERSION = "1.1.0"; } } namespace PeakMapInteractive.Tracker { internal static class Sounds { private static readonly Dictionary<string, AudioClip> _clips = new Dictionary<string, AudioClip>(); private static AudioSource _source; private static int _nextClick; private static float Volume => Mathf.Clamp01(Plugin.Settings.SoundVolume.Value); private static AudioSource Source() { if (Volume <= 0f) { return null; } if ((Object)(object)_source != (Object)null) { return _source; } Plugin instance = Plugin.Instance; if ((Object)(object)instance == (Object)null) { return null; } _source = ((Component)instance).gameObject.AddComponent<AudioSource>(); _source.playOnAwake = false; _source.loop = false; _source.spatialBlend = 0f; return _source; } internal static void PowerOn() { Play("power_on"); } internal static void PowerOff() { Play("power_off"); } internal static void Click() { Play((_nextClick == 0) ? "click_a" : ((_nextClick == 1) ? "click_b" : "click_c")); _nextClick = (_nextClick + 1) % 3; } internal static void ZoomLimit() { Play("zoom_limit"); } internal static void Verify() { string[] array = new string[6] { "power_on", "power_off", "click_a", "click_b", "click_c", "zoom_limit" }; foreach (string text in array) { AudioClip val = Load(text); if ((Object)(object)val == (Object)null) { Plugin.Logger.LogWarning((object)("Sounds: '" + text + "' did not load.")); } else { Plugin.Logger.LogInfo((object)($"Sounds: {text} {val.length * 1000f:0} ms, " + $"{val.channels} ch, {val.frequency} Hz, {val.samples} samples.")); } } } private static void Play(string name) { AudioSource val = Source(); if (!((Object)(object)val == (Object)null)) { AudioClip val2 = Load(name); if (!((Object)(object)val2 == (Object)null)) { val.PlayOneShot(val2, Volume); } } } private static AudioClip Load(string name) { if (_clips.TryGetValue(name, out var value)) { return value; } _clips[name] = null; byte[] array = Resource(name + ".wav"); if (array == null) { Plugin.Logger.LogWarning((object)("Sounds: '" + name + ".wav' is not in the assembly.")); return null; } try { _clips[name] = Decode(name, array); } catch (Exception ex) { Plugin.Logger.LogWarning((object)("Sounds: '" + name + ".wav' would not decode — " + ex.Message)); } return _clips[name]; } private static AudioClip Decode(string name, byte[] wav) { using MemoryStream memoryStream = new MemoryStream(wav, writable: false); using BinaryReader binaryReader = new BinaryReader(memoryStream); if (Encoding.ASCII.GetString(binaryReader.ReadBytes(4)) != "RIFF") { throw new IOException("not a RIFF file"); } binaryReader.ReadInt32(); if (Encoding.ASCII.GetString(binaryReader.ReadBytes(4)) != "WAVE") { throw new IOException("not a WAVE file"); } int num = 0; int num2 = 0; int num3 = 0; byte[] array = null; while (memoryStream.Position + 8 <= memoryStream.Length) { string text = Encoding.ASCII.GetString(binaryReader.ReadBytes(4)); int num4 = binaryReader.ReadInt32(); if (text == "fmt ") { int num5 = binaryReader.ReadInt16(); num = binaryReader.ReadInt16(); num2 = binaryReader.ReadInt32(); binaryReader.ReadInt32(); binaryReader.ReadInt16(); num3 = binaryReader.ReadInt16(); if (num5 != 1) { throw new IOException($"format {num5} is not plain PCM"); } memoryStream.Position += num4 - 16 + (num4 & 1); } else if (text == "data") { array = binaryReader.ReadBytes(num4); memoryStream.Position += num4 & 1; } else { memoryStream.Position += num4 + (num4 & 1); } } if (array == null) { throw new IOException("no data chunk"); } if (num3 != 16) { throw new IOException($"{num3}-bit samples; 16 expected"); } int num6 = array.Length / 2; float[] array2 = new float[num6]; for (int i = 0; i < num6; i++) { array2[i] = (float)(short)(array[i * 2] | (array[i * 2 + 1] << 8)) / 32768f; } AudioClip obj = AudioClip.Create("HikingGPS_" + name, num6 / num, num, num2, false); obj.SetData(array2, 0); return obj; } private static byte[] Resource(string name) { Assembly assembly = typeof(Sounds).Assembly; string[] manifestResourceNames = assembly.GetManifestResourceNames(); foreach (string text in manifestResourceNames) { if (!text.EndsWith(name, StringComparison.OrdinalIgnoreCase)) { continue; } using Stream stream = assembly.GetManifestResourceStream(text); if (stream == null) { return null; } byte[] array = new byte[stream.Length]; int num; for (int j = 0; j < array.Length; j += num) { num = stream.Read(array, j, array.Length - j); if (num <= 0) { break; } } return array; } return null; } } internal sealed class TrackerDevice : MonoBehaviour { private const float Travel = 0.0006f; private const float Hold = 0.09f; private const float Rise = 14f; private static readonly string[] Names = new string[3] { "Tracker_Button_L", "Tracker_Button_M", "Tracker_Button_R" }; private static readonly List<TrackerDevice> All = new List<TrackerDevice>(); private readonly Transform[] _buttons = (Transform[])(object)new Transform[3]; private readonly Vector3[] _rest = (Vector3[])(object)new Vector3[3]; private readonly float[] _pressedUntil = new float[3]; private readonly float[] _depth = new float[3]; private Material _screen; private Item _item; private bool _live; private Texture _shown; private bool _placed; private Transform _model; private bool _flippedForBackpack; private void Awake() { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < Names.Length; i++) { _buttons[i] = Find(((Component)this).transform, Names[i]); if ((Object)(object)_buttons[i] != (Object)null) { _rest[i] = _buttons[i].localPosition; } } Transform val = Find(((Component)this).transform, "Tracker_Screen"); Renderer val2 = (((Object)(object)val == (Object)null) ? null : ((Component)val).GetComponent<Renderer>()); if ((Object)(object)val2 != (Object)null) { _screen = val2.material; TrackerObject.SetTexture(_screen, null); TrackerObject.SetColour(_screen, TrackerObject.ScreenOff); } All.Add(this); } private bool Held() { Character localCharacter = Character.localCharacter; if ((Object)(object)localCharacter == (Object)null || (Object)(object)localCharacter.data == (Object)null) { return true; } if ((Object)(object)_item == (Object)null) { _item = ((Component)this).GetComponentInParent<Item>(); } if ((Object)(object)_item != (Object)null) { return (Object)(object)localCharacter.data.currentItem == (Object)(object)_item; } return false; } private void UpdateScreen() { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_screen == (Object)null)) { bool flag = Held(); Texture val = (flag ? TrackerObject.Map : null); if (flag != _live || !((Object)(object)val == (Object)(object)_shown)) { _live = flag; _shown = val; TrackerObject.SetTexture(_screen, val); TrackerObject.SetColour(_screen, ((Object)(object)val != (Object)null) ? Color.white : TrackerObject.ScreenOff); } } } private void OnDestroy() { All.Remove(this); } private void Start() { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) Rigidbody componentInParent = ((Component)this).GetComponentInParent<Rigidbody>(); if (!((Object)(object)componentInParent == (Object)null)) { float num = Mathf.Clamp(Plugin.Settings.TrackerScale.Value, 0.5f, 6f); Vector3 centerOfMass = (componentInParent.centerOfMass = new Vector3(0f, 0.03f, 0.015f) * num + TrackerItem.ModelOffset); componentInParent.sleepThreshold = 0f; Item componentInParent2 = ((Component)this).GetComponentInParent<Item>(); if ((Object)(object)componentInParent2 != (Object)null) { componentInParent2.centerOfMass = centerOfMass; } } } private void PlaceInLuggage() { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Unknown result type (might be due to invalid IL or missing references) //IL_023b: Unknown result type (might be due to invalid IL or missing references) //IL_0240: Unknown result type (might be due to invalid IL or missing references) //IL_0245: Unknown result type (might be due to invalid IL or missing references) //IL_024d: Unknown result type (might be due to invalid IL or missing references) //IL_024f: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_027b: Unknown result type (might be due to invalid IL or missing references) //IL_0280: Unknown result type (might be due to invalid IL or missing references) //IL_028d: Unknown result type (might be due to invalid IL or missing references) //IL_028f: Unknown result type (might be due to invalid IL or missing references) //IL_02a1: 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_02ca: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011a: 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_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) if (_placed) { return; } if ((Object)(object)_item == (Object)null) { _item = ((Component)this).GetComponentInParent<Item>(); } if ((Object)(object)_item == (Object)null || (Object)(object)_item.rig == (Object)null || (int)_item.itemState != 0 || !_item.rig.isKinematic) { return; } _placed = true; Luggage val = null; Vector3 val2 = Vector3.zero; float num = 0.8f; foreach (Luggage item in Luggage.ALL_LUGGAGE) { if ((Object)(object)item == (Object)null) { continue; } List<List<Transform>> list = new List<List<Transform>>(); if (((Spawner)item).spawnSpots != null) { list.Add(((Spawner)item).spawnSpots); } if (((Spawner)item).weightedSpawnSpots != null) { foreach (WeightedSpawnPointEntry weightedSpawnSpot in ((Spawner)item).weightedSpawnSpots) { if (weightedSpawnSpot != null && weightedSpawnSpot.spawnSpots != null) { list.Add(weightedSpawnSpot.spawnSpots); } } } Vector3 val3 = Vector3.zero; int num2 = 0; float num3 = float.MaxValue; foreach (List<Transform> item2 in list) { foreach (Transform item3 in item2) { if (!((Object)(object)item3 == (Object)null)) { val3 += ((Component)item).transform.InverseTransformPoint(item3.position); num2++; num3 = Mathf.Min(num3, Vector3.Distance(item3.position, _item.transform.position)); } } } if (num2 != 0 && !(num3 >= num)) { num = num3; val = item; val2 = val3 / (float)num2; } } if (!((Object)(object)val == (Object)null)) { PluginConfig settings = Plugin.Settings; Vector3 val4 = val2 + new Vector3(settings.TrackerLuggageAlong.Value, settings.TrackerLuggageLift.Value, settings.TrackerLuggageAcross.Value); Vector3 val5 = ((Component)val).transform.TransformPoint(val4); Quaternion val6 = ((Component)val).transform.rotation * Quaternion.Euler(90f, settings.TrackerLuggageTurn.Value, 0f); _item.transform.SetPositionAndRotation(val5, val6); _item.rig.position = val5; _item.rig.rotation = val6; Plugin.Logger.LogInfo((object)$"Tracker: laid in '{((Object)val).name}' at local {val4:F3}, turn {settings.TrackerLuggageTurn.Value:0}."); } } private void FaceOutOnBackpack() { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Invalid comparison between Unknown and I4 //IL_0080: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_item == (Object)null) { _item = ((Component)this).GetComponentInParent<Item>(); } if ((Object)(object)_item == (Object)null) { return; } if ((Object)(object)_model == (Object)null) { _model = ((Component)this).transform.Find("Model") ?? ((Component)this).transform; } bool flag = (int)_item.itemState == 2; if (flag != _flippedForBackpack) { _flippedForBackpack = flag; if (flag) { _model.localRotation = Quaternion.identity; } else { TrackerItem.PlaceModel(_model); } } } private void Update() { //IL_0086: 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_00a8: Unknown result type (might be due to invalid IL or missing references) UpdateScreen(); PlaceInLuggage(); FaceOutOnBackpack(); for (int i = 0; i < _buttons.Length; i++) { if (!((Object)(object)_buttons[i] == (Object)null)) { float num = ((Time.unscaledTime < _pressedUntil[i]) ? 1f : 0f); _depth[i] = ((num > _depth[i]) ? num : Mathf.MoveTowards(_depth[i], num, 14f * Time.unscaledDeltaTime)); _buttons[i].localPosition = _rest[i] + new Vector3(0f, 0f, -0.0006f * _depth[i]); } } } internal static void PressAll(int index) { if (index < 0 || index >= Names.Length) { return; } foreach (TrackerDevice item in All) { if (!((Object)(object)item == (Object)null) && item._live) { item._pressedUntil[index] = Time.unscaledTime + 0.09f; } } } private static Transform Find(Transform root, string name) { Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren<Transform>(true); foreach (Transform val in componentsInChildren) { if (((Object)val).name == name) { return val; } } return null; } } internal static class TrackerItem { internal const string ItemName = "Hiking GPS"; private const float Mass = 1.2f; internal static GameObject Prefab { get; private set; } internal static bool Registered => (Object)(object)Prefab != (Object)null; private static float GripAcross => Plugin.Settings.TrackerGripAcross.Value; private static float GripBehind => Plugin.Settings.TrackerGripBehind.Value; private static float GripHeight => Plugin.Settings.TrackerGripHeight.Value; private static float GripAngleX => Plugin.Settings.TrackerGripAngleX.Value; private static float GripAngleY => Plugin.Settings.TrackerGripAngleY.Value; private static float GripAngleZ => Plugin.Settings.TrackerGripAngleZ.Value; internal static Vector3 ModelOffset { get { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Clamp(Plugin.Settings.TrackerScale.Value, 0.5f, 6f); return new Vector3(0f, Plugin.Settings.TrackerOffsetUp.Value, Plugin.Settings.TrackerOffsetAway.Value) * num; } } private static Vector3 HoldPos => new Vector3(Plugin.Settings.TrackerHoldX.Value, Plugin.Settings.TrackerHoldY.Value, Plugin.Settings.TrackerHoldZ.Value); internal static bool Register() { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_0052: 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_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: 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_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Expected O, but got Unknown if (Registered) { return true; } GameObject val = TrackerObject.Build("Model"); if ((Object)(object)val == (Object)null) { return false; } GameObject val2 = new GameObject("Hiking_GPS"); val.transform.SetParent(val2.transform, false); val.transform.localRotation = Quaternion.Euler(0f, 180f, 0f); Object.DontDestroyOnLoad((Object)(object)val2); val2.SetActive(false); float num = Mathf.Clamp(Plugin.Settings.TrackerScale.Value, 0.5f, 6f); val.transform.localScale = Vector3.one * num; PlaceModel(val.transform); AddGrips(val2.transform); PhotonView obj = val2.AddComponent<PhotonView>(); obj.ObservedComponents = new List<Component>(); obj.Synchronization = (ViewSynchronization)0; Item obj2 = val2.AddComponent<Item>(); obj2.mass = 1.2f; obj2.defaultPos = HoldPos; LayInLuggage(obj2); obj2.forceScale = true; obj2.UIData = new ItemUIData { itemName = "Hiking GPS", icon = Icon(), hasMainInteract = true, mainInteractPrompt = "Pick up", hasSecondInteract = false, secondaryInteractPrompt = string.Empty, canDrop = true, canPocket = true, canBackpack = true, canThrow = true }; AddLoot(val2); Prefab = val2; WatchGripSettings(); return true; } private static Texture2D Icon() { Sprite val = Navigator.ItemIcon ?? Navigator.Body; if (!((Object)(object)val == (Object)null)) { return val.texture; } return null; } private static void AddGrips(Transform root) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) string[] array = new string[2] { "Hand_L", "Hand_R" }; for (int i = 0; i < array.Length; i++) { new GameObject(array[i]).transform.SetParent(root, false); } PlaceGrips(root); } private static void LayInLuggage(Item item) { item.offsetLuggageSpawn = false; } internal static void PlaceModel(Transform model) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0039: 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_0058: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)model == (Object)null)) { model.localPosition = ModelOffset; model.localScale = Vector3.one * Mathf.Clamp(Plugin.Settings.TrackerScale.Value, 0.5f, 6f); model.localRotation = Quaternion.AngleAxis(Plugin.Settings.TrackerTilt.Value, Vector3.right) * Quaternion.Euler(0f, 180f, 0f); } } private static void PlaceGrips(Transform root) { Place(root.Find("Hand_L"), -1f); Place(root.Find("Hand_R"), 1f); } private static void Place(Transform hand, float side) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)hand == (Object)null)) { float num = Mathf.Clamp(Plugin.Settings.TrackerScale.Value, 0.5f, 6f); hand.localPosition = new Vector3(side * GripAcross, GripHeight, GripBehind) * num; hand.localEulerAngles = ((side < 0f) ? new Vector3(GripAngleX, GripAngleY, GripAngleZ) : new Vector3(GripAngleX, 0f - GripAngleY, 0f - GripAngleZ)); } } private static void RefreshGrips() { //IL_003a: 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_012f: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) if (!Registered) { return; } PlaceGrips(Prefab.transform); PlaceModel(Prefab.transform.Find("Model")); Prefab.GetComponent<Item>().defaultPos = HoldPos; LayInLuggage(Prefab.GetComponent<Item>()); ushort itemID = Prefab.GetComponent<Item>().itemID; int num = 0; Item[] array = Object.FindObjectsOfType<Item>(true); foreach (Item val in array) { if (val.itemID == itemID && !((Object)(object)((Component)val).gameObject == (Object)(object)Prefab)) { PlaceGrips(val.transform); PlaceModel(val.transform.Find("Model")); val.defaultPos = HoldPos; num++; } } Plugin.Logger.LogInfo((object)($"Grip: across {GripAcross:0.000} behind {GripBehind:0.000} height {GripHeight:0.000} " + $"angles ({GripAngleX:0}, {GripAngleY:0}, {GripAngleZ:0}) offset {ModelOffset:F3} hold {HoldPos:F2}; moved on {num} device(s). " + "Drop and pick up to see it.")); } private static void WatchGripSettings() { PluginConfig settings = Plugin.Settings; settings.TrackerScale.SettingChanged += delegate { RefreshGrips(); }; settings.TrackerTilt.SettingChanged += delegate { RefreshGrips(); }; settings.TrackerLuggageLift.SettingChanged += delegate { RefreshGrips(); }; settings.TrackerLuggageTurn.SettingChanged += delegate { RefreshGrips(); }; settings.TrackerHoldX.SettingChanged += delegate { RefreshGrips(); }; settings.TrackerHoldY.SettingChanged += delegate { RefreshGrips(); }; settings.TrackerHoldZ.SettingChanged += delegate { RefreshGrips(); }; settings.TrackerOffsetUp.SettingChanged += delegate { RefreshGrips(); }; settings.TrackerOffsetAway.SettingChanged += delegate { RefreshGrips(); }; settings.TrackerGripAcross.SettingChanged += delegate { RefreshGrips(); }; settings.TrackerGripBehind.SettingChanged += delegate { RefreshGrips(); }; settings.TrackerGripHeight.SettingChanged += delegate { RefreshGrips(); }; settings.TrackerGripAngleX.SettingChanged += delegate { RefreshGrips(); }; settings.TrackerGripAngleY.SettingChanged += delegate { RefreshGrips(); }; settings.TrackerGripAngleZ.SettingChanged += delegate { RefreshGrips(); }; } private static void AddLoot(GameObject device) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) LootData obj = device.AddComponent<LootData>(); obj.Rarity = Plugin.Settings.TrackerRarity.Value; obj.spawnLocations = Plugin.Settings.TrackerSpawnPools.Value; obj.banInSolo = false; } } internal static class TrackerModel { internal sealed class Part { internal string Name; internal string Material; internal Vector3 Offset; internal Mesh Mesh; } private static readonly byte[] Magic = new byte[8] { 80, 75, 84, 82, 65, 67, 75, 1 }; private static List<Part> _parts; private static Dictionary<string, Texture2D> _textures; private static bool _tried; internal static bool Available { get { Load(); if (_parts != null) { return _parts.Count > 0; } return false; } } internal static IList<Part> Parts { get { Load(); return _parts; } } internal static Texture2D Texture(string name) { Load(); if (_textures == null) { return null; } if (!_textures.TryGetValue(name, out var value)) { return null; } return value; } internal static Part Find(string name) { Load(); if (_parts == null) { return null; } foreach (Part part in _parts) { if (part.Name == name) { return part; } } return null; } private static void Load() { if (_tried) { return; } _tried = true; byte[] array = Resource("tracker.mesh"); if (array == null) { Plugin.Logger.LogWarning((object)"Tracker: the model is not in the assembly."); return; } try { Read(array); } catch (Exception ex) { _parts = null; _textures = null; Plugin.Logger.LogError((object)("Tracker: the model would not read — " + ex.Message)); } } private static void Read(byte[] blob) { using MemoryStream input = new MemoryStream(blob, writable: false); using BinaryReader binaryReader = new BinaryReader(input, Encoding.UTF8); byte[] magic = Magic; foreach (byte b in magic) { if (binaryReader.ReadByte() != b) { throw new IOException("the header does not match; rebuild tracker.mesh"); } } int num = binaryReader.ReadInt32(); _parts = new List<Part>(num); for (int j = 0; j < num; j++) { _parts.Add(ReadPart(binaryReader)); } int num2 = binaryReader.ReadInt32(); _textures = new Dictionary<string, Texture2D>(num2); for (int k = 0; k < num2; k++) { string text = ReadString(binaryReader); byte[] png = binaryReader.ReadBytes(binaryReader.ReadInt32()); Texture2D val = Decode(text, png); if ((Object)(object)val != (Object)null) { _textures[text] = val; } } } private static Part ReadPart(BinaryReader reader) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: 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_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Expected O, but got Unknown Part part = new Part { Name = ReadString(reader), Material = ReadString(reader), Offset = ReadVector3(reader) }; int num = reader.ReadInt32(); int num2 = reader.ReadInt32(); Vector3[] array = (Vector3[])(object)new Vector3[num]; for (int i = 0; i < num; i++) { array[i] = ReadVector3(reader); } Vector3[] array2 = (Vector3[])(object)new Vector3[num]; for (int j = 0; j < num; j++) { array2[j] = ReadVector3(reader); } Vector2[] array3 = (Vector2[])(object)new Vector2[num]; for (int k = 0; k < num; k++) { array3[k] = new Vector2(reader.ReadSingle(), reader.ReadSingle()); } int[] array4 = new int[num2]; for (int l = 0; l < num2; l++) { array4[l] = reader.ReadUInt16(); } part.Mesh = new Mesh { name = "HikingGPS_" + part.Name, vertices = array, normals = array2, uv = array3 }; part.Mesh.SetTriangles(array4, 0); part.Mesh.RecalculateBounds(); return part; } private static Vector3 ReadVector3(BinaryReader reader) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) return new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); } private static string ReadString(BinaryReader reader) { int num = reader.ReadInt32(); if (num != 0) { return Encoding.UTF8.GetString(reader.ReadBytes(num)); } return string.Empty; } private static Texture2D Decode(string name, byte[] png) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false) { name = "HikingGPS_" + name, filterMode = (FilterMode)0, wrapMode = (TextureWrapMode)1, anisoLevel = 0 }; if (ImageConversion.LoadImage(val, png)) { return val; } Plugin.Logger.LogWarning((object)("Tracker: texture '" + name + "' could not be decoded.")); Object.Destroy((Object)(object)val); return null; } private static byte[] Resource(string name) { Assembly assembly = typeof(TrackerModel).Assembly; string[] manifestResourceNames = assembly.GetManifestResourceNames(); foreach (string text in manifestResourceNames) { if (!text.EndsWith(name, StringComparison.OrdinalIgnoreCase)) { continue; } using Stream stream = assembly.GetManifestResourceStream(text); if (stream == null) { return null; } byte[] array = new byte[stream.Length]; int num; for (int j = 0; j < array.Length; j += num) { num = stream.Read(array, j, array.Length - j); if (num <= 0) { break; } } return array; } return null; } } internal static class TrackerObject { private sealed class Kit { internal Material Body; internal Material Screen; } private const string ColliderPart = "Tracker_Collider"; internal const string ScreenPart = "Tracker_Screen"; private static readonly Dictionary<string, Kit> _kits = new Dictionary<string, Kit>(); private static readonly List<Material> _screenMaterials = new List<Material>(); private static Texture _map; internal static readonly Color ScreenOff = new Color(0.035f, 0.055f, 0.065f, 1f); private static Shader _lit; internal static Texture Map => _map; internal static GameObject Build(string name = "HikingGPS_Tracker", string shaderName = null) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) if (!TrackerModel.Available) { Plugin.Logger.LogWarning((object)"Tracker: asked to build the device, but the model is not loaded."); return null; } Kit kit = KitFor(shaderName); GameObject val = new GameObject(name); foreach (TrackerModel.Part part in TrackerModel.Parts) { GameObject val2 = new GameObject(part.Name); val2.transform.SetParent(val.transform, false); val2.transform.localPosition = part.Offset; if (part.Name == "Tracker_Collider") { MeshCollider obj = val2.AddComponent<MeshCollider>(); obj.sharedMesh = RestlessHull(part.Mesh.bounds); obj.convex = true; } else { val2.AddComponent<MeshFilter>().sharedMesh = part.Mesh; MeshRenderer obj2 = val2.AddComponent<MeshRenderer>(); ((Renderer)obj2).sharedMaterial = ((part.Name == "Tracker_Screen") ? kit.Screen : kit.Body); ((Renderer)obj2).shadowCastingMode = (ShadowCastingMode)1; ((Renderer)obj2).receiveShadows = true; } } val.AddComponent<TrackerDevice>(); return val; } private static Mesh RestlessHull(Bounds b) { //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_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_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0043: 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_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: 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_0067: 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) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007f: 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) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009d: 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_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00af: 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_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: 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_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_015f: 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_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0177: 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_0185: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Expected O, but got Unknown Vector3 min = ((Bounds)(ref b)).min; Vector3 max = ((Bounds)(ref b)).max; float num = max.x - min.x; float num2 = max.y - min.y; float num3 = 0.12f * Mathf.Min(num, num2); Vector3[] vertices = (Vector3[])(object)new Vector3[8] { new Vector3(min.x, min.y, max.z), new Vector3(max.x, min.y, max.z), new Vector3(max.x, max.y, max.z), new Vector3(min.x, max.y, max.z), new Vector3(min.x + num3, min.y + num3, min.z), new Vector3(max.x - num3, min.y + num3, min.z), new Vector3(max.x - num3, max.y - num3, min.z), new Vector3(min.x + num3, max.y - num3, min.z) }; int[] triangles = new int[36] { 0, 1, 2, 0, 2, 3, 4, 6, 5, 4, 7, 6, 0, 3, 7, 0, 7, 4, 1, 5, 6, 1, 6, 2, 0, 4, 5, 0, 5, 1, 3, 2, 6, 3, 6, 7 }; Mesh val = new Mesh { name = "Tracker_Collider_Restless", vertices = vertices, triangles = triangles }; val.RecalculateNormals(); val.RecalculateBounds(); return val; } private static Kit KitFor(string shaderName) { string key = shaderName ?? string.Empty; if (_kits.TryGetValue(key, out var value)) { return value; } Shader val = ((shaderName == null) ? Lit() : Shader.Find(shaderName)); if ((Object)(object)val == (Object)null) { Plugin.Logger.LogWarning((object)("Tracker: '" + shaderName + "' is not in this build; using the usual one.")); val = Lit(); } Kit kit = new Kit { Body = BuildBody(val), Screen = BuildScreen(val) }; _kits[key] = kit; return kit; } private static Material BuildBody(Shader shader) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_002e: Unknown result type (might be due to invalid IL or missing references) Material val = new Material(shader) { name = "HikingGPS_Body" }; Texture2D val2 = TrackerModel.Texture("tracker_body_palette"); if ((Object)(object)val2 != (Object)null) { SetTexture(val, (Texture)(object)val2); } SetColour(val, Color.white); SetFloat(val, "_Metallic", 0f); SetFloat(val, "_BaseMetallic", 0f); SetFloat(val, "_Smoothness", 0.15f); SetFloat(val, "_Glossiness", 0.15f); SetFloat(val, "_BaseSmooth", 0.15f); SetFloat(val, "_AddSpecular", 0f); ApplyMask(val); return val; } private static void ApplyMask(Material material) { Texture2D val = TrackerModel.Texture("tracker_body_mask"); if (!((Object)(object)val == (Object)null)) { if (material.HasProperty("_MetallicGlossMap")) { material.SetTexture("_MetallicGlossMap", (Texture)(object)val); material.EnableKeyword("_METALLICSPECGLOSSMAP"); SetFloat(material, "_SmoothnessTextureChannel", 0f); SetFloat(material, "_Metallic", 1f); SetFloat(material, "_Smoothness", 1f); SetFloat(material, "_GlossMapScale", 1f); Plugin.Logger.LogInfo((object)("Tracker: '" + ((Object)material.shader).name + "' is using the material mask.")); } else { Plugin.Logger.LogInfo((object)("Tracker: '" + ((Object)material.shader).name + "' cannot take the mask; the case is one material throughout.")); } } } private static Material BuildScreen(Shader shader) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) Material val = new Material(Shader.Find("Universal Render Pipeline/Unlit") ?? Shader.Find("Unlit/Texture") ?? shader) { name = "HikingGPS_Screen" }; SetColour(val, ScreenOff); SetFloat(val, "_Metallic", 0f); SetFloat(val, "_BaseMetallic", 0f); SetFloat(val, "_Smoothness", 0f); SetFloat(val, "_BaseSmooth", 0f); _screenMaterials.Add(val); if ((Object)(object)_map != (Object)null) { SetTexture(val, _map); SetColour(val, Color.white); } return val; } internal static void ShowMap(Texture screen) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)screen == (Object)null) { return; } _map = screen; int num = 0; foreach (Material screenMaterial in _screenMaterials) { if (!((Object)(object)screenMaterial == (Object)null)) { SetTexture(screenMaterial, screen); SetColour(screenMaterial, Color.white); num++; } } Plugin.Logger.LogInfo((object)($"Tracker: the map ({screen.width}x{screen.height}) is on {num} screen(s); " + "any built later will take it too.")); } private static Shader Lit() { if ((Object)(object)_lit != (Object)null) { return _lit; } string[] array = new string[4] { "W/Peak_Standard", "Universal Render Pipeline/Lit", "Universal Render Pipeline/Simple Lit", "Standard" }; for (int i = 0; i < array.Length; i++) { _lit = Shader.Find(array[i]); if (!((Object)(object)_lit == (Object)null)) { Plugin.Logger.LogInfo((object)("Tracker: drawing with '" + ((Object)_lit).name + "'.")); Describe(_lit); return _lit; } } _lit = Shader.Find("Universal Render Pipeline/Unlit") ?? Shader.Find("Sprites/Default"); Plugin.Logger.LogWarning((object)("Tracker: no lit shader was found; falling back to '" + (((Object)(object)_lit == (Object)null) ? "nothing" : ((Object)_lit).name) + "'.")); return _lit; } internal static void ProbeShaders() { string[] array = new string[4] { "W/Peak_Standard", "Universal Render Pipeline/Lit", "Universal Render Pipeline/Simple Lit", "Standard" }; foreach (string text in array) { Shader val = Shader.Find(text); if ((Object)(object)val == (Object)null) { Plugin.Logger.LogInfo((object)("Tracker: '" + text + "' is not in this build.")); continue; } bool flag = false; string[] array2 = new string[3] { "_MetallicGlossMap", "_MaskMap", "_SpecGlossMap" }; foreach (string text2 in array2) { if (HasProperty(val, text2)) { Plugin.Logger.LogInfo((object)("Tracker: '" + text + "' takes a mask as '" + text2 + "'.")); flag = true; } } if (!flag) { Plugin.Logger.LogInfo((object)("Tracker: '" + text + "' has no mask texture slot.")); } Describe(val); } } private static bool HasProperty(Shader shader, string name) { try { for (int i = 0; i < shader.GetPropertyCount(); i++) { if (shader.GetPropertyName(i) == name) { return true; } } } catch { } return false; } private static void Describe(Shader shader) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) try { StringBuilder stringBuilder = new StringBuilder("Tracker: '" + ((Object)shader).name + "' declares"); for (int i = 0; i < shader.GetPropertyCount(); i++) { stringBuilder.Append($" {shader.GetPropertyName(i)}:{shader.GetPropertyType(i)}"); } Plugin.Logger.LogInfo((object)stringBuilder.ToString()); } catch (Exception ex) { Plugin.Logger.LogWarning((object)("Tracker: could not read the shader's properties: " + ex.Message)); } } internal static void SetTexture(Material material, Texture texture) { bool flag = false; string[] array = new string[4] { "_BaseTexture", "_BaseMap", "_MainTex", "_BaseColorMap" }; foreach (string text in array) { if (material.HasProperty(text)) { material.SetTexture(text, texture); flag = true; break; } } if (!flag) { material.mainTexture = texture; Plugin.Logger.LogWarning((object)("Tracker: '" + ((Object)material.shader).name + "' names its base texture something unexpected.")); } SetFloat(material, "_BaseTexAmount", 1f); } internal static void SetColour(Material material, Color colour) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) bool flag = false; string[] array = new string[4] { "_BaseColor", "_Color", "_TopColor", "_Tint" }; foreach (string text in array) { if (material.HasProperty(text)) { material.SetColor(text, colour); flag = true; } } if (!flag) { material.color = colour; } } private static void SetFloat(Material material, string name, float value) { if (material.HasProperty(name)) { material.SetFloat(name, value); } } internal static IEnumerable<Renderer> Renderers(GameObject device) { if (!((Object)(object)device == (Object)null)) { return device.GetComponentsInChildren<Renderer>(true); } return (IEnumerable<Renderer>)(object)new Renderer[0]; } } internal static class TrackerRegistration { private static string _modId; internal static bool Register() { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) if (!TrackerItem.Register()) { return false; } Item component = TrackerItem.Prefab.GetComponent<Item>(); if ((Object)(object)component == (Object)null) { Plugin.Logger.LogError((object)"Tracker: the built device has no Item on it."); return false; } ModDefinition orCreate = ModDefinition.GetOrCreate(((BaseUnityPlugin)Plugin.Instance).Info); new ItemContent(component).Register(orCreate); Plugin.Logger.LogInfo((object)("Tracker: registered 'Hiking GPS' as an item " + $"({Plugin.Settings.TrackerRarity.Value}, {Plugin.Settings.TrackerSpawnPools.Value}).")); _modId = orCreate.Id; return true; } internal static bool EnsureInDatabase() { if (!TrackerItem.Registered) { return false; } Item component = TrackerItem.Prefab.GetComponent<Item>(); if ((Object)(object)component == (Object)null) { return false; } ItemDatabase instance = SingletonAsset<ItemDatabase>.Instance; if ((Object)(object)instance == (Object)null || instance.itemLookup == null) { return false; } if (component.itemID != 0 && instance.itemLookup.ContainsKey(component.itemID)) { return true; } ushort num = HashId(component); ushort num2 = num; while (instance.itemLookup.ContainsKey(num)) { num++; if (num == num2) { Plugin.Logger.LogError((object)"Tracker: every item id is taken; the device cannot be registered."); return false; } } component.itemID = num; ((DatabaseAsset<ItemDatabase, Item>)(object)instance).Objects.Add(component); instance.itemLookup.Add(num, component); LootData.AllSpawnWeightData = null; Plugin.Logger.LogWarning((object)("Tracker: PEAKLib did not add the device to the item database, so it was added " + $"directly, with id {num}.")); return true; } private static ushort HashId(Item item) { using MD5 mD = MD5.Create(); return BitConverter.ToUInt16(mD.ComputeHash(Encoding.UTF8.GetBytes((_modId ?? string.Empty) + ((Object)item).name)), 0); } } } namespace PeakMapInteractive.Pipeline { internal static class CaptureRunner { public static bool IsRunning { get; private set; } public static bool HasCompleted { get; private set; } public static IEnumerator Run() { if (IsRunning) { Plugin.Logger.LogWarning((object)"Capture already running; ignoring request."); yield break; } IsRunning = true; float startedAt = Time.realtimeSinceStartup; MapHandler mapHandler = Singleton<MapHandler>.Instance; if (mapHandler?.segments == null) { Plugin.Logger.LogError((object)"MapHandler has no segments; nothing to capture."); IsRunning = false; yield break; } int segmentCount = mapHandler.segments.Length; Plugin.Logger.LogInfo((object)$"Capturing {segmentCount} segments."); string snapshotDir = Path.Combine(Plugin.OutputDir, "snapshot"); Directory.CreateDirectory(snapshotDir); int heightRes = Plugin.Settings.HeightResolution.Value; int albedoRes = Plugin.Settings.AlbedoResolution.Value; float padding = Plugin.Settings.BoundsPadding.Value; int layerMask = BuildRaycastMask(); Snapshot snapshot = new Snapshot { GeneratedAt = SnapshotWriter.Timestamp(), GameVersion = Application.version, Capture = { HeightResolution = heightRes, AlbedoResolution = albedoRes, RaycastLayerMask = layerMask } }; DescribeMap(snapshot.Map); OrthoCapture.LogLayers(); OrthoCapture.LogLargeRenderers(800f); try { LoadingScreenHandler.KillCurrentLoadingScreen(); Plugin.Logger.LogInfo((object)"Dismissed the loading screen."); } catch (Exception ex) { Plugin.Logger.LogWarning((object)("Could not dismiss the loading screen: " + ex.Message)); } yield return OrthoCapture.WaitForWorldToRender(15f); if (Plugin.Settings.WriteDiagnostics.Value) { yield return (object)new WaitForEndOfFrame(); Texture2D val = ScreenCapture.CaptureScreenshotAsTexture(); if ((Object)(object)val != (Object)null) { File.WriteAllBytes(Path.Combine(snapshotDir, "screen-probe.jpg"), ImageConversion.EncodeToJPG(val, 85)); Plugin.Logger.LogInfo((object)$"Screen probe written: {((Texture)val).width}x{((Texture)val).height}."); Object.Destroy((Object)(object)val); } else { Plugin.Logger.LogWarning((object)"Screen probe returned nothing."); } } MarkerCollector collector = new MarkerCollector(); for (int index = 0; index < segmentCount; index++) { SegmentPreparer preparer = new SegmentPreparer(); SegmentDto dto; try { MapSegment val2 = mapHandler.segments[index]; if ((Object)(object)((val2 != null) ? val2.segmentParent : null) == (Object)null) { Plugin.Logger.LogWarning((object)$"Segment {index} has no parent object; skipped."); continue; } preparer.Prepare(val2.segmentParent, val2.segmentCampfire, val2.wallNext, val2.wallPrevious); dto = new SegmentDto { Index = index, Biome = ((object)val2.biome/*cast due to .constrained prefix*/).ToString(), DisplayName = Prettify(((object)val2.biome/*cast due to .constrained prefix*/).ToString()) }; } catch (Exception arg) { Plugin.Logger.LogError((object)$"Segment {index} preparation failed: {arg}"); preparer.Restore(); continue; } preparer.SpawnItems(); yield return null; yield return (object)new WaitForEndOfFrame(); if (!SegmentBounds.TryCompute(preparer.Root, out var bounds)) { Plugin.Logger.LogWarning((object)$"Segment {index} has no measurable geometry; skipped."); preparer.Restore(); continue; } CaptureFrame frame = CaptureFrame.FromBounds(bounds, padding); Plugin.Logger.LogInfo((object)$"Segment {index} ({dto.Biome}): {frame}"); dto.Bounds = new BoundsDto { Min = SnapshotWriter.Vec3(frame.Min), Max = SnapshotWriter.Vec3(frame.Max) }; if (index == 0 && Plugi