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 TotemPins v2.1.0
TotemPins.dll
Decompiled 2 days agousing System; using System.Collections; using System.Collections.Generic; using System.Reflection; using System.Runtime.CompilerServices; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: AssemblyVersion("0.0.0.0")] namespace TotemPins; [BepInPlugin("valheimtotems.totempins", "TotemPins", "2.1.0")] public class TotemPinsPlugin : BaseUnityPlugin { public const string Guid = "valheimtotems.totempins"; public const string Version = "2.1.0"; public const string NeutralIconName = "TotemPins_Totem"; internal static ConfigEntry<bool> Enabled; internal static ConfigEntry<string> LocationPrefix; internal static ConfigEntry<string> IconName; internal static ConfigEntry<bool> UseTravelTotemsIcon; internal static ConfigEntry<bool> LogIconNames; internal static ManualLogSource Log; private static FieldInfo _fLocations; private static FieldInfo _fPrefabName; private static FieldInfo _fPrefab; private static FieldInfo _fIconPlaced; private static PropertyInfo _pRefName; private static int _lastLocationCount = -1; private static object _lastList; private static object _registeredList; private static bool _warnedNoSprite; private void Awake() { Log = ((BaseUnityPlugin)this).Logger; Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Show Travel Totem locations on the map once their area has been generated."); LocationPrefix = ((BaseUnityPlugin)this).Config.Bind<string>("General", "LocationPrefix", "VV_TravelTotemLocation", "Locations whose prefab name starts with this get a map pin."); UseTravelTotemsIcon = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "UseTravelTotemsIcon", true, "Use the Travel Totems map icon. Requires TotemPins on the server AND every player. Set false to use the vanilla IconName below instead (server-only install works)."); IconName = ((BaseUnityPlugin)this).Config.Bind<string>("General", "IconName", "StartTemple", "Vanilla location icon used only when UseTravelTotemsIcon is false (e.g. StartTemple). Note: with StartTemple, Travel Totems' AllowSelectDefaultSpawn treats pins as spawn points."); LogIconNames = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "LogIconNames", false, "Client: log every map location icon name the game knows."); ApplyPatches(); } internal static void ApplyPatches() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Expected O, but got Unknown //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Expected O, but got Unknown if (!ResolveFields()) { return; } Type type = AccessTools.TypeByName("ZoneSystem"); Harmony val = new Harmony("valheimtotems.totempins"); HarmonyMethod val2 = new HarmonyMethod(AccessTools.Method(typeof(TotemPinsPlugin), "EnsureFlagsPrefix", (Type[])null, (Type[])null)); HarmonyMethod val3 = new HarmonyMethod(AccessTools.Method(typeof(TotemPinsPlugin), "RenameIconsPostfix", (Type[])null, (Type[])null)); int num = 0; MethodInfo[] methods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (methodInfo.Name == "PlaceLocations") { val.Patch((MethodBase)methodInfo, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); num++; } else if (methodInfo.Name == "GetLocationIcons") { val.Patch((MethodBase)methodInfo, val2, val3, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); num++; } } Type type2 = AccessTools.TypeByName("Minimap"); HarmonyMethod val4 = new HarmonyMethod(AccessTools.Method(typeof(TotemPinsPlugin), "RegisterIconPatch", (Type[])null, (Type[])null)); MethodInfo methodInfo2 = AccessTools.Method(type2, "Start", (Type[])null, (Type[])null); MethodInfo methodInfo3 = AccessTools.Method(type2, "UpdateLocationPins", (Type[])null, (Type[])null); if (methodInfo2 != null) { MethodInfo methodInfo4 = methodInfo2; HarmonyMethod val5 = val4; val.Patch((MethodBase)methodInfo4, (HarmonyMethod)null, val5, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } if (methodInfo3 != null) { val.Patch((MethodBase)methodInfo3, val4, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } Log.LogInfo((object)(string.Format("TotemPins {0} loaded ({1} methods patched). Prefix='{2}', ", "2.1.0", num, LocationPrefix.Value) + ((!UseTravelTotemsIcon.Value) ? $"using vanilla icon '{IconName.Value}'." : "using Travel Totems icon."))); } private static void RegisterIconPatch(object __instance) { if (__instance == null || !Enabled.Value) { return; } try { if (!(AccessTools.Field(__instance.GetType(), "m_locationIcons")?.GetValue(__instance) is IList list) || object.ReferenceEquals(list, _registeredList)) { return; } Type type = ((!list.GetType().IsGenericType) ? null : list.GetType().GetGenericArguments()[0]); FieldInfo fieldInfo = ((!(type != null)) ? null : AccessTools.Field(type, "m_name")); FieldInfo fieldInfo2 = ((!(type != null)) ? null : AccessTools.Field(type, "m_icon")); if (fieldInfo == null || fieldInfo2 == null) { _registeredList = list; Log.LogWarning((object)"Minimap icon list has an unexpected format."); return; } HashSet<string> hashSet = new HashSet<string>(); string text = default(string); foreach (object item in list) { if (item != null) { object obj = fieldInfo.GetValue(item) as string; if (obj != null) { text = (string)obj; obj = text; } if (obj != null) { hashSet.Add(text); } } } if (LogIconNames.Value) { Log.LogInfo((object)("Map location icons: " + string.Join(", ", new List<string>(hashSet).ToArray()))); } object obj2 = null; Type type2 = AccessTools.TypeByName("VentureValheim.TravelTotems.AssetManager"); PropertyInfo propertyInfo = ((!(type2 != null)) ? null : AccessTools.Property(type2, "TotemMapSprite")); if (propertyInfo != null) { obj2 = propertyInfo.GetValue(null, null); } if (obj2 == null) { if (!_warnedNoSprite) { _warnedNoSprite = true; Log.LogWarning((object)"Travel Totems map sprite not available yet; will retry."); } return; } if (!hashSet.Contains("TotemPins_Totem")) { object obj3 = Activator.CreateInstance(type); fieldInfo.SetValue(obj3, "TotemPins_Totem"); fieldInfo2.SetValue(obj3, obj2); list.Add(obj3); } _registeredList = list; Log.LogInfo((object)string.Format("Registered Travel Totems map icon as '{0}'.", "TotemPins_Totem")); } catch (Exception ex) { _registeredList = null; Log.LogWarning((object)("Could not register totem map icon: " + ex.Message)); } } internal static bool ResolveFields() { Type type = AccessTools.TypeByName("ZoneSystem"); Type type2 = AccessTools.TypeByName("ZoneLocation"); if (type == null || type2 == null) { Log.LogError((object)"Could not find ZoneSystem/ZoneLocation - game version not supported."); return false; } _fLocations = AccessTools.Field(type, "m_locations"); _fPrefabName = AccessTools.Field(type2, "m_prefabName"); _fPrefab = AccessTools.Field(type2, "m_prefab"); _fIconPlaced = AccessTools.Field(type2, "m_iconPlaced"); if (_fPrefab != null) { _pRefName = AccessTools.Property(_fPrefab.FieldType, "Name"); } if (_fLocations == null || _fIconPlaced == null || (_fPrefab == null && _fPrefabName == null)) { Log.LogError((object)"Expected ZoneSystem/ZoneLocation fields are missing - game version not supported."); return false; } return true; } private static string GetLocationName(object zoneLocation) { if (_fPrefab != null && _pRefName != null) { try { object value = _fPrefab.GetValue(zoneLocation); string text = ((value == null) ? null : (_pRefName.GetValue(value, null) as string)); if (!string.IsNullOrEmpty(text)) { return text; } } catch (Exception) { } } return (!(_fPrefabName != null)) ? null : (_fPrefabName.GetValue(zoneLocation) as string); } private static void EnsureFlagsPrefix(object __instance) { if (!Enabled.Value || __instance == null) { return; } try { if (!(_fLocations.GetValue(__instance) is IList list) || (object.ReferenceEquals(list, _lastList) && list.Count == _lastLocationCount)) { return; } _lastList = list; _lastLocationCount = list.Count; string value = LocationPrefix.Value; int num = 0; foreach (object item in list) { if (item == null) { continue; } string locationName = GetLocationName(item); if (locationName != null && locationName.StartsWith(value, StringComparison.Ordinal)) { if (!(bool)_fIconPlaced.GetValue(item)) { _fIconPlaced.SetValue(item, true); } num++; } } Log.LogInfo((object)$"Flagged {num} location type(s) matching '{value}' for map icons."); } catch (Exception ex) { Log.LogWarning((object)("EnsureFlags failed: " + ex.Message)); } } private static void RenameIconsPostfix(object __0) { if (!Enabled.Value || !(__0 is IDictionary { Count: not 0 } dictionary)) { return; } try { string value = LocationPrefix.Value; List<object> list = new List<object>(); foreach (DictionaryEntry item in dictionary) { if (item.Value is string text && text.StartsWith(value, StringComparison.Ordinal)) { list.Add(item.Key); } } string value2 = ((!UseTravelTotemsIcon.Value) ? IconName.Value : "TotemPins_Totem"); foreach (object item2 in list) { dictionary[item2] = value2; } } catch (Exception ex) { Log.LogWarning((object)("RenameIcons failed: " + ex.Message)); } } }