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 Huginn Map v1.0.0
Huginn.dll
Decompiled 9 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Splatform; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: AssemblyCompany("Huginn")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+4e94c02f59b8534712a3ec8f800f860554998ff0")] [assembly: AssemblyProduct("Huginn")] [assembly: AssemblyTitle("Huginn")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] namespace Huginn { internal static class Boats { private sealed class Track { public Vector3 Pos; public float Time; public float StableSince; public bool Pinned; public Vector3 PinnedPos; } private static Dictionary<int, string> _boatPrefabs; private static readonly Dictionary<string, Track> _tracks = new Dictionary<string, Track>(); private static float _lastSweep; public static void Reset() { _tracks.Clear(); _boatPrefabs = null; _lastSweep = 0f; } private static string PrefabName(GameObject go) { string name = ((Object)go).name; int num = name.IndexOf("(Clone)", StringComparison.Ordinal); if (num < 0) { return name; } return name.Substring(0, num); } private static string BoatCategory(string prefab) { if (!string.IsNullOrEmpty(prefab)) { return "boat:" + prefab; } return "boat"; } public unsafe static void Tick(float now) { //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: 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_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_0231: Unknown result type (might be due to invalid IL or missing references) //IL_0233: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) if (!Cfg.AutoPinBoats.Value || now - _lastSweep < Cfg.BoatSweepSec.Value) { return; } _lastSweep = now; ZDOMan instance = ZDOMan.instance; ZNetScene instance2 = ZNetScene.instance; if (instance == null || (Object)(object)instance2 == (Object)null) { return; } Dictionary<int, string> dictionary = BoatPrefabs(instance2); if (dictionary.Count == 0) { return; } float value = Cfg.BoatStopSpeed.Value; float value2 = Cfg.BoatStopSeconds.Value; HashSet<string> hashSet = new HashSet<string>(); foreach (ZDO value5 in instance.m_objectsByID.Values) { if (value5 == null || !dictionary.TryGetValue(value5.GetPrefab(), out var value3)) { continue; } ZDOID uid = value5.m_uid; string text = "boat:" + ((object)(*(ZDOID*)(&uid))/*cast due to .constrained prefix*/).ToString(); Vector3 position = value5.GetPosition(); hashSet.Add(text); if (!_tracks.TryGetValue(text, out var value4)) { _tracks[text] = new Track { Pos = position, Time = now, StableSince = now }; continue; } float num = now - value4.Time; Vector3 val; int num2; if (num > 0f) { val = position - value4.Pos; num2 = ((((Vector3)(ref val)).magnitude > value * num) ? 1 : 0); } else { num2 = 0; } value4.Pos = position; value4.Time = now; if (num2 != 0) { value4.StableSince = now; if (value4.Pinned) { Net.Remove(text); value4.Pinned = false; } } else if (!value4.Pinned && now - value4.StableSince >= value2) { Net.Upsert(new SharedPin { Id = text, Category = BoatCategory(value3), Name = string.Empty, Pos = position }); value4.Pinned = true; value4.PinnedPos = position; } else if (value4.Pinned) { val = position - value4.PinnedPos; if (((Vector3)(ref val)).sqrMagnitude > 16f) { Net.Upsert(new SharedPin { Id = text, Category = BoatCategory(value3), Name = string.Empty, Pos = position }); value4.PinnedPos = position; } } } List<string> list = null; foreach (KeyValuePair<string, Track> track in _tracks) { if (!hashSet.Contains(track.Key)) { (list ?? (list = new List<string>())).Add(track.Key); } } if (list == null) { return; } foreach (string item in list) { if (_tracks[item].Pinned) { Net.Remove(item); } _tracks.Remove(item); } } private static Dictionary<int, string> BoatPrefabs(ZNetScene scene) { if (_boatPrefabs != null && _boatPrefabs.Count > 0) { return _boatPrefabs; } _boatPrefabs = new Dictionary<int, string>(); foreach (GameObject prefab in scene.m_prefabs) { if ((Object)(object)prefab != (Object)null && (Object)(object)prefab.GetComponent<Ship>() != (Object)null) { _boatPrefabs[StringExtensionMethods.GetStableHashCode(((Object)prefab).name)] = ((Object)prefab).name; } } if (_boatPrefabs.Count > 0) { HuginnPlugin.Log.LogInfo((object)($"Boat sweep tracking {_boatPrefabs.Count} boat prefab(s): " + string.Join(", ", _boatPrefabs.Values))); } return _boatPrefabs; } } [HarmonyPatch(typeof(Minimap), "OnMapLeftClick")] internal static class ClearedMark { private static void Postfix(Minimap __instance) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) Vector3 world = __instance.ScreenToWorldPoint(ZInput.mousePosition); float radius = __instance.m_removeRadius * (__instance.m_largeZoom * 2f); PinBoard.ToggleClearedAt(world, radius); } } internal static class Cfg { public static ConfigEntry<bool> ShareMap; public static ConfigEntry<bool> AutoPinResources; public static ConfigEntry<bool> AutoPinPortals; public static ConfigEntry<bool> AutoPinBoats; public static ConfigEntry<bool> AutoPinPickables; public static ConfigEntry<float> ScanIntervalSec; public static ConfigEntry<float> ScanRadius; public static ConfigEntry<float> PoiScanRadius; public static ConfigEntry<string> OrePrefabs; public static ConfigEntry<string> HitPinPrefabs; public static ConfigEntry<string> PoiLocations; public static ConfigEntry<string> PickablePrefabs; public static ConfigEntry<float> ClusterMerge; public static ConfigEntry<float> BoatStopSpeed; public static ConfigEntry<float> BoatStopSeconds; public static ConfigEntry<float> BoatSweepSec; public static ConfigEntry<float> PortalSweepSec; public static ConfigEntry<string> SweepPrefabs; public static ConfigEntry<float> MapFlushIntervalSec; public static ConfigEntry<bool> ShareVanillaPins; public static ConfigEntry<bool> RemoveImportedPinsOnLoad; public static ConfigEntry<string> PinVisibility; public static ConfigEntry<bool> DefaultPinVisible; public static ConfigEntry<bool> LogNearbyPrefabs; public static ConfigEntry<bool> VerboseLogging; private static ConfigDescription Synced(string desc) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown return new ConfigDescription(desc, (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } }); } public static void Init(ConfigFile c) { //IL_02cf: Unknown result type (might be due to invalid IL or missing references) //IL_02d9: Expected O, but got Unknown //IL_02f9: Unknown result type (might be due to invalid IL or missing references) //IL_0303: Expected O, but got Unknown //IL_031f: Unknown result type (might be due to invalid IL or missing references) //IL_0329: Expected O, but got Unknown //IL_0345: Unknown result type (might be due to invalid IL or missing references) //IL_034f: Expected O, but got Unknown //IL_036b: Unknown result type (might be due to invalid IL or missing references) //IL_0375: Expected O, but got Unknown ShareMap = c.Bind<bool>("General", "ShareMap", true, Synced("Synchronize explored map (fog of war) between all players on the server.")); AutoPinResources = c.Bind<bool>("General", "AutoPinResources", true, Synced("Automatically place shared pins on detected ore deposits and dungeons.")); AutoPinPortals = c.Bind<bool>("General", "AutoPinPortals", true, Synced("Automatically place a shared pin for every portal, named after its tag.")); AutoPinBoats = c.Bind<bool>("General", "AutoPinBoats", true, Synced("Automatically pin a boat when it stops, and remove the pin when it moves again.")); AutoPinPickables = c.Bind<bool>("General", "AutoPinPickables", true, Synced("Automatically pin nearby harvestable pickables (berries, mushrooms, thistle, dandelion, ...) as you explore. Uses the ore scan radius and cluster merge. Pins persist after harvesting (pickables regrow, so the spot stays marked for a return trip). Toggle individual kinds on/off from the map's filter column.")); ScanIntervalSec = c.Bind<float>("Scanner", "ScanIntervalSec", 2f, Synced("How often (seconds) to scan nearby objects for auto-pinning.")); ScanRadius = c.Bind<float>("Scanner", "ScanRadius", 10f, Synced("Detection radius (meters) for ore-deposit auto-pins — how close you must get to a deposit.")); PoiScanRadius = c.Bind<float>("Scanner", "PoiScanRadius", 30f, Synced("Detection radius (meters) for dungeon/POI Location auto-pins (separate from ore radius).")); OrePrefabs = c.Bind<string>("Scanner", "OrePrefabs", "rock4_copper=CopperOre=Cu,MineRock_Tin=TinOre=Sn,MineRock_Obsidian=Obsidian=Ob,LeviathanLava=FlametalOreNew=Fl,giant_brain=Softtissue=ST", Synced("Comma list of surface ore deposits to pin by proximity. Format: PrefabName=IconItemPrefab=Label. Use the 'LogNearbyPrefabs' debug option to discover exact prefab names in your game version. Note: buried deposits like silver are handled by HitPinPrefabs instead, so they are not revealed before the player digs them up. Swamp iron is intentionally omitted — the Sunken Crypts that hold it are already pinned as POIs.")); PoiLocations = c.Bind<string>("Scanner", "PoiLocations", "Crypt=Tomb=$tomb,SunkenCrypt=Crypt=$crypt,MountainCave=Cave=$cave,Hildir_cave=Cave=$cave,TrollCave=Troll=$trollcave,GoblinCamp=Camp=TrophyGoblinBrute,TarPit=Tar=Tar,Mistlands_DvergrTownEntrance=Mine=TrophySeeker,Mistlands_GuardTower=Dvergr=$dvergr,Mistlands_Excavation=Dvergr=$dvergr,DrakeNest=Nest=DragonEgg,CharredFortress=Fortress=CharredBone,MorgenHole=Morgen=$morgen", Synced("Comma list of dungeon Locations to pin. Format: LocationPrefix=Label[=IconItem]. The prefix matches any Location whose name starts with it, so numbered variants (MountainCave01/02/...) are all covered. Icon (optional) is an item or build-piece prefab whose sprite to use, or $name for a built-in custom sprite. Enable 'LogNearbyPrefabs' and stand near a dungeon to see real Location names as '[NearbyLocations]'.")); HitPinPrefabs = c.Bind<string>("Scanner", "HitPinPrefabs", "silvervein=SilverOre=Ag,silvervein_frac=SilverOre=Ag", Synced("Comma list of buried/hidden deposits that are pinned only when the player actually strikes them (not by proximity), so the Wishbone hunt isn't trivialized. Format: PrefabName=IconItemPrefab=Label. Default: silver veins.")); PickablePrefabs = c.Bind<string>("Scanner", "PickablePrefabs", "Pickable_Thistle=Thistle=Thistle,Pickable_Dandelion=Dandelion=Dandelion,Pickable_Mushroom=Mushroom=Mushroom,Pickable_Mushroom_yellow=MushroomYellow=YellowMushroom,Pickable_Mushroom_blue=MushroomBlue=BlueMushroom,Pickable_Flint=Flint=Flint,RaspberryBush=Raspberry=Raspberry,BlueberryBush=Blueberries=Blueberry,CloudberryBush=Cloudberry=Cloudberry,Pickable_Mushroom_JotunPuffs=MushroomJotunPuffs=JotunPuffs,Pickable_Mushroom_Magecap=MushroomMagecap=Magecap,VineAsh=Vineberry=Vineberry,Pickable_Fiddlehead=Fiddlehead=Fiddlehead,Pickable_SmokePuff=SmokePuff=SmokePuff,Pickable_SulfurRock=Sulfur=Sulfur,Pickable_VoltureEgg=VoltureEgg=VoltureEgg", Synced("Comma list of harvestable pickables to pin by proximity (needs AutoPinPickables). Format: PrefabName=IconItemPrefab=Label. The icon/name are auto-detected from the item the plant actually drops; IconItemPrefab is only a fallback if that can't be read. Uses the ore scan radius and cluster merge. Enable the 'LogNearbyPrefabs' debug option and stand near a plant to find exact prefab names in your game version.")); ClusterMerge = c.Bind<float>("Scanner", "ClusterMerge", 8f, Synced("Resource pins within this distance (meters) collapse into a single pin.")); BoatStopSpeed = c.Bind<float>("Boats", "BoatStopSpeed", 0.5f, Synced("A boat counts as stopped when its average speed (m/s) between sweeps is below this. Tolerates a parked boat drifting on waves while still catching one under sail.")); BoatStopSeconds = c.Bind<float>("Boats", "BoatStopSeconds", 5f, Synced("A boat must stay stopped this long (seconds) before it gets pinned.")); BoatSweepSec = c.Bind<float>("Boats", "BoatSweepSec", 10f, Synced("How often (seconds) the server reconciles boat pins against every boat in the world. Parked boats stay pinned even after you sail away and their area unloads; the pin moves with the boat when it's relocated and clears when the boat is destroyed.")); SweepPrefabs = c.Bind<string>("Structures", "SweepPrefabs", "piece_sapcollector=Sap", Synced("Comma list of player-built objects pinned world-wide by a server sweep (like portals): found everywhere, the pin follows when relocated and clears when removed. Format: PrefabName=IconItem (icon = an item/build-piece prefab, or $name for a built-in sprite). Default: sap collectors. Uses the portal sweep interval.")); PortalSweepSec = c.Bind<float>("Portals", "PortalSweepSec", 60f, Synced("How often (seconds) the server reconciles shared pins against every portal in the world. Backfills portals that pre-date the mod or were built by players without it, and removes pins for portals destroyed while no mod user was present. Covers wood, stone, and modded portals alike (detected by component, not prefab name).")); MapFlushIntervalSec = c.Bind<float>("Map", "MapFlushIntervalSec", 10f, Synced("Minimum interval (seconds) between map-exploration syncs to the server.")); ShareVanillaPins = c.Bind<bool>("Map", "ShareVanillaPins", false, Synced("Allow Valheim's cartography table / shared-map feature to copy player pins between players. Off by default: Huginn manages shared pins itself, and vanilla pin-copying just creates overlapping duplicate pins. When off, the table still shares explored fog, only pins are skipped.")); RemoveImportedPinsOnLoad = c.Bind<bool>("Map", "RemoveImportedPinsOnLoad", true, new ConfigDescription("On each world load, remove pins that were copied onto your map from other players via the cartography table (pins owned by a different player). Your own pins and Huginn's managed pins are never touched. On by default because Huginn shares pins itself, so the imported vanilla copies are just stale duplicates. This is a local, per-player setting; you can also run the console command 'huginn.purgeforeignpins' at any time.", (AcceptableValueBase)null, Array.Empty<object>())); PinVisibility = c.Bind<string>("MapFilter", "Visibility", "", new ConfigDescription("Internal: per-resource-type visibility for the on-map filter column. Managed automatically when you toggle types on the map; you normally won't edit this by hand.", (AcceptableValueBase)null, Array.Empty<object>())); DefaultPinVisible = c.Bind<bool>("MapFilter", "NewTypesVisible", true, new ConfigDescription("When you discover a brand-new resource type, start it visible on the map (true) or hidden until you turn it on in the map's filter column (false). Only affects types you haven't seen before — types you've already set a preference for keep your choice. Config-only; there is no in-game toggle for this.", (AcceptableValueBase)null, Array.Empty<object>())); LogNearbyPrefabs = c.Bind<bool>("Debug", "LogNearbyPrefabs", false, new ConfigDescription("Log distinct nearby prefab names (helps you fill in OrePrefabs/PoiPrefabs).", (AcceptableValueBase)null, Array.Empty<object>())); VerboseLogging = c.Bind<bool>("Debug", "VerboseLogging", false, new ConfigDescription("Enable verbose debug logging.", (AcceptableValueBase)null, Array.Empty<object>())); } } internal static class Env { public static bool ZNetReady => (Object)(object)ZNet.instance != (Object)null; public static bool IsServer { get { if ((Object)(object)ZNet.instance != (Object)null) { return ZNet.instance.IsServer(); } return false; } } public static bool IsDedicated { get { if ((Object)(object)ZNet.instance != (Object)null) { return ZNet.instance.IsDedicated(); } return false; } } public static bool HasMinimap => (Object)(object)Minimap.instance != (Object)null; public static bool InWorld => (Object)(object)Player.m_localPlayer != (Object)null; public static bool WorldActive { get { if (!IsDedicated) { return InWorld; } if (ZNetReady) { return (Object)(object)ZNetScene.instance != (Object)null; } return false; } } public static long LocalPlayerId { get { if (!((Object)(object)Player.m_localPlayer != (Object)null)) { return 0L; } return Player.m_localPlayer.GetPlayerID(); } } public static string WorldName { get { if (!((Object)(object)ZNet.instance != (Object)null)) { return "world"; } return ZNet.instance.GetWorldName(); } } } [BepInPlugin("nightofgames.huginn", "Huginn Map", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public class HuginnPlugin : BaseUnityPlugin { public const string PluginGuid = "nightofgames.huginn"; public const string PluginName = "Huginn Map"; public const string PluginVersion = "1.0.0"; internal static ManualLogSource Log; private readonly Harmony _harmony = new Harmony("nightofgames.huginn"); private void Awake() { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown //IL_003b: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; Cfg.Init(((BaseUnityPlugin)this).Config); Net.Init(); PinCleanup.Init(); _harmony.PatchAll(); GameObject val = new GameObject("Huginn_Runner"); Object.DontDestroyOnLoad((Object)val); ((Object)val).hideFlags = (HideFlags)61; val.AddComponent<HuginnRunner>(); Log.LogInfo((object)"Huginn Map v1.0.0 loaded."); } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } } internal class HuginnRunner : MonoBehaviour { private bool _active; private float _reconcileTimer; private int _reconciledVersion = -1; private static int _warns; private void Update() { float time = Time.time; bool worldActive = Env.WorldActive; if (worldActive && !_active) { _active = true; OnEnter(); } else if (!worldActive && _active) { _active = false; OnExit(); } if (!worldActive) { return; } if (Env.IsServer) { Net.EnsureLoaded(); try { Portals.Tick(time); } catch (Exception e) { Warn("Portals", e); } try { Boats.Tick(time); } catch (Exception e2) { Warn("Boats", e2); } try { Structures.Tick(time); } catch (Exception e3) { Warn("Structures", e3); } Net.MaybeSave(time); } if (!Env.HasMinimap) { return; } try { PinCleanup.MaybePurgeOnLoad(); } catch (Exception e4) { Warn("PinCleanup", e4); } try { Scanner.Tick(time); } catch (Exception e5) { Warn("Scanner", e5); } try { MapShare.Tick(time); } catch (Exception e6) { Warn("MapShare", e6); } if (PinBoard.Version != _reconciledVersion || time - _reconcileTimer > 0.5f) { _reconcileTimer = time; _reconciledVersion = PinBoard.Version; try { PinBoard.Reconcile(); } catch (Exception e7) { Warn("PinBoard", e7); } } try { PinFilterUI.Tick(); } catch (Exception e8) { Warn("PinFilterUI", e8); } } private void OnEnter() { Icons.Reset(); PinBoard.Reset(); MapShare.Reset(); Boats.Reset(); Portals.Reset(); Structures.Reset(); PinCleanup.Reset(); Visibility.Reset(); PinFilterUI.Reset(); if (Env.IsServer) { Net.EnsureLoaded(); } if (Env.HasMinimap) { Net.RequestSnapshot(); } HuginnPlugin.Log.LogInfo((object)"Huginn active."); } private void OnExit() { if (Env.IsServer) { Net.OnWorldUnload(); } Icons.Reset(); PinBoard.Reset(); MapShare.Reset(); Boats.Reset(); Portals.Reset(); Structures.Reset(); PinCleanup.Reset(); Visibility.Reset(); PinFilterUI.Reset(); } private static void Warn(string where, Exception e) { if (_warns++ < 20) { HuginnPlugin.Log.LogWarning((object)(where + " tick error: " + e.Message)); } } } internal static class Icons { private struct Resolved { public PinType Type; public Sprite Sprite; } private const int CustomBase = 100; private static int _next = 100; private static readonly Dictionary<string, Resolved> Cache = new Dictionary<string, Resolved>(); private static readonly Dictionary<string, Sprite> GrayCache = new Dictionary<string, Sprite>(); private static Minimap _injectedInto; public static void Reset() { Cache.Clear(); GrayCache.Clear(); _next = 100; _injectedInto = null; } private static void EnsureCurrentMinimap() { if ((Object)(object)_injectedInto != (Object)(object)Minimap.instance) { Cache.Clear(); GrayCache.Clear(); _next = 100; _injectedInto = Minimap.instance; } } public static Sprite SpriteFor(string category) { if ((Object)(object)Minimap.instance == (Object)null) { return null; } EnsureCurrentMinimap(); return Resolve(category).Sprite; } public static Sprite GraySpriteFor(string category) { if (GrayCache.TryGetValue(category, out var value)) { return value; } Sprite val = SpriteFor(category); Sprite val2 = null; if ((Object)(object)val != (Object)null) { try { val2 = MakeGray(val); } catch (Exception ex) { HuginnPlugin.Log.LogWarning((object)("Greyscale icon for '" + category + "' failed: " + ex.Message)); } } GrayCache[category] = val2; return val2; } private static Sprite MakeGray(Sprite src) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) Texture2D texture = src.texture; RenderTexture temporary = RenderTexture.GetTemporary(((Texture)texture).width, ((Texture)texture).height, 0, (RenderTextureFormat)0); RenderTexture active = RenderTexture.active; try { Graphics.Blit((Texture)(object)texture, temporary); RenderTexture.active = temporary; Rect textureRect = src.textureRect; int num = Mathf.Max(1, (int)((Rect)(ref textureRect)).width); int num2 = Mathf.Max(1, (int)((Rect)(ref textureRect)).height); Texture2D val = new Texture2D(num, num2, (TextureFormat)4, false); val.ReadPixels(new Rect(((Rect)(ref textureRect)).x, ((Rect)(ref textureRect)).y, (float)num, (float)num2), 0, 0); Color[] pixels = val.GetPixels(); for (int i = 0; i < pixels.Length; i++) { Color val2 = pixels[i]; float num3 = val2.r * 0.299f + val2.g * 0.587f + val2.b * 0.114f; pixels[i] = new Color(num3, num3, num3, val2.a); } val.SetPixels(pixels); val.Apply(); return Sprite.Create(val, new Rect(0f, 0f, (float)num, (float)num2), new Vector2(0.5f, 0.5f)); } finally { RenderTexture.active = active; RenderTexture.ReleaseTemporary(temporary); } } private static Resolved Resolve(string category) { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: 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) if (Cache.TryGetValue(category, out var value)) { return value; } Sprite val = LoadSprite(category); if ((Object)(object)val != (Object)null) { value.Type = (PinType)(_next++); value.Sprite = val; Minimap.instance.m_icons.Add(new SpriteData { m_name = value.Type, m_icon = val }); } else { value.Type = FallbackType(category); value.Sprite = null; } Cache[category] = value; return value; } private static PinType FallbackType(string category) { if (!(category == "portal") && !category.StartsWith("portal:")) { if (!(category == "boat") && !category.StartsWith("boat:")) { if (!(category == "poi") && !category.StartsWith("poi:")) { return (PinType)0; } return (PinType)3; } return (PinType)1; } return (PinType)6; } private static Sprite LoadSprite(string category) { if (category.StartsWith("ore:")) { return ItemIcon(category.Substring(4)); } if (category.StartsWith("pick:")) { return ItemIcon(category.Substring(5)); } if (category.StartsWith("portal:")) { string text = category.Substring(7); return EmbeddedSprite(text) ?? PieceIcon(text); } if (category == "portal") { return EmbeddedSprite("portal") ?? PieceIcon("portal_wood"); } if (category.StartsWith("boat:")) { return PieceIcon(category.Substring(5)) ?? PieceIcon("Karve"); } if (category == "boat") { return PieceIcon("Karve") ?? PieceIcon("VikingShip") ?? PieceIcon("Raft"); } if (category.StartsWith("poi:")) { string text2 = category.Substring(4); if (text2.StartsWith("$")) { return EmbeddedSprite(text2.Substring(1)); } return ItemIcon(text2) ?? PieceIcon(text2); } return null; } private static Sprite EmbeddedSprite(string name) { //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Expected O, but got Unknown try { using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Huginn." + name + ".rgba"); if (stream == null) { return null; } byte[] array = new byte[stream.Length]; for (int i = 0; i < array.Length; i += stream.Read(array, i, array.Length - i)) { } int num = array[0] | (array[1] << 8) | (array[2] << 16) | (array[3] << 24); int num2 = array[4] | (array[5] << 8) | (array[6] << 16) | (array[7] << 24); byte[] array2 = new byte[array.Length - 8]; Array.Copy(array, 8, array2, 0, array2.Length); Texture2D val = new Texture2D(num, num2, (TextureFormat)4, false); val.LoadRawTextureData(array2); val.Apply(); return Sprite.Create(val, new Rect(0f, 0f, (float)num, (float)num2), new Vector2(0.5f, 0.5f)); } catch (Exception ex) { HuginnPlugin.Log.LogWarning((object)("Failed to load embedded sprite '" + name + "': " + ex.Message)); return null; } } private static Sprite ItemIcon(string itemPrefab) { ObjectDB instance = ObjectDB.instance; if ((Object)(object)instance == (Object)null) { return null; } GameObject itemPrefab2 = instance.GetItemPrefab(itemPrefab); Sprite[] array = (((Object)(object)itemPrefab2 != (Object)null) ? itemPrefab2.GetComponent<ItemDrop>() : null)?.m_itemData?.m_shared?.m_icons; if (array == null || array.Length == 0) { return null; } return array[0]; } private static Sprite PieceIcon(string prefab) { ZNetScene instance = ZNetScene.instance; if ((Object)(object)instance == (Object)null) { return null; } GameObject prefab2 = instance.GetPrefab(prefab); Piece val = (((Object)(object)prefab2 != (Object)null) ? prefab2.GetComponent<Piece>() : null); if (!((Object)(object)val != (Object)null)) { return null; } return val.m_icon; } public static PinData MakePin(SharedPin pin) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) EnsureCurrentMinimap(); Resolved resolved = Resolve(pin.Category); PinData val = Minimap.instance.AddPin(pin.Pos, resolved.Type, pin.Name ?? string.Empty, false, false, 0L, default(PlatformUserID)); if ((Object)(object)resolved.Sprite != (Object)null) { val.m_icon = resolved.Sprite; } return val; } } internal static class MapShare { private static int _lastSentCount = -1; private static float _lastFlush; private static bool _regenQueued; public static void Reset() { _lastSentCount = -1; _lastFlush = 0f; _regenQueued = false; } public static void ApplyRemote(byte[] blob) { if (blob == null || blob.Length == 0) { return; } Minimap instance = Minimap.instance; if ((Object)(object)instance == (Object)null) { return; } try { if (instance.AddSharedMapData(blob)) { _regenQueued = true; } } catch (Exception ex) { HuginnPlugin.Log.LogWarning((object)("AddSharedMapData failed: " + ex.Message)); } } public static void Tick(float now) { if (!Cfg.ShareMap.Value) { return; } Minimap instance = Minimap.instance; if ((Object)(object)instance == (Object)null || !Env.InWorld) { return; } if (_regenQueued) { _regenQueued = false; instance.ForceRegen(); } if (now - _lastFlush < Cfg.MapFlushIntervalSec.Value) { return; } _lastFlush = now; int num = CountExplored(instance); if (num >= 0 && (_lastSentCount < 0 || num > _lastSentCount)) { _lastSentCount = num; byte[] sharedMapData; try { sharedMapData = instance.GetSharedMapData((byte[])null); } catch (Exception ex) { HuginnPlugin.Log.LogWarning((object)("GetSharedMapData failed: " + ex.Message)); return; } if (sharedMapData != null && sharedMapData.Length != 0) { Net.SendMap(Env.LocalPlayerId, sharedMapData); } } } private static int CountExplored(Minimap map) { bool[] explored = map.m_explored; if (explored == null) { return -1; } int num = 0; for (int i = 0; i < explored.Length; i++) { if (explored[i]) { num++; } } return num; } } internal static class Names { public static string GroupKeyForPin(string category, Vector3 pos) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(category)) { return "other"; } if (category == "portal" || category.StartsWith("portal:")) { return "anywhere"; } if (category == "boat" || category.StartsWith("boat:")) { return "anywhere"; } WorldGenerator instance = WorldGenerator.instance; if (instance == null) { return "other"; } return BiomeKey(instance.GetBiome(pos)); } private static string BiomeKey(Biome b) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Invalid comparison between Unknown and I4 //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected I4, but got Unknown //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Invalid comparison between Unknown and I4 //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Invalid comparison between Unknown and I4 //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Invalid comparison between Unknown and I4 //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Invalid comparison between Unknown and I4 //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Invalid comparison between Unknown and I4 //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Invalid comparison between Unknown and I4 if ((int)b <= 16) { switch (b - 1) { default: if ((int)b != 8) { if ((int)b != 16) { break; } return "plains"; } return "blackforest"; case 0: return "meadows"; case 1: return "swamp"; case 3: return "mountain"; case 2: break; } } else if ((int)b <= 64) { if ((int)b == 32) { return "ashlands"; } if ((int)b == 64) { return "deepnorth"; } } else { if ((int)b == 256) { return "ocean"; } if ((int)b == 512) { return "mistlands"; } } return "other"; } public static string GroupLabel(string groupKey) { return groupKey switch { "meadows" => "Meadows", "blackforest" => "Black Forest", "swamp" => "Swamp", "mountain" => "Mountain", "plains" => "Plains", "mistlands" => "Mistlands", "ashlands" => "Ashlands", "deepnorth" => "Deep North", "ocean" => "Ocean", "anywhere" => "Anywhere", _ => "Other", }; } public static string Leaf(string category) { if (string.IsNullOrEmpty(category)) { return "Unknown"; } if (category.StartsWith("ore:")) { return ItemName(category.Substring(4)) ?? Pretty(category.Substring(4)); } if (category.StartsWith("pick:")) { return ItemName(category.Substring(5)) ?? Pretty(category.Substring(5)); } if (category == "portal") { return "Portal"; } if (category.StartsWith("portal:")) { return PieceName(category.Substring(7)) ?? "Portal"; } if (category == "boat") { return "Boat"; } if (category.StartsWith("boat:")) { return PieceName(category.Substring(5)) ?? "Boat"; } if (category == "poi") { return "Location"; } if (category.StartsWith("poi:")) { string text = category.Substring(4); if (text.StartsWith("$")) { return Pretty(text.Substring(1)); } return ItemName(text) ?? PieceName(text) ?? Pretty(text); } return Pretty(category); } private static string ItemName(string prefab) { ObjectDB instance = ObjectDB.instance; if ((Object)(object)instance == (Object)null) { return null; } GameObject itemPrefab = instance.GetItemPrefab(prefab); string text = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent<ItemDrop>() : null)?.m_itemData?.m_shared?.m_name; if (!string.IsNullOrEmpty(text)) { return Loc(text); } return null; } private static string PieceName(string prefab) { ZNetScene instance = ZNetScene.instance; if ((Object)(object)instance == (Object)null) { return null; } GameObject prefab2 = instance.GetPrefab(prefab); Piece val = (((Object)(object)prefab2 != (Object)null) ? prefab2.GetComponent<Piece>() : null); string text = (((Object)(object)val != (Object)null) ? val.m_name : null); if (!string.IsNullOrEmpty(text)) { return Loc(text); } return null; } private static string Loc(string token) { Localization instance = Localization.instance; if (instance == null) { return token.TrimStart(new char[1] { '$' }); } return instance.Localize(token); } private static string Pretty(string raw) { if (string.IsNullOrEmpty(raw)) { return "Unknown"; } return char.ToUpperInvariant(raw[0]) + ((raw.Length > 1) ? raw.Substring(1) : string.Empty); } } internal static class Net { private const string RpcName = "huginn_v1"; private const byte OP_UPSERT = 1; private const byte OP_REMOVE = 2; private const byte OP_SNAPSHOT = 3; private const byte OP_MAP = 4; private const byte OP_MAPSNAP = 5; private const byte OP_CHECK = 6; private const long LOCAL = long.MinValue; private static CustomRPC _rpc; private static readonly Dictionary<string, SharedPin> Registry = new Dictionary<string, SharedPin>(); private static readonly Dictionary<long, byte[]> MapBlobs = new Dictionary<long, byte[]>(); private static bool _loaded; private static bool _dirtyPins; private static bool _dirtyMap; private static float _lastSave; private static string SaveDir { get { string text = Path.Combine(Paths.ConfigPath, "Huginn"); Directory.CreateDirectory(text); return text; } } private static string PinsFile => Path.Combine(SaveDir, Sanitize(Env.WorldName) + ".pins.dat"); private static string MapFile => Path.Combine(SaveDir, Sanitize(Env.WorldName) + ".map.dat"); public static void Init() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown //IL_0027: Expected O, but got Unknown _rpc = NetworkManager.Instance.AddRPC("huginn_v1", new CoroutineHandler(RpcServer), new CoroutineHandler(RpcClient)); } private static ZPackage New(byte op) { //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_000d: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write(op); return val; } private static void ToServer(ZPackage pkg) { if (Env.IsServer) { pkg.SetPos(0); HandleServer(long.MinValue, pkg); } else if (_rpc != null && (Object)(object)ZNet.instance != (Object)null) { _rpc.SendPackage(ZRoutedRpc.instance.GetServerPeerID(), pkg); } } private static void Broadcast(Func<ZPackage> build) { if (!((Object)(object)ZNet.instance == (Object)null)) { _rpc.SendPackage(ZNet.instance.m_peers, build()); if (Env.HasMinimap) { ZPackage val = build(); val.SetPos(0); HandleClient(0L, val); } } } private static void ToPeer(long target, ZPackage pkg) { if (target == long.MinValue) { pkg.SetPos(0); HandleClient(0L, pkg); } else { _rpc.SendPackage(target, pkg); } } public static void RequestSnapshot() { EnsureLoaded(); ToServer(New(3)); } public static void Upsert(SharedPin pin) { ZPackage val = New(1); pin.Write(val); ToServer(val); } public static void Remove(string id) { ZPackage obj = New(2); obj.Write(id); ToServer(obj); } public static void SetChecked(string id, bool isChecked) { ZPackage obj = New(6); obj.Write(id); obj.Write(isChecked); ToServer(obj); } public static void SendMap(long playerId, byte[] blob) { ZPackage obj = New(4); obj.Write(playerId); obj.Write(blob); ToServer(obj); } private static IEnumerator RpcServer(long sender, ZPackage pkg) { HandleServer(sender, pkg); yield return null; } private static IEnumerator RpcClient(long sender, ZPackage pkg) { HandleClient(sender, pkg); yield return null; } private static void HandleServer(long sender, ZPackage pkg) { EnsureLoaded(); switch (pkg.ReadByte()) { case 1: { SharedPin pin = SharedPin.Read(pkg); if (Registry.TryGetValue(pin.Id, out var value)) { pin.Checked = value.Checked; } Registry[pin.Id] = pin; if (!pin.IsBoat) { _dirtyPins = true; } Broadcast(delegate { ZPackage val = New(1); pin.Write(val); return val; }); break; } case 6: { string id2 = pkg.ReadString(); bool isChecked = pkg.ReadBool(); if (Registry.TryGetValue(id2, out var value2)) { value2.Checked = isChecked; if (!value2.IsBoat) { _dirtyPins = true; } Broadcast(delegate { ZPackage obj = New(6); obj.Write(id2); obj.Write(isChecked); return obj; }); } break; } case 2: { string id = pkg.ReadString(); if (Registry.Remove(id)) { _dirtyPins = true; } Broadcast(delegate { ZPackage obj = New(2); obj.Write(id); return obj; }); break; } case 4: { long pid = pkg.ReadLong(); byte[] blob = pkg.ReadByteArray(); MapBlobs[pid] = blob; _dirtyMap = true; Broadcast(delegate { ZPackage obj = New(4); obj.Write(pid); obj.Write(blob); return obj; }); break; } case 3: SendSnapshotTo(sender); break; case 5: break; } } private static void SendSnapshotTo(long target) { ZPackage val = New(3); val.Write(Registry.Count); foreach (SharedPin value in Registry.Values) { value.Write(val); } ToPeer(target, val); ZPackage val2 = New(5); val2.Write(MapBlobs.Count); foreach (KeyValuePair<long, byte[]> mapBlob in MapBlobs) { val2.Write(mapBlob.Key); val2.Write(mapBlob.Value); } ToPeer(target, val2); } private static void HandleClient(long sender, ZPackage pkg) { switch (pkg.ReadByte()) { case 1: PinBoard.SetDesired(SharedPin.Read(pkg)); break; case 2: PinBoard.RemoveDesired(pkg.ReadString()); break; case 6: { string id = pkg.ReadString(); bool isChecked = pkg.ReadBool(); PinBoard.SetChecked(id, isChecked); break; } case 3: { int num4 = pkg.ReadInt(); List<SharedPin> list = new List<SharedPin>(num4); for (int j = 0; j < num4; j++) { list.Add(SharedPin.Read(pkg)); } PinBoard.ReplaceAll(list); break; } case 4: { long num3 = pkg.ReadLong(); byte[] blob2 = pkg.ReadByteArray(); if (num3 != Env.LocalPlayerId) { MapShare.ApplyRemote(blob2); } break; } case 5: { int num = pkg.ReadInt(); for (int i = 0; i < num; i++) { long num2 = pkg.ReadLong(); byte[] blob = pkg.ReadByteArray(); if (num2 != Env.LocalPlayerId) { MapShare.ApplyRemote(blob); } } break; } } } private static string Sanitize(string name) { char[] invalidFileNameChars = Path.GetInvalidFileNameChars(); foreach (char oldChar in invalidFileNameChars) { name = name.Replace(oldChar, '_'); } return name; } public static void EnsureLoaded() { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Expected O, but got Unknown if (_loaded || !Env.IsServer || !Env.ZNetReady) { return; } _loaded = true; try { if (File.Exists(PinsFile)) { ZPackage val = new ZPackage(File.ReadAllBytes(PinsFile)); int num = val.ReadInt(); for (int i = 0; i < num; i++) { SharedPin sharedPin = SharedPin.Read(val); if (!sharedPin.IsPortal && !string.IsNullOrEmpty(sharedPin.Name)) { sharedPin.Name = string.Empty; _dirtyPins = true; } Registry[sharedPin.Id] = sharedPin; } } if (File.Exists(MapFile)) { ZPackage val2 = new ZPackage(File.ReadAllBytes(MapFile)); int num2 = val2.ReadInt(); for (int j = 0; j < num2; j++) { long key = val2.ReadLong(); byte[] value = val2.ReadByteArray(); MapBlobs[key] = value; } } HuginnPlugin.Log.LogInfo((object)$"Loaded {Registry.Count} pins, {MapBlobs.Count} map blobs for '{Env.WorldName}'."); } catch (Exception ex) { HuginnPlugin.Log.LogWarning((object)("Failed to load saved data: " + ex.Message)); } } public static void MaybeSave(float now) { if (Env.IsServer && (_dirtyPins || _dirtyMap) && !(now - _lastSave < 5f)) { _lastSave = now; Save(); } } public static void Save() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Expected O, but got Unknown if (!Env.IsServer) { return; } try { if (_dirtyPins) { ZPackage val = new ZPackage(); List<SharedPin> list = new List<SharedPin>(); foreach (SharedPin value in Registry.Values) { if (!value.IsBoat) { list.Add(value); } } val.Write(list.Count); foreach (SharedPin item in list) { item.Write(val); } File.WriteAllBytes(PinsFile, val.GetArray()); _dirtyPins = false; } if (!_dirtyMap) { return; } ZPackage val2 = new ZPackage(); val2.Write(MapBlobs.Count); foreach (KeyValuePair<long, byte[]> mapBlob in MapBlobs) { val2.Write(mapBlob.Key); val2.Write(mapBlob.Value); } File.WriteAllBytes(MapFile, val2.GetArray()); _dirtyMap = false; } catch (Exception ex) { HuginnPlugin.Log.LogWarning((object)("Failed to save data: " + ex.Message)); } } public static void OnWorldUnload() { Save(); Registry.Clear(); MapBlobs.Clear(); _loaded = false; } } internal static class OreStrike { private sealed class Ore { public string IconItem; public string Label; } [HarmonyPatch(typeof(MineRock5), "Damage")] private static class MineRock5_Damage_Patch { private static void Postfix(MineRock5 __instance, HitData hit) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)__instance == (Object)null) && hit != null && !((Object)(object)hit.GetAttacker() != (Object)(object)Player.m_localPlayer)) { OnStruck(Prefabs.Name(__instance.m_nview), ((Component)__instance).transform.position); } } } [HarmonyPatch(typeof(MineRock5), "DamageArea")] private static class MineRock5_DamageArea_Patch { private static void Postfix(MineRock5 __instance) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)__instance == (Object)null) && __instance.m_allDestroyed) { string text = HitPinId(Prefabs.Name(__instance.m_nview), ((Component)__instance).transform.position); if (text != null) { Net.Remove(text); } } } } [HarmonyPatch(typeof(MineRock), "Damage")] private static class MineRock_Damage_Patch { private static void Postfix(MineRock __instance, HitData hit) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)__instance == (Object)null) && hit != null && !((Object)(object)hit.GetAttacker() != (Object)(object)Player.m_localPlayer)) { OnStruck(Prefabs.Name(__instance.m_nview), ((Component)__instance).transform.position); } } } [HarmonyPatch(typeof(MineRock), "RPC_Hit")] private static class MineRock_RPC_Hit_Patch { private static void Prefix(MineRock __instance, out string __state) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) __state = null; ZNetView val = (((Object)(object)__instance != (Object)null) ? __instance.m_nview : null); if ((Object)(object)val != (Object)null && val.IsValid()) { __state = HitPinId(Prefabs.Name(val), ((Component)__instance).transform.position); } } private static void Postfix(MineRock __instance, string __state) { if (__state == null || (Object)(object)__instance == (Object)null) { return; } ZNetView nview = __instance.m_nview; bool flag = (Object)(object)nview == (Object)null || !nview.IsValid(); if (!flag) { try { flag = __instance.AllDestroyed(); } catch { flag = false; } } if (flag) { Net.Remove(__state); } } } private static string _raw; private static readonly Dictionary<string, Ore> Map = new Dictionary<string, Ore>(); private static void Refresh() { if (_raw == Cfg.HitPinPrefabs.Value) { return; } _raw = Cfg.HitPinPrefabs.Value; Map.Clear(); if (string.IsNullOrEmpty(_raw)) { return; } string[] array = _raw.Split(new char[1] { ',' }); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (text.Length != 0) { string[] array2 = text.Split(new char[1] { '=' }); if (array2.Length >= 3) { Map[array2[0].Trim()] = new Ore { IconItem = array2[1].Trim(), Label = array2[2].Trim() }; } } } } private static void OnStruck(string prefab, Vector3 pos) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) if (!Cfg.AutoPinResources.Value || prefab == null) { return; } Refresh(); if (Map.TryGetValue(prefab, out var value)) { string id = HitPinId(value, pos); if (!PinBoard.Has(id)) { Net.Upsert(new SharedPin { Id = id, Category = "ore:" + value.IconItem, Name = string.Empty, Pos = pos }); } } } private static string HitPinId(string prefab, Vector3 pos) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) if (prefab == null) { return null; } Refresh(); if (!Map.TryGetValue(prefab, out var value)) { return null; } return HitPinId(value, pos); } private static string HitPinId(Ore ore, Vector3 pos) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) return "ore:" + ore.Label + "@" + SharedPin.Cell(pos, Cfg.ClusterMerge.Value); } } internal static class PinBoard { private sealed class Live { public PinData Data; public string Category; } private static readonly Dictionary<string, SharedPin> Desired = new Dictionary<string, SharedPin>(); private static readonly Dictionary<string, Live> Applied = new Dictionary<string, Live>(); private static Minimap _lastMinimap; public static int Version { get; private set; } private static void Touch() { Version++; } public static void Reset() { Desired.Clear(); Applied.Clear(); _lastMinimap = null; Touch(); } public static bool Has(string id) { return Desired.ContainsKey(id); } public static bool HasSameCategory(string id, string category) { if (Desired.TryGetValue(id, out var value)) { return value.Category == category; } return false; } public static List<SharedPin> Snapshot() { return new List<SharedPin>(Desired.Values); } public static bool IsManaged(PinData pin) { foreach (Live value in Applied.Values) { if (value.Data == pin) { return true; } } return false; } public static void SetDesired(SharedPin pin) { Desired[pin.Id] = pin; Touch(); } public static void RemoveDesired(string id) { if (Desired.Remove(id)) { Touch(); } } public static void SetChecked(string id, bool isChecked) { if (Desired.TryGetValue(id, out var value)) { value.Checked = isChecked; } Touch(); } public static void ToggleClearedAt(Vector3 world, float radius) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) string text = null; Live live = null; float num = radius; foreach (KeyValuePair<string, Live> item in Applied) { PinData data = item.Value.Data; if (data == null) { continue; } RectTransform uiElement = data.m_uiElement; if (!((Object)(object)uiElement != (Object)null) || ((Component)uiElement).gameObject.activeInHierarchy) { float num2 = Utils.DistanceXZ(world, data.m_pos); if (!(num2 >= num)) { num = num2; text = item.Key; live = item.Value; } } } if (text != null && Desired.TryGetValue(text, out var value)) { bool flag = (value.Checked = !value.Checked); live.Data.m_checked = flag; if ((Object)(object)Minimap.instance != (Object)null) { Minimap.instance.m_pinUpdateRequired = true; } Net.SetChecked(text, flag); } } public static void ReplaceAll(IEnumerable<SharedPin> pins) { Desired.Clear(); foreach (SharedPin pin in pins) { Desired[pin.Id] = pin; } Touch(); } public static void Reconcile() { //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_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) Minimap instance = Minimap.instance; if ((Object)(object)instance == (Object)null) { return; } if ((Object)(object)_lastMinimap != (Object)(object)instance) { Applied.Clear(); _lastMinimap = instance; } foreach (KeyValuePair<string, SharedPin> item in Desired) { SharedPin value = item.Value; Live value3; if (!Visibility.IsVisible(value.Category)) { if (Applied.TryGetValue(item.Key, out var value2)) { if (value2.Data != null) { instance.RemovePin(value2.Data); } Applied.Remove(item.Key); } } else if (Applied.TryGetValue(item.Key, out value3)) { if (value3.Category != value.Category) { instance.RemovePin(value3.Data); value3.Data = Icons.MakePin(value); value3.Data.m_checked = value.Checked; value3.Category = value.Category; instance.m_pinUpdateRequired = true; continue; } PinData data = value3.Data; if (data.m_pos != value.Pos) { data.m_pos = value.Pos; } if (data.m_name != value.Name) { data.m_name = value.Name ?? string.Empty; } if (data.m_checked != value.Checked) { data.m_checked = value.Checked; instance.m_pinUpdateRequired = true; } } else { PinData val = Icons.MakePin(value); val.m_checked = value.Checked; Applied[item.Key] = new Live { Data = val, Category = value.Category }; if (value.Checked) { instance.m_pinUpdateRequired = true; } } } if (Applied.Count <= Desired.Count) { return; } List<string> list = new List<string>(); foreach (KeyValuePair<string, Live> item2 in Applied) { if (!Desired.ContainsKey(item2.Key)) { list.Add(item2.Key); } } foreach (string item3 in list) { if (Applied.TryGetValue(item3, out var value4) && value4.Data != null) { instance.RemovePin(value4.Data); } Applied.Remove(item3); } } } internal static class PinCleanup { private sealed class PurgeCommand : ConsoleCommand { public override string Name => "huginn.purgeforeignpins"; public override string Help => "Remove pins copied onto your map from other players (cartography table). Your own pins and Huginn's pins are kept."; public override void Run(string[] args) { if ((Object)(object)Minimap.instance == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null) { Console instance = Console.instance; if (instance != null) { instance.Print("Huginn: can't purge pins — no map loaded."); } return; } int num = PurgeForeignPins(); Console instance2 = Console.instance; if (instance2 != null) { instance2.Print($"Huginn: removed {num} imported foreign pin(s)."); } HuginnPlugin.Log.LogInfo((object)$"huginn.purgeforeignpins removed {num} pin(s)."); } } private sealed class ClearRadiusCommand : ConsoleCommand { public override string Name => "huginn.clearpins"; public override string Help => "huginn.clearpins <radius> — remove map pins within <radius> meters of you. Affects your own and other mods' pins; Huginn's managed pins are kept."; public override void Run(string[] args) { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) Minimap instance = Minimap.instance; Player localPlayer = Player.m_localPlayer; if ((Object)(object)instance == (Object)null || (Object)(object)localPlayer == (Object)null) { Console instance2 = Console.instance; if (instance2 != null) { instance2.Print("Huginn: no map loaded."); } return; } if (args == null || args.Length < 1 || !float.TryParse(args[0], NumberStyles.Float, CultureInfo.InvariantCulture, out var result) || result <= 0f) { Console instance3 = Console.instance; if (instance3 != null) { instance3.Print("Usage: huginn.clearpins <radius> e.g. huginn.clearpins 50"); } return; } Vector3 position = ((Component)localPlayer).transform.position; float num = result * result; List<PinData> list = null; foreach (PinData pin in instance.m_pins) { if (pin != null && !PinBoard.IsManaged(pin)) { float num2 = pin.m_pos.x - position.x; float num3 = pin.m_pos.z - position.z; if (num2 * num2 + num3 * num3 <= num) { (list ?? (list = new List<PinData>())).Add(pin); } } } if (list == null) { Console instance4 = Console.instance; if (instance4 != null) { instance4.Print($"Huginn: no removable pins within {result:0}m."); } return; } foreach (PinData item in list) { instance.RemovePin(item); } Console instance5 = Console.instance; if (instance5 != null) { instance5.Print($"Huginn: removed {list.Count} pin(s) within {result:0}m."); } HuginnPlugin.Log.LogInfo((object)$"huginn.clearpins {result:0} removed {list.Count} pin(s)."); } } private sealed class LocationsCommand : ConsoleCommand { public override string Name => "huginn.locations"; public override string Help => "Log all world Location names grouped by biome (optionally filtered): huginn.locations [filter]"; public override void Run(string[] args) { ZoneSystem instance = ZoneSystem.instance; if ((Object)(object)instance == (Object)null) { Console instance2 = Console.instance; if (instance2 != null) { instance2.Print("Huginn: ZoneSystem not ready."); } return; } string text = ((args != null && args.Length != 0) ? args[0] : null); List<string> list = new List<string>(); foreach (ZoneLocation location in instance.m_locations) { if (location != null && !string.IsNullOrEmpty(location.m_prefabName) && location.m_quantity > 0) { string text2 = ((object)Unsafe.As<Biome, Biome>(ref location.m_biome)/*cast due to .constrained prefix*/).ToString(); if (text == null || text2.IndexOf(text, StringComparison.OrdinalIgnoreCase) >= 0 || location.m_prefabName.IndexOf(text, StringComparison.OrdinalIgnoreCase) >= 0) { list.Add($"{text2,-26} {location.m_prefabName} (q{location.m_quantity})"); } } } list.Sort(); HuginnPlugin.Log.LogInfo((object)($"=== huginn.locations: {list.Count} placed locations" + ((text != null) ? (" matching '" + text + "'") : "") + " ===")); foreach (string item in list) { HuginnPlugin.Log.LogInfo((object)(" " + item)); } Console instance3 = Console.instance; if (instance3 != null) { instance3.Print($"Huginn: logged {list.Count} locations to LogOutput.log."); } } } private sealed class LookingAtCommand : ConsoleCommand { public override string Name => "huginn.lookingat"; public override string Help => "Print the prefab name of the object you're looking at."; public override void Run(string[] args) { Player localPlayer = Player.m_localPlayer; GameObject val = (((Object)(object)localPlayer != (Object)null) ? localPlayer.m_hovering : null); if ((Object)(object)val == (Object)null) { Console instance = Console.instance; if (instance != null) { instance.Print("Huginn: not looking at anything (aim at it and try again)."); } return; } ZNetView componentInParent = val.GetComponentInParent<ZNetView>(); string text = (((Object)(object)componentInParent != (Object)null) ? Prefabs.Name(componentInParent) : Prefabs.Strip(((Object)val).name)); Console instance2 = Console.instance; if (instance2 != null) { instance2.Print("Huginn: looking at '" + text + "'"); } HuginnPlugin.Log.LogInfo((object)("[LookingAt] " + text)); } } private sealed class DumpCommand : ConsoleCommand { public override string Name => "huginn.dumppins"; public override string Help => "Log a summary of all map pins (type, owner, names) for diagnostics."; public override void Run(string[] args) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected I4, but got Unknown Minimap instance = Minimap.instance; Player localPlayer = Player.m_localPlayer; if ((Object)(object)instance == (Object)null || (Object)(object)localPlayer == (Object)null) { Console instance2 = Console.instance; if (instance2 != null) { instance2.Print("Huginn: no map loaded."); } return; } long playerID = localPlayer.GetPlayerID(); Dictionary<int, (int, int, int, HashSet<string>)> dictionary = new Dictionary<int, (int, int, int, HashSet<string>)>(); foreach (PinData pin in instance.m_pins) { if (pin != null) { int key = (int)pin.m_type; if (!dictionary.TryGetValue(key, out var value)) { value = (0, 0, 0, new HashSet<string>()); } value.Item1++; if (pin.m_ownerID != 0L && pin.m_ownerID != playerID) { value.Item2++; } if (pin.m_save) { value.Item3++; } if (value.Item4.Count < 6 && !string.IsNullOrEmpty(pin.m_name)) { value.Item4.Add(pin.m_name); } dictionary[key] = value; } } Console instance3 = Console.instance; if (instance3 != null) { instance3.Print($"Huginn: {instance.m_pins.Count} pins across {dictionary.Count} type(s):"); } HuginnPlugin.Log.LogInfo((object)$"=== huginn.dumppins: {instance.m_pins.Count} pins ==="); foreach (KeyValuePair<int, (int, int, int, HashSet<string>)> item in dictionary) { (int, int, int, HashSet<string>) value2 = item.Value; string text = ((value2.Item4.Count > 0) ? string.Join(", ", value2.Item4) : "(unnamed)"); string text2 = $" PinType {item.Key}: {value2.Item1} pins (foreign={value2.Item2}, saved={value2.Item3}) e.g. [{text}]"; Console instance4 = Console.instance; if (instance4 != null) { instance4.Print(text2); } HuginnPlugin.Log.LogInfo((object)text2); } } } private static bool _purgedThisWorld; public static void Init() { CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new PurgeCommand()); CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new DumpCommand()); CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new ClearRadiusCommand()); CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new LookingAtCommand()); CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new LocationsCommand()); } public static void Reset() { _purgedThisWorld = false; } public static void MaybePurgeOnLoad() { if (!_purgedThisWorld && Cfg.RemoveImportedPinsOnLoad.Value && !((Object)(object)Minimap.instance == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null)) { _purgedThisWorld = true; int num = PurgeForeignPins(); if (num > 0) { HuginnPlugin.Log.LogInfo((object)$"RemoveImportedPinsOnLoad: cleared {num} imported foreign pin(s)."); } } } public static int PurgeForeignPins() { Minimap instance = Minimap.instance; Player localPlayer = Player.m_localPlayer; if ((Object)(object)instance == (Object)null || (Object)(object)localPlayer == (Object)null) { return 0; } long playerID = localPlayer.GetPlayerID(); List<PinData> list = null; foreach (PinData pin in instance.m_pins) { if (pin != null && pin.m_ownerID != 0L && pin.m_ownerID != playerID) { (list ?? (list = new List<PinData>())).Add(pin); } } if (list == null) { return 0; } foreach (PinData item in list) { instance.RemovePin(item); } return list.Count; } } internal static class PinFilterUI { private sealed class LeafRef { public string Cat; public Image Plate; public Image Icon; public Sprite Colour; public Sprite Grey; } private sealed class GroupRef { public List<string> Cats; public Image Plate; } private struct Plate { public GameObject go; public Image plate; public Button btn; } [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static UnityAction <>9__26_0; public static UnityAction <>9__26_1; public static Comparison<string> <>9__27_0; internal void <BuildSkeleton>b__26_0() { Visibility.SetMany(AllCats, visible: true); AfterToggle(); } internal void <BuildSkeleton>b__26_1() { Visibility.SetMany(AllCats, visible: false); AfterToggle(); } internal int <Populate>b__27_0(string a, string b) { return string.Compare(Names.Leaf(a), Names.Leaf(b), StringComparison.OrdinalIgnoreCase); } } private const float PanelWidth = 248f; private const float LeafSize = 42f; private const float ButtonSize = 26f; private const int Columns = 4; private const float InsetX = 38f; private const float InsetY = 38f; private static readonly Color PlateOn = new Color(0.24f, 0.24f, 0.24f, 0.55f); private static readonly Color PlateOff = new Color(0.04f, 0.04f, 0.04f, 0.55f); private static readonly Color PlateMixed = new Color(0.13f, 0.13f, 0.13f, 0.55f); private static readonly Color PanelBg = new Color(0.05f, 0.05f, 0.05f, 0.92f); private static readonly Color TextCol = new Color(0.92f, 0.9f, 0.85f, 1f); private static readonly Color IconOff = new Color(0.55f, 0.55f, 0.55f, 0.45f); private static readonly string[] GroupOrder = new string[11] { "meadows", "blackforest", "swamp", "mountain", "plains", "mistlands", "ashlands", "deepnorth", "ocean", "anywhere", "other" }; private static GameObject _root; private static GameObject _content; private static bool _wasOpen; private static int _uiVersion = -1; private static Font _font; private static readonly List<LeafRef> Leaves = new List<LeafRef>(); private static readonly List<GroupRef> Groups = new List<GroupRef>(); private static readonly HashSet<string> Expanded = new HashSet<string>(); private static readonly List<string> AllCats = new List<string>(); public static void Reset() { if ((Object)(object)_root != (Object)null) { Object.Destroy((Object)(object)_root); } _root = null; _content = null; _wasOpen = false; _uiVersion = -1; Leaves.Clear(); Groups.Clear(); AllCats.Clear(); } public static void Tick() { //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Invalid comparison between Unknown and I4 Minimap instance = Minimap.instance; if ((Object)(object)instance == (Object)null) { return; } Transform val = (((Object)(object)instance.m_mapImageLarge != (Object)null) ? ((Component)instance.m_mapImageLarge).transform : (((Object)(object)GUIManager.CustomGUIFront != (Object)null) ? GUIManager.CustomGUIFront.transform : null)); if ((Object)(object)val == (Object)null) { return; } if ((Object)(object)_root == (Object)null || (Object)(object)_root.transform.parent != (Object)(object)val) { if ((Object)(object)_root != (Object)null) { Object.Destroy((Object)(object)_root); } BuildSkeleton(val); _uiVersion = -1; _wasOpen = false; if ((Object)(object)_root == (Object)null) { return; } } bool flag = (int)instance.m_mode == 2; if (_root.activeSelf != flag) { _root.SetActive(flag); } if (!flag) { _wasOpen = false; return; } _root.transform.SetAsLastSibling(); if (!_wasOpen || PinBoard.Version != _uiVersion) { Populate(); _uiVersion = PinBoard.Version; } _wasOpen = true; } private static void BuildSkeleton(Transform parent) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: 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) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Expected O, but got Unknown //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Expected O, but got Unknown //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Expected O, but got Unknown _root = NewUI("Huginn_Filter", parent); RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null); ManualLogSource log = HuginnPlugin.Log; string name = ((Object)parent).name; object obj; if (!((Object)(object)val != (Object)null)) { obj = "."; } else { Rect rect = val.rect; obj = $" (rect {((Rect)(ref rect)).size})."; } log.LogInfo((object)("Map filter panel built under '" + name + "'" + (string?)obj)); RectTransform component = _root.GetComponent<RectTransform>(); component.anchorMin = new Vector2(0f, 1f); component.anchorMax = new Vector2(0f, 1f); component.pivot = new Vector2(0f, 1f); component.anchoredPosition = new Vector2(38f, -38f); component.sizeDelta = new Vector2(248f, 100f); _root.transform.SetAsLastSibling(); Bg(_root, PanelBg); VerticalLayoutGroup obj2 = _root.AddComponent<VerticalLayoutGroup>(); ((LayoutGroup)obj2).padding = new RectOffset(8, 8, 8, 8); ((HorizontalOrVerticalLayoutGroup)obj2).spacing = 6f; ((LayoutGroup)obj2).childAlignment = (TextAnchor)0; ((HorizontalOrVerticalLayoutGroup)obj2).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)obj2).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandHeight = false; ContentSizeFitter obj3 = _root.AddComponent<ContentSizeFitter>(); obj3.horizontalFit = (FitMode)0; obj3.verticalFit = (FitMode)2; GameObject obj4 = Row(_root.transform, "Master"); Plate plate = MakePlate(obj4.transform, 26f, "Show all"); ((Graphic)plate.plate).color = PlateOn; ButtonClickedEvent onClick = plate.btn.onClick; object obj5 = <>c.<>9__26_0; if (obj5 == null) { UnityAction val2 = delegate { Visibility.SetMany(AllCats, visible: true); AfterToggle(); }; <>c.<>9__26_0 = val2; obj5 = (object)val2; } ((UnityEvent)onClick).AddListener((UnityAction)obj5); Plate plate2 = MakePlate(obj4.transform, 26f, "Hide all"); ((Graphic)plate2.plate).color = PlateOff; ButtonClickedEvent onClick2 = plate2.btn.onClick; object obj6 = <>c.<>9__26_1; if (obj6 == null) { UnityAction val3 = delegate { Visibility.SetMany(AllCats, visible: false); AfterToggle(); }; <>c.<>9__26_1 = val3; obj6 = (object)val3; } ((UnityEvent)onClick2).AddListener((UnityAction)obj6); _content = NewUI("Content", _root.transform); VerticalLayoutGroup obj7 = _content.AddComponent<VerticalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)obj7).spacing = 5f; ((HorizontalOrVerticalLayoutGroup)obj7).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)obj7).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)obj7).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)obj7).childForceExpandHeight = false; } private static void Populate() { //IL_00b6: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_content == (Object)null) { return; } for (int num = _content.transform.childCount - 1; num >= 0; num--) { Object.Destroy((Object)(object)((Component)_content.transform.GetChild(num)).gameObject); } Leaves.Clear(); Groups.Clear(); AllCats.Clear(); Dictionary<string, List<string>> dictionary = new Dictionary<string, List<string>>(); foreach (SharedPin item in PinBoard.Snapshot()) { if (!string.IsNullOrEmpty(item.Category)) { if (!AllCats.Contains(item.Category)) { AllCats.Add(item.Category); } string key = Names.GroupKeyForPin(item.Category, item.Pos); if (!dictionary.TryGetValue(key, out var value)) { value = (dictionary[key] = new List<string>()); } if (!value.Contains(item.Category)) { value.Add(item.Category); } } } string[] groupOrder = GroupOrder; foreach (string text in groupOrder) { if (dictionary.TryGetValue(text, out var value2) && value2.Count != 0) { value2.Sort((string a, string b) => string.Compare(Names.Leaf(a), Names.Leaf(b), StringComparison.OrdinalIgnoreCase)); BuildGroup(text, value2); } } if (Cfg.VerboseLogging != null && Cfg.VerboseLogging.Value) { HuginnPlugin.Log.LogInfo((object)$"Map filter: {AllCats.Count} discovered type(s), {dictionary.Count} group(s)."); } Restyle(); } private static void BuildGroup(string gkey, List<string> cats) { //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Expected O, but got Unknown //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Expected O, but got Unknown //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Expected O, but got Unknown GameObject val = NewUI("Group_" + gkey, _content.transform); VerticalLayoutGroup obj = val.AddComponent<VerticalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)obj).spacing = 3f; ((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false; bool flag = Expanded.Contains(gkey); GameObject obj2 = Row(val.transform, "Header"); Plate plate = MakePlate(obj2.transform, 26f, "Toggle all " + Names.GroupLabel(gkey)); Groups.Add(new GroupRef { Cats = new List<string>(cats), Plate = plate.plate }); List<string> catsCopy = new List<string>(cats); ((UnityEvent)plate.btn.onClick).AddListener((UnityAction)delegate { Visibility.SetMany(catsCopy, !AllOn(catsCopy)); AfterToggle(); }); GameObject obj3 = Label(obj2.transform, (flag ? "▼ " : "▶ ") + Names.GroupLabel(gkey)); obj3.GetComponent<LayoutElement>().flexibleWidth = 1f; Button obj4 = obj3.gameObject.AddComponent<Button>(); ((Selectable)obj4).transition = (Transition)0; string keyCopy = gkey; ((UnityEvent)obj4.onClick).AddListener((UnityAction)delegate { if (!Expanded.Remove(keyCopy)) { Expanded.Add(keyCopy); } Populate(); }); if (!flag) { return; } GameObject val2 = NewUI("Leaves", val.transform); GridLayoutGroup obj5 = val2.AddComponent<GridLayoutGroup>(); obj5.cellSize = new Vector2(42f, 42f); obj5.spacing = new Vector2(6f, 6f); ((LayoutGroup)obj5).padding = new RectOffset(24, 0, 2, 4); obj5.constraint = (Constraint)1; obj5.constraintCount = 4; ((LayoutGroup)obj5).childAlignment = (TextAnchor)0; foreach (string cat in cats) { BuildLeaf(val2.transform, cat); } } private static void BuildLeaf(Transform parent, string cat) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Expected O, but got Unknown Plate plate = MakePlate(parent, 42f, Names.Leaf(cat)); GameObject obj = NewUI("Icon", plate.go.transform); RectTransform component = obj.GetComponent<RectTransform>(); component.anchorMin = Vector2.zero; component.anchorMax = Vector2.one; component.offsetMin = new Vector2(4f, 4f); component.offsetMax = new Vector2(-4f, -4f); Image val = obj.AddComponent<Image>(); ((Graphic)val).raycastTarget = false; val.preserveAspect = true; LeafRef item = new LeafRef { Cat = cat, Plate = plate.plate, Icon = val, Colour = Icons.SpriteFor(cat), Grey = Icons.GraySpriteFor(cat) }; Leaves.Add(item); ((UnityEvent)plate.btn.onClick).AddListener((UnityAction)delegate { Visibility.Set(cat, !Visibility.IsVisible(cat)); AfterToggle(); }); } private static void Restyle() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) foreach (LeafRef leaf in Leaves) { bool flag = Visibility.IsVisible(leaf.Cat); ((Graphic)leaf.Plate).color = (flag ? PlateOn : PlateOff); if (flag) { leaf.Icon.sprite = leaf.Colour; ((Graphic)leaf.Icon).color = Color.white; } else if ((Object)(object)leaf.Grey != (Object)null) { leaf.Icon.sprite = leaf.Grey; ((Graphic)leaf.Icon).color = new Color(1f, 1f, 1f, 0.6f); } else { leaf.Icon.sprite = leaf.Colour; ((Graphic)leaf.Icon).color = IconOff; } ((Behaviour)leaf.Icon).enabled = (Object)(object)leaf.Icon.sprite != (Object)null; } foreach (GroupRef group in Groups) { bool flag2 = AllOn(group.Cats); bool flag3 = AnyOn(group.Cats); ((Graphic)group.Plate).color = (flag2 ? PlateOn : (flag3 ? PlateMixed : PlateOff)); } } private static void AfterToggle() { try { PinBoard.Reconcile(); } catch (Exception ex) { HuginnPlugin.Log.LogWarning((object)("Filter reconcile: " + ex.Message)); } Restyle(); } private static bool AllOn(List<string> cats) { foreach (string cat in cats) { if (!Visibility.IsVisible(cat)) { return false; } } return cats.Count > 0; } private static bool AnyOn(List<string> cats) { foreach (string cat in cats) { if (Visibility.IsVisible(cat)) { return true; } } return false; } private static GameObject NewUI(string name, Transform parent) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) }); val.transform.SetParent(parent, false); return val; } private static Image Bg(GameObject go, Color c) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) Image val = go.GetComponent<Image>(); if ((Object)(object)val == (Object)null) { val = go.AddComponent<Image>(); } ((Graphic)val).color = c; return val; } private static GameObject Row(Transform parent, string name) { GameObject obj = NewUI(name, parent); HorizontalLayoutGroup obj2 = obj.AddComponent<HorizontalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)obj2).spacing = 6f; ((LayoutGroup)obj2).childAlignment = (TextAnchor)3; ((HorizontalOrVerticalLayoutGroup)obj2).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)obj2).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandWidth = false; ((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandHeight = false; return obj; } private static Plate MakePlate(Transform parent, float size, string tooltip) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) GameObject val = NewUI("Plate", parent); LayoutElement obj = val.AddComponent<LayoutElement>(); obj.preferredWidth = size; obj.preferredHeight = size; obj.minWidth = size; obj.minHeight = size; Image val2 = val.AddComponent<Image>(); ((Graphic)val2).color = PlateOff; Button val3 = val.AddComponent<Button>(); ((Selectable)val3).targetGraphic = (Graphic)(object)val2; ((Selectable)val3).transition = (Transition)1; ColorBlock colors = ((Selectable)val3).colors; ((ColorBlock)(ref colors)).highlightedColor = new Color(1f, 1f, 1f, 1.2f); ((ColorBlock)(ref colors)).fadeDuration = 0.05f; ((Selectable)val3).colors = colors; if (!string.IsNullOrEmpty(tooltip)) { AddTooltip(val, tooltip); } return new Plate { go = val, plate = val2, btn = val3 }; } private static GameObject Label(Transform parent, string text) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) GameObject obj = NewUI("Label", parent); obj.AddComponent<LayoutElement>().minHeight = 28f; Text obj2 = obj.AddComponent<Text>(); obj2.font = UiFont(); obj2.fontSize = 18; ((Graphic)obj2).color = TextCol; obj2.alignment = (TextAnchor)3; obj2.horizontalOverflow = (HorizontalWrapMode)1; obj2.verticalOverflow = (VerticalWrapMode)1; obj2.text = text; return obj; } private static void AddTooltip(GameObject go, string text) { try { go.AddComponent<UITooltip>().m_text = text; } catch { } } private static Font UiFont() { if ((Object)(object)_font == (Object)null) { _font = Font.CreateDynamicFontFromOSFont("Arial", 16); } return _font; } } [HarmonyPatch(typeof(Minimap), "AddSharedMapData")] internal static class PinShareGuard { private static bool Prefix(Minimap __instance, byte[] dataArray, ref bool __result) { if (Cfg.ShareVanillaPins.Value) { return true; } __result = MergeExplorationOnly(__instance, dataArray); return false; } private static bool MergeExplorationOnly(Minimap m, byte[] dataArray) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown ZPackage val = new ZPackage(dataArray); int num = val.ReadInt(); List<bool> list = m.ReadExploredArray(val, num); if (list == null) { return false; } bool flag = false; int textureSize = m.m_textureSize; for (int i = 0; i < textureSize; i++) { for (int j = 0; j < textureSize; j++) { int num2 = i * textureSize + j; bool num3 = list[num2]; bool flag2 = m.m_exploredOthers[num2] || m.m_explored[num2]; if (num3 && !flag2 && m.ExploreOthers(j, i)) { flag = true; } } } if (flag) { m.m_fogTexture.Apply(); } return flag; } } internal static class Portals { [HarmonyPatch(typeof(Player), "PlacePiece")] private static class PlacePiece_Patch { private static void Postfix(Piece piece, Vector3 pos) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)piece != (Object)null && (Object)(object)((Component)piece).GetComponent<TeleportWorld>() != (Object)null) { Upsert(pos, "Portal", PrefabName(((Component)piece).gameObject)); } } } [HarmonyPatch(typeof(TeleportWorld), "SetText")] private static class SetText_Patch { private static void Postfix(TeleportWorld __instance, string text) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance != (Object)null) { Upsert(((Component)__instance).transform.position, text, PrefabName(((Component)__instance).gameObject)); } } } [HarmonyPatch(typeof(Piece), "DropResources")] private static class DropResources_Patch { private static void Postfix(Piece __instance) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) if (Cfg.AutoPinPortals.Value && (Object)(object)__instance != (Object)null && (Object)(object)((Component)__instance).GetComponent<TeleportWorld>() != (Object)null) { Net.Remove(PortalId(((Component)__instance).transform.position)); } } } private static Dictionary<int, string> _portalPrefabs; private static readonly Dictionary<string, string> _swept = new Dictionary<string, string>(); private static float _lastSweep; private static string PortalId(Vector3 pos) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) return "portal@" + SharedPin.Cell(pos, 1f); } private static string ResolveName(string tag) { if (!string.IsNullOrEmpty(tag)) { return tag; } return "Portal"; } private static string PrefabName(GameObject go) { string name = ((Object)go).name; int num = name.IndexOf("(Clone)", StringComparison.Ordinal); if (num < 0) { return name; } return name.Substring(0, num); } private static string PortalCategory(string prefab) { if (!string.IsNullOrEmpty(prefab) && !(prefab == "portal_wood")) { return "portal:" + prefab; } return "portal"; } private static void Upsert(Vector3 pos, string name, string prefab) { //IL_0013: 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) if (Cfg.AutoPinPortals.Value) { Net.Upsert(new SharedPin { Id = PortalId(pos), Category = PortalCategory(prefab), Name = ResolveName(name), Pos = pos }); } } public static void Tick(float now) { //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) if (!Cfg.AutoPinPortals.Value || now - _lastSweep < Cfg.PortalSweepSec.Value) { return; } _lastSweep = now; ZDOMan instance = ZDOMan.instance; ZNetScene instance2 = ZNetScene.instance; if (instance == null || (Object)(object)instance2 == (Object)null) { return; } Dictionary<int, string> dictionary = PortalPrefabs(instance2); if (dictionary.Count == 0) { return; } Dictionary<string, string> dictionary2 = new Dictionary<string, string>(); foreach (ZDO value3 in instance.m_objectsByID.Values) { if (value3 != null && dictionary.TryGetValue(value3.GetPrefab(), out var value)) { Vector3 position = value3.GetPosition(); string text = PortalId(position); string text2 = (dictionary2[text] = ResolveName(value3.GetString(ZDOVars.s_tag, ""))); if (!_swept.TryGetValue(text, out var value2) || value2 != text2) { Net.Upsert(new SharedPin { Id = text, Category = PortalCategory(value), Name = text2, Pos = position }); } } } List<string> list = null; foreach (string key in _swept.Keys) { if (!dictionary2.ContainsKey(key)) { (list ?? (list = new List<string>())).Add(key); } } if (list != null) { foreach (string item in list) { Net.Remove(item); } } _swept.Clear(); foreach (KeyValuePair<string, string> item2 in dictionary2) { _swept[item2.Key] = item2.Value; } } private static Dictionary<int, string> PortalPrefabs(ZNetScene scene) { if (_portalPrefabs != null && _portalPrefabs.Count > 0) { return _portalPrefabs; } _portalPrefabs = new Dictionary<int, string>(); foreach (GameObject prefab in scene.m_prefabs) { if ((Object)(object)prefab != (Object)null && (Object)(object)prefab.GetComponent<TeleportWorld>() != (Object)null) { _portalPrefabs[StringExtensionMethods.GetStableHashCode(((Object)prefab).name)] = ((Object)prefab).name; } } if (_portalPrefabs.Count > 0) { HuginnPlugin.Log.LogInfo((object)($"Portal sweep tracking {_portalPrefabs.Count} portal prefab(s): " + string.Join(", ", _portalPrefabs.Values))); } return _portalPrefabs; } public static void Reset() { _swept.Clear(); _portalPrefabs = null; _lastSweep = 0f; } } internal static class Prefabs { public static string Name(ZNetView nview) { if ((Object)(object)nview == (Object)null) { return null; } ZNetScene instance = ZNetScene.instance; ZDO val = (nview.IsValid() ? nview.GetZDO() : null); if ((Object)(object)instance != (Object)null && val != null) { GameObject prefab = instance.GetPrefab(val.GetPrefab()); if ((Object)(object)prefab != (Object)null) { return ((Object)prefab).name; } } return Strip(((Object)((Component)nview).gameObject).name); } public static string Strip(string name) { if (name == null) { return null; } int num = name.IndexOf("(Clone)", StringComparison.Ordinal); if (num < 0) { return name; } return name.Substring(0, num); } } internal static class Scanner { private sealed class Ore { public string IconItem; public string Label; } private sealed class Poi { public string Prefix; public string Cat; } private sealed class Pick { public string IconItem; public string Label; } private static string _oreRaw; private static string _poiRaw; private static string _pickRaw; private static readonly Dictionary<string, Ore> OreMap = new Dictionary<string, Ore>(); private static readonly List<Poi> PoiPrefixes = new List<Poi>(); private static readonly Dictionary<string, Pick> PickMap = new Dictionary<string, Pick>(); private static readonly HashSet<string> ManagedOreCats = new HashSet<string>(); private static readonly HashSet<string> ManagedPickCats = new HashSet<string>(); private static float _lastScan; private static float _lastDebugLog; public static void Tick(float now) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_04ba: Unknown result type (might be due to invalid IL or missing references) //IL_04bf: Unknown result type (might be due to invalid IL or missing references) //IL_04c0: Unknown result type (might be due to invalid IL or missing references) //IL_04c5: Unknown result type (might be due to invalid IL or missing references) //IL_055a: Unknown result type (might be due to invalid IL or missing references) //IL_055f: Unknown result type (might be due to invalid IL or missing references) //IL_0560: Unknown result type (might be due to invalid IL or missing references) //IL_0565: Unknown result type (might be due to invalid IL or missing references) //IL_02cf: Unknown result type (might be due to invalid IL or missing references) //IL_0328: Unknown result type (might be due to invalid IL or missing references) //IL_032a: Unknown result type (might be due to invalid IL or missing references) //IL_03f8: Unknown result type (might be due to invalid IL or missing references) //IL_043e: Unknown result type (might be due to invalid IL or missing references) //IL_0440: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Unknown result type (might be due to invalid IL or missing references) if (now - _lastScan < Cfg.ScanIntervalSec.Value) { return; } _lastScan = now; Player localPlayer = Player.m_localPlayer; ZNetScene instance = ZNetScene.instance; if ((Object)(object)localPlayer == (Object)null || (Object)(object)instance == (Object)null) { return; } RefreshMaps(); Vector3 position = ((Component)localPlayer).transform.position; float num = Cfg.ScanRadius.Value * Cfg.ScanRadius.Value; float num2 = Cfg.PoiScanRadius.Value * Cfg.PoiScanRadius.Value; float num3 = Mathf.Max(num, num2); float value = Cfg.ClusterMerge.Value; HashSet<string> hashSet = null; HashSet<string> hashSet2 = null; bool flag = Cfg.LogNearbyPrefabs.Value && now - _lastDebugLog > 5f; if (flag) { hashSet = new HashSet<string>(); hashSet2 = new HashSet<string>(); _lastDebugLog = now; } HashSet<string> hashSet3 = new HashSet<string>(); HashSet<string> hashSet4 = new HashSet<string>(); Vector3 val; foreach (KeyValuePair<ZDO, ZNetView> instance2 in instance.m_instances) { ZNetView value2 = instance2.Value; if ((Object)(object)value2 == (Object)null || !value2.IsValid()) { continue; } GameObject gameObject = ((Component)value2).gameObject; Vector3 position2 = gameObject.transform.position; val = position2