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 ValheimCartographer v1.0.1
plugins\ValheimCartographer\ValheimCartographer.dll
Decompiled 3 months agousing System; 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.Configs; using Jotunn.Entities; using Jotunn.Managers; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.Rendering; using UnityEngine.UI; using ValheimCartographer.Compass; using ValheimCartographer.State; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("ValheimCartographer")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Restrict map access to cartography table interactions")] [assembly: AssemblyFileVersion("1.0.1.0")] [assembly: AssemblyInformationalVersion("1.0.1")] [assembly: AssemblyProduct("ValheimCartographer")] [assembly: AssemblyTitle("ValheimCartographer")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.1.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace ValheimCartographer { [BepInPlugin("valheimcartographer.mapgate", "ValheimCartographer", "1.0.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class ValheimCartographerPlugin : BaseUnityPlugin { public const string ModGuid = "valheimcartographer.mapgate"; public const string ModName = "ValheimCartographer"; public const string ModVersion = "1.0.1"; internal static ManualLogSource Log; internal static ConfigEntry<bool> ModEnabled; internal static ConfigEntry<bool> HideMinimapWhenLocked; internal static ConfigEntry<bool> BlockBossStoneMapPing; internal static ConfigEntry<bool> DebugLogging; internal static ConfigEntry<bool> CompassEnabled; internal static ConfigEntry<int> CompassIronCost; internal static ConfigEntry<int> CompassWoodCost; internal static ConfigEntry<float> CompassHudOffsetY; internal static ConfigEntry<float> CompassRibbonUsableWidth; internal static ConfigEntry<float> CompassHudTrackOffsetY; internal static ConfigEntry<float> CompassHudScale; internal static ConfigEntry<float> CompassHudSlidePixels; internal static ConfigEntry<float> CompassHudSlideSmoothTime; internal static ConfigEntry<int> CompassHudSortOffsetFromHud; private Harmony _harmony; internal static ValheimCartographerPlugin Instance { get; private set; } private void Awake() { //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; ModEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable map gating."); HideMinimapWhenLocked = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "HideMinimapWhenLocked", true, "Hide the small minimap when map access is not granted via a cartography table."); BlockBossStoneMapPing = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "BlockBossStoneMapPing", true, "Prevent boss stones and similar from opening or pinging the map."); DebugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DebugLogging", false, "Verbose Harmony / state logging."); CompassEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Compass", "Enabled", true, "Enable the craftable compass item and HUD."); CompassIronCost = ((BaseUnityPlugin)this).Config.Bind<int>("Compass", "IronCost", 1, "Iron ingots required to craft the compass at a forge."); CompassWoodCost = ((BaseUnityPlugin)this).Config.Bind<int>("Compass", "WoodCost", 5, "Fine wood (Finewood) required to craft the compass at a forge."); CompassHudOffsetY = ((BaseUnityPlugin)this).Config.Bind<float>("Compass", "HudTopInsetY", 10f, "Distance from the top of the screen to the compass (pixels at 1080p reference). Lower = closer to the top edge."); CompassRibbonUsableWidth = ((BaseUnityPlugin)this).Config.Bind<float>("Compass", "RibbonUsableWidth", 873f, "Width of the clipped ribbon viewport over Ribbon_backing (pixels at 1080p reference)."); CompassHudTrackOffsetY = ((BaseUnityPlugin)this).Config.Bind<float>("Compass", "HudTrackOffsetY", 0f, "Additional vertical offset of the ribbon mask within the backing; positive moves the mask down (pixels at 1080p reference)."); CompassHudScale = ((BaseUnityPlugin)this).Config.Bind<float>("Compass", "HudStripScale", 0.28f, "Uniform scale for the whole compass HUD (backing + ribbon). 1 = native pixel size at 1080p reference; lower = smaller on screen."); CompassHudSlidePixels = ((BaseUnityPlugin)this).Config.Bind<float>("Compass", "HudSlidePixels", 220f, "When hiding for UI (inventory, map, etc.), how far to slide the compass on the Y axis (reference pixels). Positive = off toward the top of the screen; flip sign if it moves the wrong way."); CompassHudSlideSmoothTime = ((BaseUnityPlugin)this).Config.Bind<float>("Compass", "HudSlideSmoothTime", 0.12f, "Seconds for the compass slide when opening/closing other UI."); CompassHudSortOffsetFromHud = ((BaseUnityPlugin)this).Config.Bind<int>("Compass", "HudCanvasSortOffset", -1, "Added to vanilla Hud canvas sortingOrder (read at runtime from the same canvas as the teleport/sleep black screen). Negative draws the compass under that overlay so portal fades cover it; adjust if layering looks wrong."); CompassItemSetup.Register(); new GameObject("ValheimCartographer_CompassHud").AddComponent<CompassHud>(); _harmony = new Harmony("valheimcartographer.mapgate"); _harmony.PatchAll(Assembly.GetExecutingAssembly()); Log.LogInfo((object)"ValheimCartographer 1.0.1 loaded."); } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchAll("valheimcartographer.mapgate"); } ((BaseUnityPlugin)this).Config.Save(); } internal static void LogDebug(string message) { if (DebugLogging.Value) { Log.LogDebug((object)message); } } } } namespace ValheimCartographer.State { public static class MapAccessState { public static bool IsCartographyAccessActive { get; private set; } public static MapTable? ActiveTable { get; private set; } public static void BeginCartographyAccess(MapTable table) { IsCartographyAccessActive = true; ActiveTable = table; } public static void EndCartographyAccess() { IsCartographyAccessActive = false; ActiveTable = null; } } } namespace ValheimCartographer.Patches { [HarmonyPatch] public static class CartographyTablePatches { [HarmonyPrefix] [HarmonyPatch(typeof(MapTable), "OnRead", new Type[] { typeof(Switch), typeof(Humanoid), typeof(ItemData) })] [HarmonyPatch(typeof(MapTable), "OnRead", new Type[] { typeof(Switch), typeof(Humanoid), typeof(ItemData), typeof(bool) })] private static void OnReadPrefix(MapTable __instance, ItemData? item) { if (ValheimCartographerPlugin.ModEnabled.Value && !((Object)(object)Player.m_localPlayer == (Object)null) && item == null) { MapAccessState.BeginCartographyAccess(__instance); ValheimCartographerPlugin.LogDebug("Cartography access begin (MapTable.OnRead prefix)"); } } [HarmonyPostfix] [HarmonyPatch(typeof(MapTable), "OnRead", new Type[] { typeof(Switch), typeof(Humanoid), typeof(ItemData) })] [HarmonyPatch(typeof(MapTable), "OnRead", new Type[] { typeof(Switch), typeof(Humanoid), typeof(ItemData), typeof(bool) })] private static void OnReadPostfix(ItemData? item) { if (ValheimCartographerPlugin.ModEnabled.Value && !((Object)(object)Player.m_localPlayer == (Object)null) && item == null) { Minimap.instance.SetMapMode((MapMode)2); ValheimCartographerPlugin.LogDebug("Map opened from MapTable.OnRead postfix"); } } } [HarmonyPatch(typeof(Minimap))] public static class MinimapPatches { [HarmonyPrefix] [HarmonyPatch("SetMapMode")] private static bool SetMapMode_Prefix(MapMode mode) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Invalid comparison between Unknown and I4 if (!ValheimCartographerPlugin.ModEnabled.Value) { return true; } if ((int)mode == 2 && !MapAccessState.IsCartographyAccessActive) { ValheimCartographerPlugin.LogDebug("Blocked SetMapMode(Large) — not at cartography table"); return false; } return true; } [HarmonyPostfix] [HarmonyPatch("SetMapMode")] private static void SetMapMode_Postfix(MapMode mode) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Invalid comparison between Unknown and I4 //IL_0024: Unknown result type (might be due to invalid IL or missing references) if (ValheimCartographerPlugin.ModEnabled.Value && (int)mode <= 1) { MapAccessState.EndCartographyAccess(); ValheimCartographerPlugin.LogDebug($"Map closed or minimized ({mode}); cartography access cleared"); } } [HarmonyPostfix] [HarmonyPatch("Update")] private static void Update_Postfix(Minimap __instance) { if (ValheimCartographerPlugin.ModEnabled.Value && ValheimCartographerPlugin.HideMinimapWhenLocked.Value && (Object)(object)__instance.m_smallRoot != (Object)null && !MapAccessState.IsCartographyAccessActive) { __instance.m_smallRoot.SetActive(false); } } [HarmonyPrefix] [HarmonyPatch("ShowPointOnMap")] private static bool ShowPointOnMap_Prefix() { if (!ValheimCartographerPlugin.ModEnabled.Value || !ValheimCartographerPlugin.BlockBossStoneMapPing.Value) { return true; } if (!MapAccessState.IsCartographyAccessActive) { ValheimCartographerPlugin.LogDebug("Blocked ShowPointOnMap"); return false; } return true; } } [HarmonyPatch(typeof(Player))] public static class PlayerPatches { [HarmonyPostfix] [HarmonyPatch("UpdateStations")] private static void CloseMapWhenTooFarFromTable(Player __instance) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) if (!ValheimCartographerPlugin.ModEnabled.Value || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || !MapAccessState.IsCartographyAccessActive || (Object)(object)MapAccessState.ActiveTable == (Object)null) { return; } MapTable activeTable = MapAccessState.ActiveTable; if (!((Object)(object)activeTable == (Object)null)) { float num = Vector3.Distance(((Component)__instance).transform.position, ((Component)activeTable).transform.position); float num2 = __instance.m_maxInteractDistance + 1.75f; if (num > num2) { ValheimCartographerPlugin.LogDebug("Closing map — player left cartography table range"); Minimap.instance.SetMapMode((MapMode)1); } } } } [HarmonyPatch(typeof(Player), "UpdateWishbone")] public static class PlayerWishboneGuard { private static bool Prepare() { return AccessTools.Method(typeof(Player), "UpdateWishbone", (Type[])null, (Type[])null) != null; } private static bool Prefix(Player __instance) { if (!ValheimCartographerPlugin.ModEnabled.Value) { return true; } if (CompassItemSetup.IsCompassEquipped(__instance)) { return false; } return true; } } } namespace ValheimCartographer.Compass { public static class CompassConstants { public const string PrefabName = "VC_CartographerCompass"; public const string NameToken = "$vc_cartographer_compass"; public const string DescToken = "$vc_cartographer_compass_desc"; } internal static class CompassCustomModelLoader { private static class SimpleObjLoader { private readonly struct Corner { public readonly Vector3 Pos; public readonly Vector2 Uv; public readonly Vector3 Normal; public Corner(Vector3 pos, Vector2 uv, Vector3 normal) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) Pos = pos; Uv = uv; Normal = normal; } } public static bool TryLoad(string path, out Mesh? mesh) { //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_029c: Unknown result type (might be due to invalid IL or missing references) //IL_02a1: Unknown result type (might be due to invalid IL or missing references) //IL_02ad: Expected O, but got Unknown //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_020c: Unknown result type (might be due to invalid IL or missing references) //IL_02e9: Unknown result type (might be due to invalid IL or missing references) //IL_02ee: Unknown result type (might be due to invalid IL or missing references) mesh = null; List<Vector3> list = new List<Vector3>(); List<Vector2> list2 = new List<Vector2>(); List<Vector3> list3 = new List<Vector3>(); string[] array; try { array = File.ReadAllLines(path, Encoding.UTF8); } catch { return false; } string[] array2 = array; for (int i = 0; i < array2.Length; i++) { string text = array2[i].Trim(); if (text.Length == 0 || text[0] == '#') { continue; } if (text.StartsWith("v ", StringComparison.Ordinal)) { float[] array3 = SplitFloats(text, 3); if (array3 != null) { list.Add(new Vector3(array3[0], array3[1], array3[2])); } } else if (text.StartsWith("vt ", StringComparison.Ordinal)) { float[] array4 = SplitFloats(text, 2); if (array4 != null) { list2.Add(new Vector2(array4[0], array4[1])); } } else if (text.StartsWith("vn ", StringComparison.Ordinal)) { float[] array5 = SplitFloats(text, 3); if (array5 != null) { list3.Add(new Vector3(array5[0], array5[1], array5[2])); } } } List<(string, List<string>)> list4 = CollectFaceGroups(array); if (list4.Count == 0) { return false; } var (arg, list5) = ChooseLargestFaceGroup(list4); if (list5 == null || list5.Count == 0) { return false; } if (ValheimCartographerPlugin.DebugLogging.Value && list4.Count > 1) { ValheimCartographerPlugin.Log.LogInfo((object)$"Compass OBJ: {list4.Count} object/group(s); using \"{arg}\" ({list5.Count} face line(s))."); } List<Vector3> list6 = new List<Vector3>(); List<Vector2> list7 = new List<Vector2>(); List<Vector3> list8 = new List<Vector3>(); List<int> list9 = new List<int>(); foreach (string item in list5) { List<Corner> list10 = ParseFaceCorners(item, list, list2, list3); if (list10.Count < 3) { continue; } int count = list6.Count; foreach (Corner item2 in list10) { list6.Add(item2.Pos); list7.Add(item2.Uv); list8.Add(item2.Normal); } for (int j = 1; j < list10.Count - 1; j++) { list9.Add(count); list9.Add(count + j); list9.Add(count + j + 1); } } if (list6.Count == 0 || list9.Count < 3) { return false; } mesh = new Mesh { name = "CompassObjMesh" }; mesh.indexFormat = (IndexFormat)(list6.Count > 65535); mesh.SetVertices(list6); mesh.SetUVs(0, list7); bool flag = false; foreach (Vector3 item3 in list8) { Vector3 current2 = item3; if (((Vector3)(ref current2)).sqrMagnitude > 1E-08f) { flag = true; break; } } if (flag) { mesh.SetNormals(list8); } else { mesh.RecalculateNormals(); } mesh.SetTriangles(list9, 0); mesh.RecalculateBounds(); return true; } private static List<(string name, List<string> faces)> CollectFaceGroups(string[] lines) { List<(string, List<string>)> list = new List<(string, List<string>)>(); List<string> list2 = null; string item = "default"; for (int i = 0; i < lines.Length; i++) { string text = lines[i].Trim(); if (text.Length == 0 || text[0] == '#') { continue; } if (text.StartsWith("o ", StringComparison.Ordinal) || text.StartsWith("g ", StringComparison.Ordinal)) { string text2 = text.Substring(2).Trim(); if (string.IsNullOrEmpty(text2)) { text2 = "unnamed"; } item = text2; list2 = new List<string>(); list.Add((item, list2)); } else if (text.StartsWith("f ", StringComparison.Ordinal)) { if (list2 == null) { list2 = new List<string>(); list.Add((item, list2)); } list2.Add(text); } } return list; } private static int EstimateTriangleFanCount(string fLine) { int num = fLine.Split(new char[2] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries).Length - 1; if (num < 3) { return 0; } return num - 2; } private static (string name, List<string>? faces) ChooseLargestFaceGroup(List<(string name, List<string> faces)> groups) { List<string> list = null; string text = ""; int num = -1; foreach (var (text2, list2) in groups) { if (list2.Count == 0) { continue; } int num2 = 0; foreach (string item in list2) { num2 += EstimateTriangleFanCount(item); } if (num2 > 0) { if (num2 > num) { num = num2; list = list2; text = text2; } else if (num2 == num && list != null && LooksLikeReferencePlane(text) && !LooksLikeReferencePlane(text2)) { list = list2; text = text2; } } } return (text, list); } private static bool LooksLikeReferencePlane(string name) { if (string.IsNullOrEmpty(name)) { return false; } string text = name.Trim().ToLowerInvariant(); if (!(text == "plane")) { return text.StartsWith("plane.", StringComparison.Ordinal); } return true; } private static List<Corner> ParseFaceCorners(string line, List<Vector3> vIn, List<Vector2> vtIn, List<Vector3> vnIn) { //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_014d: 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) string[] array = line.Split(new char[2] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); List<Corner> list = new List<Corner>(); for (int i = 1; i < array.Length; i++) { string obj = array[i]; int result = 0; int result2 = 0; int result3 = 0; string[] array2 = obj.Split(new char[1] { '/' }); if (array2.Length != 0 && array2[0].Length > 0) { int.TryParse(array2[0], NumberStyles.Integer, CultureInfo.InvariantCulture, out result); } if (array2.Length > 1 && array2[1].Length > 0) { int.TryParse(array2[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out result2); } if (array2.Length > 2 && array2[2].Length > 0) { int.TryParse(array2[2], NumberStyles.Integer, CultureInfo.InvariantCulture, out result3); } int num = ResolveIndex(result, vIn.Count); if (num < 0 || num >= vIn.Count) { continue; } Vector3 pos = vIn[num]; Vector2 uv = Vector2.zero; if (result2 != 0 && vtIn.Count > 0) { int num2 = ResolveIndex(result2, vtIn.Count); if (num2 >= 0 && num2 < vtIn.Count) { uv = vtIn[num2]; } } Vector3 normal = Vector3.zero; if (result3 != 0 && vnIn.Count > 0) { int num3 = ResolveIndex(result3, vnIn.Count); if (num3 >= 0 && num3 < vnIn.Count) { normal = vnIn[num3]; } } list.Add(new Corner(pos, uv, normal)); } return list; } private static float[]? SplitFloats(string line, int count) { string[] array = line.Split(new char[2] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); if (array.Length < count + 1) { return null; } float[] array2 = new float[count]; for (int i = 0; i < count; i++) { if (!float.TryParse(array[i + 1], NumberStyles.Float, CultureInfo.InvariantCulture, out array2[i])) { return null; } } return array2; } private static int ResolveIndex(int idx, int count) { if (count <= 0) { return -1; } if (idx > 0) { return idx - 1; } if (idx < 0) { return count + idx; } return -1; } } private const string BundleFileNoExt = "valheimcartographer_compass"; private const string BundleFileAlt = "valheimcartographer_compass.bundle"; private static readonly string[] s_objCandidates = new string[2] { "CompassModel.obj", "compass_model.obj" }; private static readonly string[] s_textureFallbacks = new string[1] { "DarkTexture.png" }; public static bool TryApply(GameObject compassPrefab) { if ((Object)(object)compassPrefab == (Object)null) { return false; } string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); if (string.IsNullOrEmpty(directoryName)) { return false; } if (TryApplyFromAssetBundle(compassPrefab, directoryName)) { return true; } if (TryApplyFromObjAndTexture(compassPrefab, directoryName)) { return true; } return false; } private static bool TryApplyFromAssetBundle(GameObject compassPrefab, string dir) { string[] array = new string[2] { "valheimcartographer_compass", "valheimcartographer_compass.bundle" }; foreach (string text in array) { string text2 = Path.Combine(dir, text); if (!File.Exists(text2)) { continue; } AssetBundle val = null; try { val = AssetBundle.LoadFromFile(text2); if ((Object)(object)val == (Object)null) { continue; } string[] array2 = new string[4] { "CompassWorld", "CompassPrefab", "compass_model", "CompassMesh" }; foreach (string text3 in array2) { GameObject val2 = val.LoadAsset<GameObject>(text3); if ((Object)(object)val2 != (Object)null && CompassPickupVisual.TryCopyMeshesFromSource(compassPrefab, val2)) { ValheimCartographerPlugin.Log.LogInfo((object)("Compass world model loaded from AssetBundle \"" + text + "\" asset \"" + text3 + "\".")); return true; } } GameObject[] array3 = val.LoadAllAssets<GameObject>(); foreach (GameObject val3 in array3) { if ((Object)(object)val3 != (Object)null && CompassPickupVisual.TryCopyMeshesFromSource(compassPrefab, val3)) { ValheimCartographerPlugin.Log.LogInfo((object)("Compass world model loaded from AssetBundle \"" + text + "\" asset \"" + ((Object)val3).name + "\".")); return true; } } } finally { if (val != null) { val.Unload(false); } } } return false; } private static bool TryApplyFromObjAndTexture(GameObject compassPrefab, string dir) { //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Expected O, but got Unknown if (!TryResolveObjPath(dir, out string objPath, out string label)) { return false; } if (!SimpleObjLoader.TryLoad(objPath, out Mesh mesh) || (Object)(object)mesh == (Object)null) { ValheimCartographerPlugin.Log.LogWarning((object)("Failed to parse " + label + ". Export OBJ from Blender (File → Export → Wavefront OBJ). Raw FBX is not loaded at runtime.")); return false; } Texture2D val = LoadDiffuseTexture(dir, objPath); MeshFilter[] componentsInChildren = compassPrefab.GetComponentsInChildren<MeshFilter>(true); if (componentsInChildren.Length == 0) { Object.Destroy((Object)(object)mesh); return false; } MeshRenderer component = ((Component)componentsInChildren[0]).GetComponent<MeshRenderer>(); Material val2 = (((Object)(object)component != (Object)null) ? ((Renderer)component).sharedMaterial : null); if ((Object)(object)val2 == (Object)null) { ObjectDB instance = ObjectDB.instance; GameObject val3 = ((instance != null) ? instance.GetItemPrefab("AmberPearl") : null); if ((Object)(object)val3 != (Object)null) { MeshRenderer componentInChildren = val3.GetComponentInChildren<MeshRenderer>(true); val2 = (((Object)(object)componentInChildren != (Object)null) ? ((Renderer)componentInChildren).sharedMaterial : null); } } componentsInChildren[0].sharedMesh = mesh; if ((Object)(object)component != (Object)null && (Object)(object)val2 != (Object)null) { Material val4 = new Material(val2); if ((Object)(object)val != (Object)null) { if (val4.HasProperty("_MainTex")) { val4.SetTexture("_MainTex", (Texture)(object)val); } else if (val4.HasProperty("_Diffuse")) { val4.SetTexture("_Diffuse", (Texture)(object)val); } } ((Renderer)component).sharedMaterial = val4; } string text = (((Object)(object)val != (Object)null) ? (" with texture \"" + ((Object)val).name + "\".") : "."); ValheimCartographerPlugin.Log.LogInfo((object)("Compass world model loaded from " + label + text)); return true; } private static bool TryResolveObjPath(string dir, out string objPath, out string label) { string[] array = s_objCandidates; foreach (string text in array) { string text2 = Path.Combine(dir, text); if (File.Exists(text2)) { objPath = text2; label = text; return true; } } objPath = ""; label = ""; return false; } private static Texture2D? LoadDiffuseTexture(string pluginDir, string objPath) { string text = Path.GetDirectoryName(objPath); if (string.IsNullOrEmpty(text)) { text = pluginDir; } string text2 = ReadMtllibNameFromObj(objPath); string[] array = new string[2] { text2, Path.GetFileNameWithoutExtension(objPath) + ".mtl" }; foreach (string text3 in array) { if (string.IsNullOrEmpty(text3)) { continue; } string text4 = Path.Combine(text, text3); if (!File.Exists(text4)) { continue; } string text5 = TryParseMapKdFromMtl(text4); if (!string.IsNullOrEmpty(text5)) { string path = text5.Replace('/', Path.DirectorySeparatorChar); Texture2D val = TryLoadTextureFile(Path.GetFullPath(Path.Combine(text, path))); if ((Object)(object)val != (Object)null) { return val; } } } array = s_textureFallbacks; foreach (string path2 in array) { Texture2D val2 = TryLoadTextureFile(Path.Combine(pluginDir, path2)); if ((Object)(object)val2 != (Object)null) { return val2; } } return null; } private static string? ReadMtllibNameFromObj(string objPath) { try { foreach (string item in File.ReadLines(objPath, Encoding.UTF8)) { string text = item.Trim(); if (text.Length != 0 && text[0] != '#' && text.StartsWith("mtllib ", StringComparison.Ordinal)) { string text2 = text.Substring(7).Trim(); return string.IsNullOrEmpty(text2) ? null : text2; } } } catch { } return null; } private static string? TryParseMapKdFromMtl(string mtlPath) { try { foreach (string item in File.ReadLines(mtlPath, Encoding.UTF8)) { string text = item.Trim(); if (text.Length == 0 || text[0] == '#' || !text.StartsWith("map_Kd", StringComparison.OrdinalIgnoreCase)) { continue; } string[] array = text.Split(new char[2] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); if (array.Length < 2) { continue; } int num = 1; while (num < array.Length && array[num].StartsWith("-", StringComparison.Ordinal)) { switch (array[num].ToLowerInvariant()) { case "-o": case "-s": case "-t": num += 4; break; case "-bm": case "-mm": case "-clamp": num += 2; break; case "-cc": case "-blendu": case "-blendv": case "-imfchan": num += 2; break; default: num++; break; } } if (num < array.Length) { string text2 = string.Join(" ", array, num, array.Length - num).Trim('"', ' ', '\t'); return string.IsNullOrEmpty(text2) ? null : text2; } } } catch { } return null; } private static Texture2D? TryLoadTextureFile(string path) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown if (!File.Exists(path)) { return null; } try { byte[] bytes = File.ReadAllBytes(path); Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); if (!CompassIconLoader.TryLoadImageBytes(val, bytes)) { Object.Destroy((Object)(object)val); return null; } ((Object)val).name = Path.GetFileNameWithoutExtension(path); ((Texture)val).wrapMode = (TextureWrapMode)0; return val; } catch { return null; } } } internal static class CompassEquipment { private static MethodInfo? s_getEquippedInSlot; private static object? s_utilitySlotEnum; private static bool s_resolved; private static void EnsureResolved() { if (s_resolved) { return; } s_resolved = true; MethodInfo[] methods = typeof(Inventory).GetMethods(BindingFlags.Instance | BindingFlags.Public); foreach (MethodInfo methodInfo in methods) { if (methodInfo.Name != "GetEquippedItemInSlot") { continue; } ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length != 1) { continue; } Type parameterType = parameters[0].ParameterType; if (parameterType.IsEnum) { try { s_utilitySlotEnum = Enum.Parse(parameterType, "Utility"); s_getEquippedInSlot = methodInfo; break; } catch { } } } } public static ItemData? GetUtilityItem(Player? player) { if ((Object)(object)player == (Object)null) { return null; } Inventory inventory = ((Humanoid)player).GetInventory(); if (inventory == null) { return null; } EnsureResolved(); if (s_getEquippedInSlot != null && s_utilitySlotEnum != null) { object? obj = s_getEquippedInSlot.Invoke(inventory, new object[1] { s_utilitySlotEnum }); ItemData val = (ItemData)((obj is ItemData) ? obj : null); if (val != null && val.m_shared?.m_name == "$vc_cartographer_compass") { return val; } return null; } foreach (ItemData allItem in inventory.GetAllItems()) { if (allItem.m_equipped && !(allItem.m_shared?.m_name != "$vc_cartographer_compass")) { return allItem; } } return null; } } public sealed class CompassHud : MonoBehaviour { private Canvas? _canvas; private RectTransform? _compassRootRt; private RectTransform? _ribbon0; private RectTransform? _ribbon1; private float _ribbonWidth; private float _halfViewport; private float _pixelsPerDegree; private bool _assetsReady; private float _currentRootY; private float _smoothVel; private bool _hadEquipped; private bool _canvasSortSynced; private void Awake() { Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); BuildUi(); } private void BuildUi() { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Expected O, but got Unknown //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_022e: Unknown result type (might be due to invalid IL or missing references) //IL_0239: Unknown result type (might be due to invalid IL or missing references) //IL_0244: Unknown result type (might be due to invalid IL or missing references) //IL_024e: Unknown result type (might be due to invalid IL or missing references) //IL_0278: Unknown result type (might be due to invalid IL or missing references) //IL_0282: Expected O, but got Unknown //IL_02b0: Unknown result type (might be due to invalid IL or missing references) //IL_02c5: Unknown result type (might be due to invalid IL or missing references) //IL_02da: Unknown result type (might be due to invalid IL or missing references) //IL_02ff: Unknown result type (might be due to invalid IL or missing references) //IL_0316: Unknown result type (might be due to invalid IL or missing references) _canvas = ((Component)this).gameObject.AddComponent<Canvas>(); _canvas.renderMode = (RenderMode)0; _canvas.sortingOrder = 400; CanvasScaler obj = ((Component)this).gameObject.AddComponent<CanvasScaler>(); obj.uiScaleMode = (ScaleMode)1; obj.referenceResolution = new Vector2(1920f, 1080f); ((Component)this).gameObject.AddComponent<GraphicRaycaster>(); if (!CompassUiTextureLoader.TryLoadSprite("Ribbon_backing.png", new Vector2(0.5f, 0.5f), out Sprite sprite) || !CompassUiTextureLoader.TryLoadSprite("Ribbon.png", new Vector2(0f, 0.5f), out Sprite ribbonSprite)) { ValheimCartographerPlugin.Log.LogWarning((object)"Compass HUD: Ribbon.png and/or Ribbon_backing.png missing next to the DLL; compass ribbon will not show."); _assetsReady = false; ((Behaviour)_canvas).enabled = false; return; } Texture2D texture = sprite.texture; Texture2D ribbonTex = ribbonSprite.texture; _ribbonWidth = ((Texture)ribbonTex).width; _pixelsPerDegree = _ribbonWidth / 360f; float value = ValheimCartographerPlugin.CompassRibbonUsableWidth.Value; float value2 = ValheimCartographerPlugin.CompassHudTrackOffsetY.Value; _halfViewport = value * 0.5f; GameObject val = new GameObject("CompassRoot"); val.transform.SetParent(((Component)this).transform, false); RectTransform val2 = (_compassRootRt = val.AddComponent<RectTransform>()); val2.anchorMin = new Vector2(0.5f, 1f); val2.anchorMax = new Vector2(0.5f, 1f); val2.pivot = new Vector2(0.5f, 1f); float value3 = ValheimCartographerPlugin.CompassHudOffsetY.Value; _currentRootY = 0f - value3; val2.anchoredPosition = new Vector2(0f, _currentRootY); val2.sizeDelta = new Vector2((float)((Texture)texture).width, (float)((Texture)texture).height); float num = Mathf.Clamp(ValheimCartographerPlugin.CompassHudScale.Value, 0.08f, 1.5f); ((Transform)val2).localScale = new Vector3(num, num, 1f); GameObject val3 = new GameObject("RibbonBacking"); val3.transform.SetParent(val.transform, false); RectTransform obj2 = val3.AddComponent<RectTransform>(); obj2.anchorMin = Vector2.zero; obj2.anchorMax = Vector2.one; obj2.offsetMin = Vector2.zero; obj2.offsetMax = Vector2.zero; Image obj3 = val3.AddComponent<Image>(); obj3.sprite = sprite; obj3.preserveAspect = false; ((Graphic)obj3).raycastTarget = false; GameObject maskGo = new GameObject("RibbonScrollMask"); maskGo.transform.SetParent(val.transform, false); RectTransform obj4 = maskGo.AddComponent<RectTransform>(); obj4.anchorMin = new Vector2(0.5f, 1f); obj4.anchorMax = new Vector2(0.5f, 1f); obj4.pivot = new Vector2(0.5f, 0.5f); float num2 = (float)(-((Texture)texture).height) * 0.5f - value2; obj4.anchoredPosition = new Vector2(0f, num2); obj4.sizeDelta = new Vector2(value, (float)((Texture)ribbonTex).height); maskGo.AddComponent<RectMask2D>(); AddRibbon("Ribbon0", out _ribbon0); AddRibbon("Ribbon1", out _ribbon1); _assetsReady = true; ((Behaviour)_canvas).enabled = false; void AddRibbon(string name, out RectTransform rt) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) GameObject val4 = new GameObject(name); val4.transform.SetParent(maskGo.transform, false); rt = val4.AddComponent<RectTransform>(); rt.anchorMin = new Vector2(0f, 0.5f); rt.anchorMax = new Vector2(0f, 0.5f); rt.pivot = new Vector2(0f, 0.5f); rt.anchoredPosition = Vector2.zero; rt.sizeDelta = new Vector2((float)((Texture)ribbonTex).width, (float)((Texture)ribbonTex).height); Image obj5 = val4.AddComponent<Image>(); obj5.sprite = ribbonSprite; obj5.type = (Type)0; obj5.preserveAspect = false; ((Graphic)obj5).raycastTarget = false; } } private void TrySyncCanvasSortingBehindHud() { if (!_canvasSortSynced && !((Object)(object)_canvas == (Object)null) && !((Object)(object)Hud.instance == (Object)null)) { Canvas val = null; if ((Object)(object)Hud.instance.m_loadingScreen != (Object)null) { val = ((Component)Hud.instance.m_loadingScreen).GetComponentInParent<Canvas>(); } if ((Object)(object)val == (Object)null && (Object)(object)Hud.instance.m_rootObject != (Object)null) { val = Hud.instance.m_rootObject.GetComponent<Canvas>(); } if (!((Object)(object)val == (Object)null)) { _canvas.sortingOrder = val.sortingOrder + ValheimCartographerPlugin.CompassHudSortOffsetFromHud.Value; _canvasSortSynced = true; } } } private static float NormalizeYawDegrees(float eulerY) { float num = eulerY % 360f; if (num < 0f) { num += 360f; } return num; } private void Update() { //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) if (!_assetsReady || (Object)(object)_canvas == (Object)null || (Object)(object)_compassRootRt == (Object)null || (Object)(object)_ribbon0 == (Object)null || (Object)(object)_ribbon1 == (Object)null) { return; } TrySyncCanvasSortingBehindHud(); Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || !CompassItemSetup.IsCompassEquipped(localPlayer)) { ((Behaviour)_canvas).enabled = false; _hadEquipped = false; return; } float num = 0f - ValheimCartographerPlugin.CompassHudOffsetY.Value; float num2 = num + ValheimCartographerPlugin.CompassHudSlidePixels.Value; Camera main = Camera.main; if ((Object)(object)main == (Object)null) { ((Behaviour)_canvas).enabled = false; return; } ((Behaviour)_canvas).enabled = true; if (!_hadEquipped) { _hadEquipped = true; bool flag = CompassHudVisibility.ShouldHideAnimated(); _currentRootY = (flag ? num2 : num); _smoothVel = 0f; _compassRootRt.anchoredPosition = new Vector2(0f, _currentRootY); } float num3 = (CompassHudVisibility.ShouldHideAnimated() ? num2 : num); float num4 = Mathf.Max(0.01f, ValheimCartographerPlugin.CompassHudSlideSmoothTime.Value); _currentRootY = Mathf.SmoothDamp(_currentRootY, num3, ref _smoothVel, num4, float.PositiveInfinity, Time.unscaledDeltaTime); _compassRootRt.anchoredPosition = new Vector2(0f, _currentRootY); float num5 = NormalizeYawDegrees(((Component)main).transform.eulerAngles.y); float num6 = Mathf.Repeat(_halfViewport - (num5 + 360f) * _pixelsPerDegree, _ribbonWidth); if (num6 > 0.0001f) { num6 -= _ribbonWidth; } _ribbon0.anchoredPosition = new Vector2(num6, 0f); _ribbon1.anchoredPosition = new Vector2(num6 + _ribbonWidth, 0f); } } internal static class CompassHudVisibility { internal static bool ShouldHideAnimated() { if ((Object)(object)ZNetScene.instance == (Object)null) { return true; } if (Game.IsPaused()) { return true; } if (Time.timeScale <= 0f) { return true; } if (InventoryGui.IsVisible()) { return true; } if (TextInput.IsVisible()) { return true; } if (Minimap.IsOpen()) { return true; } if (Menu.IsVisible()) { return true; } if (StoreGui.IsVisible()) { return true; } if (Console.IsVisible()) { return true; } return false; } } internal static class CompassIconLoader { private static readonly MethodInfo? s_imageConversionLoadImage = ResolveImageConversionLoadImage(); private static MethodInfo? ResolveImageConversionLoadImage() { return Type.GetType("UnityEngine.ImageConversion, UnityEngine.ImageConversionModule")?.GetMethod("LoadImage", BindingFlags.Static | BindingFlags.Public, null, new Type[2] { typeof(Texture2D), typeof(byte[]) }, null); } internal static bool TryLoadImageBytes(Texture2D tex, byte[] bytes) { if (s_imageConversionLoadImage == null) { return false; } object obj = s_imageConversionLoadImage.Invoke(null, new object[2] { tex, bytes }); if (obj is bool) { return (bool)obj; } return false; } public static Sprite? TryLoadSprite() { //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Expected O, but got Unknown //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); if (string.IsNullOrEmpty(directoryName)) { return null; } string text = null; string[] array = new string[3] { "icon.png", "Icon.png", "CompassSprite.png" }; foreach (string path in array) { string text2 = Path.Combine(directoryName, path); if (File.Exists(text2)) { text = text2; break; } } if (text == null) { ValheimCartographerPlugin.Log.LogWarning((object)"No icon.png, Icon.png, or CompassSprite.png next to the plugin DLL; compass will use the wishbone icon."); return null; } byte[] bytes; try { bytes = File.ReadAllBytes(text); } catch (IOException ex) { ValheimCartographerPlugin.Log.LogWarning((object)("Could not read " + text + ": " + ex.Message)); return null; } Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); if (!TryLoadImageBytes(val, bytes)) { ValheimCartographerPlugin.Log.LogWarning((object)((s_imageConversionLoadImage == null) ? "UnityEngine.ImageConversion.LoadImage is not available; compass will use the wishbone icon." : ("Could not decode image: " + text))); return null; } Sprite obj = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f); ((Object)obj).name = "VC_CartographerIcon"; return obj; } } internal static class CompassItemPostprocess { private static readonly FieldInfo[] s_statusEffectFields = ResolveStatusEffectFields(); private static FieldInfo[] ResolveStatusEffectFields() { Type nestedType = typeof(ItemData).GetNestedType("SharedData", BindingFlags.Public | BindingFlags.NonPublic); if (nestedType == null) { return Array.Empty<FieldInfo>(); } string[] obj = new string[4] { "m_equipStatusEffect", "m_setStatusEffect", "m_holdStatusEffect", "m_consumeStatusEffect" }; List<FieldInfo> list = new List<FieldInfo>(); string[] array = obj; foreach (string name in array) { FieldInfo field = nestedType.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null && typeof(StatusEffect).IsAssignableFrom(field.FieldType)) { list.Add(field); } } return list.ToArray(); } public static void StripWishboneStatusEffects(ItemDrop itemDrop) { SharedData val = itemDrop.m_itemData?.m_shared; if (val == null) { return; } FieldInfo[] array = s_statusEffectFields; foreach (FieldInfo fieldInfo in array) { try { fieldInfo.SetValue(val, null); } catch { } } } } public static class CompassItemSetup { private static bool _registered; public static void Register() { if (!_registered) { PrefabManager.OnVanillaPrefabsAvailable += OnVanillaPrefabsAvailable; } } private static void OnVanillaPrefabsAvailable() { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0064: 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 PrefabManager.OnVanillaPrefabsAvailable -= OnVanillaPrefabsAvailable; int value = ValheimCartographerPlugin.CompassIronCost.Value; int value2 = ValheimCartographerPlugin.CompassWoodCost.Value; ItemConfig val = new ItemConfig { Name = "$vc_cartographer_compass", Description = "$vc_cartographer_compass_desc", CraftingStation = CraftingStations.Forge, MinStationLevel = 1 }; val.AddRequirement("Iron", value, 1); val.AddRequirement("FineWood", value2, 1); Sprite val2 = CompassIconLoader.TryLoadSprite(); if ((Object)(object)val2 != (Object)null) { val.Icon = val2; } CustomItem val3 = new CustomItem("VC_CartographerCompass", "Wishbone", val); ItemManager.Instance.AddItem(val3); CompassItemPostprocess.StripWishboneStatusEffects(val3.ItemDrop); CompassPickupVisual.ApplyToPrefab(val3.ItemPrefab); CustomLocalization localization = LocalizationManager.Instance.GetLocalization(); string text = "English"; string text2 = "$vc_cartographer_compass"; localization.AddTranslation(ref text, ref text2, "Cartographer's Compass"); text = "English"; text2 = "$vc_cartographer_compass_desc"; localization.AddTranslation(ref text, ref text2, "A simple compass for reading the land. Equip in the utility slot to see a heading strip at the top of the screen."); _registered = true; ValheimCartographerPlugin.Log.LogInfo((object)"Compass item registered."); } public static bool IsCompassEquipped(Player? player) { if ((Object)(object)player == (Object)null || !ValheimCartographerPlugin.CompassEnabled.Value) { return false; } ItemData utilityItem = CompassEquipment.GetUtilityItem(player); if (utilityItem != null) { return utilityItem.m_shared?.m_name == "$vc_cartographer_compass"; } return false; } } internal static class CompassPickupVisual { private static readonly string[] s_sourcePrefabNames = new string[3] { "AmberPearl", "Ruby", "Coins" }; public static void ApplyToPrefab(GameObject compassPrefab) { if ((Object)(object)compassPrefab == (Object)null || CompassCustomModelLoader.TryApply(compassPrefab)) { return; } string[] array = s_sourcePrefabNames; foreach (string text in array) { GameObject val = ResolveItemPrefab(text); if (!((Object)(object)val == (Object)null) && TryCopyMeshes(compassPrefab, val)) { ValheimCartographerPlugin.Log.LogInfo((object)("Compass world model meshes copied from vanilla prefab \"" + text + "\".")); return; } } ValheimCartographerPlugin.Log.LogWarning((object)"Could not replace compass world meshes; dropped item may still look like a wishbone."); } private static GameObject? ResolveItemPrefab(string name) { if ((Object)(object)ObjectDB.instance != (Object)null) { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(name); if ((Object)(object)itemPrefab != (Object)null) { return itemPrefab; } } PrefabManager instance = PrefabManager.Instance; if (instance == null) { return null; } return instance.GetPrefab(name); } internal static bool TryCopyMeshesFromSource(GameObject compassPrefab, GameObject sourcePrefab) { return TryCopyMeshes(compassPrefab, sourcePrefab); } private static bool TryCopyMeshes(GameObject compassPrefab, GameObject sourcePrefab) { MeshFilter[] componentsInChildren = sourcePrefab.GetComponentsInChildren<MeshFilter>(true); MeshFilter[] componentsInChildren2 = compassPrefab.GetComponentsInChildren<MeshFilter>(true); if (componentsInChildren.Length != 0 && componentsInChildren2.Length != 0) { int num = Mathf.Min(componentsInChildren.Length, componentsInChildren2.Length); for (int i = 0; i < num; i++) { componentsInChildren2[i].sharedMesh = componentsInChildren[i].sharedMesh; MeshRenderer component = ((Component)componentsInChildren2[i]).GetComponent<MeshRenderer>(); MeshRenderer component2 = ((Component)componentsInChildren[i]).GetComponent<MeshRenderer>(); if ((Object)(object)component != (Object)null && (Object)(object)component2 != (Object)null) { ((Renderer)component).sharedMaterials = ((Renderer)component2).sharedMaterials; } } return true; } SkinnedMeshRenderer[] componentsInChildren3 = sourcePrefab.GetComponentsInChildren<SkinnedMeshRenderer>(true); SkinnedMeshRenderer[] componentsInChildren4 = compassPrefab.GetComponentsInChildren<SkinnedMeshRenderer>(true); if (componentsInChildren3.Length != 0 && componentsInChildren4.Length != 0) { int num2 = Mathf.Min(componentsInChildren3.Length, componentsInChildren4.Length); for (int j = 0; j < num2; j++) { componentsInChildren4[j].sharedMesh = componentsInChildren3[j].sharedMesh; ((Renderer)componentsInChildren4[j]).sharedMaterials = ((Renderer)componentsInChildren3[j]).sharedMaterials; } return true; } return false; } } internal static class CompassUiTextureLoader { internal static bool TryLoadSprite(string fileName, Vector2 pivot, out Sprite sprite) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) sprite = null; string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); if (string.IsNullOrEmpty(directoryName)) { return false; } string path = Path.Combine(directoryName, fileName); if (!File.Exists(path)) { return false; } byte[] bytes; try { bytes = File.ReadAllBytes(path); } catch (IOException) { return false; } Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); if (!CompassIconLoader.TryLoadImageBytes(val, bytes)) { return false; } ((Texture)val).wrapMode = (TextureWrapMode)1; ((Texture)val).filterMode = (FilterMode)1; sprite = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), pivot, 100f); ((Object)sprite).name = "VC_" + fileName; return true; } } }