Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of BetterMap v1.1.0
BetterMap.dll
Decompiled a month 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.IO.Compression; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using BetterMap.Scripts.Creatures; using BetterMap.Scripts.Map; using BetterMap.Scripts.Pins; using BetterMap.Scripts.Vehicles; using HarmonyLib; using JetBrains.Annotations; using Microsoft.CodeAnalysis; using ServerSync; using Splatform; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("BetterMap")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("BetterMap")] [assembly: AssemblyCopyright("Copyright © 2025")] [assembly: AssemblyTrademark("")] [assembly: Guid("0FFBB82E-5492-486C-A8A5-346DED8E95E7")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: ComVisible(false)] [assembly: AssemblyVersion("1.0.0.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace BetterMap { [BepInPlugin("xtav1m.BetterMap", "BetterMap", "1.1.0")] public class Plugin : BaseUnityPlugin { public static ConfigEntry<bool> showCreatures; public static ConfigEntry<float> creatureRefreshInterval; public static ConfigEntry<float> creatureRadius; public static ConfigEntry<bool> showEntityNames; public static ConfigEntry<bool> showCreatureStars; public static ConfigEntry<bool> tintTamedCreatures; public static ConfigEntry<bool> tintHostileCreatures; public static ConfigEntry<bool> showBoats; public static ConfigEntry<bool> showCarts; public static ConfigEntry<bool> rotateBoatIcons; public static ConfigEntry<bool> showVehicleNames; public static ConfigEntry<float> vehicleRefreshInterval; public static ConfigEntry<float> vehicleRadius; public static ConfigEntry<bool> autoPin; public static ConfigEntry<bool> autoPinPortals; public static ConfigEntry<bool> nameTraderPins; public static ConfigEntry<bool> revealTraders; public static ConfigEntry<float> autoPinMergeDistance; public static ConfigEntry<float> autoPinInterval; public static ConfigEntry<float> autoPinRadius; public const PinType AutoPinType = (PinType)3; public static ConfigEntry<int> deathMarkersKept; public static ConfigEntry<float> explorationRadius; public static ConfigEntry<float> iconScale; public static ConfigEntry<bool> smoothZoom; public static ConfigEntry<bool> debugMode; public static ConfigEntry<bool> forgetPinned; public static readonly ManualLogSource Logger = Logger.CreateLogSource("BetterMap"); private static readonly ConfigSync configSync = new ConfigSync("xtav1m.BetterMap") { DisplayName = "BetterMap", CurrentVersion = "1.1.0", MinimumRequiredVersion = "1.1.0" }; private const string ForbiddenInKeys = "=\n\t\\\"'[]"; private void Awake() { InitializeConfig(); InitializeHarmonyPatches(); Logger.LogInfo((object)"BetterMap 1.1.0 loaded"); } private void Update() { CreatureTracker.Tick(); DeathMarkers.Tick(); VehicleTracker.Tick(); VehicleIndex.Tick(); AutoPins.Tick(); PinFilters.Tick(); } private ConfigEntry<T> ConfigSync<T>(string group, string name, T value, ConfigDescription description, bool synchronizedSetting = true) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown ConfigDescription val = new ConfigDescription(description.Description + (synchronizedSetting ? " [Synced with Server]" : " [Not Synced with Server]"), description.AcceptableValues, description.Tags); ConfigEntry<T> val2 = ((BaseUnityPlugin)this).Config.Bind<T>(group, name, value, val); configSync.AddConfigEntry<T>(val2).SynchronizedConfig = synchronizedSetting; return val2; } private void InitializeConfig() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Expected O, but got Unknown //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Expected O, but got Unknown //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Expected O, but got Unknown //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Expected O, but got Unknown //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Expected O, but got Unknown //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Expected O, but got Unknown //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Expected O, but got Unknown //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Expected O, but got Unknown //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Expected O, but got Unknown //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Expected O, but got Unknown //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_0240: Expected O, but got Unknown //IL_026e: Unknown result type (might be due to invalid IL or missing references) //IL_0279: Expected O, but got Unknown //IL_0295: Unknown result type (might be due to invalid IL or missing references) //IL_02a0: Expected O, but got Unknown //IL_02ce: Unknown result type (might be due to invalid IL or missing references) //IL_02d9: Expected O, but got Unknown //IL_0307: Unknown result type (might be due to invalid IL or missing references) //IL_0312: Expected O, but got Unknown //IL_032e: Unknown result type (might be due to invalid IL or missing references) //IL_0339: Expected O, but got Unknown //IL_0355: Unknown result type (might be due to invalid IL or missing references) //IL_0360: Expected O, but got Unknown //IL_037c: Unknown result type (might be due to invalid IL or missing references) //IL_0387: Expected O, but got Unknown //IL_03b5: Unknown result type (might be due to invalid IL or missing references) //IL_03c0: Expected O, but got Unknown //IL_03e3: Unknown result type (might be due to invalid IL or missing references) //IL_03ee: Expected O, but got Unknown //IL_041c: Unknown result type (might be due to invalid IL or missing references) //IL_0427: Expected O, but got Unknown //IL_0455: Unknown result type (might be due to invalid IL or missing references) //IL_0460: Expected O, but got Unknown //IL_047c: Unknown result type (might be due to invalid IL or missing references) //IL_0487: Expected O, but got Unknown //IL_04a9: Unknown result type (might be due to invalid IL or missing references) //IL_04b4: Expected O, but got Unknown //IL_04d0: Unknown result type (might be due to invalid IL or missing references) //IL_04db: Expected O, but got Unknown ((BaseUnityPlugin)this).Config.SaveOnConfigSet = false; ConfigEntry<bool> lockingConfig = ConfigSync("1 - ServerSync", "Lock Configuration", value: true, new ConfigDescription("If enabled, the configuration is locked and can be changed by server admins only.", (AcceptableValueBase)null, Array.Empty<object>())); configSync.AddLockingConfigEntry<bool>(lockingConfig); showCreatures = ConfigSync("Creatures", "Show Creatures", value: true, new ConfigDescription("Show creatures on the minimap and the map, using their trophy as the icon.", (AcceptableValueBase)null, Array.Empty<object>())); creatureRefreshInterval = ConfigSync("Creatures", "Creature Refresh Interval", 0.5f, new ConfigDescription("How often, in seconds, the set of tracked creatures is rebuilt. Their pins follow them every frame regardless.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 5f), Array.Empty<object>()), synchronizedSetting: false); creatureRadius = ConfigSync("Creatures", "Creature Radius", 100f, new ConfigDescription("How far from you, in meters, creatures are shown. The game only loads the area around you, so past about 200 there is nothing more to see.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 200f), Array.Empty<object>())); showEntityNames = ConfigSync("Creatures", "Show Creature Names", value: false, new ConfigDescription("Show a name under every creature pin. Creatures with no trophy icon, and tamed creatures that have been given a name, always show theirs regardless of this setting.", (AcceptableValueBase)null, Array.Empty<object>()), synchronizedSetting: false); showCreatureStars = ConfigSync("Creatures", "Show Creature Stars", value: true, new ConfigDescription("Show a star and a number above a creature's pin when it has stars, using the game's own star. The number is how many stars it has, so creatures past two stars from other mods show too.", (AcceptableValueBase)null, Array.Empty<object>()), synchronizedSetting: false); tintTamedCreatures = ConfigSync("Creatures", "Tint Tamed Creatures", value: true, new ConfigDescription("Tint the pins of tamed creatures green so they stand out from the wildlife.", (AcceptableValueBase)null, Array.Empty<object>()), synchronizedSetting: false); tintHostileCreatures = ConfigSync("Creatures", "Tint Hostile Creatures", value: true, new ConfigDescription("Tint red the pins of creatures that will attack you on sight. Only applies to creatures with no trophy to use as an icon, which are drawn with a plain pin: a creature drawn as its own trophy is already recognisable.", (AcceptableValueBase)null, Array.Empty<object>()), synchronizedSetting: false); showBoats = ConfigSync("Vehicles", "Show Boats", value: true, new ConfigDescription("Show boats on the map. Boats are found anywhere in the world, not only near you, which is what makes one you left adrift findable. Playing alone or hosting, that means every boat there is. As a guest on a server you get the ones in every area you have loaded since connecting, and a boat far away sits where it was when you were last near it.", (AcceptableValueBase)null, Array.Empty<object>())); showCarts = ConfigSync("Vehicles", "Show Carts", value: true, new ConfigDescription("Show carts on the map, wherever you left them.", (AcceptableValueBase)null, Array.Empty<object>())); rotateBoatIcons = ConfigSync("Vehicles", "Rotate Boat Icons", value: true, new ConfigDescription("Turn boat icons to point the way the boat is facing. While you are sailing, this also replaces the game's own boat marker so both look the same.", (AcceptableValueBase)null, Array.Empty<object>()), synchronizedSetting: false); showVehicleNames = ConfigSync("Vehicles", "Show Vehicle Names", value: true, new ConfigDescription("Show what each vehicle is under its icon, so a raft can be told from a longship.", (AcceptableValueBase)null, Array.Empty<object>()), synchronizedSetting: false); vehicleRefreshInterval = ConfigSync("Vehicles", "Vehicle Refresh Interval", 5f, new ConfigDescription("How often, in seconds, vehicles anywhere in the world are looked up. Vehicles near the player follow them continuously.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 60f), Array.Empty<object>())); vehicleRadius = ConfigSync("Vehicles", "Vehicle Radius", 100f, new ConfigDescription("How far from you, in meters, vehicles are followed as they move. Past it they are shown where they were last looked up.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 200f), Array.Empty<object>()), synchronizedSetting: false); autoPin = ConfigSync("Auto Pins", "Enable", value: true, new ConfigDescription("Pin resources as you come across them. What gets pinned is chosen biome by biome below, and a pin you delete is never put back.", (AcceptableValueBase)null, Array.Empty<object>())); autoPinInterval = ConfigSync("Auto Pins", "Sweep Interval", 2f, new ConfigDescription("How often, in seconds, the loaded world is looked over for anything worth pinning.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 30f), Array.Empty<object>()), synchronizedSetting: false); autoPinRadius = ConfigSync("Auto Pins", "Pin Radius", 100f, new ConfigDescription("How far from you, in meters, anything worth pinning is spotted. The game only loads the area around you, so past about 200 there is nothing more to find.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 200f), Array.Empty<object>())); autoPinPortals = ConfigSync("Auto Pins", "Pin Portals", value: true, new ConfigDescription("Pin portals where they stand, named by their tag, using the game's own portal icon. Renaming a portal renames its pin.", (AcceptableValueBase)null, Array.Empty<object>()), synchronizedSetting: false); revealTraders = ConfigSync("Auto Pins", "Reveal Traders", value: false, new ConfigDescription("Put every trader in the world on your map at once, Haldor and Hildir and the bog witch, without having to stumble across them. Off by default because finding them is part of the game. On a server this is decided by the server, and takes effect the next time you connect.", (AcceptableValueBase)null, Array.Empty<object>())); nameTraderPins = ConfigSync("Auto Pins", "Name Trader Pins", value: true, new ConfigDescription("Put the trader's name on the pin the game already places for them, so Haldor, Hildir and the bog witch can be told apart on the map.", (AcceptableValueBase)null, Array.Empty<object>()), synchronizedSetting: false); autoPinMergeDistance = ConfigSync("Auto Pins", "Merge Distance", 5f, new ConfigDescription("Do not place an automatic pin within this many meters of one that is already there, so walking past the same deposit does not stack pins on it.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 50f), Array.Empty<object>()), synchronizedSetting: false); deathMarkersKept = ConfigSync("Map", "Death Markers Kept", 3, new ConfigDescription("How many of your death markers to keep on the map. The game drops a marker where you died but never saves it, so without this they are gone the next time you load the world.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 20), Array.Empty<object>()), synchronizedSetting: false); explorationRadius = ConfigSync("Map", "Exploration Radius", 100f, new ConfigDescription("How much of the map is uncovered as you walk, in meters. 100 is the vanilla value. Creatures, vehicles and auto pins each have a radius of their own.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(20f, 500f), Array.Empty<object>())); iconScale = ConfigSync("Map", "Icon Scale", 1.25f, new ConfigDescription("Size of every pin on the map, as a multiple of its normal size. 1 leaves the game's own size, 32 pixels on the minimap and 48 on the map.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 3f), Array.Empty<object>()), synchronizedSetting: false); smoothZoom = ConfigSync("Map", "Smooth Zoom", value: true, new ConfigDescription("Glide between zoom levels on the map and the minimap instead of jumping.", (AcceptableValueBase)null, Array.Empty<object>()), synchronizedSetting: false); BindPinRules(); debugMode = ConfigSync("Debug", "Debug Mode", value: false, new ConfigDescription("Log what is being pinned and tracked.", (AcceptableValueBase)null, Array.Empty<object>()), synchronizedSetting: false); forgetPinned = ConfigSync("Debug", "Forget Pinned Places", value: false, new ConfigDescription("Once, on the next world you load, throw away this character's record of where it has already pinned, so everything is pinned again. Turn it back off afterwards. This also undoes every automatic pin you deleted on purpose.", (AcceptableValueBase)null, Array.Empty<object>()), synchronizedSetting: false); ((BaseUnityPlugin)this).Config.SaveOnConfigSet = true; ((BaseUnityPlugin)this).Config.Save(); } private void BindPinRules() { //IL_006a: 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_009c: Expected O, but got Unknown foreach (PinRules.Rule item in PinRules.All) { if (item.Name == null || item.Name.IndexOfAny("=\n\t\\\"'[]".ToCharArray()) >= 0) { Logger.LogError((object)("PinRules: \"" + item.Name + "\" cannot be a setting, it uses one of =\n\t\\\"'[]. Skipped.")); } else { item.Enabled = ConfigSync($"Auto Pins - {item.Biome}", item.Name, item.DefaultOn, new ConfigDescription(item.Description, (AcceptableValueBase)null, Array.Empty<object>()), synchronizedSetting: false); } } } private static void InitializeHarmonyPatches() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) new Harmony("xtav1m.BetterMap").PatchAll(); } } internal static class PluginInfo { public const string PLUGIN_NAME = "BetterMap"; public const string PLUGIN_GUID = "xtav1m.BetterMap"; public const string PLUGIN_VERSION = "1.1.0"; } } namespace BetterMap.Scripts { public static class Icons { private static readonly Dictionary<string, Sprite> _sprites = new Dictionary<string, Sprite>(); private static readonly MethodInfo LoadImageMethod = FindLoadImage(); public static Sprite Boat => Get("boat.png"); public static Sprite Cart => Get("cart.png"); private static MethodInfo FindLoadImage() { Type type = AccessTools.TypeByName("UnityEngine.ImageConversion"); if (type == null) { return null; } return AccessTools.Method(type, "LoadImage", new Type[3] { typeof(Texture2D), typeof(byte[]), typeof(bool) }, (Type[])null) ?? AccessTools.Method(type, "LoadImage", new Type[2] { typeof(Texture2D), typeof(byte[]) }, (Type[])null); } public static Sprite For(PinCategory category) { return (Sprite)(category switch { PinCategory.Ore => Get("ore.png"), PinCategory.Forage => Get("forage.png"), PinCategory.Dungeon => Get("dungeon.png"), PinCategory.Loot => Get("loot.png"), PinCategory.Spawner => Get("spawner.png"), PinCategory.Vegvisir => Get("vegvisir.png"), PinCategory.Beehive => Get("beehive.png"), PinCategory.Tar => Get("tar.png"), PinCategory.Sap => Get("sap.png"), _ => null, }); } private static Sprite Get(string file) { if (_sprites.TryGetValue(file, out Sprite value)) { return value; } Sprite val = Load(file); _sprites[file] = val; return val; } private static Sprite Load(string file) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) try { byte[] array = Read(file); if (array == null) { Plugin.Logger.LogWarning((object)("Icons: " + file + " is not in the assembly")); return null; } Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false) { filterMode = (FilterMode)1, wrapMode = (TextureWrapMode)1 }; if (!Decode(val, array)) { Plugin.Logger.LogWarning((object)("Icons: " + file + " could not be decoded")); return null; } return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f)); } catch (Exception arg) { Plugin.Logger.LogError((object)$"Icons: {file} failed to load: {arg}"); return null; } } private static bool Decode(Texture2D texture, byte[] bytes) { if (LoadImageMethod == null) { Plugin.Logger.LogWarning((object)"Icons: the game's image decoder was not found"); return false; } object[] parameters = ((LoadImageMethod.GetParameters().Length != 3) ? new object[2] { texture, bytes } : new object[3] { texture, bytes, false }); return (bool)LoadImageMethod.Invoke(null, parameters); } private static byte[] Read(string file) { Assembly executingAssembly = Assembly.GetExecutingAssembly(); string value = "." + file; string[] manifestResourceNames = executingAssembly.GetManifestResourceNames(); foreach (string text in manifestResourceNames) { if (!text.EndsWith(value, StringComparison.OrdinalIgnoreCase)) { continue; } using Stream stream = executingAssembly.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; } } public static class MapPins { private static readonly FieldRef<Minimap, bool> PinUpdateRequired = AccessTools.FieldRefAccess<Minimap, bool>("m_pinUpdateRequired"); private static readonly FieldRef<Minimap, List<PinData>> Pins = AccessTools.FieldRefAccess<Minimap, List<PinData>>("m_pins"); public static void RequestRedraw() { if ((Object)(object)Minimap.instance != (Object)null) { PinUpdateRequired.Invoke(Minimap.instance) = true; } } public static List<PinData> Of(Minimap map) { return Pins.Invoke(map); } public static void ApplyScale() { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Invalid comparison between Unknown and I4 //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) Minimap instance = Minimap.instance; if ((Object)(object)instance == (Object)null) { return; } float value = Plugin.iconScale.Value; if (Mathf.Approximately(value, 1f)) { return; } float num = (((int)instance.m_mode == 2) ? instance.m_pinSizeLarge : instance.m_pinSizeSmall); foreach (PinData item in Pins.Invoke(instance)) { if (!((Object)(object)item?.m_uiElement == (Object)null) && !(item.m_worldSize > 0f)) { float num2; Rect rect; if (!item.m_animate) { num2 = (item.m_doubleSize ? (num * 2f) : num) * value; } else { rect = item.m_uiElement.rect; num2 = ((Rect)(ref rect)).width * value; } float num3 = num2; rect = item.m_uiElement.rect; if (!Mathf.Approximately(((Rect)(ref rect)).width, num3)) { item.m_uiElement.SetSizeWithCurrentAnchors((Axis)0, num3); item.m_uiElement.SetSizeWithCurrentAnchors((Axis)1, num3); } } } } } } namespace BetterMap.Scripts.Map { public static class DeathMarkers { private struct Marker { public long World; public Vector3 Pos; public string Label; } private const string CustomDataKey = "BetterMap.deaths"; private static readonly FieldRef<Minimap, List<PinData>> MapPins = AccessTools.FieldRefAccess<Minimap, List<PinData>>("m_pins"); private static readonly Func<Minimap, Vector3, Vector3> ScreenToWorld = AccessTools.MethodDelegate<Func<Minimap, Vector3, Vector3>>(AccessTools.Method(typeof(Minimap), "ScreenToWorldPoint", (Type[])null, (Type[])null), (object)null, true); private static readonly Func<Minimap, float> InteractRadius = AccessTools.MethodDelegate<Func<Minimap, float>>(AccessTools.PropertyGetter(typeof(Minimap), "PinInteractRadius"), (object)null, true); private static bool _rebuilt; public static void Tick() { if ((Object)(object)Player.m_localPlayer == (Object)null) { _rebuilt = false; } else if (!_rebuilt && !((Object)(object)Minimap.instance == (Object)null)) { _rebuilt = true; Rebuild(); } } public static void Invalidate() { _rebuilt = false; } public static void Record(Vector3 pos) { //IL_0042: 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) if (!((Object)(object)Player.m_localPlayer == (Object)null) && !((Object)(object)ZNet.instance == (Object)null)) { List<Marker> list = Load(); list.Add(new Marker { World = ZNet.instance.GetWorldUID(), Pos = pos, Label = DayLabel() }); Store(list); Rebuild(); } } public static bool RemoveUnderPointer(Minimap map) { //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_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)map == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)ZNet.instance == (Object)null) { return false; } if (ScreenToWorld == null || InteractRadius == null) { return false; } Vector3 val = ScreenToWorld(map, ZInput.pointerPosition); float num = InteractRadius(map); long worldUID = ZNet.instance.GetWorldUID(); List<Marker> list = Load(); int num2 = -1; float num3 = num; for (int i = 0; i < list.Count; i++) { if (list[i].World == worldUID) { float num4 = Utils.DistanceXZ(val, list[i].Pos); if (!(num4 > num3)) { num3 = num4; num2 = i; } } } if (num2 < 0) { return false; } list.RemoveAt(num2); Store(list); Rebuild(); return true; } private static string DayLabel() { if ((Object)(object)EnvMan.instance == (Object)null || (Object)(object)ZNet.instance == (Object)null) { return ""; } return $"$hud_mapday {EnvMan.instance.GetDay(ZNet.instance.GetTimeSeconds())}"; } private static void Rebuild() { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Invalid comparison between Unknown and I4 //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) Minimap instance = Minimap.instance; if ((Object)(object)instance == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)ZNet.instance == (Object)null) { return; } List<PinData> list = MapPins.Invoke(instance); for (int num = list.Count - 1; num >= 0; num--) { if ((int)list[num].m_type == 4) { instance.RemovePin(list[num]); } } long worldUID = ZNet.instance.GetWorldUID(); foreach (Marker item in Trim(Load())) { if (item.World == worldUID) { instance.AddPin(item.Pos, (PinType)4, item.Label, false, false, 0L, default(PlatformUserID)); } } } private static List<Marker> Trim(List<Marker> markers) { int value = Plugin.deathMarkersKept.Value; Dictionary<long, int> dictionary = new Dictionary<long, int>(); List<Marker> list = new List<Marker>(); for (int num = markers.Count - 1; num >= 0; num--) { Marker item = markers[num]; dictionary.TryGetValue(item.World, out var value2); if (value2 < value) { dictionary[item.World] = value2 + 1; list.Add(item); } } list.Reverse(); return list; } private static List<Marker> Load() { //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) List<Marker> list = new List<Marker>(); if ((Object)(object)Player.m_localPlayer == (Object)null) { return list; } if (!Player.m_localPlayer.m_customData.TryGetValue("BetterMap.deaths", out var value)) { return list; } if (string.IsNullOrEmpty(value)) { return list; } string[] array = value.Split(new char[1] { '|' }); for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Split(new char[1] { ';' }, 5); if (array2.Length >= 5 && long.TryParse(array2[0], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) && TryFloat(array2[1], out var value2) && TryFloat(array2[2], out var value3) && TryFloat(array2[3], out var value4)) { list.Add(new Marker { World = result, Pos = new Vector3(value2, value3, value4), Label = array2[4] }); } } return list; } private static void Store(List<Marker> markers) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0068: 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) if ((Object)(object)Player.m_localPlayer == (Object)null) { return; } List<string> list = new List<string>(); foreach (Marker item in Trim(markers)) { string[] array = new string[5]; long world = item.World; array[0] = world.ToString(CultureInfo.InvariantCulture); array[1] = Float(item.Pos.x); array[2] = Float(item.Pos.y); array[3] = Float(item.Pos.z); array[4] = item.Label; list.Add(string.Join(";", array)); } Player.m_localPlayer.m_customData["BetterMap.deaths"] = string.Join("|", list.ToArray()); } private static string Float(float value) { return value.ToString("R", CultureInfo.InvariantCulture); } private static bool TryFloat(string text, out float value) { return float.TryParse(text, NumberStyles.Float, CultureInfo.InvariantCulture, out value); } } public static class MapLayout { private const float Margin = 10f; private const float RowGap = 4f; private const float HintScale = 0.7f; private const float ToggleRow = 30f; private const float IconGap = 6f; private static readonly List<RectTransform> Rows = new List<RectTransform>(); public static void Apply() { Minimap instance = Minimap.instance; if (!((Object)(object)instance == (Object)null)) { Biome(instance); Toggles(instance); Hints(instance); } } private static void Biome(Minimap map) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)map.m_biomeNameLarge == (Object)null)) { PinLegend.Anchor(map.m_biomeNameLarge.rectTransform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f)); map.m_biomeNameLarge.rectTransform.anchoredPosition = new Vector2(0f, -10f); map.m_biomeNameLarge.alignment = (TextAlignmentOptions)258; } } private static bool Carries(Transform candidate, Minimap map) { if (!Inside(candidate, (Component)(object)map.m_mapImageLarge) && !Inside(candidate, (Component)(object)map.m_pinRootLarge)) { return Inside(candidate, (Component)(object)map.m_pinNameRootLarge); } return true; } private static bool Inside(Transform candidate, Component thing) { if ((Object)(object)thing != (Object)null) { return thing.transform.IsChildOf(candidate); } return false; } private static void Toggles(Minimap map) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Expected O, but got Unknown //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) Transform val = (((Object)(object)map.m_largeRoot != (Object)null) ? map.m_largeRoot.transform : null); if ((Object)(object)val == (Object)null) { return; } Rows.Clear(); Toggle[] componentsInChildren = ((Component)val).GetComponentsInChildren<Toggle>(true); foreach (Toggle val2 in componentsInChildren) { if ((Object)(object)val2 == (Object)null) { continue; } Transform parent = ((Component)val2).transform.parent; RectTransform val3 = (RectTransform)(((object)((parent is RectTransform) ? parent : null)) ?? ((object)/*isinst with value type is only supported in some contexts*/)); if (!((Object)(object)val3 == (Object)null) && !((Object)(object)val3 == (Object)(object)val) && !Rows.Contains(val3)) { if (Carries((Transform)(object)val3, map)) { Plugin.Logger.LogWarning((object)("MapLayout: " + Path((Transform)(object)val3) + " holds the map itself, leaving the toggles where they are")); Rows.Clear(); return; } Rows.Add(val3); } } if (Rows.Count == 0) { return; } Rows.Sort((RectTransform a, RectTransform b) => a.anchoredPosition.y.CompareTo(b.anchoredPosition.y)); float num = 10f; foreach (RectTransform row in Rows) { PinLegend.Anchor(row, Vector2.zero, Vector2.zero); row.anchoredPosition = new Vector2(10f, num); float num2 = num; Rect rect = row.rect; float num3; if (!(((Rect)(ref rect)).height > 0f)) { num3 = 30f; } else { rect = row.rect; num3 = ((Rect)(ref rect)).height; } num = num2 + (num3 + 4f); } Rows.Clear(); } private static void Hints(Minimap map) { //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: 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_0108: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_012f: 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_0145: Unknown result type (might be due to invalid IL or missing references) if (map.m_hints == null) { return; } foreach (GameObject hint in map.m_hints) { RectTransform val = (RectTransform)(((Object)(object)hint != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null); if ((Object)(object)val == (Object)null) { continue; } if (Carries((Transform)(object)val, map)) { Plugin.Logger.LogWarning((object)("MapLayout: " + Path((Transform)(object)val) + " holds the map itself, leaving the key hints where they are")); continue; } float num = 0f; for (int i = 0; i < ((Transform)val).childCount; i++) { Transform child = ((Transform)val).GetChild(i); RectTransform val2 = (RectTransform)(object)((child is RectTransform) ? child : null); if (val2 != null) { num = Mathf.Max(num, Column(val2)); } } val.anchorMin = new Vector2(val.anchorMin.x, 1f); val.anchorMax = new Vector2(val.anchorMax.x, 1f); val.pivot = new Vector2(val.pivot.x, 1f); val.anchoredPosition = new Vector2(val.anchoredPosition.x, -10f); val.sizeDelta = new Vector2(val.sizeDelta.x, num); ((Transform)val).localScale = Vector3.one; Flush(val, 10f); } } private static float Column(RectTransform panel) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) Strip((Component)(object)panel); float num = 0f; for (int i = 0; i < ((Transform)panel).childCount; i++) { Transform child = ((Transform)panel).GetChild(i); RectTransform val = (RectTransform)(object)((child is RectTransform) ? child : null); if (!((Object)(object)val == (Object)null)) { Rect rect = val.rect; float num2 = ((Rect)(ref rect)).height * 0.7f; Row(val); val.anchorMin = new Vector2(0f, 1f); val.anchorMax = new Vector2(0f, 1f); val.pivot = new Vector2(0f, 1f); ((Transform)val).localScale = Vector3.one * 0.7f; val.anchoredPosition = new Vector2(0f, num); num -= num2 + 4f; } } Flush(panel, 0f); return 0f - num; } private static void Row(RectTransform row) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0098: 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_00d6: 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) //IL_0100: 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_0126: 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) Strip((Component)(object)row); RectTransform val = null; Image[] componentsInChildren = ((Component)row).GetComponentsInChildren<Image>(true); foreach (Image val2 in componentsInChildren) { if (!((Object)(object)val2 == (Object)null) && !((Object)(object)((Component)val2).transform.parent != (Object)(object)row)) { val = ((Graphic)val2).rectTransform; break; } } if ((Object)(object)val != (Object)null) { val.anchorMin = new Vector2(0f, 0.5f); val.anchorMax = new Vector2(0f, 0.5f); val.pivot = new Vector2(0f, 0.5f); val.anchoredPosition = Vector2.zero; } TMP_Text componentInChildren = ((Component)row).GetComponentInChildren<TMP_Text>(true); if (!((Object)(object)componentInChildren == (Object)null)) { RectTransform rectTransform = componentInChildren.rectTransform; rectTransform.anchorMin = new Vector2(0f, 0.5f); rectTransform.anchorMax = new Vector2(0f, 0.5f); rectTransform.pivot = new Vector2(0f, 0.5f); float num; if (!((Object)(object)val != (Object)null)) { num = 0f; } else { Rect rect = val.rect; num = ((Rect)(ref rect)).width + 6f; } rectTransform.anchoredPosition = new Vector2(num, 0f); componentInChildren.alignment = (TextAlignmentOptions)513; } } private static void Strip(Component holder) { LayoutGroup component = holder.GetComponent<LayoutGroup>(); if ((Object)(object)component != (Object)null) { Object.DestroyImmediate((Object)(object)component); } ContentSizeFitter component2 = holder.GetComponent<ContentSizeFitter>(); if ((Object)(object)component2 != (Object)null) { Object.DestroyImmediate((Object)(object)component2); } } private static void Flush(RectTransform rect, float left) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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) if (!Mathf.Approximately(rect.anchorMin.x, rect.anchorMax.x)) { rect.offsetMin = new Vector2(left, rect.offsetMin.y); rect.offsetMax = new Vector2(0f, rect.offsetMax.y); } } private static string Path(Transform t) { string text = ((Object)t).name; Transform parent = t.parent; while ((Object)(object)parent != (Object)null) { text = ((Object)parent).name + "/" + text; parent = parent.parent; } return text; } } [HarmonyPatch] public static class MapZoom { private class Zoom { public float Target; public float Shown; public bool Ready; } private const float Speed = 18f; private static readonly FieldRef<Minimap, float> LargeField = AccessTools.FieldRefAccess<Minimap, float>("m_largeZoom"); private static readonly FieldRef<Minimap, float> SmallField = AccessTools.FieldRefAccess<Minimap, float>("m_smallZoom"); private static readonly Zoom Large = new Zoom(); private static readonly Zoom Small = new Zoom(); private static bool _input; private static bool Active { get { if (Plugin.smoothZoom.Value) { return !ZInput.IsTouchActive(); } return false; } } [HarmonyPrefix] [HarmonyPatch(typeof(Minimap), "UpdateMap")] private static void Minimap_UpdateMap_Prefix(Minimap __instance, float dt) { if (!Active) { Large.Ready = false; Small.Ready = false; return; } if (Step(Large, ref LargeField.Invoke(__instance), dt) | Step(Small, ref SmallField.Invoke(__instance), dt)) { MapPins.RequestRedraw(); } _input = true; } [HarmonyPostfix] [HarmonyPatch(typeof(Minimap), "UpdateMap")] private static void Minimap_UpdateMap_Postfix() { _input = false; } [HarmonyPrefix] [HarmonyPatch(/*Could not decode attribute arguments.*/)] private static void Minimap_LargeZoom_Prefix(Minimap __instance, ref float value) { Retarget(__instance, Large, ref value, LargeField.Invoke(__instance)); } [HarmonyPrefix] [HarmonyPatch(/*Could not decode attribute arguments.*/)] private static void Minimap_SmallZoom_Prefix(Minimap __instance, ref float value) { Retarget(__instance, Small, ref value, SmallField.Invoke(__instance)); } private static void Retarget(Minimap map, Zoom zoom, ref float value, float current) { if (_input && zoom.Ready && !(current <= 0f)) { zoom.Target = Mathf.Clamp(zoom.Target * (value / current), map.m_minZoom, map.m_maxZoom); value = current; } } private static bool Step(Zoom zoom, ref float field, float dt) { if (!zoom.Ready || !Mathf.Approximately(field, zoom.Shown)) { zoom.Target = field; zoom.Shown = field; zoom.Ready = true; return false; } if (Mathf.Approximately(field, zoom.Target)) { return false; } float num = 1f - Mathf.Exp(-18f * dt); float num2 = Mathf.Exp(Mathf.Lerp(Mathf.Log(field), Mathf.Log(zoom.Target), num)); if (Mathf.Abs(num2 / zoom.Target - 1f) < 0.001f) { num2 = zoom.Target; } field = num2; zoom.Shown = num2; return true; } } [HarmonyPatch] public static class MapPatches { [HarmonyPrefix] [HarmonyPatch(typeof(Minimap), "UpdateExplore")] private static void Minimap_UpdateExplore_Prefix(Minimap __instance) { __instance.m_exploreRadius = Plugin.explorationRadius.Value; } [HarmonyPostfix] [HarmonyPatch(typeof(Minimap), "Start")] private static void Minimap_Start_Postfix() { PinLegend.Install(); MapLayout.Apply(); } [HarmonyPostfix] [HarmonyPatch(typeof(Minimap), "SetMapMode")] private static void Minimap_SetMapMode_Postfix(MapMode mode) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 if ((int)mode == 2) { PinLegend.Rescale(); } } [HarmonyPostfix] [HarmonyPatch(typeof(Minimap), "UpdatePins")] private static void Minimap_UpdatePins_Postfix() { MapPins.ApplyScale(); } [HarmonyPrefix] [HarmonyPatch(typeof(Minimap), "RemovePinUnderPointer")] private static void Minimap_RemovePinUnderPointer_Prefix(Minimap __instance, out int __state) { __state = MapPins.Of(__instance).Count; } [HarmonyPostfix] [HarmonyPatch(typeof(Minimap), "RemovePinUnderPointer")] private static void Minimap_RemovePinUnderPointer_Postfix(Minimap __instance, int __state) { if (MapPins.Of(__instance).Count == __state) { DeathMarkers.RemoveUnderPointer(__instance); } } [HarmonyPostfix] [HarmonyPatch(typeof(Player), "OnDeath")] private static void Player_OnDeath_Postfix(Player __instance) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer)) { DeathMarkers.Record(((Component)__instance).transform.position); } } [HarmonyPostfix] [HarmonyPatch(typeof(LocationProxy), "SpawnLocation")] private static void LocationProxy_SpawnLocation_Postfix(LocationProxy __instance, bool __result) { if (__result) { AutoPins.Spawned(__instance); } } [HarmonyPrefix] [HarmonyPatch(typeof(ZNetScene), "OnZDODestroyed")] private static void ZNetScene_OnZDODestroyed_Prefix(ZDO zdo) { PortalPins.Destroyed(zdo); } [HarmonyPostfix] [HarmonyPatch(typeof(Minimap), "SetMapData")] private static void Minimap_SetMapData_Postfix() { DeathMarkers.Invalidate(); AutoPins.Restore(); } } } namespace BetterMap.Scripts.Vehicles { public static class VehicleKinds { public class Kind { public string Prefab; public int Hash; public bool IsBoat; public string Label; } private static List<Kind> _all; private static Dictionary<int, Kind> _byHash; private static readonly List<Kind> Empty = new List<Kind>(); public static bool Ready => Discover() != null; public static List<Kind> All => Discover() ?? Empty; public static Kind Get(int hash) { if (Discover() == null) { return null; } if (!_byHash.TryGetValue(hash, out Kind value)) { return null; } return value; } private static List<Kind> Discover() { if (_all != null) { return _all; } ZNetScene instance = ZNetScene.instance; if ((Object)(object)instance == (Object)null || instance.m_prefabs == null) { return null; } List<Kind> list = new List<Kind>(); Dictionary<int, Kind> dictionary = new Dictionary<int, Kind>(); foreach (GameObject prefab in instance.m_prefabs) { if (!((Object)(object)prefab == (Object)null)) { bool flag = (Object)(object)prefab.GetComponent<Ship>() != (Object)null; if (flag || !((Object)(object)prefab.GetComponent<Vagon>() == (Object)null)) { Piece component = prefab.GetComponent<Piece>(); string label = (((Object)(object)component != (Object)null && !string.IsNullOrEmpty(component.m_name) && Localization.instance != null) ? Localization.instance.Localize(component.m_name) : null); Kind kind = new Kind { Prefab = ((Object)prefab).name, Hash = StringExtensionMethods.GetStableHashCode(((Object)prefab).name), IsBoat = flag, Label = label }; list.Add(kind); dictionary[kind.Hash] = kind; } } } if (list.Count == 0) { return null; } _all = list; _byHash = dictionary; if (Plugin.debugMode.Value) { foreach (Kind item in list) { Plugin.Logger.LogInfo((object)("VehicleKinds: " + item.Prefab + " (" + (item.IsBoat ? "boat" : "cart") + ", " + (item.Label ?? "unnamed") + ")")); } } return _all; } } public readonly struct Owned : IEquatable<Owned> { public readonly long User; public readonly uint Id; public Owned(long user, uint id) { User = user; Id = id; } public bool Equals(Owned other) { if (User == other.User) { return Id == other.Id; } return false; } public override bool Equals(object other) { if (other is Owned other2) { return Equals(other2); } return false; } public override int GetHashCode() { long user = User; return (user.GetHashCode() * 397) ^ (int)Id; } } public static class VehicleMemory { private const string CustomDataKey = "BetterMap.vehicles"; private static readonly HashSet<Owned> _used = new HashSet<Owned>(); private static long _world; private static bool _loaded; public static void Remember(ZDOID id) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) if (id == ZDOID.None) { return; } Load(); if (_loaded && _used.Add(new Owned(((ZDOID)(ref id)).UserID, ((ZDOID)(ref id)).ID))) { Store(); if (Plugin.debugMode.Value) { Plugin.Logger.LogInfo((object)$"VehicleMemory: remembered {id}"); } } } public static HashSet<Owned> Used() { Load(); return _used; } public static void Forget() { _used.Clear(); _loaded = false; _world = 0L; } private static void Load() { if ((Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)ZNet.instance == (Object)null) { return; } long worldUID = ZNet.instance.GetWorldUID(); if (_loaded && _world == worldUID) { return; } _used.Clear(); _world = worldUID; _loaded = true; if (!Player.m_localPlayer.m_customData.TryGetValue("BetterMap.vehicles", out var value) || string.IsNullOrEmpty(value)) { return; } string[] array = value.Split(new char[1] { '|' }); for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Split(new char[1] { ';' }); if (array2.Length == 3 && long.TryParse(array2[0], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) && result == worldUID && long.TryParse(array2[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result2) && uint.TryParse(array2[2], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result3)) { _used.Add(new Owned(result2, result3)); } } } private static void Store() { if ((Object)(object)Player.m_localPlayer == (Object)null) { return; } List<string> list = new List<string>(); if (Player.m_localPlayer.m_customData.TryGetValue("BetterMap.vehicles", out var value) && !string.IsNullOrEmpty(value)) { string[] array = value.Split(new char[1] { '|' }); foreach (string text in array) { string[] array2 = text.Split(new char[1] { ';' }); if (array2.Length == 3 && long.TryParse(array2[0], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) && result != _world) { list.Add(text); } } } foreach (Owned item in _used) { string[] obj = new string[3] { _world.ToString(CultureInfo.InvariantCulture), null, null }; long user = item.User; obj[1] = user.ToString(CultureInfo.InvariantCulture); uint id = item.Id; obj[2] = id.ToString(CultureInfo.InvariantCulture); list.Add(string.Join(";", obj)); } Player.m_localPlayer.m_customData["BetterMap.vehicles"] = string.Join("|", list.ToArray()); } } public static class VehicleIndex { public struct Record { public ZDOID Id; public int Prefab; public Vector3 Pos; public float Heading; public long Creator; } private class Request { public long Peer; public long Player; public HashSet<ZDOID> Used; } private static readonly List<Record> _records = new List<Record>(); private static readonly List<Request> _pending = new List<Request>(); private static readonly List<ZDO> _found = new List<ZDO>(); private static readonly List<Record> _matched = new List<Record>(); private static int _kindIndex; private static int _sectorIndex; private static bool _scanning; private static float _scannedAt = float.NegativeInfinity; public static void Ask(long peer, long player, HashSet<ZDOID> used) { if (!_scanning && Time.time - _scannedAt < Plugin.vehicleRefreshInterval.Value) { Answer(new Request { Peer = peer, Player = player, Used = used }); } else { _pending.Add(new Request { Peer = peer, Player = player, Used = used }); } } public static void Tick() { if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || ZDOMan.instance == null || !VehicleKinds.Ready) { return; } if (!_scanning) { if (_pending.Count == 0) { return; } _scanning = true; _kindIndex = 0; _sectorIndex = 0; _found.Clear(); } Scan(); } private static void Scan() { List<VehicleKinds.Kind> all = VehicleKinds.All; if (_kindIndex < all.Count) { if (ZDOMan.instance.GetAllZDOsWithPrefabIterative(all[_kindIndex].Prefab, _found, ref _sectorIndex)) { _kindIndex++; _sectorIndex = 0; } return; } Collect(); _scanning = false; _scannedAt = Time.time; foreach (Request item in _pending) { Answer(item); } _pending.Clear(); } private static void Collect() { //IL_0043: 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_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) _records.Clear(); foreach (ZDO item2 in _found) { if (item2 != null && item2.IsValid()) { List<Record> records = _records; Record item = new Record { Id = item2.m_uid, Prefab = item2.GetPrefab(), Pos = item2.GetPosition() }; Quaternion rotation = item2.GetRotation(); item.Heading = ((Quaternion)(ref rotation)).eulerAngles.y; item.Creator = item2.GetLong(ZDOVars.s_creator, 0L); records.Add(item); } } _found.Clear(); } private static void Answer(Request request) { //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Expected O, but got Unknown //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) _matched.Clear(); foreach (Record record in _records) { if ((record.Creator != 0L && record.Creator == request.Player) || (request.Used != null && request.Used.Contains(record.Id))) { _matched.Add(record); } } ZPackage val = new ZPackage(); val.Write(_matched.Count); foreach (Record item in _matched) { val.Write(item.Id); val.Write(item.Prefab); val.Write(item.Pos); val.Write(item.Heading); } VehicleRpc.Reply(request.Peer, val); } } public static class VehicleRpc { private const string RequestName = "BetterMap_VehiclesRequest"; private const string ResponseName = "BetterMap_VehiclesResponse"; public static readonly List<VehicleIndex.Record> Remote = new List<VehicleIndex.Record>(); private static bool _registered; private static float _nextRequest; public static void Register() { if (!_registered && ZRoutedRpc.instance != null) { _registered = true; ZRoutedRpc.instance.Register<ZPackage>("BetterMap_VehiclesRequest", (Action<long, ZPackage>)OnRequest); ZRoutedRpc.instance.Register<ZPackage>("BetterMap_VehiclesResponse", (Action<long, ZPackage>)OnResponse); } } public static void Reset() { _registered = false; _nextRequest = 0f; Remote.Clear(); } public static void Tick() { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown if (ZRoutedRpc.instance == null || (Object)(object)Player.m_localPlayer == (Object)null || Time.time < _nextRequest) { return; } _nextRequest = Time.time + Plugin.vehicleRefreshInterval.Value; ZPackage val = new ZPackage(); val.Write(Player.m_localPlayer.GetPlayerID()); HashSet<Owned> hashSet = VehicleMemory.Used(); val.Write(hashSet.Count); foreach (Owned item in hashSet) { val.Write(item.User); val.Write(item.Id); } ZRoutedRpc.instance.InvokeRoutedRPC("BetterMap_VehiclesRequest", new object[1] { val }); } private static void OnRequest(long sender, ZPackage package) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer() && package != null) { long player = package.ReadLong(); int num = package.ReadInt(); HashSet<ZDOID> hashSet = new HashSet<ZDOID>(); for (int i = 0; i < num; i++) { hashSet.Add(package.ReadZDOID()); } VehicleIndex.Ask(sender, player, hashSet); } } public static void Reply(long peer, ZPackage package) { if (ZRoutedRpc.instance != null) { ZRoutedRpc.instance.InvokeRoutedRPC(peer, "BetterMap_VehiclesResponse", new object[1] { package }); } } private static void OnResponse(long sender, ZPackage package) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) if (package != null) { Remote.Clear(); int num = package.ReadInt(); for (int i = 0; i < num; i++) { Remote.Add(new VehicleIndex.Record { Id = package.ReadZDOID(), Prefab = package.ReadInt(), Pos = package.ReadVector3(), Heading = package.ReadSingle() }); } if (Plugin.debugMode.Value) { Plugin.Logger.LogInfo((object)$"VehicleRpc: {num} of my vehicles"); } } } } public static class VehicleTracker { private class Tracked { public PinData Pin; public Transform Instance; public float Heading; } private struct Vehicle { public Transform Instance; public Vector3 Pos; public float Heading; public VehicleKinds.Kind Kind; } private static readonly FieldRef<List<Vagon>> Carts = AccessTools.StaticFieldRefAccess<List<Vagon>>(AccessTools.Field(typeof(Vagon), "m_instances")); private static readonly Dictionary<ZDOID, Tracked> _tracked = new Dictionary<ZDOID, Tracked>(); private static readonly Dictionary<ZDOID, Vehicle> _wanted = new Dictionary<ZDOID, Vehicle>(); private static readonly List<ZDOID> _gone = new List<ZDOID>(); private static bool _named; public static void Tick() { bool value = Plugin.showBoats.Value; bool value2 = Plugin.showCarts.Value; if (!value && !value2) { if (_tracked.Count > 0) { Clear(); } } else if (!((Object)(object)Minimap.instance == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null) && VehicleKinds.Ready) { if (_named != Plugin.showVehicleNames.Value) { _named = Plugin.showVehicleNames.Value; Clear(); } VehicleRpc.Tick(); Gather(value, value2); Reconcile(); UpdatePositions(); } } private static void Gather(bool wantBoats, bool wantCarts) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_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) _wanted.Clear(); Vector3 position = ((Component)Player.m_localPlayer).transform.position; float value = Plugin.vehicleRadius.Value; float rangeSqr = value * value; foreach (IMonoUpdater instance in Ship.Instances) { Ship val = (Ship)(object)((instance is Ship) ? instance : null); if (!((Object)(object)val == (Object)null)) { Consider(((Component)val).gameObject, wantBoats, wantCarts, position, rangeSqr); } } List<Vagon> list = Carts.Invoke(); if (list != null) { foreach (Vagon item in list) { if (!((Object)(object)item == (Object)null)) { Consider(((Component)item).gameObject, wantBoats, wantCarts, position, rangeSqr); } } } foreach (VehicleIndex.Record item2 in VehicleRpc.Remote) { if (!_wanted.ContainsKey(item2.Id)) { VehicleKinds.Kind kind = VehicleKinds.Get(item2.Prefab); if (kind != null && !(kind.IsBoat ? (!wantBoats) : (!wantCarts))) { _wanted[item2.Id] = new Vehicle { Instance = null, Pos = item2.Pos, Heading = item2.Heading, Kind = kind }; } } } } private static void Consider(GameObject go, bool wantBoats, bool wantCarts, Vector3 origin, float rangeSqr) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) ZNetView component = go.GetComponent<ZNetView>(); if ((Object)(object)component == (Object)null || !component.IsValid()) { return; } Vector3 position = go.transform.position; Vector3 val = position - origin; if (!(((Vector3)(ref val)).sqrMagnitude > rangeSqr)) { ZDO zDO = component.GetZDO(); VehicleKinds.Kind kind = VehicleKinds.Get(zDO.GetPrefab()); if (kind != null && !(kind.IsBoat ? (!wantBoats) : (!wantCarts))) { Dictionary<ZDOID, Vehicle> wanted = _wanted; ZDOID uid = zDO.m_uid; Vehicle value = new Vehicle { Instance = go.transform, Pos = position }; Quaternion rotation = go.transform.rotation; value.Heading = ((Quaternion)(ref rotation)).eulerAngles.y; value.Kind = kind; wanted[uid] = value; } } } private static void Reconcile() { //IL_002f: 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_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008a: 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) //IL_00ee: 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_012d: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Expected O, but got Unknown Minimap instance = Minimap.instance; _gone.Clear(); foreach (KeyValuePair<ZDOID, Tracked> item in _tracked) { if (!_wanted.ContainsKey(item.Key)) { _gone.Add(item.Key); } } foreach (ZDOID item2 in _gone) { instance.RemovePin(_tracked[item2].Pin); _tracked.Remove(item2); } foreach (KeyValuePair<ZDOID, Vehicle> item3 in _wanted) { Vehicle value = item3.Value; if (_tracked.TryGetValue(item3.Key, out Tracked value2)) { value2.Instance = value.Instance; if ((Object)(object)value.Instance == (Object)null) { value2.Pin.m_pos = value.Pos; value2.Heading = value.Heading; } continue; } bool flag = _named && !string.IsNullOrEmpty(value.Kind.Label); PinData val = instance.AddPin(value.Pos, PinLegend.VehicleType, flag ? value.Kind.Label : "", false, false, 0L, default(PlatformUserID)); Sprite val2 = (value.Kind.IsBoat ? Icons.Boat : Icons.Cart); if ((Object)(object)val2 != (Object)null) { val.m_icon = val2; } if (flag) { val.m_NamePinData = new PinNameData(val); } _tracked[item3.Key] = new Tracked { Pin = val, Instance = value.Instance, Heading = value.Heading }; } } private static void UpdatePositions() { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: 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_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) bool flag = false; foreach (KeyValuePair<ZDOID, Tracked> item in _tracked) { Tracked value = item.Value; if (!((Object)(object)value.Instance == (Object)null)) { Vector3 position = value.Instance.position; if (value.Pin.m_pos != position) { value.Pin.m_pos = position; flag = true; } Quaternion rotation = value.Instance.rotation; value.Heading = ((Quaternion)(ref rotation)).eulerAngles.y; } } if (flag) { MapPins.RequestRedraw(); } } public static void RestylePins() { //IL_007c: Unknown result type (might be due to invalid IL or missing references) if (_tracked.Count == 0 || !Plugin.rotateBoatIcons.Value) { return; } foreach (KeyValuePair<ZDOID, Tracked> item in _tracked) { Tracked value = item.Value; if (value.Pin != null && !((Object)(object)value.Pin.m_uiElement == (Object)null)) { ((Transform)value.Pin.m_uiElement).localRotation = Quaternion.Euler(0f, 0f, 0f - value.Heading); } } } public static void Clear() { if ((Object)(object)Minimap.instance != (Object)null) { foreach (KeyValuePair<ZDOID, Tracked> item in _tracked) { if (item.Value.Pin != null) { Minimap.instance.RemovePin(item.Value.Pin); } } } _tracked.Clear(); _wanted.Clear(); } } [HarmonyPatch] public static class VehiclePatches { [HarmonyPostfix] [HarmonyPatch(typeof(Minimap), "UpdatePins")] private static void Minimap_UpdatePins_Postfix() { VehicleTracker.RestylePins(); } [HarmonyPostfix] [HarmonyPatch(typeof(Minimap), "UpdatePlayerMarker")] private static void Minimap_UpdatePlayerMarker_Postfix(Minimap __instance) { if (Plugin.showBoats.Value) { if ((Object)(object)__instance.m_smallShipMarker != (Object)null) { ((Component)__instance.m_smallShipMarker).gameObject.SetActive(false); } if ((Object)(object)__instance.m_largeShipMarker != (Object)null) { ((Component)__instance.m_largeShipMarker).gameObject.SetActive(false); } } } [HarmonyPostfix] [HarmonyPatch(typeof(Player), "StartDoodadControl")] private static void Player_StartDoodadControl_Postfix(Player __instance, IDoodadController shipControl) { if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && shipControl != null) { Remember(shipControl.GetControlledComponent()); } } [HarmonyPostfix] [HarmonyPatch(typeof(Vagon), "AttachTo")] private static void Vagon_AttachTo_Postfix(Vagon __instance, GameObject go) { if (!((Object)(object)Player.m_localPlayer == (Object)null) && !((Object)(object)go != (Object)(object)((Component)Player.m_localPlayer).gameObject)) { Remember((Component)(object)__instance); } } private static void Remember(Component component) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)component == (Object)null)) { ZNetView component2 = component.GetComponent<ZNetView>(); if (!((Object)(object)component2 == (Object)null) && component2.IsValid() && VehicleKinds.Get(component2.GetZDO().GetPrefab()) != null) { VehicleMemory.Remember(component2.GetZDO().m_uid); } } } [HarmonyPostfix] [HarmonyPatch(typeof(Game), "Start")] private static void Game_Start_Postfix() { VehicleRpc.Register(); } [HarmonyPostfix] [HarmonyPatch(typeof(Game), "Logout")] private static void Game_Logout_Postfix() { VehicleRpc.Reset(); VehicleMemory.Forget(); } } } namespace BetterMap.Scripts.Creatures { public static class CreatureIcons { private static readonly Dictionary<string, Sprite> _icons = new Dictionary<string, Sprite>(); public static Sprite Get(Character creature) { if ((Object)(object)creature == (Object)null) { return null; } string text = PrefabName(((Component)creature).gameObject); if (_icons.TryGetValue(text, out Sprite value)) { return value; } Sprite val = Resolve(((Component)creature).gameObject); _icons[text] = val; if (Plugin.debugMode.Value) { Plugin.Logger.LogInfo((object)("CreatureIcons: " + text + " -> " + (((Object)(object)val != (Object)null) ? ((Object)val).name : "no trophy"))); } return val; } private static Sprite Resolve(GameObject prefab) { //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Expected O, but got Unknown CharacterDrop component = prefab.GetComponent<CharacterDrop>(); if (component?.m_drops == null) { return null; } foreach (Drop drop in component.m_drops) { if (!((Object)(object)drop?.m_prefab == (Object)null) && ((Object)drop.m_prefab).name.StartsWith("Trophy", StringComparison.OrdinalIgnoreCase)) { Sprite[] array = drop.m_prefab.GetComponent<ItemDrop>()?.m_itemData?.m_shared?.m_icons; if (array != null && array.Length != 0) { return array[0]; } } } return null; } public static string PrefabName(GameObject go) { string name = ((Object)go).name; int num = name.IndexOf("(Clone)", StringComparison.Ordinal); if (num >= 0) { return name.Substring(0, num); } return name; } public static void Clear() { _icons.Clear(); } } public static class CreatureTracker { private class Tracked { public Character Creature; public PinData Pin; public bool Tamed; public bool Named; public string Label; public bool Hostile; public bool HasIcon; public int Level; } private struct Style { public Sprite Icon; public bool Tamed; public bool Named; public string Label; public bool Hostile; } private static readonly Dictionary<Character, Tracked> _tracked = new Dictionary<Character, Tracked>(); private static readonly List<Character> _leaving = new List<Character>(); private static readonly List<Character> _characters = new List<Character>(); private static float _nextRefresh; private static readonly HashSet<string> Excluded = new HashSet<string> { "piece_TrainingDummy", "FrozenKing_p2", "FrozenKing_p3" }; private static readonly Color TamedTint = new Color(0.45f, 0.95f, 0.45f, 1f); private static readonly Color HostileTint = new Color(0.95f, 0.4f, 0.4f, 1f); public static void Tick() { if (!Plugin.showCreatures.Value) { if (_tracked.Count > 0) { Clear(); } } else if (!((Object)(object)Minimap.instance == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null)) { if (Time.time >= _nextRefresh) { _nextRefresh = Time.time + Plugin.creatureRefreshInterval.Value; Refresh(); } UpdatePositions(); } } private static void Refresh() { //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_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //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_024d: Unknown result type (might be due to invalid IL or missing references) //IL_0252: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Unknown result type (might be due to invalid IL or missing references) Vector3 position = ((Component)Player.m_localPlayer).transform.position; float value = Plugin.creatureRadius.Value; float num = value * value; _leaving.Clear(); Vector3 val; foreach (KeyValuePair<Character, Tracked> item in _tracked) { Character key = item.Key; if (!((Object)(object)key == (Object)null) && !key.IsDead()) { val = ((Component)key).transform.position - position; if (!(((Vector3)(ref val)).sqrMagnitude > num)) { continue; } } _leaving.Add(key); } foreach (Character item2 in _leaving) { Remove(item2); } _leaving.Clear(); foreach (KeyValuePair<Character, Tracked> item3 in _tracked) { if (!((Object)(object)item3.Key == (Object)null)) { Style style = Describe(item3.Key); Tracked value2 = item3.Value; value2.Hostile = style.Hostile; if (style.Tamed != value2.Tamed || style.Named != value2.Named || (style.Named && style.Label != value2.Label)) { _leaving.Add(item3.Key); } } } foreach (Character item4 in _leaving) { Remove(item4); Add(item4); } _characters.Clear(); _characters.AddRange(Character.GetAllCharacters()); foreach (Character character in _characters) { if (!_tracked.ContainsKey(character) && ShouldTrack(character)) { val = ((Component)character).transform.position - position; if (!(((Vector3)(ref val)).sqrMagnitude > num)) { Add(character); } } } } private static void UpdatePositions() { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: 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_0066: 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) bool flag = false; foreach (KeyValuePair<Character, Tracked> item in _tracked) { if (!((Object)(object)item.Key == (Object)null)) { Vector3 position = ((Component)item.Key).transform.position; if (!(item.Value.Pin.m_pos == position)) { item.Value.Pin.m_pos = position; flag = true; } } } if (flag) { MapPins.RequestRedraw(); } } private static bool ShouldTrack(Character creature) { if ((Object)(object)creature == (Object)null || creature.IsDead()) { return false; } if (creature.IsPlayer()) { return false; } if ((Object)(object)((Component)creature).GetComponent<CharacterTimedDestruction>() != (Object)null) { return false; } string text = CreatureIcons.PrefabName(((Component)creature).gameObject); if (text.StartsWith("Aspect_", StringComparison.Ordinal)) { return false; } if (Excluded.Contains(text)) { return false; } return true; } private static Style Describe(Character creature) { Sprite val = CreatureIcons.Get(creature); bool flag = creature.IsTamed(); string text = GivenName(creature); bool flag2 = (Object)(object)val == (Object)null || (flag && !string.IsNullOrEmpty(text)) || Plugin.showEntityNames.Value; return new Style { Icon = val, Tamed = flag, Named = flag2, Hostile = IsHostile(creature, flag), Label = ((!flag2) ? null : ((!string.IsNullOrEmpty(text)) ? text : Localization.instance.Localize(creature.m_name))) }; } private static void Add(Character creature) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_003d: 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_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Expected O, but got Unknown Style style = Describe(creature); PinData val = Minimap.instance.AddPin(((Component)creature).transform.position, PinLegend.CreatureType, style.Named ? style.Label : "", false, false, 0L, default(PlatformUserID)); if ((Object)(object)style.Icon != (Object)null) { val.m_icon = style.Icon; } if (style.Named) { val.m_NamePinData = new PinNameData(val); } _tracked[creature] = new Tracked { Creature = creature, Pin = val, Tamed = style.Tamed, Named = style.Named, Label = style.Label, Hostile = style.Hostile, HasIcon = ((Object)(object)style.Icon != (Object)null), Level = creature.GetLevel() }; } private static bool IsHostile(Character creature, bool tamed) { if (tamed) { return false; } BaseAI baseAI = creature.GetBaseAI(); MonsterAI val = (MonsterAI)(object)((baseAI is MonsterAI) ? baseAI : null); if ((Object)(object)val == (Object)null) { return false; } if (((BaseAI)val).m_aggravatable && !((BaseAI)val).IsAggravated()) { return false; } if ((Object)(object)ZoneSystem.instance != (Object)null && ZoneSystem.instance.GetGlobalKey((GlobalKeys)30)) { return false; } return true; } private static void Remove(Character creature) { if (_tracked.TryGetValue(creature, out Tracked value)) { _tracked.Remove(creature); if ((Object)(object)Minimap.instance != (Object)null && value.Pin != null) { Minimap.instance.RemovePin(value.Pin); } } } private static string GivenName(Character creature) { Tameable component = ((Component)creature).GetComponent<Tameable>(); if ((Object)(object)component == (Object)null) { return null; } string text = component.GetText(); if (!string.IsNullOrEmpty(text)) { return text; } return null; } public static void RestylePins() { //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) if (_tracked.Count == 0 || (Object)(object)Minimap.instance == (Object)null) { return; } bool value = Plugin.tintTamedCreatures.Value; bool value2 = Plugin.tintHostileCreatures.Value; foreach (KeyValuePair<Character, Tracked> item in _tracked) { Tracked value3 = item.Value; PinData pin = value3.Pin; if ((Object)(object)pin?.m_iconElement == (Object)null) { continue; } CreatureStars.Apply(pin, value3.Level); if (value3.Tamed) { if (value) { ((Graphic)pin.m_iconElement).color = TamedTint; } } else if (value2 && value3.Hostile && !value3.HasIcon) { ((Graphic)pin.m_iconElement).color = HostileTint; } } } public static void Clear() { if ((Object)(object)Minimap.instance != (Object)null) { foreach (KeyValuePair<Character, Tracked> item in _tracked) { if (item.Value.Pin != null) { Minimap.instance.RemovePin(item.Value.Pin); } } } _tracked.Clear(); } } public static class CreatureStars { private const string ChildName = "BetterMap_Stars"; private static Sprite _star; private static TMP_FontAsset _font; private static Material _material; private static Color _color; private static readonly Color Gold = new Color(1f, 0.8f, 0.2f, 1f); private static bool _gaveUp; public static void Apply(PinData pin, int level) { if ((Object)(object)pin?.m_uiElement == (Object)null) { return; } Transform val = ((Transform)pin.m_uiElement).Find("BetterMap_Stars"); int num = level - 1; if (num < 1 || !Plugin.showCreatureStars.Value) { if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)((Component)val).gameObject); } } else if (!((Object)(object)val != (Object)null) && Borrow()) { Build(pin.m_uiElement, num); } } private static bool Borrow() { //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_star != (Object)null && (Object)(object)_font != (Object)null) { return true; } if (_gaveUp) { return false; } EnemyHud instance = EnemyHud.instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance.m_baseHud == (Object)null) { return false; } Transform val = instance.m_baseHud.transform.Find("level_2"); Image val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponentInChildren<Image>(true) : null); Transform val3 = instance.m_baseHud.transform.Find("Name"); TextMeshProUGUI val4 = (((Object)(object)val3 != (Object)null) ? ((Component)val3).GetComponent<TextMeshProUGUI>() : null); if ((Object)(object)val2 == (Object)null || (Object)(object)val2.sprite == (Object)null || (Object)(object)val4 == (Object)null || (Object)(object)((TMP_Text)val4).font == (Object)null) { _gaveUp = true; Plugin.Logger.LogWarning((object)"CreatureStars: the creature health bar does not look the way it used to, no stars on the map"); return false; } _star = val2.sprite; _font = ((TMP_Text)val4).font; _material = ((TMP_Text)val4).fontSharedMaterial; float num = default(float); float num2 = default(float); float num3 = default(float); Color.RGBToHSV(((Graphic)val2).color, ref num, ref num2, ref num3); _color = ((num2 > 0.3f) ? ((Graphic)val2).color : Gold); return true; } private static void Build(RectTransform marker, int stars) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: 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_00d8: 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_00fd: 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_013e: Unknown result type (might be due to invalid IL or missing references) //IL_015c: 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_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) Transform transform = new GameObject("BetterMap_Stars", new Type[1] { typeof(RectTransform) }).transform; RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null); ((Transform)val).SetParent((Transform)(object)marker, false); val.anchorMin = new Vector2(0.1f, 0.95f); val.anchorMax = new Vector2(0.9f, 1.45f); val.offsetMin = Vector2.zero; val.offsetMax = Vector2.zero; GameObject val2 = new GameObject("Star", new Type[2] { typeof(RectTransform), typeof(Image) }); Transform transform2 = val2.transform; Transform obj = ((transform2 is RectTransform) ? transform2 : null); obj.SetParent((Transform)(object)val, false); ((RectTransform)obj).anchorMin = new Vector2(0.15f, 0f); ((RectTransform)obj).anchorMax = new Vector2(0.5f, 1f); ((RectTransform)obj).offsetMin = Vector2.zero; ((RectTransform)obj).offsetMax = Vector2.zero; Image component = val2.GetComponent<Image>(); component.sprite = _star; ((Graphic)component).color = _color; component.preserveAspect = true; ((Graphic)component).raycastTarget = false; GameObject val3 = new GameObject("Count", new Type[2] { typeof(RectTransform), typeof(TextMeshProUGUI) }); Transform transform3 = val3.transform; Transform obj2 = ((transform3 is RectTransform) ? transform3 : null); obj2.SetParent((Transform)(object)val, false); ((RectTransform)obj2).anchorMin = new Vector2(0.52f, 0f); ((RectTransform)obj2).anchorMax = new Vector2(0.95f, 1f); ((RectTransform)obj2).offsetMin = Vector2.zero; ((RectTransform)obj2).offsetMax = Vector2.zero; TextMeshProUGUI component2 = val3.GetComponent<TextMeshProUGUI>(); ((TMP_Text)component2).font = _font; if ((Object)(object)_material != (Object)null) { ((TMP_Text)component2).fontSharedMaterial = _material; } ((TMP_Text)component2).text = stars.ToString(); ((TMP_Text)component2).enableAutoSizing = true; ((TMP_Text)component2).fontSizeMin = 1f; ((TMP_Text)component2).fontSizeMax = 72f; ((TMP_Text)component2).fontStyle = (FontStyles)1; ((TMP_Text)component2).alignment = (TextAlignmentOptions)4097; ((TMP_Text)component2).textWrappingMode = (TextWrappingModes)0; ((Graphic)component2).color = Color.white; ((Graphic)component2).raycastTarget = false; } } [HarmonyPatch] public static class CreaturePatches { [HarmonyPostfix] [HarmonyPatch(typeof(Minimap), "UpdatePins")] private static void Minimap_UpdatePins_Postfix() { CreatureTracker.RestylePins(); } } } namespace BetterMap.Scripts.Pins { public enum PinCategory { Ore, Forage, Dungeon, Loot, Spawner, Vegvisir, Beehive, Tar, Sap, Boss, Portal } public static class PinRules { public class Rule { public string Name; public string Description; public string NameToken; public string[] Prefabs; public Biome Biome; public PinCategory Category; public bool DefaultOn; public bool IsLocation; public ConfigEntry<bool> Enabled; public Type Component; } public static readonly List<Rule> All = new List<Rule> { new Rule { Name = "Beehives", Description = "Wild beehives, in and around the abandoned houses. Honey and a queen bee.", NameToken = "$piece_beehive", Prefabs = new string[1] { "Beehive" }, Biome = (Biome)1, Category = PinCategory.Beehive, DefaultOn = true, IsLocation = false }, new Rule { Name = "Vegvisirs", Description = "The runestones that reveal a boss on your map.", NameToken = "$piece_vegvisir", Component = typeof(Vegvisir), Biome = (Biome)1, Category = PinCategory.Vegvisir, DefaultOn = true, IsLocation = false }, new Rule { Name = "Raspberry Bushes", Description = "Raspberry bushes.", Prefabs = new string[1] { "RaspberryBush" }, Biome = (Biome)1, Category = PinCategory.Forage, DefaultOn = false, IsLocation = false }, new Rule { Name = "Flint", Description = "Flint along the shoreline.", Prefabs = new string[1] { "Pickable_Flint" }, Biome = (Biome)1, Category = PinCategory.Forage, DefaultOn = false, IsLocation = false }, new Rule { Name = "Mushrooms", Description = "Ordinary mushrooms.", Prefabs = new string[1] { "Pickable_Mushroom" }, Biome = (Biome)1, Category = PinCategory.Forage, DefaultOn = false, IsLocation = false }, new Rule { Name = "Dandelions", Description = "Dandelions.", Prefabs = new string[1] { "Pickable_Dandelion" }, Biome = (Biome)1, Category = PinCategory.Forage, DefaultOn = false, IsLocation = false }, new Rule { Name = "Boar Runestones", Description = "Runestones ringed by boar spawners. A place to farm, not a place to gather.", Prefabs = new string[1] { "Runestone_Boars" }, Biome = (Biome)1, Category = PinCategory.Spawner, DefaultOn = false, IsLocation = true }, new Rule { Name = "Altar of Eikthyr", Description = "Where Eikthyr is summoned. Off by default: use a vegvisir and the game pins it for you.", Prefabs = new string[1] { "Eikthyrnir" }, Biome = (Biome)1, Category = PinCategory.Boss, DefaultOn = false, IsLocation = true }, new Rule { Name = "Vegvisirs", Description = "The runestones that reveal a boss on your map. Pinned wherever they stand, rather than the ruin around them.", NameToken = "$piece_vegvisir", Component = typeof(Vegvisir), Biome = (Biome)8, Category = PinCategory.Vegvisir, DefaultOn = true, IsLocation = false }, new Rule { Name = "Copper Deposits", Description = "The large half buried rocks you mine for copper.", Prefabs = new string[1] { "rock4_copper" }, Biome = (Biome)8, Category = PinCategory.Ore, DefaultOn = true, IsLocation = false }, new Rule { Name = "Tin Deposits", Description = "Tin along the water's edge.", Prefabs = new string[1] { "MineRock_Tin" }, Biome = (Biome)8, Category = PinCategory.Ore, DefaultOn = true, IsLocation = false }, new Rule { Name = "Beehives", Description = "Wild beehives in the abandoned houses.", NameToken = "$piece_beehive", Prefabs = new string[1] { "Beehive" }, Biome = (Biome)8, Category = PinCategory.Beehive, DefaultOn = true, IsLocation = false }, new Rule { Name = "Blueberry Bushes", Description = "Blueberry bushes. Common enough that pinning them fills the map quickly.", Prefabs = new string[1] { "BlueberryBush" }, Biome = (Biome)8, Category = PinCategory.Forage, DefaultOn = false, IsLocation = false }, new Rule { Name = "Thistle", Description = "Thistle, which glows at night and is easier to spot than to pin.", Prefabs = new string[1] { "Pickable_Thistle" }, Biome = (Biome)8, Category = PinCategory.Forage, DefaultOn = false, IsLocation = false }, new Rule { Name = "Carrot Seeds", Description = "Wild carrot seeds. Rare, and the only way to start a carrot farm.", Prefabs = new string[1] { "Pickable_SeedCarrot" }, Biome = (Biome)8, Category = PinCategory.Forage, DefaultOn = true, IsLocation = false }, new Rule { Name = "Greydwarf Nests", Description = "The nests that keep sending greydwarfs at you. Break one for an ancient seed.", NameToken = "Greydwarf Nest", Prefabs = new string[1] { "Spawner_GreydwarfNest" }, Biome = (Biome)8, Category = PinCategory.Spawner, DefaultOn = false, IsLocation = false }, new Rule { Name = "Greydwarf Runestones", Description = "Runestones ringed by greydwarf spawners.", Prefabs = new string[1] { "Runestone_Greydwarfs" }, Biome = (Biome)8, Category = PinCategory.Spawner, DefaultOn = false, IsLocation = true }, new Rule { Name = "Burial Chambers", Description = "The entrances to burial chambers, where the surtling cores are.", Prefabs = new string[3] { "Crypt2", "Crypt3", "Crypt4" }, Biome = (Biome)8, Category = PinCategory.Dungeon, DefaultOn = true, IsLocation = true }, new Rule { Name = "Troll Caves", Description = "Troll cave entrances.", Prefabs = new string[1] { "TrollCave02" }, Biome = (Biome)8, Category = PinCategory.Dungeon, DefaultOn = true, IsLocation = true }, new Rule { Name = "Bear Caves", Description = "Bear cave entrances.", Prefabs = new string[1] { "BearCave" }, Biome = (Biome)8, Category = PinCategory.Dungeon, DefaultOn = true, IsLocation = true }, new Rule { Name = "Mushrooms", Description = "Ordinary mushrooms.", Prefabs = new string[1] { "Pickable_Mushroom" }, Biome = (Biome)8, Category = PinCategory.Forage, DefaultOn = false, IsLocation = false }, new Rule { Name = "Altar of the Elder", Description = "Where the Elder is summoned. Off by default: use a vegvisir and the game pins it for you.", Prefabs = new string[1] { "GDKing" }, Biome = (Biome)8, Category = PinCategory.Boss, DefaultOn = false, IsLocation = true }, new Rule { Name = "Vegvisirs", Description = "The runestones that reveal a boss on your map.", NameToken = "$piece_vegvisir", Component = typeof(Vegvisir), Biome = (Biome)2, Category = PinCategory.Vegvisir, DefaultOn = true, IsLocation = false }, new Rule { Name = "Turnip Seeds", Description = "Wild turnip seeds. Rare, and the only way to start a turnip farm.", Prefabs = new string[1] { "Pickable_SeedTurnip" }, Biome = (Biome)2, Category = PinCategory.Forage, DefaultOn = true, IsLocation = false }, new Rule { Name = "Thistle", Description = "Thistle.", Prefabs = new string[1] { "Pickable_Thistle" }, Biome = (Biome)2, Category = PinCategory.Forage, DefaultOn = false, IsLocation = false }, new Rule { Name = "Sunken Crypts", Description = "The iron doors into the sunken crypts, where the iron scrap is.", Prefabs = new string[1] { "SunkenCrypt4" }, Biome = (Biome)2, Category = PinCategory.Dungeon, DefaultOn = true, IsLocation = true }, new Rule { Name = "Muddy Scrap Piles", Description = "The mud piles you dig for iron scrap. Only inside the crypts, so rarely worth a pin.", Prefabs = new string[1] { "mudpile_beacon" }, Biome = (Biome)2, Category = PinCategory.Ore, DefaultOn = false, IsLocation = false }, new Rule { Name = "Surtling Fire Holes", Description = "The burning holes that keep producing surtlings.", Prefabs = new string[1] { "FireHole" }, Biome = (Biome)2, Category = PinCategory.Spawner, DefaultOn = false, IsLocation = true }, new Rule { Name = "Draugr Runestones", Description = "Runestones ringed by draugr spawners.", Prefabs = new string[1] { "Runestone_Draugr" }, Biome = (Biome)2, Category = PinCategory.Spawner, DefaultOn = false, IsLocation = true }, new Rule { Name = "Mushrooms", Description = "Ordinary mushrooms.", Prefabs = new string[1] { "Pickable_Mushroom" }, Biome = (Biome)2, Category = PinCategory.Forage, DefaultOn = false, IsLocation = false }, new Rule { Name = "Altar of Bonemass", Description = "Where Bonemass is summoned. Off by default: use a vegvisir and the game pins it for you.", Prefabs = new string[1] { "Bonemass" }, Biome = (Biome)2, Category = PinCategory.Boss, DefaultOn = false, IsLocation = true }, new Rule { Name = "Vegvisirs", Description = "The runestones that reveal a boss on your map.", NameToken = "$piece_vegvisir", Component = typeof(Vegvisir), Biome = (Biome)4, Category = PinCategory.Vegvisir, DefaultOn = true, IsLocation = false }, new Rule { Name = "Silver Deposits", Description = "Silver under the snow. Buried, so a pin is worth more here than anywhere else.", Prefabs = new string[1] { "silvervein" }, Biome = (Biome)4, Category = PinCategory.Ore, DefaultOn = true, IsLocation = false }, new Rule { Name = "Obsidian Deposits", Description = "The black spires you mine for obsidian.", Prefabs = new string[1] { "MineRock_Obsidian" }, Biome = (Biome)4, Category = PinCategory.Ore, DefaultOn = false, IsLocation = false }, new Rule { Name = "Drake Nests", Description = "The nests on the peaks, each holding a dragon egg.", Prefabs = new string[1] { "DrakeNest01" }, Biome = (Biome)4, Category = PinCategory.Forage, DefaultOn = true, IsLocation = true },