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 Radar Love v1.4.0
RadarLove.dll
Decompiled a week agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn.Utils; using Microsoft.CodeAnalysis; using Splatform; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("RadarLove")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.4.0.0")] [assembly: AssemblyInformationalVersion("1.4.0+e6a3304c36e59bd0d96f2f5066f3270355b88690")] [assembly: AssemblyProduct("RadarLove")] [assembly: AssemblyTitle("RadarLove")] [assembly: AssemblyVersion("1.4.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace DwarfHavenGames.RadarLove { internal class Entry { public readonly string Section; public readonly string Display; public readonly string[] Names; public readonly string IconItem; public readonly bool DefaultOn; public ConfigEntry<bool> Toggle; public ConfigEntry<bool> Group; public ConfigEntry<bool> NameSetting; public bool Enabled { get { if (Group.Value) { if (Toggle != null) { return Toggle.Value; } return true; } return false; } } public Entry(string section, string display, string[] names, string iconItem, bool defaultOn = true) { Section = section; Display = display; Names = names; IconItem = iconItem; DefaultOn = defaultOn; } } internal static class Catalog { private static readonly Dictionary<string, Entry> Creatures = new Dictionary<string, Entry>(StringComparer.OrdinalIgnoreCase); private static readonly Dictionary<string, Entry> Fish = new Dictionary<string, Entry>(StringComparer.OrdinalIgnoreCase); private static readonly Dictionary<string, Entry> Pickables = new Dictionary<string, Entry>(StringComparer.OrdinalIgnoreCase); private static readonly Dictionary<string, Entry> Ores = new Dictionary<string, Entry>(StringComparer.OrdinalIgnoreCase); private static readonly Dictionary<string, Entry> Dungeons = new Dictionary<string, Entry>(StringComparer.OrdinalIgnoreCase); private static readonly Dictionary<string, Entry> Locations = new Dictionary<string, Entry>(StringComparer.OrdinalIgnoreCase); private static readonly Dictionary<string, Entry> Pois = new Dictionary<string, Entry>(StringComparer.OrdinalIgnoreCase); private static readonly Dictionary<string, Entry> Custom = new Dictionary<string, Entry>(StringComparer.OrdinalIgnoreCase); private static ConfigEntry<bool> _customGroup; private static ConfigEntry<bool> _customNames; private static readonly char[] InvalidKeyChars = new char[8] { '=', '\n', '\t', '\\', '"', '\'', '[', ']' }; private static readonly Entry[] CreatureEntries = new Entry[69] { new Entry("03 - Creatures (Meadows)", "Boar", new string[3] { "boar", "boar_piggy", "boar_spiritcaller" }, "TrophyBoar"), new Entry("03 - Creatures (Meadows)", "Neck", new string[1] { "neck" }, null), new Entry("03 - Creatures (Meadows)", "Deer", new string[2] { "deer", "deer_white" }, "TrophyDeer"), new Entry("03 - Creatures (Meadows)", "Greyling", new string[1] { "greyling" }, "TrophyGreydwarf"), new Entry("03 - Creatures (Meadows)", "Hen", new string[2] { "hen", "chicken" }, null), new Entry("03 - Creatures (Black Forest)", "Greydwarf", new string[1] { "greydwarf" }, null), new Entry("03 - Creatures (Black Forest)", "Greydwarf Brute", new string[1] { "greydwarf_elite" }, null), new Entry("03 - Creatures (Black Forest)", "Greydwarf Shaman", new string[1] { "greydwarf_shaman" }, null), new Entry("03 - Creatures (Black Forest)", "Skeleton", new string[2] { "skeleton", "skeleton_noarcher" }, "TrophySkeleton"), new Entry("03 - Creatures (Black Forest)", "Rancid Remains", new string[1] { "skeleton_poison" }, null), new Entry("03 - Creatures (Black Forest)", "Troll", new string[1] { "troll" }, null), new Entry("03 - Creatures (Black Forest)", "Bear", new string[2] { "bjorn", "bjorn_spiritcaller" }, "TrophyBjorn"), new Entry("03 - Creatures (Black Forest)", "Ghost", new string[1] { "ghost" }, null), new Entry("03 - Creatures (Swamp)", "Draugr", new string[2] { "draugr", "draugr_ranged" }, "TrophyDraugr"), new Entry("03 - Creatures (Swamp)", "Draugr Elite", new string[1] { "draugr_elite" }, null), new Entry("03 - Creatures (Swamp)", "Blob", new string[1] { "blob" }, null), new Entry("03 - Creatures (Swamp)", "Oozer", new string[1] { "blobelite" }, null), new Entry("03 - Creatures (Swamp)", "Leech", new string[2] { "leech", "leech_cave" }, "TrophyLeech"), new Entry("03 - Creatures (Swamp)", "Wraith", new string[1] { "wraith" }, null), new Entry("03 - Creatures (Swamp)", "Abomination", new string[1] { "abomination" }, null), new Entry("03 - Creatures (Swamp)", "Surtling", new string[1] { "surtling" }, null), new Entry("03 - Creatures (Swamp)", "Writhan", new string[1] { "writhan" }, null), new Entry("03 - Creatures (Swamp)", "Kvastur", new string[1] { "bogwitchkvastur" }, null), new Entry("03 - Creatures (Mountain)", "Wolf", new string[3] { "wolf", "wolf_cub", "wolf_spiritcaller" }, "TrophyWolf"), new Entry("03 - Creatures (Mountain)", "Fenring", new string[1] { "fenring" }, null), new Entry("03 - Creatures (Mountain)", "Cultist", new string[1] { "fenring_cultist" }, null), new Entry("03 - Creatures (Mountain)", "Ulv", new string[1] { "ulv" }, null), new Entry("03 - Creatures (Mountain)", "Stone Golem", new string[1] { "stonegolem" }, null), new Entry("03 - Creatures (Mountain)", "Drake", new string[1] { "hatchling" }, null), new Entry("03 - Creatures (Mountain)", "Bat", new string[1] { "bat" }, null), new Entry("03 - Creatures (Mountain)", "Gammeltroll", new string[1] { "trollfrost" }, null), new Entry("03 - Creatures (Mountain)", "Frost Wisp", new string[1] { "frostwisp" }, null), new Entry("03 - Creatures (Plains)", "Lox", new string[2] { "lox", "lox_calf" }, "TrophyLox"), new Entry("03 - Creatures (Plains)", "Deathsquito", new string[1] { "deathsquito" }, null), new Entry("03 - Creatures (Plains)", "Fuling", new string[2] { "goblin", "goblinarcher" }, "TrophyGoblin"), new Entry("03 - Creatures (Plains)", "Fuling Berserker", new string[1] { "goblinbrute" }, null), new Entry("03 - Creatures (Plains)", "Fuling Shaman", new string[1] { "goblinshaman" }, null), new Entry("03 - Creatures (Plains)", "Riktig Fuling", new string[1] { "goblin_gem" }, null), new Entry("03 - Creatures (Plains)", "Growth", new string[1] { "blobtar" }, null), new Entry("03 - Creatures (Plains)", "Vile", new string[1] { "unbjorn" }, null), new Entry("03 - Creatures (Mistlands)", "Seeker", new string[1] { "seeker" }, null), new Entry("03 - Creatures (Mistlands)", "Seeker Brood", new string[1] { "seekerbrood" }, "TrophySeeker"), new Entry("03 - Creatures (Mistlands)", "Seeker Soldier", new string[1] { "seekerbrute" }, null), new Entry("03 - Creatures (Mistlands)", "Gjall", new string[1] { "gjall" }, null), new Entry("03 - Creatures (Mistlands)", "Tick", new string[1] { "tick" }, null), new Entry("03 - Creatures (Mistlands)", "Dvergr Rogue", new string[2] { "dverger", "dvergerashlands" }, null), new Entry("03 - Creatures (Mistlands)", "Dvergr Mage", new string[4] { "dvergermage", "dvergermagefire", "dvergermageice", "dvergermagesupport" }, null), new Entry("03 - Creatures (Mistlands)", "Hare", new string[1] { "hare" }, null), new Entry("03 - Creatures (Ashlands)", "Asksvin", new string[2] { "asksvin", "asksvin_hatchling" }, "TrophyAsksvin"), new Entry("03 - Creatures (Ashlands)", "Charred Warrior", new string[1] { "charred_melee" }, null), new Entry("03 - Creatures (Ashlands)", "Charred Marksman", new string[1] { "charred_archer" }, null), new Entry("03 - Creatures (Ashlands)", "Charred Warlock", new string[1] { "charred_mage" }, null), new Entry("03 - Creatures (Ashlands)", "Charred Twitcher", new string[1] { "charred_twitcher" }, null), new Entry("03 - Creatures (Ashlands)", "Fallen Valkyrie", new string[1] { "fallenvalkyrie" }, null), new Entry("03 - Creatures (Ashlands)", "Lava Blob", new string[1] { "bloblava" }, null), new Entry("03 - Creatures (Ashlands)", "Morgen", new string[2] { "morgen", "morgen_nonsleeping" }, null), new Entry("03 - Creatures (Ashlands)", "Volture", new string[1] { "volture" }, null), new Entry("03 - Creatures (Ashlands)", "Bonemaw", new string[1] { "bonemawserpent" }, null), new Entry("03 - Creatures (Deep North)", "Moose", new string[3] { "moose", "moose_calf", "moose_spiritcaller" }, "TrophyMoose"), new Entry("03 - Creatures (Deep North)", "Seal", new string[2] { "seal", "seal_pup" }, "TrophySeal"), new Entry("03 - Creatures (Deep North)", "Barka", new string[1] { "barka" }, null), new Entry("03 - Creatures (Deep North)", "Elaking", new string[2] { "elaking", "elakinglantern" }, null), new Entry("03 - Creatures (Deep North)", "Eyeless One", new string[1] { "elakingmole" }, null), new Entry("03 - Creatures (Deep North)", "Hexen", new string[1] { "jotunwitch" }, null), new Entry("03 - Creatures (Deep North)", "Krigen", new string[2] { "jotunwarrior", "jotunwarriordualwield" }, null), new Entry("03 - Creatures (Deep North)", "Shadow", new string[1] { "shadowperson" }, null), new Entry("03 - Creatures (Deep North)", "Frysling", new string[1] { "frysling" }, null), new Entry("03 - Creatures (Deep North)", "Fallen Warrior", new string[1] { "fallenwarrior" }, null), new Entry("03 - Creatures (Ocean)", "Sea Serpent", new string[1] { "serpent" }, null) }; private static readonly string[] NotCreatures = new string[28] { "eikthyr", "gd_king", "bonemass", "dragon", "goblinking", "seekerqueen", "fader", "frozenking*", "aspect_*", "thehive", "hive", "charred_melee_dyrnwyn", "skeleton_hildir*", "fenring_cultist_hildir*", "goblinbrute_hildir", "goblinshaman_hildir*", "goblinbrutebros*", "*_summoned", "charred_archer_fader", "charred_melee_fader", "staff_*", "tentaroot", "skeleton_friendly", "trainingdummy", "dvergertest", "mistile", "dvergerdeepnorth", "goblindeepnorth" }; private static readonly Entry[] FishEntries = new Entry[12] { new Entry("04 - Fish", "Perch", new string[1] { "fish1" }, null), new Entry("04 - Fish", "Pike", new string[1] { "fish2" }, null), new Entry("04 - Fish", "Tuna", new string[1] { "fish3" }, null), new Entry("04 - Fish", "Tetra", new string[1] { "fish4_cave" }, null), new Entry("04 - Fish", "Trollfish", new string[1] { "fish5" }, null), new Entry("04 - Fish", "Giant Herring", new string[1] { "fish6" }, null), new Entry("04 - Fish", "Grouper", new string[1] { "fish7" }, null), new Entry("04 - Fish", "Coral Cod", new string[1] { "fish8" }, null), new Entry("04 - Fish", "Anglerfish", new string[1] { "fish9" }, null), new Entry("04 - Fish", "Northern Salmon", new string[1] { "fish10" }, null), new Entry("04 - Fish", "Magmafish", new string[1] { "fish11" }, null), new Entry("04 - Fish", "Pufferfish", new string[1] { "fish12" }, null) }; private static readonly Entry[] PickableEntries = new Entry[42] { new Entry("05 - Pickables", "Raspberries", new string[1] { "raspberry" }, null), new Entry("05 - Pickables", "Blueberries", new string[1] { "blueberries" }, null), new Entry("05 - Pickables", "Cloudberries", new string[1] { "cloudberry" }, null), new Entry("05 - Pickables", "Lingonberries", new string[1] { "lingonberry" }, null), new Entry("05 - Pickables", "Vineberries", new string[1] { "vineberry" }, null), new Entry("05 - Pickables", "Mushrooms", new string[1] { "mushroom" }, null), new Entry("05 - Pickables", "Yellow Mushrooms", new string[1] { "mushroomyellow" }, null), new Entry("05 - Pickables", "Blue Mushrooms", new string[1] { "mushroomblue" }, null), new Entry("05 - Pickables", "Magecaps", new string[1] { "mushroommagecap" }, null), new Entry("05 - Pickables", "Jotun Puffs", new string[1] { "mushroomjotunpuffs" }, null), new Entry("05 - Pickables", "Smoke Puffs", new string[1] { "mushroomsmokepuff" }, null), new Entry("05 - Pickables", "Dandelions", new string[1] { "dandelion" }, null), new Entry("05 - Pickables", "Thistle", new string[1] { "thistle" }, null), new Entry("05 - Pickables", "Fiddleheads", new string[1] { "fiddleheadfern" }, null), new Entry("05 - Pickables", "Carrots", new string[2] { "carrotseeds", "carrot" }, null), new Entry("05 - Pickables", "Turnips", new string[2] { "turnipseeds", "turnip" }, null), new Entry("05 - Pickables", "Onions", new string[2] { "onionseeds", "onion" }, null), new Entry("05 - Pickables", "Kale", new string[2] { "kaleseeds", "kale" }, null), new Entry("05 - Pickables", "Oats", new string[1] { "oatseeds" }, null), new Entry("05 - Pickables", "Poteitr", new string[1] { "poteitr" }, null), new Entry("05 - Pickables", "Barley", new string[1] { "barley" }, null), new Entry("05 - Pickables", "Flax", new string[1] { "flax" }, null), new Entry("05 - Pickables", "Surtling Cores", new string[1] { "surtlingcore" }, null), new Entry("05 - Pickables", "Black Cores", new string[1] { "blackcore" }, null), new Entry("05 - Pickables", "Molten Cores", new string[1] { "moltencore" }, null), new Entry("05 - Pickables", "Frost Cores", new string[1] { "frostcore" }, null), new Entry("05 - Pickables", "Crystals", new string[1] { "crystal" }, null), new Entry("05 - Pickables", "Dragon Eggs", new string[1] { "dragonegg" }, null), new Entry("05 - Pickables", "Volture Eggs", new string[1] { "voltureegg" }, null), new Entry("05 - Pickables", "Fenris Hair", new string[1] { "wolfhairbundle" }, null), new Entry("05 - Pickables", "Royal Jelly", new string[1] { "royaljelly" }, null), new Entry("05 - Pickables", "Sulfur", new string[1] { "sulfurstone" }, null), new Entry("05 - Pickables", "Tar", new string[1] { "tar" }, null), new Entry("05 - Pickables", "Fuling Totems", new string[1] { "goblintotem" }, null), new Entry("05 - Pickables", "Luminous Larva", new string[1] { "glowworm" }, null), new Entry("05 - Pickables", "Pot Shards", new string[1] { "pot_shard_green" }, null, defaultOn: false), new Entry("05 - Pickables", "Meat Piles", new string[1] { "entrails" }, null, defaultOn: false), new Entry("05 - Pickables", "Grausten", new string[1] { "grausten" }, null, defaultOn: false), new Entry("05 - Pickables", "Flint", new string[1] { "flint" }, null, defaultOn: false), new Entry("05 - Pickables", "Stones", new string[1] { "stone" }, null, defaultOn: false), new Entry("05 - Pickables", "Branches", new string[1] { "wood" }, null, defaultOn: false), new Entry("05 - Pickables", "Snowballs", new string[1] { "snowball" }, null, defaultOn: false) }; private static readonly Entry[] OreEntries = new Entry[10] { new Entry("06 - Ores", "Copper", new string[1] { "copperore" }, null), new Entry("06 - Ores", "Tin", new string[1] { "tinore" }, null), new Entry("06 - Ores", "Iron", new string[2] { "ironscrap", "ironore" }, null), new Entry("06 - Ores", "Silver", new string[1] { "silverore" }, null), new Entry("06 - Ores", "Obsidian", new string[1] { "obsidian" }, null), new Entry("06 - Ores", "Flametal", new string[1] { "flametalorenew" }, null), new Entry("06 - Ores", "Black Marble", new string[1] { "blackmarble" }, null), new Entry("06 - Ores", "Soft Tissue", new string[1] { "softtissue" }, null), new Entry("06 - Ores", "Leviathan", new string[1] { "chitin" }, null), new Entry("06 - Ores", "Guck", new string[1] { "guck" }, null) }; private static readonly Entry[] DungeonEntries = new Entry[7] { new Entry("07 - Dungeons", "Burial Chambers", new string[1] { "$location_forestcrypt" }, "SurtlingCore"), new Entry("07 - Dungeons", "Sunken Crypts", new string[1] { "$location_sunkencrypt" }, "WitheredBone"), new Entry("07 - Dungeons", "Troll Caves", new string[1] { "$location_forestcave" }, "TrophyForestTroll"), new Entry("07 - Dungeons", "Mountain Caves", new string[1] { "$location_mountaincave" }, "JuteRed"), new Entry("07 - Dungeons", "Bear Caves", new string[1] { "$location_bearcave" }, "TrophyBjorn"), new Entry("07 - Dungeons", "Infested Mines", new string[1] { "$location_dvergrtown" }, "BlackCore"), new Entry("07 - Dungeons", "Morgen Holes", new string[1] { "$location_morgenhole" }, "TrophyMorgen") }; private static readonly Entry[] PoiEntries = new Entry[7] { new Entry("08 - Points of Interest", "Wild Beehives", new string[1] { "beehive" }, "QueenBee"), new Entry("08 - Points of Interest", "Greydwarf Nests", new string[1] { "spawner_greydwarfnest" }, "AncientSeed"), new Entry("08 - Points of Interest", "Body Piles", new string[1] { "spawner_draugrpile" }, "TrophyDraugr"), new Entry("08 - Points of Interest", "Evil Bone Piles", new string[1] { "bonepilespawner" }, "TrophySkeleton"), new Entry("08 - Points of Interest", "Effigies of Malice", new string[1] { "spawner_charredcross" }, null), new Entry("08 - Points of Interest", "Monuments of Torment", new string[2] { "spawner_charredstone", "spawner_charredstone_elite" }, null), new Entry("08 - Points of Interest", "Malicious Ice", new string[1] { "blackice_core" }, null) }; private const string RunestoneIcon = "TankardAnniversary|Thunderstone"; private static readonly Entry[] LocationEntries = new Entry[47] { new Entry("09 - Locations", "Runestones", new string[11] { "runestone_greydwarfs", "runestone_blackforest", "runestone_meadows", "runestone_boars", "runestone_mistlands", "runestone_mountains", "runestone_draugr", "runestone_swamps", "runestone_plains", "runestone_ashlands", "drakelorestone" }, "TankardAnniversary|Thunderstone"), new Entry("09 - Locations", "Drake Nest", new string[1] { "drakenest01" }, "DragonEgg"), new Entry("09 - Locations", "Tar Pit", new string[3] { "tarpit1", "tarpit2", "tarpit3" }, "Tar"), new Entry("09 - Locations", "Fuling Camp", new string[1] { "goblincamp2" }, "GoblinTotem"), new Entry("09 - Locations", "Charred Fortress", new string[1] { "charredfortress" }, null), new Entry("09 - Locations", "Shipwreck", new string[4] { "shipwreck01", "shipwreck02", "shipwreck03", "shipwreck04" }, null, defaultOn: false), new Entry("09 - Locations", "Black Forest Ruins", new string[3] { "ruin1", "ruin2", "combatruin01" }, null, defaultOn: false), new Entry("09 - Locations", "Stone Tower Ruins", new string[7] { "stonetowerruins03", "stonetowerruins04", "stonetowerruins05", "stonetowerruins07", "stonetowerruins08", "stonetowerruins09", "stonetowerruins10" }, null, defaultOn: false), new Entry("09 - Locations", "Greydwarf Camp", new string[1] { "greydwarf_camp1" }, null, defaultOn: false), new Entry("09 - Locations", "Wood House", new string[13] { "woodhouse1", "woodhouse2", "woodhouse3", "woodhouse4", "woodhouse5", "woodhouse6", "woodhouse7", "woodhouse8", "woodhouse9", "woodhouse10", "woodhouse11", "woodhouse12", "woodhouse13" }, null, defaultOn: false), new Entry("09 - Locations", "Abandoned Farm", new string[1] { "woodfarm1" }, null, defaultOn: false), new Entry("09 - Locations", "Abandoned Village", new string[1] { "woodvillage1" }, null, defaultOn: false), new Entry("09 - Locations", "Ship Setting", new string[1] { "shipsetting01" }, null, defaultOn: false), new Entry("09 - Locations", "Stone Circle", new string[1] { "stonecircle" }, null, defaultOn: false), new Entry("09 - Locations", "Dolmen", new string[3] { "dolmen01", "dolmen02", "dolmen03" }, null, defaultOn: false), new Entry("09 - Locations", "Swamp Hut", new string[5] { "swamphut1", "swamphut2", "swamphut3", "swamphut4", "swamphut5" }, null, defaultOn: false), new Entry("09 - Locations", "Swamp Ruin", new string[2] { "swampruin1", "swampruin2" }, null, defaultOn: false), new Entry("09 - Locations", "Fire Hole", new string[1] { "firehole" }, null, defaultOn: false), new Entry("09 - Locations", "Infested Tree", new string[1] { "infestedtree01" }, "Guck", defaultOn: false), new Entry("09 - Locations", "Grave", new string[2] { "grave1", "mountaingrave01" }, null, defaultOn: false), new Entry("09 - Locations", "Well", new string[2] { "swampwell1", "mountainwell1" }, null, defaultOn: false), new Entry("09 - Locations", "Log Cabin", new string[3] { "abandonedlogcabin02", "abandonedlogcabin03", "abandonedlogcabin04" }, null, defaultOn: false), new Entry("09 - Locations", "Waymarker", new string[2] { "waymarker01", "waymarker02" }, null, defaultOn: false), new Entry("09 - Locations", "Stone Henge", new string[6] { "stonehenge1", "stonehenge2", "stonehenge3", "stonehenge4", "stonehenge5", "stonehenge6" }, null, defaultOn: false), new Entry("09 - Locations", "Stone House", new string[5] { "stonehouse1_heath", "stonehouse2_heath", "stonehouse3", "stonehouse4", "stonehouse5_heath" }, null, defaultOn: false), new Entry("09 - Locations", "Stone Tower", new string[3] { "stonetower1", "stonetower3", "ruin3" }, null, defaultOn: false), new Entry("09 - Locations", "Dvergr Excavation", new string[3] { "mistlands_excavation1", "mistlands_excavation2", "mistlands_excavation3" }, null, defaultOn: false), new Entry("09 - Locations", "Dvergr Guard Tower", new string[6] { "mistlands_guardtower1_new", "mistlands_guardtower2_new", "mistlands_guardtower3_new", "mistlands_guardtower1_ruined_new", "mistlands_guardtower1_ruined_new2", "mistlands_guardtower3_ruined_new" }, null, defaultOn: false), new Entry("09 - Locations", "Dvergr Harbour", new string[1] { "mistlands_harbour1" }, null, defaultOn: false), new Entry("09 - Locations", "Dvergr Lighthouse", new string[1] { "mistlands_lighthouse1_new" }, null, defaultOn: false), new Entry("09 - Locations", "Giant Remains", new string[2] { "mistlands_giant1", "mistlands_giant2" }, null, defaultOn: false), new Entry("09 - Locations", "Sword Stones", new string[3] { "mistlands_swords1", "mistlands_swords2", "mistlands_swords3" }, null, defaultOn: false), new Entry("09 - Locations", "Road Post", new string[1] { "mistlands_roadpost1" }, null, defaultOn: false), new Entry("09 - Locations", "Statues", new string[3] { "mistlands_statue1", "mistlands_statue2", "mistlands_statuegroup1" }, null, defaultOn: false), new Entry("09 - Locations", "Viaduct", new string[2] { "mistlands_viaduct1", "mistlands_viaduct2" }, null, defaultOn: false), new Entry("09 - Locations", "Rock Spire", new string[1] { "mistlands_rockspire1" }, null, defaultOn: false), new Entry("09 - Locations", "Charred Ruin", new string[4] { "charredruins1", "charredruins2", "charredruins3", "charredruins4" }, null, defaultOn: false), new Entry("09 - Locations", "Charred Tower", new string[4] { "charredtowerruins1", "charredtowerruins1_dvergr", "charredtowerruins2", "charredtowerruins3" }, null, defaultOn: false), new Entry("09 - Locations", "Fortress Ruin", new string[1] { "fortressruins" }, null, defaultOn: false), new Entry("09 - Locations", "Ashlands Ruin", new string[1] { "ashlandruins" }, null, defaultOn: false), new Entry("09 - Locations", "Place of Mystery", new string[3] { "placeofmystery1", "placeofmystery2", "placeofmystery3" }, null, defaultOn: false), new Entry("09 - Locations", "Sulfur Arch", new string[1] { "sulfurarch" }, null, defaultOn: false), new Entry("09 - Locations", "Volture Nest", new string[1] { "volturenest" }, "VoltureEgg", defaultOn: false), new Entry("09 - Locations", "Frozen Ship", new string[3] { "frozenship01_dn", "frozenship02_dn", "frozenship03_dn" }, null, defaultOn: false), new Entry("09 - Locations", "North Village", new string[1] { "northvillage" }, null, defaultOn: false), new Entry("09 - Locations", "Lumber Camp", new string[1] { "lumbercamp" }, null, defaultOn: false), new Entry("09 - Locations", "North Memorial", new string[1] { "northmemorialplace" }, null, defaultOn: false) }; public static Entry OtherCreatures { get; private set; } public static Entry OtherPickables { get; private set; } public static Entry OtherDungeons { get; private set; } public static IEnumerable<Entry> AllDungeons => DungeonEntries; public static void Bind(ConfigFile config, Config settings) { OtherCreatures = new Entry("03 - Creatures (Other)", "Other Creatures", new string[0], null); OtherPickables = new Entry("05 - Pickables", "Other Pickables", new string[0], null, defaultOn: false); OtherDungeons = new Entry("07 - Dungeons", "Other Dungeons", new string[0], null); BindAll(config, CreatureEntries, settings.GroupCreatures, Creatures); BindOne(config, OtherCreatures, settings.GroupCreatures, "Creatures not listed above, such as ones other mods add."); BindAll(config, FishEntries, settings.GroupFish, Fish); BindAll(config, PickableEntries, settings.GroupPickables, Pickables); BindOne(config, OtherPickables, settings.GroupPickables, "Pickables not listed above."); BindAll(config, OreEntries, settings.GroupOres, Ores); BindAll(config, DungeonEntries, settings.GroupDungeons, Dungeons); BindOne(config, OtherDungeons, settings.GroupDungeons, "Dungeons not listed above, such as ones other mods add."); Entry[] dungeonEntries = DungeonEntries; for (int i = 0; i < dungeonEntries.Length; i++) { dungeonEntries[i].NameSetting = settings.DungeonNames; } OtherDungeons.NameSetting = settings.DungeonNames; BindAll(config, PoiEntries, settings.GroupPois, Pois); BindAll(config, LocationEntries, settings.GroupLocations, Locations); _customGroup = settings.GroupCustom; _customNames = settings.CustomNames; ParseCustom(settings.CustomPins.Value); } public static void ParseCustom(string value) { Custom.Clear(); string[] array = value.Split(new char[2] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Split(new char[1] { '=' }); string text = array2[0].Trim(); if (text.Length != 0) { string text2 = ((array2.Length > 1) ? array2[1].Trim() : ""); string display = ((array2.Length > 2 && array2[2].Trim().Length > 0) ? array2[2].Trim() : text); Custom[text] = new Entry("11 - Custom", display, new string[1] { text }, (text2.Length > 0) ? text2 : null) { Group = _customGroup, NameSetting = _customNames }; } } } public static Entry CustomFor(string prefab) { if (!Custom.TryGetValue(prefab, out var value)) { return null; } return value; } private static void BindAll(ConfigFile config, Entry[] entries, ConfigEntry<bool> group, Dictionary<string, Entry> lookup) { foreach (Entry entry in entries) { BindOne(config, entry, group, "Show " + entry.Display + " on the radar."); string[] names = entry.Names; foreach (string key in names) { lookup[key] = entry; } } } private static void BindOne(ConfigFile config, Entry entry, ConfigEntry<bool> group, string description) { entry.Group = group; string text = string.Concat(entry.Display.Split(InvalidKeyChars)); entry.Toggle = config.Bind<bool>(entry.Section, text, entry.DefaultOn, description); } public static Entry Creature(string prefab) { if (Creatures.TryGetValue(prefab, out var value)) { return value; } if (!Matches(NotCreatures, prefab)) { return OtherCreatures; } return null; } private static bool Matches(string[] patterns, string prefab) { foreach (string obj in patterns) { bool flag = obj.StartsWith("*"); bool flag2 = obj.EndsWith("*"); string value = obj.Trim(new char[1] { '*' }); if (flag ? prefab.EndsWith(value, StringComparison.OrdinalIgnoreCase) : (flag2 ? prefab.StartsWith(value, StringComparison.OrdinalIgnoreCase) : prefab.Equals(value, StringComparison.OrdinalIgnoreCase))) { return true; } } return false; } public static Entry FishKind(string prefab) { if (!Fish.TryGetValue(prefab, out var value)) { return null; } return value; } public static Entry Pickable(string item) { if (!Pickables.TryGetValue(item, out var value)) { return OtherPickables; } return value; } public static Entry Ore(string item) { if (!Ores.TryGetValue(item, out var value)) { return null; } return value; } public static Entry Dungeon(string enterText) { if (enterText == null || !Dungeons.TryGetValue(enterText, out var value)) { return OtherDungeons; } return value; } public static Entry Location(string prefab) { if (!Locations.TryGetValue(prefab, out var value)) { return null; } return value; } public static Entry Poi(string prefab) { if (!Pois.TryGetValue(prefab, out var value)) { return null; } return value; } } internal class Config { public ConfigEntry<bool> Enabled { get; } public ConfigEntry<float> Radius { get; } public ConfigEntry<bool> ShowLabels { get; } public ConfigEntry<bool> DungeonNames { get; } public ConfigEntry<bool> CustomNames { get; } public ConfigEntry<float> GroupDistance { get; } public ConfigEntry<float> CreatureGroupDistance { get; } public ConfigEntry<bool> RestoreDismissed { get; } public ConfigEntry<bool> ConfirmDismiss { get; } public ConfigEntry<KeyboardShortcut> KeepKey { get; } public ConfigEntry<bool> GroupCreatures { get; } public ConfigEntry<bool> GroupFish { get; } public ConfigEntry<bool> GroupPickables { get; } public ConfigEntry<bool> GroupOres { get; } public ConfigEntry<bool> GroupDungeons { get; } public ConfigEntry<bool> GroupPois { get; } public ConfigEntry<bool> GroupCustom { get; } public ConfigEntry<string> CustomPins { get; } public ConfigEntry<bool> GroupLocations { get; } public ConfigEntry<bool> AutoPinDungeons { get; } public ConfigEntry<float> DiscoverDistance { get; } public ConfigEntry<bool> PinMessage { get; } public Config(ConfigFile config) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Expected O, but got Unknown //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Expected O, but got Unknown //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_037b: Unknown result type (might be due to invalid IL or missing references) //IL_0385: Expected O, but got Unknown Enabled = config.Bind<bool>("01 - General", "Enabled", true, "Turn the radar on or off. Dungeon pins have their own switch."); Radius = config.Bind<float>("01 - General", "Radius", 70f, new ConfigDescription("How close something has to be, in metres, before it appears on the map.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 150f), Array.Empty<object>())); ShowLabels = config.Bind<bool>("01 - General", "Show Labels", false, "Show a name under every radar icon. When off, a name only appears under icons that do not already say what they are."); DungeonNames = config.Bind<bool>("01 - General", "Show Dungeon Names", true, "Show the dungeon's name under dungeon pins, both on the radar and on the pins saved when you find one."); CustomNames = config.Bind<bool>("01 - General", "Show Custom Names", false, "Show the name under pins you added in Custom Pins."); ShowLabels.SettingChanged += delegate { Radar.Refresh(); }; DungeonNames.SettingChanged += delegate { Radar.Refresh(); }; CustomNames.SettingChanged += delegate { Radar.Refresh(); }; GroupDistance = config.Bind<float>("01 - General", "Group Distance", 15f, new ConfigDescription("Things of the same kind closer together than this, in metres, share one pin with a count.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 50f), Array.Empty<object>())); CreatureGroupDistance = config.Bind<float>("01 - General", "Creature Group Distance", 15f, new ConfigDescription("The same for creatures and fish. Lower it to see them one by one.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 50f), Array.Empty<object>())); ConfirmDismiss = config.Bind<bool>("01 - General", "Confirm Before Dismiss", true, "Ask before a right-click removes a radar pin: right-click once, then again within a few seconds to remove it. Your own pins are not affected."); KeepKey = config.Bind<KeyboardShortcut>("01 - General", "Keep Pin Key", new KeyboardShortcut((KeyCode)112, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "Saves the nearest radar pin to your map, or pins where you stand if there is none nearby."); RestoreDismissed = config.Bind<bool>("01 - General", "Restore Dismissed Pins", false, "Set to true to bring back every radar pin you right-clicked away in this world. It switches itself back off."); RestoreDismissed.SettingChanged += delegate { if (RestoreDismissed.Value) { Dismissals.RestoreAll(); RestoreDismissed.Value = false; } }; GroupCreatures = config.Bind<bool>("02 - Groups", "Creatures", true, "Show creatures. Each one also has its own switch."); GroupFish = config.Bind<bool>("02 - Groups", "Fish", true, "Show fish. Each one also has its own switch."); GroupPickables = config.Bind<bool>("02 - Groups", "Pickables", true, "Show pickables. Each one also has its own switch."); GroupOres = config.Bind<bool>("02 - Groups", "Ores", true, "Show ore deposits. Each one also has its own switch."); GroupDungeons = config.Bind<bool>("02 - Groups", "Dungeons", true, "Show dungeon entrances. Each one also has its own switch."); GroupPois = config.Bind<bool>("02 - Groups", "Points of Interest", true, "Show spawners and wild beehives. Each one also has its own switch."); GroupLocations = config.Bind<bool>("02 - Groups", "Locations", true, "Show runestones, ruins and other locations. Each one also has its own switch."); GroupCustom = config.Bind<bool>("02 - Groups", "Custom", true, "Show what you have added under Custom Pins."); CustomPins = config.Bind<string>("11 - Custom", "Custom Pins", "", "Add anything the radar does not already know, such as things from other mods. Write the prefab name, then = and the item whose icon to show, separated by commas: MyOreRock=CopperOre, SomeCave=TrophySkeleton. Add a third part for the name shown under the pin: SomeCave=TrophySkeleton=Spooky Cave. Leave the icon out to use the object's own. Look at the thing and use the radar_hover console command to get its prefab name."); CustomPins.SettingChanged += delegate { Catalog.ParseCustom(CustomPins.Value); Radar.Rescan(); }; AutoPinDungeons = config.Bind<bool>("10 - Dungeon Pins", "Auto-Pin Dungeons", true, "Pin a dungeon entrance to your map the first time you reach it. These pins are saved like your own."); DiscoverDistance = config.Bind<float>("10 - Dungeon Pins", "Discover Distance", 10f, new ConfigDescription("How close to the edge of a dungeon entrance you have to come, in metres, for it to be pinned.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f), Array.Empty<object>())); PinMessage = config.Bind<bool>("10 - Dungeon Pins", "Pinned Message", true, "Show a message when a dungeon is pinned."); Catalog.Bind(config, this); } } internal static class Dismissals { private class SpotStore { private readonly string _prefix; private readonly HashSet<string> _spots = new HashSet<string>(); private Player _loadedFor; public SpotStore(string prefix) { _prefix = prefix; } public bool Contains(string spot) { return Loaded().Contains(spot); } public void Add(string spot) { Loaded().Add(spot); } public void Remove(string spot) { Loaded().Remove(spot); } public void Clear() { Loaded().Clear(); } public void Save() { Player localPlayer = Player.m_localPlayer; string text = Key(); if (Object.op_Implicit((Object)(object)localPlayer) && text != null) { if (_spots.Count == 0) { localPlayer.m_customData.Remove(text); } else { localPlayer.m_customData[text] = string.Join(";", _spots); } } } private string Key() { if (!Object.op_Implicit((Object)(object)ZNet.instance)) { return null; } return _prefix + ZNet.instance.GetWorldUID(); } private HashSet<string> Loaded() { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)(object)_loadedFor) { return _spots; } _loadedFor = localPlayer; _spots.Clear(); string text = Key(); if (Object.op_Implicit((Object)(object)localPlayer) && text != null && localPlayer.m_customData.TryGetValue(text, out var value)) { string[] array = value.Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries); foreach (string item in array) { _spots.Add(item); } } return _spots; } } private static readonly SpotStore Dismissed = new SpotStore("dwarfhavengames.radarlove.dismissed."); private static readonly SpotStore Crossed = new SpotStore("dwarfhavengames.radarlove.checked."); private const float ConfirmWindow = 3f; private static Blip _pending; private static float _pendingUntil; private static readonly FieldRef<Minimap, List<PinData>> PinsRef = AccessTools.FieldRefAccess<Minimap, List<PinData>>("m_pins"); public static bool IsDismissed(Blip blip) { if (!blip.Moves) { return Dismissed.Contains(SpotOf(blip)); } return false; } public static bool IsCrossed(Blip blip) { if (!blip.Moves) { return Crossed.Contains(SpotOf(blip)); } return blip.Crossed; } public static bool IsCrossed(List<Blip> members) { if (members.Count > 0) { return members.All(IsCrossed); } return false; } public static bool TryDismiss(Minimap minimap, Vector3 pointer, float radius) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) Blip blip = RadarPinUnder(minimap, pointer, radius); if (blip == null) { return false; } if (RadarLovePlugin.Settings.ConfirmDismiss.Value && (_pending != blip || Time.time > _pendingUntil)) { _pending = blip; _pendingUntil = Time.time + 3f; string text = ((blip.Members.Count > 1) ? $"these {blip.Members.Count} pins" : ("the " + blip.Name() + " pin")); Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, "Right-click again to remove " + text, 0, (Sprite)null, false); } return true; } _pending = null; foreach (Blip member in blip.Members) { member.Hidden = true; if (!member.Moves && Object.op_Implicit((Object)(object)member.Source)) { Dismissed.Add(SpotOf(member)); } } Dismissed.Save(); Radar.Unpin(blip); return true; } public static void TryToggleCross(Minimap minimap, Vector3 pointer, float radius) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) Blip blip = RadarPinUnder(minimap, pointer, radius); if (blip == null) { return; } bool flag = !IsCrossed(blip.Members); foreach (Blip member in blip.Members) { if (member.Moves) { member.Crossed = flag; } else if (Object.op_Implicit((Object)(object)member.Source) && flag) { Crossed.Add(SpotOf(member)); } else if (Object.op_Implicit((Object)(object)member.Source)) { Crossed.Remove(SpotOf(member)); } } Crossed.Save(); blip.Pin.m_checked = flag; } public static void RestoreAll() { Dismissed.Clear(); Dismissed.Save(); Radar.ClearHidden(); } internal static Blip RadarPinUnder(Minimap minimap, Vector3 pointer, float radius) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) if (PinsRef.Invoke(minimap).Any((PinData p) => p.m_save && Visible(p) && Utils.DistanceXZ(pointer, p.m_pos) < radius)) { return null; } return Radar.ClosestPinned(pointer, radius); } private static bool Visible(PinData pin) { if (Object.op_Implicit((Object)(object)pin.m_uiElement)) { return ((Component)pin.m_uiElement).gameObject.activeInHierarchy; } return false; } internal static string SpotOf(Blip blip) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) if (blip.Spot == null) { Vector3 position = blip.Source.transform.position; blip.Spot = $"{blip.Entry.Display}@{Mathf.RoundToInt(position.x)},{Mathf.RoundToInt(position.z)}"; } return blip.Spot; } } internal static class DungeonPins { private const PinType SavedType = (PinType)3; private const string PinnedKeyPrefix = "dwarfhavengames.radarlove.dungeon."; private static readonly FieldRef<Minimap, List<PinData>> PinsRef = AccessTools.FieldRefAccess<Minimap, List<PinData>>("m_pins"); private static readonly List<Location> Dungeons = new List<Location>(); public static void Track(Location location) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0043: 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) if (Radar.PrefabName(((Component)location).gameObject).StartsWith("Hildir_", StringComparison.OrdinalIgnoreCase)) { return; } if (!Dungeons.Contains(location)) { Dungeons.Add(location); } Player localPlayer = Player.m_localPlayer; Vector3 position = ((Component)location).transform.position; string text = PinnedKey(position); if (Object.op_Implicit((Object)(object)localPlayer) && text != null && localPlayer.m_customData.TryGetValue(text, out var value) && !TryParse(value, out var _, out var _, out var _)) { int num = value.IndexOf('|'); if (num >= 0) { localPlayer.m_customData[text] = Record(value.Substring(0, num), position, value.Substring(num + 1)); } } } public static void Clear() { Dungeons.Clear(); } public static void Tick(Vector3 here) { //IL_0058: 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_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) if (!RadarLovePlugin.Settings.AutoPinDungeons.Value) { return; } float value = RadarLovePlugin.Settings.DiscoverDistance.Value; for (int num = Dungeons.Count - 1; num >= 0; num--) { Location val = Dungeons[num]; if (!Object.op_Implicit((Object)(object)val)) { Dungeons.RemoveAt(num); } else { Vector3 position = ((Component)val).transform.position; float num2 = val.m_exteriorRadius + value; if (!(Utils.DistanceXZ(here, position) > num2)) { Dungeons.RemoveAt(num); Discover(val, position); } } } } private static void Discover(Location location, Vector3 pos) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) string text = PinnedKey(pos); Player localPlayer = Player.m_localPlayer; if (text == null || localPlayer.m_customData.ContainsKey(text)) { Radar.Suppress((Component)(object)location); } else if (!HasSavedPinNear(pos, Mathf.Max(location.m_exteriorRadius, 10f))) { string text2 = Catalog.Dungeon(EnterText(location)).IconItem ?? ""; string text3 = NameFor(location); localPlayer.m_customData[text] = Record(text2, pos, text3); Sprite val = Icons.ItemIcon(text2); AddPin(Minimap.instance, pos, text3, val, isChecked: false); Radar.Suppress((Component)(object)location); if (RadarLovePlugin.Settings.PinMessage.Value) { ((Character)localPlayer).Message((MessageType)1, text3 + " pinned to map", 0, val, false); } } } private static bool ShowName(Sprite icon) { if (!RadarLovePlugin.Settings.DungeonNames.Value) { return (Object)(object)icon == (Object)null; } return true; } private static PinData AddPin(Minimap minimap, Vector3 pos, string name, Sprite icon, bool isChecked) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) PinData val = minimap.AddPin(pos, (PinType)3, ShowName(icon) ? name : "", true, isChecked, 0L, default(PlatformUserID)); if (Object.op_Implicit((Object)(object)icon)) { val.m_icon = icon; } return val; } public static void Sync(Minimap minimap) { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Invalid comparison between Unknown and I4 //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0231: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer)) { return; } List<PinData> list = PinsRef.Invoke(minimap); for (int num = list.Count - 1; num >= 0; num--) { PinData pin = list[num]; if (!pin.m_save || (int)pin.m_type != 3) { continue; } string text = PinnedKey(pin.m_pos); if (text == null || !localPlayer.m_customData.TryGetValue(text, out var value)) { continue; } if (!TryParse(value, out var iconItem, out var spot, out var name)) { if (pin.m_name.Length == 0 || !IsDungeonName(value, pin.m_name)) { continue; } int num2 = value.IndexOf('|'); iconItem = ((num2 >= 0) ? value.Substring(0, num2) : (Catalog.AllDungeons.First((Entry e) => e.Names.Any((string t) => Radar.Localize(t) == pin.m_name)).IconItem ?? "")); name = pin.m_name; spot = pin.m_pos; localPlayer.m_customData[text] = Record(iconItem, spot, name); } if (Utils.DistanceXZ(pin.m_pos, spot) > 1f) { continue; } Entry entry = Catalog.AllDungeons.FirstOrDefault((Entry e) => e.Names.Any((string t) => Radar.Localize(t) == name)); if (entry != null && entry.IconItem != null && entry.IconItem != iconItem) { iconItem = entry.IconItem; localPlayer.m_customData[text] = Record(iconItem, spot, name); } if (pin.m_name != name && pin.m_name.Length > 0) { continue; } Sprite val = Icons.ItemIcon(iconItem); if (pin.m_name != (ShowName(val) ? name : "")) { minimap.RemovePin(pin); AddPin(minimap, pin.m_pos, name, val, pin.m_checked); } else if (Object.op_Implicit((Object)(object)val) && (Object)(object)pin.m_icon != (Object)(object)val) { pin.m_icon = val; if (Object.op_Implicit((Object)(object)pin.m_iconElement)) { pin.m_iconElement.sprite = val; } } } } public static Sprite IconFor(Location location) { return Icons.ItemIcon(Catalog.Dungeon(EnterText(location)).IconItem); } public static string NameFor(Location location) { string text = EnterText(location); if (text == null) { return Radar.PrefabName(((Component)location).gameObject); } return Radar.Localize(text); } public static string EnterText(Location location) { return ((IEnumerable<Teleport>)((Component)location).GetComponentsInChildren<Teleport>(true)).FirstOrDefault((Func<Teleport, bool>)((Teleport t) => !string.IsNullOrEmpty(t.m_enterText) && t.m_enterText != "$location_exit"))?.m_enterText; } private static string Record(string iconItem, Vector3 pos, string name) { return string.Join("|", iconItem, pos.x.ToString("R", CultureInfo.InvariantCulture), pos.z.ToString("R", CultureInfo.InvariantCulture), name); } private static bool TryParse(string record, out string iconItem, out Vector3 spot, out string name) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) iconItem = (name = null); spot = default(Vector3); string[] array = record.Split(new char[1] { '|' }, 4); if (array.Length < 4 || !float.TryParse(array[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var result) || !float.TryParse(array[2], NumberStyles.Float, CultureInfo.InvariantCulture, out var result2)) { return false; } iconItem = array[0]; spot = new Vector3(result, 0f, result2); name = array[3]; return true; } private static bool IsDungeonName(string record, string pinName) { int num = record.IndexOf('|'); if (num >= 0) { return record.Substring(num + 1) == pinName; } return Catalog.AllDungeons.Any((Entry e) => e.Names.Any((string t) => Radar.Localize(t) == pinName)); } private static bool HasSavedPinNear(Vector3 pos, float radius) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) return PinsRef.Invoke(Minimap.instance).Any((PinData p) => p.m_save && Utils.DistanceXZ(p.m_pos, pos) < radius); } private static string PinnedKey(Vector3 pos) { //IL_000e: 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_0014: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)ZNet.instance)) { return null; } Vector2s zone = ZoneSystem.GetZone(pos); return string.Format("{0}{1}.{2}.{3}", "dwarfhavengames.radarlove.dungeon.", ZNet.instance.GetWorldUID(), zone.x, zone.y); } } internal static class HoverCommand { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static ConsoleEvent <>9__1_0; public static Func<RaycastHit, float> <>9__2_0; public static Func<string, bool> <>9__4_0; public static Func<MonoBehaviour, bool> <>9__4_1; public static Func<MonoBehaviour, string> <>9__4_2; public static Func<Drop, bool> <>9__6_2; internal void <Register>b__1_0(ConsoleEventArgs args) { Run(args.Context); } internal float <Run>b__2_0(RaycastHit h) { return ((RaycastHit)(ref h)).distance; } internal bool <Report>b__4_0(string d) { return Catalog.Ore(d) != null; } internal bool <Report>b__4_1(MonoBehaviour c) { return Object.op_Implicit((Object)(object)c); } internal string <Report>b__4_2(MonoBehaviour c) { return ((object)c).GetType().Name; } internal bool <DropNames>b__6_2(Drop d) { return IsTrophy(d.m_prefab); } } private const float Reach = 50f; public static void Register() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown object obj = <>c.<>9__1_0; if (obj == null) { ConsoleEvent val = delegate(ConsoleEventArgs args) { Run(args.Context); }; <>c.<>9__1_0 = val; obj = (object)val; } new ConsoleCommand("radar_hover", "Radar Love: shows the prefab name of what you are looking at, for the Custom Pins setting.", (ConsoleEvent)obj, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } private static void Run(Terminal terminal) { //IL_0125: 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_0075: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer)) { Say(terminal, "radar_hover: no player."); return; } HashSet<GameObject> hashSet = new HashSet<GameObject>(); Report(terminal, ((Humanoid)localPlayer).GetHoverObject(), hashSet); Character hoverCreature = localPlayer.GetHoverCreature(); if (Object.op_Implicit((Object)(object)hoverCreature)) { Report(terminal, ((Component)hoverCreature).gameObject, hashSet); } Transform val = (Object.op_Implicit((Object)(object)GameCamera.instance) ? ((Component)GameCamera.instance).transform : null); if (Object.op_Implicit((Object)(object)val)) { foreach (RaycastHit item in from h in Physics.RaycastAll(val.position, val.forward, 50f) orderby ((RaycastHit)(ref h)).distance select h) { RaycastHit current = item; if (!Object.op_Implicit((Object)(object)((Component)((RaycastHit)(ref current)).collider).GetComponentInParent<Player>()) && (Object.op_Implicit((Object)(object)((Component)((RaycastHit)(ref current)).collider).GetComponentInParent<ZNetView>()) || Object.op_Implicit((Object)(object)((Component)((RaycastHit)(ref current)).collider).GetComponentInParent<Location>()))) { Report(terminal, ((Component)((RaycastHit)(ref current)).collider).gameObject, hashSet); break; } } } Location location = Location.GetLocation(((Component)localPlayer).transform.position, true); if (Object.op_Implicit((Object)(object)location)) { string text = Radar.PrefabName(((Component)location).gameObject); Say(terminal, "Standing in location: " + text); Say(terminal, " Custom Pins: " + text + "="); } if (hashSet.Count == 0 && !Object.op_Implicit((Object)(object)location)) { Say(terminal, "radar_hover: nothing under the crosshair."); } } private static void Say(Terminal terminal, string text) { terminal.AddString(text); RadarLovePlugin.Log.LogInfo((object)("[radar_hover] " + text)); } private static void Report(Terminal terminal, GameObject go, HashSet<GameObject> seen) { //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)go)) { return; } ZNetView componentInParent = go.GetComponentInParent<ZNetView>(); GameObject val = (Object.op_Implicit((Object)(object)componentInParent) ? ((Component)componentInParent).gameObject : go); if (seen.Add(val)) { string text = Radar.PrefabName(val); List<string> list = DropNames(val); Say(terminal, (list.Count > 0) ? (text + " (gives: " + string.Join(", ", list) + ")") : text); string text2 = list.FirstOrDefault((string d) => Catalog.Ore(d) != null) ?? list.FirstOrDefault(); Say(terminal, " Custom Pins: " + text + "=" + text2); Say(terminal, " Components: " + string.Join(", ", (from c in val.GetComponents<MonoBehaviour>() where Object.op_Implicit((Object)(object)c) select ((object)c).GetType().Name).Distinct())); Destructible component = val.GetComponent<Destructible>(); if (Object.op_Implicit((Object)(object)component)) { Say(terminal, " Destructible: " + Damage(component.m_damages, component.m_minToolTier)); } MineRock component2 = val.GetComponent<MineRock>(); if (Object.op_Implicit((Object)(object)component2)) { Say(terminal, " MineRock: " + Damage(component2.m_damageModifiers, component2.m_minToolTier)); } MineRock5 component3 = val.GetComponent<MineRock5>(); if (Object.op_Implicit((Object)(object)component3)) { Say(terminal, " MineRock5: " + Damage(component3.m_damageModifiers, component3.m_minToolTier)); } } } private static string Damage(DamageModifiers d, int minToolTier) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0029: 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_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0038: 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_0046: Unknown result type (might be due to invalid IL or missing references) return $"blunt {d.m_blunt}, slash {d.m_slash}, pierce {d.m_pierce}, chop {d.m_chop}, pickaxe {d.m_pickaxe}, tool tier {minToolTier}"; } private static List<string> DropNames(GameObject root) { List<string> names = new List<string>(); Pickable component = root.GetComponent<Pickable>(); if (Object.op_Implicit((Object)(object)component)) { Add(component.m_itemPrefab); } CharacterDrop component2 = root.GetComponent<CharacterDrop>(); if (Object.op_Implicit((Object)(object)component2)) { foreach (Drop item in component2.m_drops.Where((Drop d) => IsTrophy(d.m_prefab))) { Add(item.m_prefab); } foreach (Drop drop in component2.m_drops) { Add(drop.m_prefab); } } MineRock5 component3 = root.GetComponent<MineRock5>(); if (Object.op_Implicit((Object)(object)component3)) { AddTable(component3.m_dropItems); } MineRock component4 = root.GetComponent<MineRock>(); if (Object.op_Implicit((Object)(object)component4)) { AddTable(component4.m_dropItems); } DropOnDestroyed component5 = root.GetComponent<DropOnDestroyed>(); if (Object.op_Implicit((Object)(object)component5)) { AddTable(component5.m_dropWhenDestroyed); } Destructible component6 = root.GetComponent<Destructible>(); if (Object.op_Implicit((Object)(object)component6) && Object.op_Implicit((Object)(object)component6.m_spawnWhenDestroyed)) { GameObject spawnWhenDestroyed = component6.m_spawnWhenDestroyed; if (Object.op_Implicit((Object)(object)spawnWhenDestroyed.GetComponent<MineRock5>())) { AddTable(spawnWhenDestroyed.GetComponent<MineRock5>().m_dropItems); } if (Object.op_Implicit((Object)(object)spawnWhenDestroyed.GetComponent<MineRock>())) { AddTable(spawnWhenDestroyed.GetComponent<MineRock>().m_dropItems); } if (Object.op_Implicit((Object)(object)spawnWhenDestroyed.GetComponent<DropOnDestroyed>())) { AddTable(spawnWhenDestroyed.GetComponent<DropOnDestroyed>().m_dropWhenDestroyed); } } return names; void Add(GameObject item) { if (Object.op_Implicit((Object)(object)item) && !names.Contains(((Object)item).name)) { names.Add(((Object)item).name); } } void AddTable(DropTable table) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) if (table != null) { foreach (DropData drop2 in table.m_drops) { Add(drop2.m_item); } } } } private static bool IsTrophy(GameObject item) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Invalid comparison between Unknown and I4 ItemDrop val = (Object.op_Implicit((Object)(object)item) ? item.GetComponent<ItemDrop>() : null); if (Object.op_Implicit((Object)(object)val)) { return (int)val.m_itemData.m_shared.m_itemType == 13; } return false; } } internal static class Icons { private static readonly HashSet<string> MissingLogged = new HashSet<string>(); private static readonly Dictionary<string, Sprite> SpritesByName = new Dictionary<string, Sprite>(); private static ObjectDB _indexedFor; public static Sprite ItemIcon(GameObject itemPrefab) { ItemDrop val = (Object.op_Implicit((Object)(object)itemPrefab) ? itemPrefab.GetComponent<ItemDrop>() : null); Sprite[] array = (Object.op_Implicit((Object)(object)val) ? val.m_itemData.m_shared.m_icons : null); if (array == null || array.Length == 0) { return null; } return array[0]; } public static Sprite ItemIcon(string itemNames) { if (!Object.op_Implicit((Object)(object)ObjectDB.instance) || string.IsNullOrEmpty(itemNames)) { return null; } string[] array = itemNames.Split(new char[1] { '|' }); foreach (string text in array) { Sprite val = ItemIcon(ObjectDB.instance.GetItemPrefab(text)); if ((Object)(object)val != (Object)null) { return val; } if (MissingLogged.Add(text)) { RadarLovePlugin.Log.LogWarning((object)("No item named '" + text + "' to take an icon from.")); } } return null; } public static Sprite FromDrops(Character character) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Invalid comparison between Unknown and I4 CharacterDrop component = ((Component)character).GetComponent<CharacterDrop>(); if (!Object.op_Implicit((Object)(object)component)) { return null; } Sprite val = null; foreach (Drop drop in component.m_drops) { ItemDrop val2 = (Object.op_Implicit((Object)(object)drop.m_prefab) ? drop.m_prefab.GetComponent<ItemDrop>() : null); if (Object.op_Implicit((Object)(object)val2)) { if ((int)val2.m_itemData.m_shared.m_itemType == 13) { return ItemIcon(drop.m_prefab); } if ((Object)(object)val == (Object)null) { val = ItemIcon(drop.m_prefab); } } } return val; } public static Sprite VanillaLocationIcon(string prefabName) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0028: 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) if (!Object.op_Implicit((Object)(object)Minimap.instance)) { return null; } foreach (LocationSpriteData locationIcon in Minimap.instance.m_locationIcons) { if (locationIcon.m_name == prefabName) { return locationIcon.m_icon; } } return null; } public static Sprite ByName(string spriteName) { //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(spriteName) || !Object.op_Implicit((Object)(object)ObjectDB.instance)) { return null; } if ((Object)(object)_indexedFor != (Object)(object)ObjectDB.instance) { _indexedFor = ObjectDB.instance; SpritesByName.Clear(); foreach (GameObject item in ObjectDB.instance.m_items) { ItemDrop val = (Object.op_Implicit((Object)(object)item) ? item.GetComponent<ItemDrop>() : null); if (!Object.op_Implicit((Object)(object)val) || val.m_itemData.m_shared.m_icons == null) { continue; } Sprite[] icons = val.m_itemData.m_shared.m_icons; foreach (Sprite val2 in icons) { if (Object.op_Implicit((Object)(object)val2) && !SpritesByName.ContainsKey(((Object)val2).name)) { SpritesByName[((Object)val2).name] = val2; } } } } if (SpritesByName.TryGetValue(spriteName, out var value)) { return value; } if (Object.op_Implicit((Object)(object)Minimap.instance)) { foreach (LocationSpriteData locationIcon in Minimap.instance.m_locationIcons) { if (Object.op_Implicit((Object)(object)locationIcon.m_icon) && ((Object)locationIcon.m_icon).name == spriteName) { return locationIcon.m_icon; } } } return null; } public static Sprite Generic() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Invalid comparison between Unknown and I4 //IL_0031: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)Minimap.instance)) { return null; } foreach (SpriteData icon in Minimap.instance.m_icons) { if ((int)icon.m_name == 3) { return icon.m_icon; } } return null; } } internal static class KeptPins { private class Kept { public string Sprite; public Vector3 Pos; public string Label; public HashSet<string> Spots = new HashSet<string>(); } private const PinType SavedType = (PinType)3; private const string KeyPrefix = "dwarfhavengames.radarlove.kept."; private const float KeyReach = 20f; private static readonly FieldRef<Minimap, List<PinData>> PinsRef = AccessTools.FieldRefAccess<Minimap, List<PinData>>("m_pins"); private static readonly FieldRef<Minimap, bool> MapLoaded = AccessTools.FieldRefAccess<Minimap, bool>("m_hasGenerated"); private static readonly MethodInfo TakeInput = AccessTools.Method(typeof(Player), "TakeInput", (Type[])null, (Type[])null); private static readonly List<Kept> Records = new List<Kept>(); private static readonly HashSet<string> KeptSpots = new HashSet<string>(); private static Player _loadedFor; private static string _loadedKey; public static bool IsKept(Blip blip) { if (!blip.Moves && Loaded()) { return KeptSpots.Contains(Dismissals.SpotOf(blip)); } return false; } public static void CheckKey() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_005d: 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_0093: 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) Player localPlayer = Player.m_localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer) || !Object.op_Implicit((Object)(object)Minimap.instance)) { return; } KeyboardShortcut value = RadarLovePlugin.Settings.KeepKey.Value; if (((KeyboardShortcut)(ref value)).IsDown() && (bool)TakeInput.Invoke(localPlayer, null)) { Blip blip = Radar.LeaderOf(((Humanoid)localPlayer).GetHoverObject()) ?? Radar.ClosestPinned(((Component)localPlayer).transform.position, 20f); if (blip != null) { Keep(blip); return; } Minimap.instance.AddPin(((Component)localPlayer).transform.position, (PinType)3, "", true, false, 0L, default(PlatformUserID)); ((Character)localPlayer).Message((MessageType)1, "Your position pinned to map", 0, (Sprite)null, false); } } public static bool TryKeep(Minimap minimap, Vector3 pointer, float radius) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) Blip blip = Dismissals.RadarPinUnder(minimap, pointer, radius); if (blip == null) { return false; } Keep(blip); return true; } private static void Keep(Blip leader) { //IL_0056: 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_00cd: Unknown result type (might be due to invalid IL or missing references) if (!Loaded() || leader.Pin == null) { return; } Sprite icon = leader.Pin.m_icon; bool flag = (Object)(object)icon == (Object)null || (Object)(object)icon == (Object)(object)Icons.Generic(); Kept kept = new Kept { Sprite = (flag ? "" : ((Object)icon).name), Pos = leader.Pin.m_pos, Label = Radar.LabelFor(leader) }; foreach (Blip member in leader.Members) { if (!member.Moves && Object.op_Implicit((Object)(object)member.Source)) { kept.Spots.Add(Dismissals.SpotOf(member)); } } AddPin(Minimap.instance, kept.Pos, kept.Label, flag ? null : icon); Records.Add(kept); KeptSpots.UnionWith(kept.Spots); Save(); Radar.Unpin(leader); Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)1, leader.Name() + " pinned to map", 0, flag ? null : icon, false); } } private static PinData AddPin(Minimap minimap, Vector3 pos, string label, Sprite icon) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) PinData val = minimap.AddPin(pos, (PinType)3, label, true, false, 0L, default(PlatformUserID)); if (Object.op_Implicit((Object)(object)icon)) { val.m_icon = icon; } return val; } public static void Sync(Minimap minimap) { if (!Loaded() || Records.Count == 0 || !MapLoaded.Invoke(minimap)) { return; } List<PinData> source = PinsRef.Invoke(minimap); bool flag = false; for (int num = Records.Count - 1; num >= 0; num--) { Kept kept = Records[num]; PinData val = ((IEnumerable<PinData>)source).FirstOrDefault((Func<PinData, bool>)((PinData p) => p.m_save && (int)p.m_type == 3 && Utils.DistanceXZ(p.m_pos, kept.Pos) < 1f)); if (val == null) { Records.RemoveAt(num); flag = true; } else { Sprite val2 = Icons.ByName(kept.Sprite); if (Object.op_Implicit((Object)(object)val2) && (Object)(object)val.m_icon != (Object)(object)val2) { val.m_icon = val2; if (Object.op_Implicit((Object)(object)val.m_iconElement)) { val.m_iconElement.sprite = val2; } } } } if (!flag) { return; } KeptSpots.Clear(); foreach (Kept record in Records) { KeptSpots.UnionWith(record.Spots); } Save(); } private static void Save() { Player localPlayer = Player.m_localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer) || _loadedKey == null) { return; } if (Records.Count == 0) { localPlayer.m_customData.Remove(_loadedKey); return; } localPlayer.m_customData[_loadedKey] = string.Join("\n", Records.Select((Kept k) => string.Join("|", k.Sprite, k.Pos.x.ToString("R", CultureInfo.InvariantCulture), k.Pos.z.ToString("R", CultureInfo.InvariantCulture), string.Join(";", k.Spots), k.Label))); } private static bool Loaded() { //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; string text = ((Object.op_Implicit((Object)(object)localPlayer) && Object.op_Implicit((Object)(object)ZNet.instance)) ? ("dwarfhavengames.radarlove.kept." + ZNet.instance.GetWorldUID()) : null); if (text == null) { return false; } if ((Object)(object)localPlayer == (Object)(object)_loadedFor && text == _loadedKey) { return true; } _loadedFor = localPlayer; _loadedKey = text; Records.Clear(); KeptSpots.Clear(); if (!localPlayer.m_customData.TryGetValue(text, out var value)) { return true; } string[] array = value.Split(new char[1] { '\n' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Split(new char[1] { '|' }, 5); if (array2.Length >= 5 && float.TryParse(array2[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var result) && float.TryParse(array2[2], NumberStyles.Float, CultureInfo.InvariantCulture, out var result2)) { Kept kept = new Kept { Sprite = array2[0], Pos = new Vector3(result, 0f, result2), Label = array2[4] }; string[] array3 = array2[3].Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries); foreach (string item in array3) { kept.Spots.Add(item); } Records.Add(kept); KeptSpots.UnionWith(kept.Spots); } } return true; } } [HarmonyPatch(typeof(Location), "Awake")] internal static class LocationAwakePatch { private static void Postfix(Location __instance) { Radar.AddLocation(__instance); } } [HarmonyPatch(typeof(Pickable), "Awake")] internal static class PickableAwakePatch { private static void Postfix(Pickable __instance) { Radar.AddPickable(__instance); } } [HarmonyPatch(typeof(Character), "Awake")] internal static class CharacterAwakePatch { private static void Postfix(Character __instance) { Radar.AddCreature(__instance); } } [HarmonyPatch(typeof(Fish), "Awake")] internal static class FishAwakePatch { private static void Postfix(Fish __instance) { Radar.AddFish(__instance); } } [HarmonyPatch(typeof(DropOnDestroyed), "Awake")] internal static class DropOnDestroyedAwakePatch { private static void Postfix(DropOnDestroyed __instance) { Radar.AddOre((Component)(object)__instance, __instance.m_dropWhenDestroyed); } } [HarmonyPatch(typeof(Destructible), "Awake")] internal static class DestructibleAwakePatch { private static void Postfix(Destructible __instance) { Radar.AddDestructible(__instance); } } [HarmonyPatch(typeof(ZNetView), "Awake")] internal static class ZNetViewAwakePatch { private static void Postfix(ZNetView __instance) { Radar.AddNetworked((Component)(object)__instance); } } [HarmonyPatch(typeof(MineRock), "Start")] internal static class MineRockStartPatch { private static void Postfix(MineRock __instance) { Radar.AddOre((Component)(object)__instance, __instance.m_dropItems); } } [HarmonyPatch(typeof(MineRock5), "Awake")] internal static class MineRock5AwakePatch { private static void Postfix(MineRock5 __instance) { Radar.AddOre((Component)(object)__instance, __instance.m_dropItems); } } [HarmonyPatch(typeof(Minimap), "RemovePinUnderPointer")] internal static class MinimapRemovePinUnderPointerPatch { internal static readonly MethodInfo ScreenToWorldPoint = AccessTools.Method(typeof(Minimap), "ScreenToWorldPoint", (Type[])null, (Type[])null); internal static readonly MethodInfo PinInteractRadius = AccessTools.PropertyGetter(typeof(Minimap), "PinInteractRadius"); private static bool Prefix(Minimap __instance) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: 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) Vector3 pointer = (Vector3)ScreenToWorldPoint.Invoke(__instance, new object[1] { ZInput.pointerPosition }); float radius = (float)PinInteractRadius.Invoke(__instance, null); return !Dismissals.TryDismiss(__instance, pointer, radius); } } [HarmonyPatch(typeof(Minimap), "OnMapLeftClick")] internal static class MinimapOnMapLeftClickPatch { private static bool Prefix(Minimap __instance) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0060: 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) Vector3 pointer = (Vector3)MinimapRemovePinUnderPointerPatch.ScreenToWorldPoint.Invoke(__instance, new object[1] { ZInput.pointerPosition }); float radius = (float)MinimapRemovePinUnderPointerPatch.PinInteractRadius.Invoke(__instance, null); if ((ZInput.GetKey((KeyCode)304, true) || ZInput.GetKey((KeyCode)303, true)) && KeptPins.TryKeep(__instance, pointer, radius)) { return false; } Dismissals.TryToggleCross(__instance, pointer, radius); return true; } } [BepInPlugin("dwarfhavengames.radarlove", "Radar Love", "1.4.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public class RadarLovePlugin : BaseUnityPlugin { public const string Guid = "dwarfhavengames.radarlove"; internal static ManualLogSource Log; internal static Config Settings; private void Awake() { //IL_0020: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; Settings = new Config(((BaseUnityPlugin)this).Config); new Harmony("dwarfhavengames.radarlove").PatchAll(); HoverCommand.Register(); } private void Update() { Radar.Tick(); KeptPins.CheckKey(); } } internal class Blip { public Component Source; public Entry Entry; public Func<Sprite> FindIcon; public Func<string> Name; public bool Moves; public Pickable Pickable; public bool Suppressed; public bool Hidden; public bool Crossed; public string Spot; public bool InRange; public readonly List<Blip> Members = new List<Blip>(); public PinData Pin; public int PinCount; private Sprite _icon; private bool _iconResolved; public Sprite Icon { get { if (!_iconResolved) { _icon = FindIcon(); _iconResolved = true; } return _icon; } } } internal static class Radar { private const float Hysteresis = 10f; private const float RangeInterval = 0.25f; private const float InteriorHeight = 3000f; private static readonly List<Blip> Blips = new List<Blip>(); private static readonly HashSet<GameObject> Tracked = new HashSet<GameObject>(); private static readonly Dictionary<Entry, List<Blip>> ByKind = new Dictionary<Entry, List<Blip>>(); private static Minimap _minimap; private static float _nextRangeCheck; private static Config Cfg => RadarLovePlugin.Settings; public static void AddLocation(Location location) { string prefab = PrefabName(((Component)location).gameObject); if (location.m_hasInterior) { DungeonPins.Track(location); Entry dungeon = Catalog.Dungeon(DungeonPins.EnterText(location)); Add((Component)(object)location, dungeon, () => Icons.ItemIcon(dungeon.IconItem), () => DungeonPins.NameFor(location)); return; } Entry entry = Catalog.Location(prefab); if (entry != null) { Add((Component)(object)location, entry, () => Icons.ItemIcon(entry.IconItem) ?? Icons.VanillaLocationIcon(prefab), () => entry.Display); } } public static void AddPickable(Pickable pickable) { GameObject item = pickable.m_itemPrefab; if (Object.op_Implicit((Object)(object)item)) { Entry entry = Catalog.Ore(((Object)item).name) ?? Catalog.Pickable(((Object)item).name); Blip blip = Add((Component)(object)pickable, entry, () => Icons.ItemIcon(item), () => ItemName(item)); if (blip != null) { blip.Pickable = pickable; } } } public static void AddOre(Component source, DropTable drops) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) if (drops == null) { return; } foreach (DropData drop in drops.m_drops) { GameObject item = drop.m_item; Entry entry = (Object.op_Implicit((Object)(object)item) ? Catalog.Ore(((Object)item).name) : null); if (entry == null) { continue; } if (IsDeposit(source.gameObject, drops, entry)) { Add(source, entry, () => Icons.ItemIcon(item), () => entry.Display); } break; } } private static bool IsDeposit(GameObject go, DropTable drops, Entry ore) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)go.GetComponent<MineRock>()) || Object.op_Implicit((Object)(object)go.GetComponent<MineRock5>())) { return true; } Destructible component = go.GetComponent<Destructible>(); if (Object.op_Implicit((Object)(object)component) && IsMined(component.m_damages)) { return true; } return drops.m_drops.All((DropData d) => Object.op_Implicit((Object)(object)d.m_item) && Catalog.Ore(((Object)d.m_item).name) == ore); } private static bool IsMined(DamageModifiers d) { //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_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0028: 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_0035: Unknown result type (might be due to invalid IL or missing references) if (Shrugs(d.m_blunt) && Shrugs(d.m_slash) && Shrugs(d.m_pierce) && Shrugs(d.m_chop)) { return !Shrugs(d.m_pickaxe); } return false; } private static bool Shrugs(DamageModifier m) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 if ((int)m != 3) { return (int)m == 4; } return true; } public static void AddDestructible(Destructible destructible) { GameObject spawnWhenDestroyed = destructible.m_spawnWhenDestroyed; if (Object.op_Implicit((Object)(object)spawnWhenDestroyed)) { MineRock5 component = spawnWhenDestroyed.GetComponent<MineRock5>(); MineRock component2 = spawnWhenDestroyed.GetComponent<MineRock>(); DropOnDestroyed component3 = spawnWhenDestroyed.GetComponent<DropOnDestroyed>(); AddOre((Component)(object)destructible, Object.op_Implicit((Object)(object)component) ? component.m_dropItems : (Object.op_Implicit((Object)(object)component2) ? component2.m_dropItems : (Object.op_Implicit((Object)(object)component3) ? component3.m_dropWhenDestroyed : null))); } } public static bool AddPoi(Component source) { Entry entry = Catalog.Poi(PrefabName(source.gameObject)); if (entry == null) { return false; } Add(source, entry, () => Icons.ItemIcon(entry.IconItem), () => entry.Display); return true; } public static void AddCreature(Character character) { if (!character.IsPlayer()) { Entry entry = Catalog.Creature(PrefabName(((Component)character).gameObject)); Blip blip = Add((Component)(object)character, entry, () => Icons.ItemIcon(entry.IconItem) ?? Icons.FromDrops(character), () => Localize(character.m_name)); if (blip != null) { blip.Moves = true; } } } public static void AddFish(Fish fish) { Entry entry = Catalog.FishKind(PrefabName(((Component)fish).gameObject)); ItemDrop item = ((Component)fish).GetComponent<ItemDrop>(); if (entry != null && Object.op_Implicit((Object)(object)item)) { Blip blip = Add((Component)(object)fish, entry, () => Icons.ItemIcon(((Component)fish).gameObject), () => Localize(item.m_itemData.m_shared.m_name)); if (blip != null) { blip.Moves = true; } } } public static void Suppress(Component source) { foreach (Blip blip in Blips) { if ((Object)(object)blip.Source == (Object)(object)source) { blip.Suppressed = true; } } } public static void AddNetworked(Component source) { Entry custom = Catalog.CustomFor(PrefabName(source.gameObject)); if (custom != null) { Add(source, custom, () => (Sprite)null, () => custom.Display); } else { AddPoi(source); } } private static Blip Add(Component source, Entry entry, Func<Sprite> icon, Func<string> name) { Entry custom = Catalog.CustomFor(PrefabName(source.gameObject)); if (custom != null) { Func<Sprite> own = icon; entry = custom; icon = () => Icons.ItemIcon(custom.IconItem) ?? own(); name = () => custom.Display; } if (entry == null || !Tracked.Add(source.gameObject)) { return null; } Blip blip = new Blip { Source = source, Entry = entry, FindIcon = icon, Name = name, Moves = (Object.op_Implicit((Object)(object)source.GetComponent<Character>()) || Object.op_Implicit((Object)(object)source.GetComponent<Fish>())) }; Blips.Add(blip); return blip; } public static void Rescan() { foreach (Blip blip in Blips) { Unpin(blip); } Blips.Clear(); Tracked.Clear(); DungeonPins.Clear(); Location[] array = Object.FindObjectsOfType<Location>(); for (int i = 0; i < array.Length; i++) { AddLocation(array[i]); } Pickable[] array2 = Object.FindObjectsOfType<Pickable>(); for (int i = 0; i < array2.Length; i++) { AddPickable(array2[i]); } Character[] array3 = Object.FindObjectsOfType<Character>(); for (int i = 0; i < array3.Length; i++) { AddCreature(array3[i]); } Fish[] array4 = Object.FindObjectsOfType<Fish>(); for (int i = 0; i < array4.Length; i++) { AddFish(array4[i]); } Destructible[] array5 = Object.FindObjectsOfType<Destructible>(); for (int i = 0; i < array5.Length; i++) { AddDestructible(array5[i]); } DropOnDestroyed[] array6 = Object.FindObjectsOfType<DropOnDestroyed>(); foreach (DropOnDestroyed val in array6) { AddOre((Component)(object)val, val.m_dropWhenDestroyed); } MineRock[] array7 = Object.FindObjectsOfType<MineRock>(); foreach (MineRock val2 in array7) { AddOre((Component)(object)val2, val2.m_dropItems); } MineRock5[] array8 = Object.FindObjectsOfType<MineRock5>(); foreach (MineRock5 val3 in array8) { AddOre((Component)(object)val3, val3.m_dropItems); } ZNetView[] array9 = Object.FindObjectsOfType<ZNetView>(); for (int i = 0; i < array9.Length; i++) { AddNetworked((Component)(object)array9[i]); } } public static void Tick() { //IL_008c: 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_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; Minimap instance = Minimap.instance; if (!Object.op_Implicit((Object)(object)localPlayer) || !Object.op_Implicit((Object)(object)instance)) { return; } if ((Object)(object)instance != (Object)(object)_minimap) { _minimap = instance; foreach (Blip blip in Blips) { blip.Pin = null; } } foreach (Blip blip2 in Blips) { if (blip2.Pin != null) { blip2.Pin.m_pos = Centre(blip2.Members); } } if (!(Time.time < _nextRangeCheck)) { _nextRangeCheck = Time.time + 0.25f; Vector3 position = ((Component)localPlayer).transform.position; UpdateRange(position); UpdateGroups(); RaiseCrossed(); Tracked.RemoveWhere((GameObject go) => !Object.op_Implicit((Object)(object)go)); DungeonPins.Tick(position); DungeonPins.Sync(instance); KeptPins.Sync(instance); } } private static void UpdateRange(Vector3 here) { //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) bool value = Cfg.Enabled.Value; float value2 = Cfg.Radius.Value; for (int num = Blips.Count - 1; num >= 0; num--) { Blip blip = Blips[num]; if (!Object.op_Implicit((Object)(object)blip.Source)) { Unpin(blip); Blips.RemoveAt(num); } else { Vector3 position = blip.Source.transform.position; float num2 = (blip.InRange ? (value2 + 10f) : value2); blip.InRange = value && blip.Entry.Enabled && !blip.Suppressed && !blip.Hidden && position.y < 3000f && Utils.DistanceXZ(here, position) < num2 && ((Object)(object)blip.Pickable == (Object)null || blip.Pickable.CanBePicked()) && !Dismissals.IsDismissed(blip) && !KeptPins.IsKept(blip); } } } private static void UpdateGroups() { //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) foreach (List<Blip> value2 in ByKind.Values) { value2.Clear(); } foreach (Blip blip in Blips) { if (!blip.InRange) { Unpin(blip); continue; } if (!ByKind.TryGetValue(blip.Entry, out var value)) { value = (ByKind[blip.Entry] = new List<Blip>()); } value.Add(blip); } HashSet<Blip> hashSet = new HashSet<Blip>(); foreach (List<Blip> value3 in ByKind.Values) { if (value3.Count == 0) { continue; } float num = (value3[0].Moves ? Cfg.CreatureGroupDistance.Value : Cfg.GroupDistance.Value); value3.Sort((Blip a, Blip b) => (b.Pin != null).CompareTo(a.Pin != null)); foreach (Blip item in value3) { if (hashSet.Contains(item)) { continue; } item.Members.Clear(); Vector3 position = item.Source.transform.position; foreach (Blip item2 in value3) { if (!hashSet.Contains(item2) && !(Utils.DistanceXZ(position, item2.Source.transform.position) > num)) { hashSet.Add(item2); item.Members.Add(item2); } } foreach (Blip member in item.Members) { if (member != item) { Unpin(member); } } if (item.Pin == null || item.PinCount != item.Members.Count) { Unpin(item); Pin(item); } } } } private static void Pin(Blip blip) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) Sprite icon = blip.Icon ?? Icons.Generic(); int count = blip.Members.Count; string text = LabelFor(blip); string text2 = ((count > 1) ? $"{count}x {text}".TrimEnd(Array.Empty<char>()) : text); blip.Pin = Minimap.instance.AddPin(Centre(blip.Members), (PinType)8, text2, false, Dismissals.IsCrossed(blip.Members), 0L, default(PlatformUserID)); blip.Pin.m_icon = icon; blip.PinCount = count; } internal static string LabelFor(Blip blip) { if (!Cfg.ShowLabels.Value && !((Object)(object)blip.Icon == (Object)null)) { ConfigEntry<bool> nameSetting = blip.Entry.NameSetting; if (nameSetting == null || !nameSetting.Value) { return ""; } } return blip.Name(); } internal static Blip LeaderOf(GameObject go) { if (!Object.op_Implicit((Object)(object)go)) { return null; } foreach (Blip blip in Blips) { if (blip.Pin != null && blip.Members.Any((Blip m) => Object.op_Implicit((Object)(object)m.Source) && go.transform.IsChildOf(m.Source.transform))) { return blip; } } return null; } internal static void Unpin(Blip blip) { if (blip.Pin != null && Object.op_Implicit((Object)(object)Minimap.instance)) { Minimap.instance.RemovePin(blip.Pin); } blip.Pin = null; blip.PinCount = 0; } internal static Blip ClosestPinned(Vector3 point, float radius) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) Blip result = null; float num = radius; foreach (Blip blip in Blips) { if (blip.Pin != null) { float num2 = Utils.DistanceXZ(point, blip.Pin.m_pos); if (num2 < num) { result = blip; num = num2; } } } return result; } private static void RaiseCrossed() { foreach (Blip blip in Blips) { PinData pin = blip.Pin; if (pin != null && pin.m_checked && Object.op_Implicit((Object)(object)pin.m_uiElement) && Object.op_Implicit((Object)(object)pin.m_checkedElement)) { ((Transform)pin.m_uiElement).SetAsLastSibling(); pin.m_checkedElement.transform.SetAsLastSibling(); } } } internal static void Refresh() { foreach (Blip blip in Blips) { Unpin(blip); } } internal static void ClearHidden() { foreach (Blip blip in Blips) { blip.Hidden = false; } } private static Vector3 Centre(List<Blip> members) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) Vector3 val = Vector3.zero; int num = 0; foreach (Blip member in members) { if (Object.op_Implicit((Object)(object)member.Source)) { val += member.Source.transform.position; num++; } } if (num <= 0) { return Vector3.zero; } return val / (float)num; } internal static string PrefabName(GameObject go) { ZNetView component = go.GetComponent<ZNetView>(); ZDO val = (Object.op_Implicit((Object)(object)component) ? component.GetZDO() : null); GameObject val2 = ((val != null && Object.op_Implicit((Object)(object)ZNetScene.instance)) ? ZNetScene.instance.GetPrefab(val.GetPrefab()) : null); if (Object.op_Implicit((Object)(object)val2)) { return ((Object)val2).name; } string name = ((Object)go).name; int num = name.IndexOf("(Clone)", StringComparison.Ordinal); if (num < 0) { return name; } return name.Substring(0, num).TrimEnd(Array.Empty<char>()); } private static string ItemName(GameObject item) { ItemDrop component = item.GetComponent<ItemDrop>(); if (!Object.op_Implicit((Object)(object)component)) { return ((Object)item).name; } return Localize(component.m_itemData.m_shared.m_name); } internal static string Localize(string text) { if (Localization.instance == null) { return text; } return Localization.instance.Localize(text); } } }